blob: 99b57b911d384fbb46130d7a94caecf4c0b38d45 [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;
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08001384
1385 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301386 }
1387
1388 if (temp_total_len < rem_len)
1389 {
1390 ret = temp_total_len + 1;
1391 strlcpy(pDest, temp, ret);
1392 pAdapter->isTruncated = FALSE;
1393 }
1394 else
1395 {
1396 pAdapter->isTruncated = TRUE;
1397 if (rem_len >= strlen("%%%%"))
1398 {
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08001399 ret = snprintf(pDest, strlen("%%%%"), "%%%%%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301400 }
1401 {
1402 ret = 0;
1403 }
1404 }
1405
1406 return ret;
1407
1408}/*End of hdd_format_batch_scan_rsp*/
1409
1410/**---------------------------------------------------------------------------
1411
1412 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1413 buffer starting with head of hdd batch scan response queue
1414
1415 \param - pAdapter Pointer to HDD adapter
1416 \param - pDest Pointer to user data buffer
1417 \param - cur_len current offset in user buffer
1418 \param - rem_len remaining no of bytes in user buffer
1419
1420 \return - number of bytes written in user buffer
1421
1422 --------------------------------------------------------------------------*/
1423
1424tANI_U32 hdd_populate_user_batch_scan_rsp
1425(
1426 hdd_adapter_t* pAdapter,
1427 tANI_U8 *pDest,
1428 tANI_U32 cur_len,
1429 tANI_U32 rem_len
1430)
1431{
1432 tHddBatchScanRsp *pHead;
1433 tHddBatchScanRsp *pPrev;
1434 tANI_U32 len;
1435
Rajeev79dbe4c2013-10-05 11:03:42 +05301436 pAdapter->isTruncated = FALSE;
1437
1438 /*head of hdd batch scan response queue*/
1439 pHead = pAdapter->pBatchScanRsp;
1440 while (pHead)
1441 {
1442 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1443 pAdapter);
1444 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001445 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301446 cur_len += len;
1447 if(TRUE == pAdapter->isTruncated)
1448 {
1449 /*result is truncated return rest of scan rsp in next req*/
1450 cur_len = rem_len;
1451 break;
1452 }
1453 pPrev = pHead;
1454 pHead = pHead->pNext;
1455 pAdapter->pBatchScanRsp = pHead;
1456 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1457 vos_mem_free(pPrev);
1458 }
1459
1460 return cur_len;
1461}/*End of hdd_populate_user_batch_scan_rsp*/
1462
1463/**---------------------------------------------------------------------------
1464
1465 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1466 scan response data from HDD queue to user space
1467 It does following in detail:
1468 a) if HDD has enough data in its queue then it 1st copies data to user
1469 space and then send get batch scan indication message to FW. In this
1470 case it does not wait on any event and batch scan response data will
1471 be populated in HDD response queue in MC thread context after receiving
1472 indication from FW
1473 b) else send get batch scan indication message to FW and wait on an event
1474 which will be set once HDD receives complete batch scan response from
1475 FW and then this function returns batch scan response to user space
1476
1477 \param - pAdapter Pointer to HDD adapter
1478 \param - pPrivData Pointer to priv_data
1479
1480 \return - 0 for success -EFAULT for failure
1481
1482 --------------------------------------------------------------------------*/
1483
1484int hdd_return_batch_scan_rsp_to_user
1485(
1486 hdd_adapter_t* pAdapter,
1487 hdd_priv_data_t *pPrivData,
1488 tANI_U8 *command
1489)
1490{
1491 tANI_U8 *pDest;
1492 tANI_U32 count = 0;
1493 tANI_U32 len = 0;
1494 tANI_U32 cur_len = 0;
1495 tANI_U32 rem_len = 0;
1496 eHalStatus halStatus;
1497 unsigned long rc;
1498 tSirTriggerBatchScanResultInd *pReq;
1499
1500 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1501 pReq->param = 0;/*batch scan client*/
1502 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1503 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1504
1505 cur_len = pPrivData->used_len;
1506 if (pPrivData->total_len > pPrivData->used_len)
1507 {
1508 rem_len = pPrivData->total_len - pPrivData->used_len;
1509 }
1510 else
1511 {
1512 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1513 "%s: Invalid user data buffer total_len %d used_len %d",
1514 __func__, pPrivData->total_len, pPrivData->used_len);
1515 return -EFAULT;
1516 }
1517
1518 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1519 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1520 cur_len, rem_len);
1521 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1522
1523 /*enough scan result available in cache to return to user space or
1524 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001525 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301526 {
1527 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1528 halStatus = sme_TriggerBatchScanResultInd(
1529 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1530 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1531 pAdapter);
1532 if ( eHAL_STATUS_SUCCESS == halStatus )
1533 {
1534 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1535 {
1536 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1537 rc = wait_for_completion_timeout(
1538 &pAdapter->hdd_get_batch_scan_req_var,
1539 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1540 if (0 == rc)
1541 {
1542 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1543 "%s: Timeout waiting to fetch batch scan rsp from fw",
1544 __func__);
1545 return -EFAULT;
1546 }
1547 }
1548
1549 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001550 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301551 pDest += len;
1552 cur_len += len;
1553
1554 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1555 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1556 cur_len, rem_len);
1557 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1558
1559 count = 0;
1560 len = (len - pPrivData->used_len);
1561 pDest = (command + pPrivData->used_len);
1562 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001563 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301564 while(count < len)
1565 {
1566 printk("%c", *(pDest + count));
1567 count++;
1568 }
1569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1570 "%s: copy %d data to user buffer", __func__, len);
1571 if (copy_to_user(pPrivData->buf, pDest, len))
1572 {
1573 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1574 "%s: failed to copy data to user buffer", __func__);
1575 return -EFAULT;
1576 }
1577 }
1578 else
1579 {
1580 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1581 "sme_GetBatchScanScan returned failure halStatus %d",
1582 halStatus);
1583 return -EINVAL;
1584 }
1585 }
1586 else
1587 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301588 count = 0;
1589 len = (len - pPrivData->used_len);
1590 pDest = (command + pPrivData->used_len);
1591 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001592 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301593 while(count < len)
1594 {
1595 printk("%c", *(pDest + count));
1596 count++;
1597 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1599 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301600 if (copy_to_user(pPrivData->buf, pDest, len))
1601 {
1602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1603 "%s: failed to copy data to user buffer", __func__);
1604 return -EFAULT;
1605 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301606 }
1607
1608 return 0;
1609} /*End of hdd_return_batch_scan_rsp_to_user*/
1610
1611#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1612
Jeff Johnson295189b2012-06-20 16:38:30 -07001613int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1614{
1615 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1616 hdd_priv_data_t priv_data;
1617 tANI_U8 *command = NULL;
1618 int ret = 0;
1619
1620 if (NULL == pAdapter)
1621 {
1622 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001623 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001624 ret = -ENODEV;
1625 goto exit;
1626 }
1627
Jeff Johnsone7245742012-09-05 17:12:55 -07001628 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001629 {
1630 ret = -EINVAL;
1631 goto exit;
1632 }
1633
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001634 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1635 {
1636 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1637 "%s:LOGP in Progress. Ignore!!!", __func__);
1638 ret = -EBUSY;
1639 goto exit;
1640 }
1641
Jeff Johnson295189b2012-06-20 16:38:30 -07001642 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1643 {
1644 ret = -EFAULT;
1645 goto exit;
1646 }
1647
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001648 if (priv_data.total_len <= 0)
1649 {
1650 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1651 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1652 priv_data.total_len);
1653 ret = -EINVAL;
1654 goto exit;
1655 }
1656
1657 /* Allocate +1 for '\0' */
1658 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001659 if (!command)
1660 {
1661 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001662 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001663 ret = -ENOMEM;
1664 goto exit;
1665 }
1666
1667 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1668 {
1669 ret = -EFAULT;
1670 goto exit;
1671 }
1672
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001673 /* Making sure the command is NUL-terminated */
1674 command[priv_data.total_len] = '\0';
1675
Jeff Johnson295189b2012-06-20 16:38:30 -07001676 if ((SIOCDEVPRIVATE + 1) == cmd)
1677 {
1678 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1679
1680 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001681 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001682
1683 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1684 {
1685 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1686 sizeof(tSirMacAddr)))
1687 {
1688 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001689 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001690 ret = -EFAULT;
1691 }
1692 }
Amar Singhal0974e402013-02-12 14:27:46 -08001693 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001694 {
Amar Singhal0974e402013-02-12 14:27:46 -08001695 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001696 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001697
Jeff Johnson295189b2012-06-20 16:38:30 -07001698 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001699
1700 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001701 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001702 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001703 "%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 -07001704 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001705 ret = hdd_setBand_helper(dev, ptr);
1706 }
Kiet Lamf040f472013-11-20 21:15:23 +05301707 else if(strncmp(command, "SETWMMPS", 8) == 0)
1708 {
1709 tANI_U8 *ptr = command;
1710 ret = hdd_wmmps_helper(pAdapter, ptr);
1711 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001712 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1713 {
1714 char *country_code;
1715
1716 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001717
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001718 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001719 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001720#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301721 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001722#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001723 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1724 (void *)(tSmeChangeCountryCallback)
1725 wlan_hdd_change_country_code_callback,
1726 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
1727 if (eHAL_STATUS_SUCCESS == ret)
1728 {
1729 ret = wait_for_completion_interruptible_timeout(
1730 &pAdapter->change_country_code,
1731 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1732 if (0 >= ret)
1733 {
1734 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1735 __func__);
1736 }
1737 }
1738 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001739 {
1740 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001741 "%s: SME Change Country code fail ret=%d", __func__, ret);
1742 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001743 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001744
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001745 }
1746 /*
1747 command should be a string having format
1748 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1749 */
Amar Singhal0974e402013-02-12 14:27:46 -08001750 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001751 {
Amar Singhal0974e402013-02-12 14:27:46 -08001752 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001753
1754 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001755 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001756
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001757 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001758 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001759 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1760 {
1761 int suspend = 0;
1762 tANI_U8 *ptr = (tANI_U8*)command + 15;
1763
1764 suspend = *ptr - '0';
1765 hdd_set_wlan_suspend_mode(suspend);
1766 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001767#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1768 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1769 {
1770 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001771 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001772 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1773 eHalStatus status = eHAL_STATUS_SUCCESS;
1774
1775 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1776 value = value + 15;
1777
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001778 /* Convert the value from ascii to integer */
1779 ret = kstrtos8(value, 10, &rssi);
1780 if (ret < 0)
1781 {
1782 /* If the input value is greater than max value of datatype, then also
1783 kstrtou8 fails */
1784 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1785 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07001786 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001787 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1788 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1789 ret = -EINVAL;
1790 goto exit;
1791 }
1792
Srinivas Girigowdade697412013-02-14 16:31:48 -08001793 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001794
Srinivas Girigowdade697412013-02-14 16:31:48 -08001795 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1796 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1797 {
1798 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1799 "Neighbor lookup threshold value %d is out of range"
1800 " (Min: %d Max: %d)", lookUpThreshold,
1801 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1802 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1803 ret = -EINVAL;
1804 goto exit;
1805 }
1806
1807 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1808 "%s: Received Command to Set Roam trigger"
1809 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1810
1811 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1812 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1813 if (eHAL_STATUS_SUCCESS != status)
1814 {
1815 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1816 "%s: Failed to set roam trigger, try again", __func__);
1817 ret = -EPERM;
1818 goto exit;
1819 }
1820
1821 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1822 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1823 }
1824 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1825 {
1826 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1827 int rssi = (-1) * lookUpThreshold;
1828 char extra[32];
1829 tANI_U8 len = 0;
1830
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001831 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001832 if (copy_to_user(priv_data.buf, &extra, len + 1))
1833 {
1834 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1835 "%s: failed to copy data to user buffer", __func__);
1836 ret = -EFAULT;
1837 goto exit;
1838 }
1839 }
1840 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1841 {
1842 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001843 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001844 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001845
Srinivas Girigowdade697412013-02-14 16:31:48 -08001846 /* input refresh period is in terms of seconds */
1847 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1848 value = value + 18;
1849 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001850 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001851 if (ret < 0)
1852 {
1853 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001854 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001855 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001856 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001857 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001858 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1859 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001860 ret = -EINVAL;
1861 goto exit;
1862 }
1863
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001864 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1865 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001866 {
1867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001868 "Roam scan period value %d is out of range"
1869 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001870 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1871 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001872 ret = -EINVAL;
1873 goto exit;
1874 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001875 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001876
1877 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1878 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001879 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001880
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001881 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1882 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001883 }
1884 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1885 {
1886 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1887 char extra[32];
1888 tANI_U8 len = 0;
1889
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001890 len = scnprintf(extra, sizeof(extra), "%s %d",
1891 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001892 /* Returned value is in units of seconds */
1893 if (copy_to_user(priv_data.buf, &extra, len + 1))
1894 {
1895 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1896 "%s: failed to copy data to user buffer", __func__);
1897 ret = -EFAULT;
1898 goto exit;
1899 }
1900 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001901 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1902 {
1903 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001904 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001905 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001906
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001907 /* input refresh period is in terms of seconds */
1908 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1909 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001910
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001911 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001912 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001913 if (ret < 0)
1914 {
1915 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001916 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001917 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001918 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001919 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001920 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1921 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1922 ret = -EINVAL;
1923 goto exit;
1924 }
1925
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001926 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1927 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1928 {
1929 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1930 "Neighbor scan results refresh period value %d is out of range"
1931 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1932 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1933 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1934 ret = -EINVAL;
1935 goto exit;
1936 }
1937 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1938
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001939 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1940 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001941 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001942
1943 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1944 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1945 }
1946 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1947 {
1948 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1949 char extra[32];
1950 tANI_U8 len = 0;
1951
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001952 len = scnprintf(extra, sizeof(extra), "%s %d",
1953 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001954 /* Returned value is in units of seconds */
1955 if (copy_to_user(priv_data.buf, &extra, len + 1))
1956 {
1957 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1958 "%s: failed to copy data to user buffer", __func__);
1959 ret = -EFAULT;
1960 goto exit;
1961 }
1962 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001963#ifdef FEATURE_WLAN_LFR
1964 /* SETROAMMODE */
1965 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1966 {
1967 tANI_U8 *value = command;
1968 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1969
1970 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1971 value = value + SIZE_OF_SETROAMMODE + 1;
1972
1973 /* Convert the value from ascii to integer */
1974 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1975 if (ret < 0)
1976 {
1977 /* If the input value is greater than max value of datatype, then also
1978 kstrtou8 fails */
1979 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1980 "%s: kstrtou8 failed range [%d - %d]", __func__,
1981 CFG_LFR_FEATURE_ENABLED_MIN,
1982 CFG_LFR_FEATURE_ENABLED_MAX);
1983 ret = -EINVAL;
1984 goto exit;
1985 }
1986 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1987 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
1988 {
1989 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1990 "Roam Mode value %d is out of range"
1991 " (Min: %d Max: %d)", roamMode,
1992 CFG_LFR_FEATURE_ENABLED_MIN,
1993 CFG_LFR_FEATURE_ENABLED_MAX);
1994 ret = -EINVAL;
1995 goto exit;
1996 }
1997
1998 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1999 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2000 /*
2001 * Note that
2002 * SETROAMMODE 0 is to enable LFR while
2003 * SETROAMMODE 1 is to disable LFR, but
2004 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2005 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2006 */
2007 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2008 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2009 else
2010 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2011
2012 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2013 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2014 }
2015 /* GETROAMMODE */
2016 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2017 {
2018 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2019 char extra[32];
2020 tANI_U8 len = 0;
2021
2022 /*
2023 * roamMode value shall be inverted because the sementics is different.
2024 */
2025 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2026 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2027 else
2028 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2029
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002030 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002031 if (copy_to_user(priv_data.buf, &extra, len + 1))
2032 {
2033 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2034 "%s: failed to copy data to user buffer", __func__);
2035 ret = -EFAULT;
2036 goto exit;
2037 }
2038 }
2039#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002040#endif
2041#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2042 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2043 {
2044 tANI_U8 *value = command;
2045 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2046
2047 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2048 value = value + 13;
2049 /* Convert the value from ascii to integer */
2050 ret = kstrtou8(value, 10, &roamRssiDiff);
2051 if (ret < 0)
2052 {
2053 /* If the input value is greater than max value of datatype, then also
2054 kstrtou8 fails */
2055 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2056 "%s: kstrtou8 failed range [%d - %d]", __func__,
2057 CFG_ROAM_RSSI_DIFF_MIN,
2058 CFG_ROAM_RSSI_DIFF_MAX);
2059 ret = -EINVAL;
2060 goto exit;
2061 }
2062
2063 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2064 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2065 {
2066 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2067 "Roam rssi diff value %d is out of range"
2068 " (Min: %d Max: %d)", roamRssiDiff,
2069 CFG_ROAM_RSSI_DIFF_MIN,
2070 CFG_ROAM_RSSI_DIFF_MAX);
2071 ret = -EINVAL;
2072 goto exit;
2073 }
2074
2075 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2076 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2077
2078 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2079 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2080 }
2081 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2082 {
2083 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2084 char extra[32];
2085 tANI_U8 len = 0;
2086
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002087 len = scnprintf(extra, sizeof(extra), "%s %d",
2088 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002089 if (copy_to_user(priv_data.buf, &extra, len + 1))
2090 {
2091 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2092 "%s: failed to copy data to user buffer", __func__);
2093 ret = -EFAULT;
2094 goto exit;
2095 }
2096 }
2097#endif
2098#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2099 else if (strncmp(command, "GETBAND", 7) == 0)
2100 {
2101 int band = -1;
2102 char extra[32];
2103 tANI_U8 len = 0;
2104 hdd_getBand_helper(pHddCtx, &band);
2105
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002106 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002107 if (copy_to_user(priv_data.buf, &extra, len + 1))
2108 {
2109 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2110 "%s: failed to copy data to user buffer", __func__);
2111 ret = -EFAULT;
2112 goto exit;
2113 }
2114 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002115 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2116 {
2117 tANI_U8 *value = command;
2118 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2119 tANI_U8 numChannels = 0;
2120 eHalStatus status = eHAL_STATUS_SUCCESS;
2121
2122 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2123 if (eHAL_STATUS_SUCCESS != status)
2124 {
2125 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2126 "%s: Failed to parse channel list information", __func__);
2127 ret = -EINVAL;
2128 goto exit;
2129 }
2130
2131 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2132 {
2133 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2134 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2135 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2136 ret = -EINVAL;
2137 goto exit;
2138 }
2139 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2140 numChannels);
2141 if (eHAL_STATUS_SUCCESS != status)
2142 {
2143 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2144 "%s: Failed to update channel list information", __func__);
2145 ret = -EINVAL;
2146 goto exit;
2147 }
2148 }
2149 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2150 {
2151 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2152 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002153 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002154 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002155 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002156
2157 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2158 ChannelList, &numChannels ))
2159 {
2160 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2161 "%s: failed to get roam scan channel list", __func__);
2162 ret = -EFAULT;
2163 goto exit;
2164 }
2165 /* output channel list is of the format
2166 [Number of roam scan channels][Channel1][Channel2]... */
2167 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002168 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002169 for (j = 0; (j < numChannels); j++)
2170 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002171 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2172 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002173 }
2174
2175 if (copy_to_user(priv_data.buf, &extra, len + 1))
2176 {
2177 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2178 "%s: failed to copy data to user buffer", __func__);
2179 ret = -EFAULT;
2180 goto exit;
2181 }
2182 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002183 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2184 {
2185 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2186 char extra[32];
2187 tANI_U8 len = 0;
2188
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002189 /* Check if the features OKC/CCX/11R are supported simultaneously,
2190 then this operation is not permitted (return FAILURE) */
2191 if (ccxMode &&
2192 hdd_is_okc_mode_enabled(pHddCtx) &&
2193 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2194 {
2195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2196 "%s: OKC/CCX/11R are supported simultaneously"
2197 " hence this operation is not permitted!", __func__);
2198 ret = -EPERM;
2199 goto exit;
2200 }
2201
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002202 len = scnprintf(extra, sizeof(extra), "%s %d",
2203 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002204 if (copy_to_user(priv_data.buf, &extra, len + 1))
2205 {
2206 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2207 "%s: failed to copy data to user buffer", __func__);
2208 ret = -EFAULT;
2209 goto exit;
2210 }
2211 }
2212 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2213 {
2214 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2215 char extra[32];
2216 tANI_U8 len = 0;
2217
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002218 /* Check if the features OKC/CCX/11R are supported simultaneously,
2219 then this operation is not permitted (return FAILURE) */
2220 if (okcMode &&
2221 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2222 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2223 {
2224 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2225 "%s: OKC/CCX/11R are supported simultaneously"
2226 " hence this operation is not permitted!", __func__);
2227 ret = -EPERM;
2228 goto exit;
2229 }
2230
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002231 len = scnprintf(extra, sizeof(extra), "%s %d",
2232 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002233 if (copy_to_user(priv_data.buf, &extra, len + 1))
2234 {
2235 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2236 "%s: failed to copy data to user buffer", __func__);
2237 ret = -EFAULT;
2238 goto exit;
2239 }
2240 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002241 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002242 {
2243 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2244 char extra[32];
2245 tANI_U8 len = 0;
2246
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002247 len = scnprintf(extra, sizeof(extra), "%s %d",
2248 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002249 if (copy_to_user(priv_data.buf, &extra, len + 1))
2250 {
2251 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2252 "%s: failed to copy data to user buffer", __func__);
2253 ret = -EFAULT;
2254 goto exit;
2255 }
2256 }
2257 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2258 {
2259 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2260 char extra[32];
2261 tANI_U8 len = 0;
2262
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002263 len = scnprintf(extra, sizeof(extra), "%s %d",
2264 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002265 if (copy_to_user(priv_data.buf, &extra, len + 1))
2266 {
2267 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2268 "%s: failed to copy data to user buffer", __func__);
2269 ret = -EFAULT;
2270 goto exit;
2271 }
2272 }
2273 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2274 {
2275 tANI_U8 *value = command;
2276 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2277
2278 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2279 value = value + 26;
2280 /* Convert the value from ascii to integer */
2281 ret = kstrtou8(value, 10, &minTime);
2282 if (ret < 0)
2283 {
2284 /* If the input value is greater than max value of datatype, then also
2285 kstrtou8 fails */
2286 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2287 "%s: kstrtou8 failed range [%d - %d]", __func__,
2288 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2289 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2290 ret = -EINVAL;
2291 goto exit;
2292 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002293 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2294 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2295 {
2296 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2297 "scan min channel time value %d is out of range"
2298 " (Min: %d Max: %d)", minTime,
2299 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2300 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2301 ret = -EINVAL;
2302 goto exit;
2303 }
2304
2305 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2306 "%s: Received Command to change channel min time = %d", __func__, minTime);
2307
2308 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2309 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2310 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002311 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2312 {
2313 tANI_U8 *value = command;
2314 tANI_U8 channel = 0;
2315 tANI_U8 dwellTime = 0;
2316 tANI_U8 bufLen = 0;
2317 tANI_U8 *buf = NULL;
2318 tSirMacAddr targetApBssid;
2319 eHalStatus status = eHAL_STATUS_SUCCESS;
2320 struct ieee80211_channel chan;
2321 tANI_U8 finalLen = 0;
2322 tANI_U8 *finalBuf = NULL;
2323 tANI_U8 temp = 0;
2324 u64 cookie;
2325 hdd_station_ctx_t *pHddStaCtx = NULL;
2326 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2327
2328 /* if not associated, no need to send action frame */
2329 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2330 {
2331 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2332 ret = -EINVAL;
2333 goto exit;
2334 }
2335
2336 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2337 &dwellTime, &buf, &bufLen);
2338 if (eHAL_STATUS_SUCCESS != status)
2339 {
2340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2341 "%s: Failed to parse send action frame data", __func__);
2342 ret = -EINVAL;
2343 goto exit;
2344 }
2345
2346 /* if the target bssid is different from currently associated AP,
2347 then no need to send action frame */
2348 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2349 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2350 {
2351 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2352 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002353 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002354 goto exit;
2355 }
2356
2357 /* if the channel number is different from operating channel then
2358 no need to send action frame */
2359 if (channel != pHddStaCtx->conn_info.operationChannel)
2360 {
2361 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2362 "%s: channel(%d) is different from operating channel(%d)",
2363 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2364 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002365 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002366 goto exit;
2367 }
2368 chan.center_freq = sme_ChnToFreq(channel);
2369
2370 finalLen = bufLen + 24;
2371 finalBuf = vos_mem_malloc(finalLen);
2372 if (NULL == finalBuf)
2373 {
2374 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2375 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002376 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002377 goto exit;
2378 }
2379 vos_mem_zero(finalBuf, finalLen);
2380
2381 /* Fill subtype */
2382 temp = SIR_MAC_MGMT_ACTION << 4;
2383 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2384
2385 /* Fill type */
2386 temp = SIR_MAC_MGMT_FRAME;
2387 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2388
2389 /* Fill destination address (bssid of the AP) */
2390 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2391
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002392 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002393 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2394
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002395 /* Fill BSSID (AP mac address) */
2396 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002397
2398 /* Fill received buffer from 24th address */
2399 vos_mem_copy(finalBuf + 24, buf, bufLen);
2400
Jeff Johnson11c33152013-04-16 17:52:40 -07002401 /* done with the parsed buffer */
2402 vos_mem_free(buf);
2403
Yue Maf49ba872013-08-19 12:04:25 -07002404 wlan_hdd_action( NULL,
2405#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2406 &(pAdapter->wdev),
2407#else
2408 dev,
2409#endif
2410 &chan, 0,
2411#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2412 NL80211_CHAN_HT20, 1,
2413#endif
2414 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002415 1, &cookie );
2416 vos_mem_free(finalBuf);
2417 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002418 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2419 {
2420 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2421 char extra[32];
2422 tANI_U8 len = 0;
2423
2424 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002425 len = scnprintf(extra, sizeof(extra), "%s %d",
2426 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002427 if (copy_to_user(priv_data.buf, &extra, len + 1))
2428 {
2429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2430 "%s: failed to copy data to user buffer", __func__);
2431 ret = -EFAULT;
2432 goto exit;
2433 }
2434 }
2435 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2436 {
2437 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002438 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002439 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002440
2441 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2442 value = value + 19;
2443 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002444 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002445 if (ret < 0)
2446 {
2447 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002448 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002449 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002450 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002451 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2452 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2453 ret = -EINVAL;
2454 goto exit;
2455 }
2456
2457 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2458 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2459 {
2460 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2461 "lfr mode value %d is out of range"
2462 " (Min: %d Max: %d)", maxTime,
2463 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2464 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2465 ret = -EINVAL;
2466 goto exit;
2467 }
2468
2469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2470 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2471
2472 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002473
2474 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2475 * where RFS is the RF Switching time. It is twice RFS to consider the
2476 * time to go off channel and return to the home channel. */
2477 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2478 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2479 {
2480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002481 "%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 -07002482 " Hence enforcing home away time to disable (0)",
2483 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2484 homeAwayTime = 0;
2485 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2486 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
2487 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002488 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2489 }
2490 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2491 {
2492 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2493 char extra[32];
2494 tANI_U8 len = 0;
2495
2496 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002497 len = scnprintf(extra, sizeof(extra), "%s %d",
2498 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002499 if (copy_to_user(priv_data.buf, &extra, len + 1))
2500 {
2501 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2502 "%s: failed to copy data to user buffer", __func__);
2503 ret = -EFAULT;
2504 goto exit;
2505 }
2506 }
2507 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2508 {
2509 tANI_U8 *value = command;
2510 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2511
2512 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2513 value = value + 16;
2514 /* Convert the value from ascii to integer */
2515 ret = kstrtou16(value, 10, &val);
2516 if (ret < 0)
2517 {
2518 /* If the input value is greater than max value of datatype, then also
2519 kstrtou16 fails */
2520 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2521 "%s: kstrtou16 failed range [%d - %d]", __func__,
2522 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2523 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2524 ret = -EINVAL;
2525 goto exit;
2526 }
2527
2528 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2529 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2530 {
2531 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2532 "scan home time value %d is out of range"
2533 " (Min: %d Max: %d)", val,
2534 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2535 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2536 ret = -EINVAL;
2537 goto exit;
2538 }
2539
2540 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2541 "%s: Received Command to change scan home time = %d", __func__, val);
2542
2543 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2544 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2545 }
2546 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2547 {
2548 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2549 char extra[32];
2550 tANI_U8 len = 0;
2551
2552 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002553 len = scnprintf(extra, sizeof(extra), "%s %d",
2554 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002555 if (copy_to_user(priv_data.buf, &extra, len + 1))
2556 {
2557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2558 "%s: failed to copy data to user buffer", __func__);
2559 ret = -EFAULT;
2560 goto exit;
2561 }
2562 }
2563 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2564 {
2565 tANI_U8 *value = command;
2566 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2567
2568 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2569 value = value + 17;
2570 /* Convert the value from ascii to integer */
2571 ret = kstrtou8(value, 10, &val);
2572 if (ret < 0)
2573 {
2574 /* If the input value is greater than max value of datatype, then also
2575 kstrtou8 fails */
2576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2577 "%s: kstrtou8 failed range [%d - %d]", __func__,
2578 CFG_ROAM_INTRA_BAND_MIN,
2579 CFG_ROAM_INTRA_BAND_MAX);
2580 ret = -EINVAL;
2581 goto exit;
2582 }
2583
2584 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2585 (val > CFG_ROAM_INTRA_BAND_MAX))
2586 {
2587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2588 "intra band mode value %d is out of range"
2589 " (Min: %d Max: %d)", val,
2590 CFG_ROAM_INTRA_BAND_MIN,
2591 CFG_ROAM_INTRA_BAND_MAX);
2592 ret = -EINVAL;
2593 goto exit;
2594 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002595 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2596 "%s: Received Command to change intra band = %d", __func__, val);
2597
2598 pHddCtx->cfg_ini->nRoamIntraBand = val;
2599 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2600 }
2601 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2602 {
2603 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2604 char extra[32];
2605 tANI_U8 len = 0;
2606
2607 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002608 len = scnprintf(extra, sizeof(extra), "%s %d",
2609 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002610 if (copy_to_user(priv_data.buf, &extra, len + 1))
2611 {
2612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2613 "%s: failed to copy data to user buffer", __func__);
2614 ret = -EFAULT;
2615 goto exit;
2616 }
2617 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002618 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2619 {
2620 tANI_U8 *value = command;
2621 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2622
2623 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2624 value = value + 15;
2625 /* Convert the value from ascii to integer */
2626 ret = kstrtou8(value, 10, &nProbes);
2627 if (ret < 0)
2628 {
2629 /* If the input value is greater than max value of datatype, then also
2630 kstrtou8 fails */
2631 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2632 "%s: kstrtou8 failed range [%d - %d]", __func__,
2633 CFG_ROAM_SCAN_N_PROBES_MIN,
2634 CFG_ROAM_SCAN_N_PROBES_MAX);
2635 ret = -EINVAL;
2636 goto exit;
2637 }
2638
2639 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2640 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2641 {
2642 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2643 "NProbes value %d is out of range"
2644 " (Min: %d Max: %d)", nProbes,
2645 CFG_ROAM_SCAN_N_PROBES_MIN,
2646 CFG_ROAM_SCAN_N_PROBES_MAX);
2647 ret = -EINVAL;
2648 goto exit;
2649 }
2650
2651 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2652 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2653
2654 pHddCtx->cfg_ini->nProbes = nProbes;
2655 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2656 }
2657 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2658 {
2659 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2660 char extra[32];
2661 tANI_U8 len = 0;
2662
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002663 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002664 if (copy_to_user(priv_data.buf, &extra, len + 1))
2665 {
2666 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2667 "%s: failed to copy data to user buffer", __func__);
2668 ret = -EFAULT;
2669 goto exit;
2670 }
2671 }
2672 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2673 {
2674 tANI_U8 *value = command;
2675 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002676 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002677
2678 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2679 /* input value is in units of msec */
2680 value = value + 20;
2681 /* Convert the value from ascii to integer */
2682 ret = kstrtou16(value, 10, &homeAwayTime);
2683 if (ret < 0)
2684 {
2685 /* If the input value is greater than max value of datatype, then also
2686 kstrtou8 fails */
2687 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2688 "%s: kstrtou8 failed range [%d - %d]", __func__,
2689 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2690 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2691 ret = -EINVAL;
2692 goto exit;
2693 }
2694
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002695 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2696 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2697 {
2698 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2699 "homeAwayTime value %d is out of range"
2700 " (Min: %d Max: %d)", homeAwayTime,
2701 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2702 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2703 ret = -EINVAL;
2704 goto exit;
2705 }
2706
2707 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2708 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
2709
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002710 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2711 * where RFS is the RF Switching time. It is twice RFS to consider the
2712 * time to go off channel and return to the home channel. */
2713 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2714 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2715 {
2716 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002717 "%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 -07002718 " Hence enforcing home away time to disable (0)",
2719 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2720 homeAwayTime = 0;
2721 }
2722
2723 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2724 {
2725 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2726 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2727 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002728 }
2729 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2730 {
2731 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2732 char extra[32];
2733 tANI_U8 len = 0;
2734
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002735 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002736 if (copy_to_user(priv_data.buf, &extra, len + 1))
2737 {
2738 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2739 "%s: failed to copy data to user buffer", __func__);
2740 ret = -EFAULT;
2741 goto exit;
2742 }
2743 }
2744 else if (strncmp(command, "REASSOC", 7) == 0)
2745 {
2746 tANI_U8 *value = command;
2747 tANI_U8 channel = 0;
2748 tSirMacAddr targetApBssid;
2749 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002750#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2751 tCsrHandoffRequest handoffInfo;
2752#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002753 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002754 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2755
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002756 /* if not associated, no need to proceed with reassoc */
2757 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2758 {
2759 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2760 ret = -EINVAL;
2761 goto exit;
2762 }
2763
2764 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2765 if (eHAL_STATUS_SUCCESS != status)
2766 {
2767 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2768 "%s: Failed to parse reassoc command data", __func__);
2769 ret = -EINVAL;
2770 goto exit;
2771 }
2772
2773 /* if the target bssid is same as currently associated AP,
2774 then no need to proceed with reassoc */
2775 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2776 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2777 {
2778 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2779 ret = -EINVAL;
2780 goto exit;
2781 }
2782
2783 /* Check channel number is a valid channel number */
2784 if(VOS_STATUS_SUCCESS !=
2785 wlan_hdd_validate_operation_channel(pAdapter, channel))
2786 {
2787 hddLog(VOS_TRACE_LEVEL_ERROR,
2788 "%s: Invalid Channel [%d] \n", __func__, channel);
2789 return -EINVAL;
2790 }
2791
2792 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002793#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2794 handoffInfo.channel = channel;
2795 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2796 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2797#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002798 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002799 else if (strncmp(command, "SETWESMODE", 10) == 0)
2800 {
2801 tANI_U8 *value = command;
2802 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
2803
2804 /* Move pointer to ahead of SETWESMODE<delimiter> */
2805 value = value + 11;
2806 /* Convert the value from ascii to integer */
2807 ret = kstrtou8(value, 10, &wesMode);
2808 if (ret < 0)
2809 {
2810 /* If the input value is greater than max value of datatype, then also
2811 kstrtou8 fails */
2812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2813 "%s: kstrtou8 failed range [%d - %d]", __func__,
2814 CFG_ENABLE_WES_MODE_NAME_MIN,
2815 CFG_ENABLE_WES_MODE_NAME_MAX);
2816 ret = -EINVAL;
2817 goto exit;
2818 }
2819
2820 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
2821 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
2822 {
2823 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2824 "WES Mode value %d is out of range"
2825 " (Min: %d Max: %d)", wesMode,
2826 CFG_ENABLE_WES_MODE_NAME_MIN,
2827 CFG_ENABLE_WES_MODE_NAME_MAX);
2828 ret = -EINVAL;
2829 goto exit;
2830 }
2831 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2832 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
2833
2834 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
2835 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
2836 }
2837 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
2838 {
2839 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
2840 char extra[32];
2841 tANI_U8 len = 0;
2842
Arif Hussain826d9412013-11-12 16:44:54 -08002843 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002844 if (copy_to_user(priv_data.buf, &extra, len + 1))
2845 {
2846 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2847 "%s: failed to copy data to user buffer", __func__);
2848 ret = -EFAULT;
2849 goto exit;
2850 }
2851 }
2852#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002853#ifdef FEATURE_WLAN_LFR
2854 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2855 {
2856 tANI_U8 *value = command;
2857 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2858
2859 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2860 value = value + 12;
2861 /* Convert the value from ascii to integer */
2862 ret = kstrtou8(value, 10, &lfrMode);
2863 if (ret < 0)
2864 {
2865 /* If the input value is greater than max value of datatype, then also
2866 kstrtou8 fails */
2867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2868 "%s: kstrtou8 failed range [%d - %d]", __func__,
2869 CFG_LFR_FEATURE_ENABLED_MIN,
2870 CFG_LFR_FEATURE_ENABLED_MAX);
2871 ret = -EINVAL;
2872 goto exit;
2873 }
2874
2875 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2876 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2877 {
2878 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2879 "lfr mode value %d is out of range"
2880 " (Min: %d Max: %d)", lfrMode,
2881 CFG_LFR_FEATURE_ENABLED_MIN,
2882 CFG_LFR_FEATURE_ENABLED_MAX);
2883 ret = -EINVAL;
2884 goto exit;
2885 }
2886
2887 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2888 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2889
2890 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2891 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2892 }
2893#endif
2894#ifdef WLAN_FEATURE_VOWIFI_11R
2895 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2896 {
2897 tANI_U8 *value = command;
2898 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2899
2900 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2901 value = value + 18;
2902 /* Convert the value from ascii to integer */
2903 ret = kstrtou8(value, 10, &ft);
2904 if (ret < 0)
2905 {
2906 /* If the input value is greater than max value of datatype, then also
2907 kstrtou8 fails */
2908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2909 "%s: kstrtou8 failed range [%d - %d]", __func__,
2910 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2911 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2912 ret = -EINVAL;
2913 goto exit;
2914 }
2915
2916 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2917 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2918 {
2919 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2920 "ft mode value %d is out of range"
2921 " (Min: %d Max: %d)", ft,
2922 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2923 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2924 ret = -EINVAL;
2925 goto exit;
2926 }
2927
2928 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2929 "%s: Received Command to change ft mode = %d", __func__, ft);
2930
2931 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2932 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2933 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302934
2935 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2936 {
2937 tANI_U8 *value = command;
2938 tSirMacAddr targetApBssid;
2939 tANI_U8 trigger = 0;
2940 eHalStatus status = eHAL_STATUS_SUCCESS;
2941 hdd_station_ctx_t *pHddStaCtx = NULL;
2942 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2943
2944 /* if not associated, no need to proceed with reassoc */
2945 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2946 {
2947 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2948 ret = -EINVAL;
2949 goto exit;
2950 }
2951
2952 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2953 if (eHAL_STATUS_SUCCESS != status)
2954 {
2955 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2956 "%s: Failed to parse reassoc command data", __func__);
2957 ret = -EINVAL;
2958 goto exit;
2959 }
2960
2961 /* if the target bssid is same as currently associated AP,
2962 then no need to proceed with reassoc */
2963 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2964 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2965 {
2966 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2967 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2968 __func__);
2969 ret = -EINVAL;
2970 goto exit;
2971 }
2972
2973 /* Proceed with scan/roam */
2974 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2975 &targetApBssid[0],
2976 (tSmeFastRoamTrigger)(trigger));
2977 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002978#endif
2979#ifdef FEATURE_WLAN_CCX
2980 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2981 {
2982 tANI_U8 *value = command;
2983 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2984
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002985 /* Check if the features OKC/CCX/11R are supported simultaneously,
2986 then this operation is not permitted (return FAILURE) */
2987 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2988 hdd_is_okc_mode_enabled(pHddCtx) &&
2989 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2990 {
2991 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2992 "%s: OKC/CCX/11R are supported simultaneously"
2993 " hence this operation is not permitted!", __func__);
2994 ret = -EPERM;
2995 goto exit;
2996 }
2997
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002998 /* Move pointer to ahead of SETCCXMODE<delimiter> */
2999 value = value + 11;
3000 /* Convert the value from ascii to integer */
3001 ret = kstrtou8(value, 10, &ccxMode);
3002 if (ret < 0)
3003 {
3004 /* If the input value is greater than max value of datatype, then also
3005 kstrtou8 fails */
3006 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3007 "%s: kstrtou8 failed range [%d - %d]", __func__,
3008 CFG_CCX_FEATURE_ENABLED_MIN,
3009 CFG_CCX_FEATURE_ENABLED_MAX);
3010 ret = -EINVAL;
3011 goto exit;
3012 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003013 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
3014 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
3015 {
3016 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3017 "Ccx mode value %d is out of range"
3018 " (Min: %d Max: %d)", ccxMode,
3019 CFG_CCX_FEATURE_ENABLED_MIN,
3020 CFG_CCX_FEATURE_ENABLED_MAX);
3021 ret = -EINVAL;
3022 goto exit;
3023 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003024 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3025 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
3026
3027 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
3028 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
3029 }
3030#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003031 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3032 {
3033 tANI_U8 *value = command;
3034 tANI_BOOLEAN roamScanControl = 0;
3035
3036 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3037 value = value + 19;
3038 /* Convert the value from ascii to integer */
3039 ret = kstrtou8(value, 10, &roamScanControl);
3040 if (ret < 0)
3041 {
3042 /* If the input value is greater than max value of datatype, then also
3043 kstrtou8 fails */
3044 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3045 "%s: kstrtou8 failed ", __func__);
3046 ret = -EINVAL;
3047 goto exit;
3048 }
3049
3050 if (0 != roamScanControl)
3051 {
3052 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3053 "roam scan control invalid value = %d",
3054 roamScanControl);
3055 ret = -EINVAL;
3056 goto exit;
3057 }
3058 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3059 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3060
3061 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3062 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003063#ifdef FEATURE_WLAN_OKC
3064 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3065 {
3066 tANI_U8 *value = command;
3067 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3068
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003069 /* Check if the features OKC/CCX/11R are supported simultaneously,
3070 then this operation is not permitted (return FAILURE) */
3071 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3072 hdd_is_okc_mode_enabled(pHddCtx) &&
3073 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3074 {
3075 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3076 "%s: OKC/CCX/11R are supported simultaneously"
3077 " hence this operation is not permitted!", __func__);
3078 ret = -EPERM;
3079 goto exit;
3080 }
3081
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003082 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3083 value = value + 11;
3084 /* Convert the value from ascii to integer */
3085 ret = kstrtou8(value, 10, &okcMode);
3086 if (ret < 0)
3087 {
3088 /* If the input value is greater than max value of datatype, then also
3089 kstrtou8 fails */
3090 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3091 "%s: kstrtou8 failed range [%d - %d]", __func__,
3092 CFG_OKC_FEATURE_ENABLED_MIN,
3093 CFG_OKC_FEATURE_ENABLED_MAX);
3094 ret = -EINVAL;
3095 goto exit;
3096 }
3097
3098 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3099 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3100 {
3101 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3102 "Okc mode value %d is out of range"
3103 " (Min: %d Max: %d)", okcMode,
3104 CFG_OKC_FEATURE_ENABLED_MIN,
3105 CFG_OKC_FEATURE_ENABLED_MAX);
3106 ret = -EINVAL;
3107 goto exit;
3108 }
3109
3110 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3111 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3112
3113 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3114 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003115#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003116 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3117 {
3118 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3119 char extra[32];
3120 tANI_U8 len = 0;
3121
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003122 len = scnprintf(extra, sizeof(extra), "%s %d",
3123 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003124 if (copy_to_user(priv_data.buf, &extra, len + 1))
3125 {
3126 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3127 "%s: failed to copy data to user buffer", __func__);
3128 ret = -EFAULT;
3129 goto exit;
3130 }
3131 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303132#ifdef WLAN_FEATURE_PACKET_FILTERING
3133 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3134 {
3135 tANI_U8 filterType = 0;
3136 tANI_U8 *value = command;
3137
3138 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3139 value = value + 22;
3140
3141 /* Convert the value from ascii to integer */
3142 ret = kstrtou8(value, 10, &filterType);
3143 if (ret < 0)
3144 {
3145 /* If the input value is greater than max value of datatype,
3146 * then also kstrtou8 fails
3147 */
3148 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3149 "%s: kstrtou8 failed range ", __func__);
3150 ret = -EINVAL;
3151 goto exit;
3152 }
3153
3154 if (filterType != 0 && filterType != 1)
3155 {
3156 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3157 "%s: Accepted Values are 0 and 1 ", __func__);
3158 ret = -EINVAL;
3159 goto exit;
3160 }
3161 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3162 pAdapter->sessionId);
3163 }
3164#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303165 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3166 {
3167 char *dhcpPhase;
3168 dhcpPhase = command + 12;
3169 if ('1' == *dhcpPhase)
3170 {
3171 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3172 pAdapter->macAddressCurrent.bytes);
3173 }
3174 else if ('2' == *dhcpPhase)
3175 {
3176 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3177 pAdapter->macAddressCurrent.bytes);
3178 }
3179 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003180 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3181 {
3182 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3183 }
3184 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3185 {
3186 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3187 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303188 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3189 {
3190 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3191 char extra[32];
3192 tANI_U8 len = 0;
3193
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003194 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303195 (int)pCfg->nActiveMaxChnTime);
3196 if (copy_to_user(priv_data.buf, &extra, len + 1))
3197 {
3198 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3199 "%s: failed to copy data to user buffer", __func__);
3200 ret = -EFAULT;
3201 goto exit;
3202 }
3203 ret = len;
3204 }
3205 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3206 {
3207 tANI_U8 *value = command;
3208 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3209 int val = 0, temp;
3210
3211 value = value + 13;
3212 temp = kstrtou32(value, 10, &val);
3213 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3214 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3215 {
3216 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3217 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3218 ret = -EFAULT;
3219 goto exit;
3220 }
3221 pCfg->nActiveMaxChnTime = val;
3222 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003223 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3224 {
3225 tANI_U8 filterType = 0;
3226 tANI_U8 *value;
3227 value = command + 9;
3228
3229 /* Convert the value from ascii to integer */
3230 ret = kstrtou8(value, 10, &filterType);
3231 if (ret < 0)
3232 {
3233 /* If the input value is greater than max value of datatype,
3234 * then also kstrtou8 fails
3235 */
3236 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3237 "%s: kstrtou8 failed range ", __func__);
3238 ret = -EINVAL;
3239 goto exit;
3240 }
3241 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3242 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3243 {
3244 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3245 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3246 " 2-Sink ", __func__);
3247 ret = -EINVAL;
3248 goto exit;
3249 }
3250 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3251 pHddCtx->drvr_miracast = filterType;
3252 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3253 }
Leo Chang614d2072013-08-22 14:59:44 -07003254 else if (strncmp(command, "SETMCRATE", 9) == 0)
3255 {
Leo Chang614d2072013-08-22 14:59:44 -07003256 tANI_U8 *value = command;
3257 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003258 tSirRateUpdateInd *rateUpdate;
3259 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003260
3261 /* Only valid for SAP mode */
3262 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3263 {
3264 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3265 "%s: SAP mode is not running", __func__);
3266 ret = -EFAULT;
3267 goto exit;
3268 }
3269
3270 /* Move pointer to ahead of SETMCRATE<delimiter> */
3271 /* input value is in units of hundred kbps */
3272 value = value + 10;
3273 /* Convert the value from ascii to integer, decimal base */
3274 ret = kstrtouint(value, 10, &targetRate);
3275
Leo Chang1f98cbd2013-10-17 15:03:52 -07003276 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3277 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003278 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003279 hddLog(VOS_TRACE_LEVEL_ERROR,
3280 "%s: SETMCRATE indication alloc fail", __func__);
3281 ret = -EFAULT;
3282 goto exit;
3283 }
3284 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3285
3286 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3287 "MC Target rate %d", targetRate);
3288 /* Ignore unicast */
3289 rateUpdate->ucastDataRate = -1;
3290 rateUpdate->mcastDataRate24GHz = targetRate;
3291 rateUpdate->mcastDataRate5GHz = targetRate;
3292 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3293 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3294 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3295 if (eHAL_STATUS_SUCCESS != status)
3296 {
3297 hddLog(VOS_TRACE_LEVEL_ERROR,
3298 "%s: SET_MC_RATE failed", __func__);
3299 vos_mem_free(rateUpdate);
3300 ret = -EFAULT;
3301 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003302 }
3303 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303304#ifdef FEATURE_WLAN_BATCH_SCAN
3305 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3306 {
3307 char extra[32];
3308 tANI_U8 len = 0;
3309 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3310
3311 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3312 {
3313 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3314 "%s: Batch scan feature is not supported by FW", __func__);
3315 ret = -EINVAL;
3316 goto exit;
3317 }
3318
3319 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3320 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3321 {
3322 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3323 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3324 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3325 " mode",
3326 pAdapter->device_mode);
3327 ret = -EINVAL;
3328 goto exit;
3329 }
3330
Arif Hussain826d9412013-11-12 16:44:54 -08003331 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
Rajeev79dbe4c2013-10-05 11:03:42 +05303332 version);
3333 if (copy_to_user(priv_data.buf, &extra, len + 1))
3334 {
3335 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3336 "%s: failed to copy data to user buffer", __func__);
3337 ret = -EFAULT;
3338 goto exit;
3339 }
3340 ret = HDD_BATCH_SCAN_VERSION;
3341 }
3342 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3343 {
3344 int status;
3345 tANI_U8 *value = (command + 16);
3346 eHalStatus halStatus;
3347 unsigned long rc;
3348 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3349 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3350
3351 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3352 {
3353 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3354 "%s: Batch scan feature is not supported by FW", __func__);
3355 ret = -EINVAL;
3356 goto exit;
3357 }
3358
Rajeev Kumar20140c12013-10-21 19:39:02 -07003359
Rajeev79dbe4c2013-10-05 11:03:42 +05303360 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3361 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3362 {
3363 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003364 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303365 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3366 pAdapter->device_mode);
3367 ret = -EINVAL;
3368 goto exit;
3369 }
3370
Rajeev Kumar20140c12013-10-21 19:39:02 -07003371
Rajeev79dbe4c2013-10-05 11:03:42 +05303372 status = hdd_parse_set_batchscan_command(value, pReq);
3373 if (status)
3374 {
3375 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003376 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303377 ret = -EINVAL;
3378 goto exit;
3379 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003380
3381
Rajeev79dbe4c2013-10-05 11:03:42 +05303382 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3383 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3384 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3385 pAdapter);
3386
3387 if ( eHAL_STATUS_SUCCESS == halStatus )
3388 {
3389 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3390 "sme_SetBatchScanReq returned success halStatus %d",
3391 halStatus);
3392 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3393 {
3394 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3395 rc = wait_for_completion_timeout(
3396 &pAdapter->hdd_set_batch_scan_req_var,
3397 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3398 if (0 == rc)
3399 {
3400 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3401 "%s: Timeout waiting for set batch scan to complete",
3402 __func__);
3403 ret = -EINVAL;
3404 goto exit;
3405 }
3406 }
3407 if ( !pRsp->nScansToBatch )
3408 {
3409 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3410 "%s: Received set batch scan failure response from FW",
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003411 __func__);
Rajeev79dbe4c2013-10-05 11:03:42 +05303412 ret = -EINVAL;
3413 goto exit;
3414 }
3415 /*As per the Batch Scan Framework API we should return the MIN of
3416 either MSCAN or the max # of scans firmware can cache*/
3417 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3418
Rajeev Kumar20140c12013-10-21 19:39:02 -07003419 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3420
Rajeev79dbe4c2013-10-05 11:03:42 +05303421 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3422 "%s: request MSCAN %d response MSCAN %d ret %d",
3423 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3424 }
3425 else
3426 {
3427 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3428 "sme_SetBatchScanReq returned failure halStatus %d",
3429 halStatus);
3430 ret = -EINVAL;
3431 goto exit;
3432 }
3433 }
3434 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3435 {
3436 eHalStatus halStatus;
3437 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3438 pInd->param = 0;
3439
3440 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3441 {
3442 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3443 "%s: Batch scan feature is not supported by FW", __func__);
3444 ret = -EINVAL;
3445 goto exit;
3446 }
3447
Rajeev Kumar20140c12013-10-21 19:39:02 -07003448 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303449 {
3450 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003451 "Batch scan is not yet enabled batch scan state %d",
3452 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303453 ret = -EINVAL;
3454 goto exit;
3455 }
3456
Rajeev Kumar20140c12013-10-21 19:39:02 -07003457 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3458
Rajeev79dbe4c2013-10-05 11:03:42 +05303459 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3460 pAdapter->sessionId);
3461 if ( eHAL_STATUS_SUCCESS == halStatus )
3462 {
3463 ret = 0;
3464 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3465 "sme_StopBatchScanInd returned success halStatus %d",
3466 halStatus);
3467 }
3468 else
3469 {
3470 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3471 "sme_StopBatchScanInd returned failure halStatus %d",
3472 halStatus);
3473 ret = -EINVAL;
3474 goto exit;
3475 }
3476 }
3477 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3478 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003479 tANI_U32 remain_len;
3480
Rajeev79dbe4c2013-10-05 11:03:42 +05303481 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3482 {
3483 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3484 "%s: Batch scan feature is not supported by FW", __func__);
3485 ret = -EINVAL;
3486 goto exit;
3487 }
3488
Rajeev Kumar20140c12013-10-21 19:39:02 -07003489 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303490 {
3491 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003492 "Batch scan is not yet enabled could not return results"
3493 "Batch Scan state %d",
3494 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303495 ret = -EINVAL;
3496 goto exit;
3497 }
3498
3499 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003500 remain_len = priv_data.total_len - priv_data.used_len;
3501 if (remain_len < priv_data.total_len)
3502 {
3503 /*Clear previous batch scan response data if any*/
3504 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3505 }
3506 else
3507 {
3508 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3509 "Invalid total length from user space can't fetch batch"
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003510 " scan response total_len %d used_len %d remain len %d",
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003511 priv_data.total_len, priv_data.used_len, remain_len);
3512 ret = -EINVAL;
3513 goto exit;
3514 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303515 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3516 }
3517#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003518#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3519 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3520 {
3521 tANI_U8 *value = command;
3522 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3523 tANI_U8 numChannels = 0;
3524 eHalStatus status = eHAL_STATUS_SUCCESS;
3525
3526 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3527 if (eHAL_STATUS_SUCCESS != status)
3528 {
3529 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3530 "%s: Failed to parse channel list information", __func__);
3531 ret = -EINVAL;
3532 goto exit;
3533 }
3534
3535 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3536 {
3537 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3538 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3539 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3540 ret = -EINVAL;
3541 goto exit;
3542 }
3543 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3544 ChannelList,
3545 numChannels);
3546 if (eHAL_STATUS_SUCCESS != status)
3547 {
3548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3549 "%s: Failed to update channel list information", __func__);
3550 ret = -EINVAL;
3551 goto exit;
3552 }
3553 }
3554 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3555 {
3556 tANI_U8 *value = command;
3557 char extra[128] = {0};
3558 int len = 0;
3559 tANI_U8 tid = 0;
3560 hdd_station_ctx_t *pHddStaCtx = NULL;
3561 tAniTrafStrmMetrics tsmMetrics;
3562 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3563
3564 /* if not associated, return error */
3565 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3566 {
3567 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3568 ret = -EINVAL;
3569 goto exit;
3570 }
3571
3572 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3573 value = value + 12;
3574 /* Convert the value from ascii to integer */
3575 ret = kstrtou8(value, 10, &tid);
3576 if (ret < 0)
3577 {
3578 /* If the input value is greater than max value of datatype, then also
3579 kstrtou8 fails */
3580 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3581 "%s: kstrtou8 failed range [%d - %d]", __func__,
3582 TID_MIN_VALUE,
3583 TID_MAX_VALUE);
3584 ret = -EINVAL;
3585 goto exit;
3586 }
3587
3588 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3589 {
3590 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3591 "tid value %d is out of range"
3592 " (Min: %d Max: %d)", tid,
3593 TID_MIN_VALUE,
3594 TID_MAX_VALUE);
3595 ret = -EINVAL;
3596 goto exit;
3597 }
3598
3599 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3600 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3601
3602 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3603 {
3604 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3605 "%s: failed to get tsm stats", __func__);
3606 ret = -EFAULT;
3607 goto exit;
3608 }
3609
3610 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3611 "UplinkPktQueueDly(%d)\n"
3612 "UplinkPktQueueDlyHist[0](%d)\n"
3613 "UplinkPktQueueDlyHist[1](%d)\n"
3614 "UplinkPktQueueDlyHist[2](%d)\n"
3615 "UplinkPktQueueDlyHist[3](%d)\n"
3616 "UplinkPktTxDly(%lu)\n"
3617 "UplinkPktLoss(%d)\n"
3618 "UplinkPktCount(%d)\n"
3619 "RoamingCount(%d)\n"
3620 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3621 tsmMetrics.UplinkPktQueueDlyHist[0],
3622 tsmMetrics.UplinkPktQueueDlyHist[1],
3623 tsmMetrics.UplinkPktQueueDlyHist[2],
3624 tsmMetrics.UplinkPktQueueDlyHist[3],
3625 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3626 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3627
3628 /* Output TSM stats is of the format
3629 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3630 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003631 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003632 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3633 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3634 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3635 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3636 tsmMetrics.RoamingDly);
3637
3638 if (copy_to_user(priv_data.buf, &extra, len + 1))
3639 {
3640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3641 "%s: failed to copy data to user buffer", __func__);
3642 ret = -EFAULT;
3643 goto exit;
3644 }
3645 }
3646 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3647 {
3648 tANI_U8 *value = command;
3649 tANI_U8 *cckmIe = NULL;
3650 tANI_U8 cckmIeLen = 0;
3651 eHalStatus status = eHAL_STATUS_SUCCESS;
3652
3653 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3654 if (eHAL_STATUS_SUCCESS != status)
3655 {
3656 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3657 "%s: Failed to parse cckm ie data", __func__);
3658 ret = -EINVAL;
3659 goto exit;
3660 }
3661
3662 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3663 {
3664 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3665 "%s: CCKM Ie input length is more than max[%d]", __func__,
3666 DOT11F_IE_RSN_MAX_LEN);
3667 if (NULL != cckmIe)
3668 {
3669 vos_mem_free(cckmIe);
3670 }
3671 ret = -EINVAL;
3672 goto exit;
3673 }
3674 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
3675 if (NULL != cckmIe)
3676 {
3677 vos_mem_free(cckmIe);
3678 }
3679 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003680 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3681 {
3682 tANI_U8 *value = command;
3683 tCsrCcxBeaconReq ccxBcnReq;
3684 eHalStatus status = eHAL_STATUS_SUCCESS;
3685 status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
3686 if (eHAL_STATUS_SUCCESS != status)
3687 {
3688 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3689 "%s: Failed to parse ccx beacon req", __func__);
3690 ret = -EINVAL;
3691 goto exit;
3692 }
3693
3694 sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
3695 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003696#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003697 else {
3698 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3699 __func__, command);
3700 }
3701
Jeff Johnson295189b2012-06-20 16:38:30 -07003702 }
3703exit:
3704 if (command)
3705 {
3706 kfree(command);
3707 }
3708 return ret;
3709}
3710
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003711
3712
3713#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003714/**---------------------------------------------------------------------------
3715
3716 \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
3717
3718 This function parses the ccx beacon request passed in the format
3719 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3720 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3721 <space>Scan Mode N<space>Meas Duration N
3722 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3723 then take N.
3724 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3725 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3726 This function does not take care of removing duplicate channels from the list
3727
3728 \param - pValue Pointer to data
3729 \param - pCcxBcnReq output pointer to store parsed ie information
3730
3731 \return - 0 for success non-zero for failure
3732
3733 --------------------------------------------------------------------------*/
3734static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
3735 tCsrCcxBeaconReq *pCcxBcnReq)
3736{
3737 tANI_U8 *inPtr = pValue;
3738 int tempInt = 0;
3739 int j = 0, i = 0, v = 0;
3740 char buf[32];
3741
3742 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3743 /*no argument after the command*/
3744 if (NULL == inPtr)
3745 {
3746 return -EINVAL;
3747 }
3748 /*no space after the command*/
3749 else if (SPACE_ASCII_VALUE != *inPtr)
3750 {
3751 return -EINVAL;
3752 }
3753
3754 /*removing empty spaces*/
3755 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3756
3757 /*no argument followed by spaces*/
3758 if ('\0' == *inPtr) return -EINVAL;
3759
3760 /*getting the first argument ie measurement token*/
3761 v = sscanf(inPtr, "%32s ", buf);
3762 if (1 != v) return -EINVAL;
3763
3764 v = kstrtos32(buf, 10, &tempInt);
3765 if ( v < 0) return -EINVAL;
3766
3767 pCcxBcnReq->numBcnReqIe = tempInt;
3768
3769 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3770 "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
3771
3772 for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
3773 {
3774 for (i = 0; i < 4; i++)
3775 {
3776 /*inPtr pointing to the beginning of first space after number of ie fields*/
3777 inPtr = strpbrk( inPtr, " " );
3778 /*no ie data after the number of ie fields argument*/
3779 if (NULL == inPtr) return -EINVAL;
3780
3781 /*removing empty space*/
3782 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3783
3784 /*no ie data after the number of ie fields argument and spaces*/
3785 if ( '\0' == *inPtr ) return -EINVAL;
3786
3787 v = sscanf(inPtr, "%32s ", buf);
3788 if (1 != v) return -EINVAL;
3789
3790 v = kstrtos32(buf, 10, &tempInt);
3791 if (v < 0) return -EINVAL;
3792
3793 switch (i)
3794 {
3795 case 0: /* Measurement token */
3796 if (tempInt <= 0)
3797 {
3798 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3799 "Invalid Measurement Token(%d)", tempInt);
3800 return -EINVAL;
3801 }
3802 pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
3803 break;
3804
3805 case 1: /* Channel number */
3806 if ((tempInt <= 0) ||
3807 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3808 {
3809 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3810 "Invalid Channel Number(%d)", tempInt);
3811 return -EINVAL;
3812 }
3813 pCcxBcnReq->bcnReq[j].channel = tempInt;
3814 break;
3815
3816 case 2: /* Scan mode */
3817 if ((tempInt < 0) || (tempInt > 2))
3818 {
3819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3820 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
3821 return -EINVAL;
3822 }
3823 pCcxBcnReq->bcnReq[j].scanMode= tempInt;
3824 break;
3825
3826 case 3: /* Measurement duration */
3827 if (tempInt <= 0)
3828 {
3829 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3830 "Invalid Measurement Duration(%d)", tempInt);
3831 return -EINVAL;
3832 }
3833 pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
3834 break;
3835 }
3836 }
3837 }
3838
3839 for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
3840 {
3841 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3842 "Index(%d) Measurement Token(%lu)Channel(%lu) Scan Mode(%lu) Measurement Duration(%lu)\n",
3843 j,
3844 pCcxBcnReq->bcnReq[j].measurementToken,
3845 pCcxBcnReq->bcnReq[j].channel,
3846 pCcxBcnReq->bcnReq[j].scanMode,
3847 pCcxBcnReq->bcnReq[j].measurementDuration);
3848 }
3849
3850 return VOS_STATUS_SUCCESS;
3851}
3852
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003853static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3854{
3855 struct statsContext *pStatsContext = NULL;
3856 hdd_adapter_t *pAdapter = NULL;
3857
3858 if (NULL == pContext)
3859 {
3860 hddLog(VOS_TRACE_LEVEL_ERROR,
3861 "%s: Bad param, pContext [%p]",
3862 __func__, pContext);
3863 return;
3864 }
3865
3866 /* there is a race condition that exists between this callback function
3867 and the caller since the caller could time out either before or
3868 while this code is executing. we'll assume the timeout hasn't
3869 occurred, but we'll verify that right before we save our work */
3870
3871 pStatsContext = pContext;
3872 pAdapter = pStatsContext->pAdapter;
3873 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3874 {
3875 /* the caller presumably timed out so there is nothing we can do */
3876 hddLog(VOS_TRACE_LEVEL_WARN,
3877 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3878 __func__, pAdapter, pStatsContext->magic);
3879 return;
3880 }
3881
3882 /* the race is on. caller could have timed out immediately after
3883 we verified the magic, but if so, caller will wait a short time
3884 for us to copy over the tsm stats */
3885 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3886 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3887 tsmMetrics.UplinkPktQueueDlyHist,
3888 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3889 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3890 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3891 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3892 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3893 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3894 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3895
3896 /* and notify the caller */
3897 complete(&pStatsContext->completion);
3898}
3899
3900
3901
3902static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3903 tAniTrafStrmMetrics* pTsmMetrics)
3904{
3905 hdd_station_ctx_t *pHddStaCtx = NULL;
3906 eHalStatus hstatus;
3907 long lrc;
3908 struct statsContext context;
3909 hdd_context_t *pHddCtx = NULL;
3910
3911 if (NULL == pAdapter)
3912 {
3913 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3914 return VOS_STATUS_E_FAULT;
3915 }
3916
3917 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3918 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3919
3920 /* we are connected prepare our callback context */
3921 init_completion(&context.completion);
3922 context.pAdapter = pAdapter;
3923 context.magic = STATS_CONTEXT_MAGIC;
3924
3925 /* query tsm stats */
3926 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3927 pHddStaCtx->conn_info.staId[ 0 ],
3928 pHddStaCtx->conn_info.bssId,
3929 &context, pHddCtx->pvosContext, tid);
3930
3931 if (eHAL_STATUS_SUCCESS != hstatus)
3932 {
3933 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics", __func__);
3934 return hstatus;
3935 }
3936 else
3937 {
3938 /* request was sent -- wait for the response */
3939 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3940 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
3941 /* either we have a response or we timed out
3942 either way, first invalidate our magic */
3943 context.magic = 0;
3944 if (lrc <= 0)
3945 {
3946 hddLog(VOS_TRACE_LEVEL_ERROR,
3947 "%s: SME %s while retrieving statistics",
3948 __func__, (0 == lrc) ? "timeout" : "interrupt");
3949 /* there is a race condition such that the callback
3950 function could be executing at the same time we are. of
3951 primary concern is if the callback function had already
3952 verified the "magic" but hasn't yet set the completion
3953 variable. Since the completion variable is on our
3954 stack, we'll delay just a bit to make sure the data is
3955 still valid if that is the case */
3956 msleep(50);
3957 return (VOS_STATUS_E_TIMEOUT);
3958 }
3959 }
3960 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
3961 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
3962 pAdapter->tsmStats.UplinkPktQueueDlyHist,
3963 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3964 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3965 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
3966 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
3967 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
3968 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
3969 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
3970
3971 return VOS_STATUS_SUCCESS;
3972}
3973#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
3974
Srinivas Girigowdade697412013-02-14 16:31:48 -08003975#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3976void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3977{
3978 eCsrBand band = -1;
3979 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3980 switch (band)
3981 {
3982 case eCSR_BAND_ALL:
3983 *pBand = WLAN_HDD_UI_BAND_AUTO;
3984 break;
3985
3986 case eCSR_BAND_24:
3987 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3988 break;
3989
3990 case eCSR_BAND_5G:
3991 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3992 break;
3993
3994 default:
3995 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3996 *pBand = -1;
3997 break;
3998 }
3999}
4000
4001/**---------------------------------------------------------------------------
4002
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004003 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4004
4005 This function parses the send action frame data passed in the format
4006 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4007
Srinivas Girigowda56076852013-08-20 14:00:50 -07004008 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004009 \param - pTargetApBssid Pointer to target Ap bssid
4010 \param - pChannel Pointer to the Target AP channel
4011 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4012 \param - pBuf Pointer to data
4013 \param - pBufLen Pointer to data length
4014
4015 \return - 0 for success non-zero for failure
4016
4017 --------------------------------------------------------------------------*/
4018VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4019 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4020{
4021 tANI_U8 *inPtr = pValue;
4022 tANI_U8 *dataEnd;
4023 int tempInt;
4024 int j = 0;
4025 int i = 0;
4026 int v = 0;
4027 tANI_U8 tempBuf[32];
4028 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004029 /* 12 hexa decimal digits and 5 ':' */
4030 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004031
4032 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4033 /*no argument after the command*/
4034 if (NULL == inPtr)
4035 {
4036 return -EINVAL;
4037 }
4038
4039 /*no space after the command*/
4040 else if (SPACE_ASCII_VALUE != *inPtr)
4041 {
4042 return -EINVAL;
4043 }
4044
4045 /*removing empty spaces*/
4046 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4047
4048 /*no argument followed by spaces*/
4049 if ('\0' == *inPtr)
4050 {
4051 return -EINVAL;
4052 }
4053
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004054 v = sscanf(inPtr, "%17s", macAddress);
4055 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004056 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004057 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4058 "Invalid MAC address or All hex inputs are not read (%d)", v);
4059 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004060 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004061
4062 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4063 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4064 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4065 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4066 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4067 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004068
4069 /* point to the next argument */
4070 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4071 /*no argument after the command*/
4072 if (NULL == inPtr) return -EINVAL;
4073
4074 /*removing empty spaces*/
4075 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4076
4077 /*no argument followed by spaces*/
4078 if ('\0' == *inPtr)
4079 {
4080 return -EINVAL;
4081 }
4082
4083 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004084 v = sscanf(inPtr, "%32s ", tempBuf);
4085 if (1 != v) return -EINVAL;
4086
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004087 v = kstrtos32(tempBuf, 10, &tempInt);
4088 if ( v < 0) return -EINVAL;
4089
4090 *pChannel = tempInt;
4091
4092 /* point to the next argument */
4093 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4094 /*no argument after the command*/
4095 if (NULL == inPtr) return -EINVAL;
4096 /*removing empty spaces*/
4097 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4098
4099 /*no argument followed by spaces*/
4100 if ('\0' == *inPtr)
4101 {
4102 return -EINVAL;
4103 }
4104
4105 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004106 v = sscanf(inPtr, "%32s ", tempBuf);
4107 if (1 != v) return -EINVAL;
4108
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004109 v = kstrtos32(tempBuf, 10, &tempInt);
4110 if ( v < 0) return -EINVAL;
4111
4112 *pDwellTime = tempInt;
4113
4114 /* point to the next argument */
4115 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4116 /*no argument after the command*/
4117 if (NULL == inPtr) return -EINVAL;
4118 /*removing empty spaces*/
4119 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4120
4121 /*no argument followed by spaces*/
4122 if ('\0' == *inPtr)
4123 {
4124 return -EINVAL;
4125 }
4126
4127 /* find the length of data */
4128 dataEnd = inPtr;
4129 while(('\0' != *dataEnd) )
4130 {
4131 dataEnd++;
4132 ++(*pBufLen);
4133 }
4134 if ( *pBufLen <= 0) return -EINVAL;
4135
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004136 /* Allocate the number of bytes based on the number of input characters
4137 whether it is even or odd.
4138 if the number of input characters are even, then we need N/2 byte.
4139 if the number of input characters are odd, then we need do (N+1)/2 to
4140 compensate rounding off.
4141 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4142 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4143 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004144 if (NULL == *pBuf)
4145 {
4146 hddLog(VOS_TRACE_LEVEL_FATAL,
4147 "%s: vos_mem_alloc failed ", __func__);
4148 return -EINVAL;
4149 }
4150
4151 /* the buffer received from the upper layer is character buffer,
4152 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4153 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4154 and f0 in 3rd location */
4155 for (i = 0, j = 0; j < *pBufLen; j += 2)
4156 {
4157 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4158 (*pBuf)[i++] = tempByte;
4159 }
4160 *pBufLen = i;
4161 return VOS_STATUS_SUCCESS;
4162}
4163
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004164/**---------------------------------------------------------------------------
4165
Srinivas Girigowdade697412013-02-14 16:31:48 -08004166 \brief hdd_parse_channellist() - HDD Parse channel list
4167
4168 This function parses the channel list passed in the format
4169 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004170 if the Number of channels (N) does not match with the actual number of channels passed
4171 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4172 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4173 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4174 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004175
4176 \param - pValue Pointer to input channel list
4177 \param - ChannelList Pointer to local output array to record channel list
4178 \param - pNumChannels Pointer to number of roam scan channels
4179
4180 \return - 0 for success non-zero for failure
4181
4182 --------------------------------------------------------------------------*/
4183VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4184{
4185 tANI_U8 *inPtr = pValue;
4186 int tempInt;
4187 int j = 0;
4188 int v = 0;
4189 char buf[32];
4190
4191 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4192 /*no argument after the command*/
4193 if (NULL == inPtr)
4194 {
4195 return -EINVAL;
4196 }
4197
4198 /*no space after the command*/
4199 else if (SPACE_ASCII_VALUE != *inPtr)
4200 {
4201 return -EINVAL;
4202 }
4203
4204 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004205 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004206
4207 /*no argument followed by spaces*/
4208 if ('\0' == *inPtr)
4209 {
4210 return -EINVAL;
4211 }
4212
4213 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004214 v = sscanf(inPtr, "%32s ", buf);
4215 if (1 != v) return -EINVAL;
4216
Srinivas Girigowdade697412013-02-14 16:31:48 -08004217 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004218 if ((v < 0) ||
4219 (tempInt <= 0) ||
4220 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4221 {
4222 return -EINVAL;
4223 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004224
4225 *pNumChannels = tempInt;
4226
4227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4228 "Number of channels are: %d", *pNumChannels);
4229
4230 for (j = 0; j < (*pNumChannels); j++)
4231 {
4232 /*inPtr pointing to the beginning of first space after number of channels*/
4233 inPtr = strpbrk( inPtr, " " );
4234 /*no channel list after the number of channels argument*/
4235 if (NULL == inPtr)
4236 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004237 if (0 != j)
4238 {
4239 *pNumChannels = j;
4240 return VOS_STATUS_SUCCESS;
4241 }
4242 else
4243 {
4244 return -EINVAL;
4245 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004246 }
4247
4248 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004249 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004250
4251 /*no channel list after the number of channels argument and spaces*/
4252 if ( '\0' == *inPtr )
4253 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004254 if (0 != j)
4255 {
4256 *pNumChannels = j;
4257 return VOS_STATUS_SUCCESS;
4258 }
4259 else
4260 {
4261 return -EINVAL;
4262 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004263 }
4264
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004265 v = sscanf(inPtr, "%32s ", buf);
4266 if (1 != v) return -EINVAL;
4267
Srinivas Girigowdade697412013-02-14 16:31:48 -08004268 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004269 if ((v < 0) ||
4270 (tempInt <= 0) ||
4271 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4272 {
4273 return -EINVAL;
4274 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004275 pChannelList[j] = tempInt;
4276
4277 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4278 "Channel %d added to preferred channel list",
4279 pChannelList[j] );
4280 }
4281
Srinivas Girigowdade697412013-02-14 16:31:48 -08004282 return VOS_STATUS_SUCCESS;
4283}
4284
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004285
4286/**---------------------------------------------------------------------------
4287
4288 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4289
4290 This function parses the reasoc command data passed in the format
4291 REASSOC<space><bssid><space><channel>
4292
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004293 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004294 \param - pTargetApBssid Pointer to target Ap bssid
4295 \param - pChannel Pointer to the Target AP channel
4296
4297 \return - 0 for success non-zero for failure
4298
4299 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004300VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4301 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004302{
4303 tANI_U8 *inPtr = pValue;
4304 int tempInt;
4305 int v = 0;
4306 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004307 /* 12 hexa decimal digits and 5 ':' */
4308 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004309
4310 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4311 /*no argument after the command*/
4312 if (NULL == inPtr)
4313 {
4314 return -EINVAL;
4315 }
4316
4317 /*no space after the command*/
4318 else if (SPACE_ASCII_VALUE != *inPtr)
4319 {
4320 return -EINVAL;
4321 }
4322
4323 /*removing empty spaces*/
4324 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4325
4326 /*no argument followed by spaces*/
4327 if ('\0' == *inPtr)
4328 {
4329 return -EINVAL;
4330 }
4331
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004332 v = sscanf(inPtr, "%17s", macAddress);
4333 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004334 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004335 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4336 "Invalid MAC address or All hex inputs are not read (%d)", v);
4337 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004338 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004339
4340 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4341 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4342 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4343 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4344 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4345 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004346
4347 /* point to the next argument */
4348 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4349 /*no argument after the command*/
4350 if (NULL == inPtr) return -EINVAL;
4351
4352 /*removing empty spaces*/
4353 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4354
4355 /*no argument followed by spaces*/
4356 if ('\0' == *inPtr)
4357 {
4358 return -EINVAL;
4359 }
4360
4361 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004362 v = sscanf(inPtr, "%32s ", tempBuf);
4363 if (1 != v) return -EINVAL;
4364
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004365 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004366 if ((v < 0) ||
4367 (tempInt <= 0) ||
4368 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4369 {
4370 return -EINVAL;
4371 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004372
4373 *pChannel = tempInt;
4374 return VOS_STATUS_SUCCESS;
4375}
4376
4377#endif
4378
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004379#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4380/**---------------------------------------------------------------------------
4381
4382 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4383
4384 This function parses the SETCCKM IE command
4385 SETCCKMIE<space><ie data>
4386
4387 \param - pValue Pointer to input data
4388 \param - pCckmIe Pointer to output cckm Ie
4389 \param - pCckmIeLen Pointer to output cckm ie length
4390
4391 \return - 0 for success non-zero for failure
4392
4393 --------------------------------------------------------------------------*/
4394VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4395 tANI_U8 *pCckmIeLen)
4396{
4397 tANI_U8 *inPtr = pValue;
4398 tANI_U8 *dataEnd;
4399 int j = 0;
4400 int i = 0;
4401 tANI_U8 tempByte = 0;
4402
4403 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4404 /*no argument after the command*/
4405 if (NULL == inPtr)
4406 {
4407 return -EINVAL;
4408 }
4409
4410 /*no space after the command*/
4411 else if (SPACE_ASCII_VALUE != *inPtr)
4412 {
4413 return -EINVAL;
4414 }
4415
4416 /*removing empty spaces*/
4417 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4418
4419 /*no argument followed by spaces*/
4420 if ('\0' == *inPtr)
4421 {
4422 return -EINVAL;
4423 }
4424
4425 /* find the length of data */
4426 dataEnd = inPtr;
4427 while(('\0' != *dataEnd) )
4428 {
4429 dataEnd++;
4430 ++(*pCckmIeLen);
4431 }
4432 if ( *pCckmIeLen <= 0) return -EINVAL;
4433
4434 /* Allocate the number of bytes based on the number of input characters
4435 whether it is even or odd.
4436 if the number of input characters are even, then we need N/2 byte.
4437 if the number of input characters are odd, then we need do (N+1)/2 to
4438 compensate rounding off.
4439 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4440 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4441 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4442 if (NULL == *pCckmIe)
4443 {
4444 hddLog(VOS_TRACE_LEVEL_FATAL,
4445 "%s: vos_mem_alloc failed ", __func__);
4446 return -EINVAL;
4447 }
4448 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4449 /* the buffer received from the upper layer is character buffer,
4450 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4451 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4452 and f0 in 3rd location */
4453 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4454 {
4455 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4456 (*pCckmIe)[i++] = tempByte;
4457 }
4458 *pCckmIeLen = i;
4459
4460 return VOS_STATUS_SUCCESS;
4461}
4462#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4463
Jeff Johnson295189b2012-06-20 16:38:30 -07004464/**---------------------------------------------------------------------------
4465
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004466 \brief hdd_is_valid_mac_address() - Validate MAC address
4467
4468 This function validates whether the given MAC address is valid or not
4469 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4470 where X is the hexa decimal digit character and separated by ':'
4471 This algorithm works even if MAC address is not separated by ':'
4472
4473 This code checks given input string mac contains exactly 12 hexadecimal digits.
4474 and a separator colon : appears in the input string only after
4475 an even number of hex digits.
4476
4477 \param - pMacAddr pointer to the input MAC address
4478 \return - 1 for valid and 0 for invalid
4479
4480 --------------------------------------------------------------------------*/
4481
4482v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4483{
4484 int xdigit = 0;
4485 int separator = 0;
4486 while (*pMacAddr)
4487 {
4488 if (isxdigit(*pMacAddr))
4489 {
4490 xdigit++;
4491 }
4492 else if (':' == *pMacAddr)
4493 {
4494 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4495 break;
4496
4497 ++separator;
4498 }
4499 else
4500 {
4501 separator = -1;
4502 /* Invalid MAC found */
4503 return 0;
4504 }
4505 ++pMacAddr;
4506 }
4507 return (xdigit == 12 && (separator == 5 || separator == 0));
4508}
4509
4510/**---------------------------------------------------------------------------
4511
Jeff Johnson295189b2012-06-20 16:38:30 -07004512 \brief hdd_open() - HDD Open function
4513
4514 This is called in response to ifconfig up
4515
4516 \param - dev Pointer to net_device structure
4517
4518 \return - 0 for success non-zero for failure
4519
4520 --------------------------------------------------------------------------*/
4521int hdd_open (struct net_device *dev)
4522{
4523 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4524 hdd_context_t *pHddCtx;
4525 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4526 VOS_STATUS status;
4527 v_BOOL_t in_standby = TRUE;
4528
4529 if (NULL == pAdapter)
4530 {
4531 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004532 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004533 return -ENODEV;
4534 }
4535
4536 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4537 if (NULL == pHddCtx)
4538 {
4539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004540 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004541 return -ENODEV;
4542 }
4543
4544 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4545 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4546 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004547 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4548 {
4549 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304550 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004551 in_standby = FALSE;
4552 break;
4553 }
4554 else
4555 {
4556 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4557 pAdapterNode = pNext;
4558 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004559 }
4560
4561 if (TRUE == in_standby)
4562 {
4563 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4564 {
4565 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4566 "wlan out of power save", __func__);
4567 return -EINVAL;
4568 }
4569 }
4570
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004571 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004572 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4573 {
4574 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004575 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004576 /* Enable TX queues only when we are connected */
4577 netif_tx_start_all_queues(dev);
4578 }
4579
4580 return 0;
4581}
4582
4583int hdd_mon_open (struct net_device *dev)
4584{
4585 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4586
4587 if(pAdapter == NULL) {
4588 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004589 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004590 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004591 }
4592
4593 netif_start_queue(dev);
4594
4595 return 0;
4596}
4597/**---------------------------------------------------------------------------
4598
4599 \brief hdd_stop() - HDD stop function
4600
4601 This is called in response to ifconfig down
4602
4603 \param - dev Pointer to net_device structure
4604
4605 \return - 0 for success non-zero for failure
4606
4607 --------------------------------------------------------------------------*/
4608
4609int hdd_stop (struct net_device *dev)
4610{
4611 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4612 hdd_context_t *pHddCtx;
4613 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4614 VOS_STATUS status;
4615 v_BOOL_t enter_standby = TRUE;
4616
4617 ENTER();
4618
4619 if (NULL == pAdapter)
4620 {
4621 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004622 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004623 return -ENODEV;
4624 }
4625
4626 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4627 if (NULL == pHddCtx)
4628 {
4629 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004630 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004631 return -ENODEV;
4632 }
4633
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004634 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004635 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4636 netif_tx_disable(pAdapter->dev);
4637 netif_carrier_off(pAdapter->dev);
4638
4639
4640 /* SoftAP ifaces should never go in power save mode
4641 making sure same here. */
4642 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4643 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004644 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004645 )
4646 {
4647 /* SoftAP mode, so return from here */
4648 EXIT();
4649 return 0;
4650 }
4651
4652 /* Find if any iface is up then
4653 if any iface is up then can't put device to sleep/ power save mode. */
4654 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4655 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4656 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004657 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4658 {
4659 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304660 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004661 enter_standby = FALSE;
4662 break;
4663 }
4664 else
4665 {
4666 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4667 pAdapterNode = pNext;
4668 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004669 }
4670
4671 if (TRUE == enter_standby)
4672 {
4673 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4674 "entering standby", __func__);
4675 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4676 {
4677 /*log and return success*/
4678 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4679 "wlan in power save", __func__);
4680 }
4681 }
4682
4683 EXIT();
4684 return 0;
4685}
4686
4687/**---------------------------------------------------------------------------
4688
4689 \brief hdd_uninit() - HDD uninit function
4690
4691 This is called during the netdev unregister to uninitialize all data
4692associated with the device
4693
4694 \param - dev Pointer to net_device structure
4695
4696 \return - void
4697
4698 --------------------------------------------------------------------------*/
4699static void hdd_uninit (struct net_device *dev)
4700{
4701 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4702
4703 ENTER();
4704
4705 do
4706 {
4707 if (NULL == pAdapter)
4708 {
4709 hddLog(VOS_TRACE_LEVEL_FATAL,
4710 "%s: NULL pAdapter", __func__);
4711 break;
4712 }
4713
4714 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4715 {
4716 hddLog(VOS_TRACE_LEVEL_FATAL,
4717 "%s: Invalid magic", __func__);
4718 break;
4719 }
4720
4721 if (NULL == pAdapter->pHddCtx)
4722 {
4723 hddLog(VOS_TRACE_LEVEL_FATAL,
4724 "%s: NULL pHddCtx", __func__);
4725 break;
4726 }
4727
4728 if (dev != pAdapter->dev)
4729 {
4730 hddLog(VOS_TRACE_LEVEL_FATAL,
4731 "%s: Invalid device reference", __func__);
4732 /* we haven't validated all cases so let this go for now */
4733 }
4734
4735 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4736
4737 /* after uninit our adapter structure will no longer be valid */
4738 pAdapter->dev = NULL;
4739 pAdapter->magic = 0;
4740 } while (0);
4741
4742 EXIT();
4743}
4744
4745/**---------------------------------------------------------------------------
4746
4747 \brief hdd_release_firmware() -
4748
4749 This function calls the release firmware API to free the firmware buffer.
4750
4751 \param - pFileName Pointer to the File Name.
4752 pCtx - Pointer to the adapter .
4753
4754
4755 \return - 0 for success, non zero for failure
4756
4757 --------------------------------------------------------------------------*/
4758
4759VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4760{
4761 VOS_STATUS status = VOS_STATUS_SUCCESS;
4762 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4763 ENTER();
4764
4765
4766 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4767
4768 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4769
4770 if(pHddCtx->fw) {
4771 release_firmware(pHddCtx->fw);
4772 pHddCtx->fw = NULL;
4773 }
4774 else
4775 status = VOS_STATUS_E_FAILURE;
4776 }
4777 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4778 if(pHddCtx->nv) {
4779 release_firmware(pHddCtx->nv);
4780 pHddCtx->nv = NULL;
4781 }
4782 else
4783 status = VOS_STATUS_E_FAILURE;
4784
4785 }
4786
4787 EXIT();
4788 return status;
4789}
4790
4791/**---------------------------------------------------------------------------
4792
4793 \brief hdd_request_firmware() -
4794
4795 This function reads the firmware file using the request firmware
4796 API and returns the the firmware data and the firmware file size.
4797
4798 \param - pfileName - Pointer to the file name.
4799 - pCtx - Pointer to the adapter .
4800 - ppfw_data - Pointer to the pointer of the firmware data.
4801 - pSize - Pointer to the file size.
4802
4803 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4804
4805 --------------------------------------------------------------------------*/
4806
4807
4808VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4809{
4810 int status;
4811 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4812 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4813 ENTER();
4814
4815 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4816
4817 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4818
4819 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4820 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4821 __func__, pfileName);
4822 retval = VOS_STATUS_E_FAILURE;
4823 }
4824
4825 else {
4826 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4827 *pSize = pHddCtx->fw->size;
4828 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4829 __func__, *pSize);
4830 }
4831 }
4832 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4833
4834 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4835
4836 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4837 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4838 __func__, pfileName);
4839 retval = VOS_STATUS_E_FAILURE;
4840 }
4841
4842 else {
4843 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4844 *pSize = pHddCtx->nv->size;
4845 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4846 __func__, *pSize);
4847 }
4848 }
4849
4850 EXIT();
4851 return retval;
4852}
4853/**---------------------------------------------------------------------------
4854 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4855
4856 This is the function invoked by SME to inform the result of a full power
4857 request issued by HDD
4858
4859 \param - callbackcontext - Pointer to cookie
4860 status - result of request
4861
4862 \return - None
4863
4864--------------------------------------------------------------------------*/
4865void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4866{
4867 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4868
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004869 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004870 if(&pHddCtx->full_pwr_comp_var)
4871 {
4872 complete(&pHddCtx->full_pwr_comp_var);
4873 }
4874}
4875
4876/**---------------------------------------------------------------------------
4877
4878 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4879
4880 This is the function invoked by SME to inform the result of BMPS
4881 request issued by HDD
4882
4883 \param - callbackcontext - Pointer to cookie
4884 status - result of request
4885
4886 \return - None
4887
4888--------------------------------------------------------------------------*/
4889void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4890{
4891
4892 struct completion *completion_var = (struct completion*) callbackContext;
4893
4894 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
4895 if(completion_var != NULL)
4896 {
4897 complete(completion_var);
4898 }
4899}
4900
4901/**---------------------------------------------------------------------------
4902
4903 \brief hdd_get_cfg_file_size() -
4904
4905 This function reads the configuration file using the request firmware
4906 API and returns the configuration file size.
4907
4908 \param - pCtx - Pointer to the adapter .
4909 - pFileName - Pointer to the file name.
4910 - pBufSize - Pointer to the buffer size.
4911
4912 \return - 0 for success, non zero for failure
4913
4914 --------------------------------------------------------------------------*/
4915
4916VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4917{
4918 int status;
4919 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4920
4921 ENTER();
4922
4923 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4924
4925 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4926 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4927 status = VOS_STATUS_E_FAILURE;
4928 }
4929 else {
4930 *pBufSize = pHddCtx->fw->size;
4931 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4932 release_firmware(pHddCtx->fw);
4933 pHddCtx->fw = NULL;
4934 }
4935
4936 EXIT();
4937 return VOS_STATUS_SUCCESS;
4938}
4939
4940/**---------------------------------------------------------------------------
4941
4942 \brief hdd_read_cfg_file() -
4943
4944 This function reads the configuration file using the request firmware
4945 API and returns the cfg data and the buffer size of the configuration file.
4946
4947 \param - pCtx - Pointer to the adapter .
4948 - pFileName - Pointer to the file name.
4949 - pBuffer - Pointer to the data buffer.
4950 - pBufSize - Pointer to the buffer size.
4951
4952 \return - 0 for success, non zero for failure
4953
4954 --------------------------------------------------------------------------*/
4955
4956VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4957 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4958{
4959 int status;
4960 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4961
4962 ENTER();
4963
4964 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4965
4966 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4967 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4968 return VOS_STATUS_E_FAILURE;
4969 }
4970 else {
4971 if(*pBufSize != pHddCtx->fw->size) {
4972 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4973 "file size", __func__);
4974 release_firmware(pHddCtx->fw);
4975 pHddCtx->fw = NULL;
4976 return VOS_STATUS_E_FAILURE;
4977 }
4978 else {
4979 if(pBuffer) {
4980 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4981 }
4982 release_firmware(pHddCtx->fw);
4983 pHddCtx->fw = NULL;
4984 }
4985 }
4986
4987 EXIT();
4988
4989 return VOS_STATUS_SUCCESS;
4990}
4991
4992/**---------------------------------------------------------------------------
4993
Jeff Johnson295189b2012-06-20 16:38:30 -07004994 \brief hdd_set_mac_address() -
4995
4996 This function sets the user specified mac address using
4997 the command ifconfig wlanX hw ether <mac adress>.
4998
4999 \param - dev - Pointer to the net device.
5000 - addr - Pointer to the sockaddr.
5001 \return - 0 for success, non zero for failure
5002
5003 --------------------------------------------------------------------------*/
5004
5005static int hdd_set_mac_address(struct net_device *dev, void *addr)
5006{
5007 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5008 struct sockaddr *psta_mac_addr = addr;
5009 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5010
5011 ENTER();
5012
5013 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5014
5015#ifdef HDD_SESSIONIZE
5016 // set the MAC address though the STA ID CFG.
5017 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5018 (v_U8_t *)&pAdapter->macAddressCurrent,
5019 sizeof( pAdapter->macAddressCurrent ),
5020 hdd_set_mac_addr_cb, VOS_FALSE );
5021#endif
5022
5023 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5024
5025 EXIT();
5026 return halStatus;
5027}
5028
5029tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5030{
5031 int i;
5032 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5033 {
5034 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
5035 break;
5036 }
5037
5038 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5039 return NULL;
5040
5041 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5042 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5043}
5044
5045void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5046{
5047 int i;
5048 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5049 {
5050 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5051 {
5052 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5053 break;
5054 }
5055 }
5056 return;
5057}
5058
5059#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5060 static struct net_device_ops wlan_drv_ops = {
5061 .ndo_open = hdd_open,
5062 .ndo_stop = hdd_stop,
5063 .ndo_uninit = hdd_uninit,
5064 .ndo_start_xmit = hdd_hard_start_xmit,
5065 .ndo_tx_timeout = hdd_tx_timeout,
5066 .ndo_get_stats = hdd_stats,
5067 .ndo_do_ioctl = hdd_ioctl,
5068 .ndo_set_mac_address = hdd_set_mac_address,
5069 .ndo_select_queue = hdd_select_queue,
5070#ifdef WLAN_FEATURE_PACKET_FILTERING
5071#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5072 .ndo_set_rx_mode = hdd_set_multicast_list,
5073#else
5074 .ndo_set_multicast_list = hdd_set_multicast_list,
5075#endif //LINUX_VERSION_CODE
5076#endif
5077 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005078 static struct net_device_ops wlan_mon_drv_ops = {
5079 .ndo_open = hdd_mon_open,
5080 .ndo_stop = hdd_stop,
5081 .ndo_uninit = hdd_uninit,
5082 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5083 .ndo_tx_timeout = hdd_tx_timeout,
5084 .ndo_get_stats = hdd_stats,
5085 .ndo_do_ioctl = hdd_ioctl,
5086 .ndo_set_mac_address = hdd_set_mac_address,
5087 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005088
5089#endif
5090
5091void hdd_set_station_ops( struct net_device *pWlanDev )
5092{
5093#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005094 pWlanDev->netdev_ops = &wlan_drv_ops;
5095#else
5096 pWlanDev->open = hdd_open;
5097 pWlanDev->stop = hdd_stop;
5098 pWlanDev->uninit = hdd_uninit;
5099 pWlanDev->hard_start_xmit = NULL;
5100 pWlanDev->tx_timeout = hdd_tx_timeout;
5101 pWlanDev->get_stats = hdd_stats;
5102 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005103 pWlanDev->set_mac_address = hdd_set_mac_address;
5104#endif
5105}
5106
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005107static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005108{
5109 struct net_device *pWlanDev = NULL;
5110 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005111 /*
5112 * cfg80211 initialization and registration....
5113 */
5114 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5115
Jeff Johnson295189b2012-06-20 16:38:30 -07005116 if(pWlanDev != NULL)
5117 {
5118
5119 //Save the pointer to the net_device in the HDD adapter
5120 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5121
Jeff Johnson295189b2012-06-20 16:38:30 -07005122 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5123
5124 pAdapter->dev = pWlanDev;
5125 pAdapter->pHddCtx = pHddCtx;
5126 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5127
5128 init_completion(&pAdapter->session_open_comp_var);
5129 init_completion(&pAdapter->session_close_comp_var);
5130 init_completion(&pAdapter->disconnect_comp_var);
5131 init_completion(&pAdapter->linkup_event_var);
5132 init_completion(&pAdapter->cancel_rem_on_chan_var);
5133 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005134#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5135 init_completion(&pAdapter->offchannel_tx_event);
5136#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005137 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005138#ifdef FEATURE_WLAN_TDLS
5139 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005140 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005141 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305142 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005143#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005144 init_completion(&pHddCtx->mc_sus_event_var);
5145 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305146 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005147 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005148 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005149
Rajeev79dbe4c2013-10-05 11:03:42 +05305150#ifdef FEATURE_WLAN_BATCH_SCAN
5151 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5152 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5153 pAdapter->pBatchScanRsp = NULL;
5154 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005155 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08005156 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305157 mutex_init(&pAdapter->hdd_batch_scan_lock);
5158#endif
5159
Jeff Johnson295189b2012-06-20 16:38:30 -07005160 pAdapter->isLinkUpSvcNeeded = FALSE;
5161 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5162 //Init the net_device structure
5163 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5164
5165 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5166 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5167 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5168 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5169
5170 hdd_set_station_ops( pAdapter->dev );
5171
5172 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005173 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5174 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5175 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005176 /* set pWlanDev's parent to underlying device */
5177 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5178 }
5179
5180 return pAdapter;
5181}
5182
5183VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5184{
5185 struct net_device *pWlanDev = pAdapter->dev;
5186 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5187 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5188 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5189
5190 if( rtnl_lock_held )
5191 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005192 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005193 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5194 {
5195 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5196 return VOS_STATUS_E_FAILURE;
5197 }
5198 }
5199 if (register_netdevice(pWlanDev))
5200 {
5201 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5202 return VOS_STATUS_E_FAILURE;
5203 }
5204 }
5205 else
5206 {
5207 if(register_netdev(pWlanDev))
5208 {
5209 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5210 return VOS_STATUS_E_FAILURE;
5211 }
5212 }
5213 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5214
5215 return VOS_STATUS_SUCCESS;
5216}
5217
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005218static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005219{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005220 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005221
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005222 if (NULL == pAdapter)
5223 {
5224 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5225 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005226 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005227
5228 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5229 {
5230 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5231 return eHAL_STATUS_NOT_INITIALIZED;
5232 }
5233
5234 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5235
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005236#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005237 /* need to make sure all of our scheduled work has completed.
5238 * This callback is called from MC thread context, so it is safe to
5239 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005240 *
5241 * Even though this is called from MC thread context, if there is a faulty
5242 * work item in the system, that can hang this call forever. So flushing
5243 * this global work queue is not safe; and now we make sure that
5244 * individual work queues are stopped correctly. But the cancel work queue
5245 * is a GPL only API, so the proprietary version of the driver would still
5246 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005247 */
5248 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005249#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005250
5251 /* We can be blocked while waiting for scheduled work to be
5252 * flushed, and the adapter structure can potentially be freed, in
5253 * which case the magic will have been reset. So make sure the
5254 * magic is still good, and hence the adapter structure is still
5255 * valid, before signaling completion */
5256 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5257 {
5258 complete(&pAdapter->session_close_comp_var);
5259 }
5260
Jeff Johnson295189b2012-06-20 16:38:30 -07005261 return eHAL_STATUS_SUCCESS;
5262}
5263
5264VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5265{
5266 struct net_device *pWlanDev = pAdapter->dev;
5267 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5268 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5269 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5270 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5271 int rc = 0;
5272
5273 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005274 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005275 //Open a SME session for future operation
5276 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005277 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005278 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5279 {
5280 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005281 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005282 halStatus, halStatus );
5283 status = VOS_STATUS_E_FAILURE;
5284 goto error_sme_open;
5285 }
5286
5287 //Block on a completion variable. Can't wait forever though.
5288 rc = wait_for_completion_interruptible_timeout(
5289 &pAdapter->session_open_comp_var,
5290 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5291 if (!rc)
5292 {
5293 hddLog(VOS_TRACE_LEVEL_FATAL,
5294 "Session is not opened within timeout period code %08d", rc );
5295 status = VOS_STATUS_E_FAILURE;
5296 goto error_sme_open;
5297 }
5298
5299 // Register wireless extensions
5300 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5301 {
5302 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005303 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005304 halStatus, halStatus );
5305 status = VOS_STATUS_E_FAILURE;
5306 goto error_register_wext;
5307 }
5308 //Safe to register the hard_start_xmit function again
5309#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5310 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5311#else
5312 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5313#endif
5314
5315 //Set the Connection State to Not Connected
5316 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5317
5318 //Set the default operation channel
5319 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5320
5321 /* Make the default Auth Type as OPEN*/
5322 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5323
5324 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5325 {
5326 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005327 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005328 status, status );
5329 goto error_init_txrx;
5330 }
5331
5332 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5333
5334 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5335 {
5336 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005337 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005338 status, status );
5339 goto error_wmm_init;
5340 }
5341
5342 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5343
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005344#ifdef FEATURE_WLAN_TDLS
5345 if(0 != wlan_hdd_tdls_init(pAdapter))
5346 {
5347 status = VOS_STATUS_E_FAILURE;
5348 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5349 goto error_tdls_init;
5350 }
5351 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5352#endif
5353
Jeff Johnson295189b2012-06-20 16:38:30 -07005354 return VOS_STATUS_SUCCESS;
5355
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005356#ifdef FEATURE_WLAN_TDLS
5357error_tdls_init:
5358 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5359 hdd_wmm_adapter_close(pAdapter);
5360#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005361error_wmm_init:
5362 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5363 hdd_deinit_tx_rx(pAdapter);
5364error_init_txrx:
5365 hdd_UnregisterWext(pWlanDev);
5366error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005367 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005368 {
5369 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005370 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005371 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005372 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005373 {
5374 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005375 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005376 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005377 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005378 }
5379}
5380error_sme_open:
5381 return status;
5382}
5383
Jeff Johnson295189b2012-06-20 16:38:30 -07005384void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5385{
5386 hdd_cfg80211_state_t *cfgState;
5387
5388 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5389
5390 if( NULL != cfgState->buf )
5391 {
5392 int rc;
5393 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5394 rc = wait_for_completion_interruptible_timeout(
5395 &pAdapter->tx_action_cnf_event,
5396 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5397 if(!rc)
5398 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005399 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005400 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
5401 }
5402 }
5403 return;
5404}
Jeff Johnson295189b2012-06-20 16:38:30 -07005405
5406void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5407{
5408 ENTER();
5409 switch ( pAdapter->device_mode )
5410 {
5411 case WLAN_HDD_INFRA_STATION:
5412 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005413 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005414 {
5415 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5416 {
5417 hdd_deinit_tx_rx( pAdapter );
5418 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5419 }
5420
5421 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5422 {
5423 hdd_wmm_adapter_close( pAdapter );
5424 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5425 }
5426
Jeff Johnson295189b2012-06-20 16:38:30 -07005427 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005428#ifdef FEATURE_WLAN_TDLS
5429 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5430 {
5431 wlan_hdd_tdls_exit(pAdapter);
5432 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5433 }
5434#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005435
5436 break;
5437 }
5438
5439 case WLAN_HDD_SOFTAP:
5440 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005441 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305442
5443 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5444 {
5445 hdd_wmm_adapter_close( pAdapter );
5446 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5447 }
5448
Jeff Johnson295189b2012-06-20 16:38:30 -07005449 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005450
5451 hdd_unregister_hostapd(pAdapter);
5452 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005453 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005454 break;
5455 }
5456
5457 case WLAN_HDD_MONITOR:
5458 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005459 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005460 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5461 {
5462 hdd_deinit_tx_rx( pAdapter );
5463 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5464 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005465 if(NULL != pAdapterforTx)
5466 {
5467 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5468 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005469 break;
5470 }
5471
5472
5473 default:
5474 break;
5475 }
5476
5477 EXIT();
5478}
5479
5480void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5481{
5482 struct net_device *pWlanDev = pAdapter->dev;
5483
Rajeev79dbe4c2013-10-05 11:03:42 +05305484#ifdef FEATURE_WLAN_BATCH_SCAN
5485 tHddBatchScanRsp *pNode;
5486 tHddBatchScanRsp *pPrev;
5487 if (pAdapter)
5488 {
5489 mutex_lock(&pAdapter->hdd_batch_scan_lock);
5490 pNode = pAdapter->pBatchScanRsp;
5491 while (pNode)
5492 {
5493 pPrev = pNode;
5494 pNode = pNode->pNext;
5495 vos_mem_free((v_VOID_t * )pPrev);
5496 }
5497 pAdapter->pBatchScanRsp = NULL;
5498 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
5499 }
5500#endif
5501
Jeff Johnson295189b2012-06-20 16:38:30 -07005502 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5503 if( rtnl_held )
5504 {
5505 unregister_netdevice(pWlanDev);
5506 }
5507 else
5508 {
5509 unregister_netdev(pWlanDev);
5510 }
5511 // note that the pAdapter is no longer valid at this point
5512 // since the memory has been reclaimed
5513 }
5514
5515}
5516
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005517void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5518{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305519 VOS_STATUS status;
5520 hdd_adapter_t *pAdapter = NULL;
5521 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005522
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305523 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005524
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305525 /*loop through all adapters.*/
5526 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005527 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305528 pAdapter = pAdapterNode->pAdapter;
5529 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5530 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005531
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305532 { // we skip this registration for modes other than STA and P2P client modes.
5533 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5534 pAdapterNode = pNext;
5535 continue;
5536 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005537
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305538 //Apply Dynamic DTIM For P2P
5539 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5540 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5541 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5542 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5543 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5544 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5545 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5546 (eConnectionState_Associated ==
5547 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5548 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5549 {
5550 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005551
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305552 powerRequest.uIgnoreDTIM = 1;
5553 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5554
5555 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5556 {
5557 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5558 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5559 }
5560 else
5561 {
5562 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5563 }
5564
5565 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5566 * specified during Enter/Exit BMPS when LCD off*/
5567 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5568 NULL, eANI_BOOLEAN_FALSE);
5569 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5570 NULL, eANI_BOOLEAN_FALSE);
5571
5572 /* switch to the DTIM specified in cfg.ini */
5573 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5574 "Switch to DTIM %d", powerRequest.uListenInterval);
5575 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5576 break;
5577
5578 }
5579
5580 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5581 pAdapterNode = pNext;
5582 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005583}
5584
5585void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5586{
5587 /*Switch back to DTIM 1*/
5588 tSirSetPowerParamsReq powerRequest = { 0 };
5589
5590 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5591 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005592 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005593
5594 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5595 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5596 NULL, eANI_BOOLEAN_FALSE);
5597 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5598 NULL, eANI_BOOLEAN_FALSE);
5599
5600 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5601 "Switch to DTIM%d",powerRequest.uListenInterval);
5602 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5603
5604}
5605
Jeff Johnson295189b2012-06-20 16:38:30 -07005606VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5607{
5608 VOS_STATUS status = VOS_STATUS_SUCCESS;
5609
5610 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5611 {
5612 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5613 }
5614
5615 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5616 {
5617 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5618 }
5619
5620 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5621 {
5622 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5623 }
5624
5625 return status;
5626}
5627
5628VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5629{
5630 hdd_adapter_t *pAdapter = NULL;
5631 eHalStatus halStatus;
5632 VOS_STATUS status = VOS_STATUS_E_INVAL;
5633 v_BOOL_t disableBmps = FALSE;
5634 v_BOOL_t disableImps = FALSE;
5635
5636 switch(session_type)
5637 {
5638 case WLAN_HDD_INFRA_STATION:
5639 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005640 case WLAN_HDD_P2P_CLIENT:
5641 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005642 //Exit BMPS -> Is Sta/P2P Client is already connected
5643 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5644 if((NULL != pAdapter)&&
5645 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5646 {
5647 disableBmps = TRUE;
5648 }
5649
5650 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5651 if((NULL != pAdapter)&&
5652 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5653 {
5654 disableBmps = TRUE;
5655 }
5656
5657 //Exit both Bmps and Imps incase of Go/SAP Mode
5658 if((WLAN_HDD_SOFTAP == session_type) ||
5659 (WLAN_HDD_P2P_GO == session_type))
5660 {
5661 disableBmps = TRUE;
5662 disableImps = TRUE;
5663 }
5664
5665 if(TRUE == disableImps)
5666 {
5667 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5668 {
5669 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5670 }
5671 }
5672
5673 if(TRUE == disableBmps)
5674 {
5675 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5676 {
5677 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5678
5679 if(eHAL_STATUS_SUCCESS != halStatus)
5680 {
5681 status = VOS_STATUS_E_FAILURE;
5682 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
5683 VOS_ASSERT(0);
5684 return status;
5685 }
5686 }
5687
5688 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5689 {
5690 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5691
5692 if(eHAL_STATUS_SUCCESS != halStatus)
5693 {
5694 status = VOS_STATUS_E_FAILURE;
5695 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
5696 VOS_ASSERT(0);
5697 return status;
5698 }
5699 }
5700 }
5701
5702 if((TRUE == disableBmps) ||
5703 (TRUE == disableImps))
5704 {
5705 /* Now, get the chip into Full Power now */
5706 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5707 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5708 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5709
5710 if(halStatus != eHAL_STATUS_SUCCESS)
5711 {
5712 if(halStatus == eHAL_STATUS_PMC_PENDING)
5713 {
5714 //Block on a completion variable. Can't wait forever though
5715 wait_for_completion_interruptible_timeout(
5716 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5717 }
5718 else
5719 {
5720 status = VOS_STATUS_E_FAILURE;
5721 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
5722 VOS_ASSERT(0);
5723 return status;
5724 }
5725 }
5726
5727 status = VOS_STATUS_SUCCESS;
5728 }
5729
5730 break;
5731 }
5732 return status;
5733}
5734
5735hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005736 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005737 tANI_U8 rtnl_held )
5738{
5739 hdd_adapter_t *pAdapter = NULL;
5740 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5741 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5742 VOS_STATUS exitbmpsStatus;
5743
5744 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
5745
5746 //Disable BMPS incase of Concurrency
5747 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5748
5749 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5750 {
5751 //Fail to Exit BMPS
5752 VOS_ASSERT(0);
5753 return NULL;
5754 }
5755
5756 switch(session_type)
5757 {
5758 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005759 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005760 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005761 {
5762 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5763
5764 if( NULL == pAdapter )
5765 return NULL;
5766
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305767#ifdef FEATURE_WLAN_TDLS
5768 /* A Mutex Lock is introduced while changing/initializing the mode to
5769 * protect the concurrent access for the Adapters by TDLS module.
5770 */
5771 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5772 {
5773 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5774 "%s: unable to lock list", __func__);
5775 return NULL;
5776 }
5777#endif
5778
Jeff Johnsone7245742012-09-05 17:12:55 -07005779 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5780 NL80211_IFTYPE_P2P_CLIENT:
5781 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005782
Jeff Johnson295189b2012-06-20 16:38:30 -07005783 pAdapter->device_mode = session_type;
5784
5785 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305786#ifdef FEATURE_WLAN_TDLS
5787 mutex_unlock(&pHddCtx->tdls_lock);
5788#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005789 if( VOS_STATUS_SUCCESS != status )
5790 goto err_free_netdev;
5791
5792 status = hdd_register_interface( pAdapter, rtnl_held );
5793 if( VOS_STATUS_SUCCESS != status )
5794 {
5795 hdd_deinit_adapter(pHddCtx, pAdapter);
5796 goto err_free_netdev;
5797 }
5798 //Stop the Interface TX queue.
5799 netif_tx_disable(pAdapter->dev);
5800 //netif_tx_disable(pWlanDev);
5801 netif_carrier_off(pAdapter->dev);
5802
5803 break;
5804 }
5805
Jeff Johnson295189b2012-06-20 16:38:30 -07005806 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005807 case WLAN_HDD_SOFTAP:
5808 {
5809 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5810 if( NULL == pAdapter )
5811 return NULL;
5812
Jeff Johnson295189b2012-06-20 16:38:30 -07005813 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5814 NL80211_IFTYPE_AP:
5815 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005816 pAdapter->device_mode = session_type;
5817
5818 status = hdd_init_ap_mode(pAdapter);
5819 if( VOS_STATUS_SUCCESS != status )
5820 goto err_free_netdev;
5821
5822 status = hdd_register_hostapd( pAdapter, rtnl_held );
5823 if( VOS_STATUS_SUCCESS != status )
5824 {
5825 hdd_deinit_adapter(pHddCtx, pAdapter);
5826 goto err_free_netdev;
5827 }
5828
5829 netif_tx_disable(pAdapter->dev);
5830 netif_carrier_off(pAdapter->dev);
5831
5832 hdd_set_conparam( 1 );
5833 break;
5834 }
5835 case WLAN_HDD_MONITOR:
5836 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005837 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5838 if( NULL == pAdapter )
5839 return NULL;
5840
5841 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5842 pAdapter->device_mode = session_type;
5843 status = hdd_register_interface( pAdapter, rtnl_held );
5844#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5845 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5846#else
5847 pAdapter->dev->open = hdd_mon_open;
5848 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5849#endif
5850 hdd_init_tx_rx( pAdapter );
5851 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5852 //Set adapter to be used for data tx. It will use either GO or softap.
5853 pAdapter->sessionCtx.monitor.pAdapterForTx =
5854 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005855 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5856 {
5857 pAdapter->sessionCtx.monitor.pAdapterForTx =
5858 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5859 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005860 /* This workqueue will be used to transmit management packet over
5861 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005862 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5863 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5864 return NULL;
5865 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005866
Jeff Johnson295189b2012-06-20 16:38:30 -07005867 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5868 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005869 }
5870 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005871 case WLAN_HDD_FTM:
5872 {
5873 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5874
5875 if( NULL == pAdapter )
5876 return NULL;
5877 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5878 * message while loading driver in FTM mode. */
5879 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5880 pAdapter->device_mode = session_type;
5881 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305882
5883 hdd_init_tx_rx( pAdapter );
5884
5885 //Stop the Interface TX queue.
5886 netif_tx_disable(pAdapter->dev);
5887 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005888 }
5889 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005890 default:
5891 {
5892 VOS_ASSERT(0);
5893 return NULL;
5894 }
5895 }
5896
5897
5898 if( VOS_STATUS_SUCCESS == status )
5899 {
5900 //Add it to the hdd's session list.
5901 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5902 if( NULL == pHddAdapterNode )
5903 {
5904 status = VOS_STATUS_E_NOMEM;
5905 }
5906 else
5907 {
5908 pHddAdapterNode->pAdapter = pAdapter;
5909 status = hdd_add_adapter_back ( pHddCtx,
5910 pHddAdapterNode );
5911 }
5912 }
5913
5914 if( VOS_STATUS_SUCCESS != status )
5915 {
5916 if( NULL != pAdapter )
5917 {
5918 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5919 pAdapter = NULL;
5920 }
5921 if( NULL != pHddAdapterNode )
5922 {
5923 vos_mem_free( pHddAdapterNode );
5924 }
5925
5926 goto resume_bmps;
5927 }
5928
5929 if(VOS_STATUS_SUCCESS == status)
5930 {
5931 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5932
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005933 //Initialize the WoWL service
5934 if(!hdd_init_wowl(pAdapter))
5935 {
5936 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5937 goto err_free_netdev;
5938 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005939 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005940 return pAdapter;
5941
5942err_free_netdev:
5943 free_netdev(pAdapter->dev);
5944 wlan_hdd_release_intf_addr( pHddCtx,
5945 pAdapter->macAddressCurrent.bytes );
5946
5947resume_bmps:
5948 //If bmps disabled enable it
5949 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5950 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305951 if (pHddCtx->hdd_wlan_suspended)
5952 {
5953 hdd_set_pwrparams(pHddCtx);
5954 }
5955 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005956 }
5957 return NULL;
5958}
5959
5960VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5961 tANI_U8 rtnl_held )
5962{
5963 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5964 VOS_STATUS status;
5965
5966 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5967 if( VOS_STATUS_SUCCESS != status )
5968 return status;
5969
5970 while ( pCurrent->pAdapter != pAdapter )
5971 {
5972 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5973 if( VOS_STATUS_SUCCESS != status )
5974 break;
5975
5976 pCurrent = pNext;
5977 }
5978 pAdapterNode = pCurrent;
5979 if( VOS_STATUS_SUCCESS == status )
5980 {
5981 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5982 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305983
5984#ifdef FEATURE_WLAN_TDLS
5985
5986 /* A Mutex Lock is introduced while changing/initializing the mode to
5987 * protect the concurrent access for the Adapters by TDLS module.
5988 */
5989 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5990 {
5991 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5992 "%s: unable to lock list", __func__);
5993 return VOS_STATUS_E_FAILURE;
5994 }
5995#endif
5996
Jeff Johnson295189b2012-06-20 16:38:30 -07005997 hdd_remove_adapter( pHddCtx, pAdapterNode );
5998 vos_mem_free( pAdapterNode );
5999
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306000#ifdef FEATURE_WLAN_TDLS
6001 mutex_unlock(&pHddCtx->tdls_lock);
6002#endif
6003
Jeff Johnson295189b2012-06-20 16:38:30 -07006004
6005 /* If there is a single session of STA/P2P client, re-enable BMPS */
6006 if ((!vos_concurrent_sessions_running()) &&
6007 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6008 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6009 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306010 if (pHddCtx->hdd_wlan_suspended)
6011 {
6012 hdd_set_pwrparams(pHddCtx);
6013 }
6014 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006015 }
6016
6017 return VOS_STATUS_SUCCESS;
6018 }
6019
6020 return VOS_STATUS_E_FAILURE;
6021}
6022
6023VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6024{
6025 hdd_adapter_list_node_t *pHddAdapterNode;
6026 VOS_STATUS status;
6027
6028 ENTER();
6029
6030 do
6031 {
6032 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6033 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6034 {
6035 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6036 vos_mem_free( pHddAdapterNode );
6037 }
6038 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6039
6040 EXIT();
6041
6042 return VOS_STATUS_SUCCESS;
6043}
6044
6045void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6046{
6047 v_U8_t addIE[1] = {0};
6048
6049 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6050 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6051 eANI_BOOLEAN_FALSE) )
6052 {
6053 hddLog(LOGE,
6054 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
6055 }
6056
6057 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6058 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6059 eANI_BOOLEAN_FALSE) )
6060 {
6061 hddLog(LOGE,
6062 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
6063 }
6064
6065 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6066 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6067 eANI_BOOLEAN_FALSE) )
6068 {
6069 hddLog(LOGE,
6070 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
6071 }
6072}
6073
6074VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6075{
6076 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6077 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6078 union iwreq_data wrqu;
6079
6080 ENTER();
6081
6082 switch(pAdapter->device_mode)
6083 {
6084 case WLAN_HDD_INFRA_STATION:
6085 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006086 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006087 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6088 {
6089 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6090 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6091 pAdapter->sessionId,
6092 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6093 else
6094 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6095 pAdapter->sessionId,
6096 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6097 //success implies disconnect command got queued up successfully
6098 if(halStatus == eHAL_STATUS_SUCCESS)
6099 {
6100 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
6101 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6102 }
6103 memset(&wrqu, '\0', sizeof(wrqu));
6104 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6105 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6106 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6107 }
6108 else
6109 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306110 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006111 }
6112
6113 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6114 {
6115 INIT_COMPLETION(pAdapter->session_close_comp_var);
6116 if (eHAL_STATUS_SUCCESS ==
6117 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6118 hdd_smeCloseSessionCallback, pAdapter))
6119 {
6120 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006121 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006122 &pAdapter->session_close_comp_var,
6123 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
6124 }
6125 }
6126
6127 break;
6128
6129 case WLAN_HDD_SOFTAP:
6130 case WLAN_HDD_P2P_GO:
6131 //Any softap specific cleanup here...
6132 mutex_lock(&pHddCtx->sap_lock);
6133 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6134 {
6135 VOS_STATUS status;
6136 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6137
6138 //Stop Bss.
6139 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6140 if (VOS_IS_STATUS_SUCCESS(status))
6141 {
6142 hdd_hostapd_state_t *pHostapdState =
6143 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6144
6145 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6146
6147 if (!VOS_IS_STATUS_SUCCESS(status))
6148 {
6149 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006150 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006151 }
6152 }
6153 else
6154 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006155 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006156 }
6157 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6158
6159 if (eHAL_STATUS_FAILURE ==
6160 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6161 0, NULL, eANI_BOOLEAN_FALSE))
6162 {
6163 hddLog(LOGE,
6164 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006165 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006166 }
6167
6168 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6169 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6170 eANI_BOOLEAN_FALSE) )
6171 {
6172 hddLog(LOGE,
6173 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6174 }
6175
6176 // Reset WNI_CFG_PROBE_RSP Flags
6177 wlan_hdd_reset_prob_rspies(pAdapter);
6178 kfree(pAdapter->sessionCtx.ap.beacon);
6179 pAdapter->sessionCtx.ap.beacon = NULL;
6180 }
6181 mutex_unlock(&pHddCtx->sap_lock);
6182 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006183
Jeff Johnson295189b2012-06-20 16:38:30 -07006184 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006185#ifdef WLAN_OPEN_SOURCE
6186 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6187#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006188 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006189
Jeff Johnson295189b2012-06-20 16:38:30 -07006190 default:
6191 break;
6192 }
6193
6194 EXIT();
6195 return VOS_STATUS_SUCCESS;
6196}
6197
6198VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6199{
6200 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6201 VOS_STATUS status;
6202 hdd_adapter_t *pAdapter;
6203
6204 ENTER();
6205
6206 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6207
6208 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6209 {
6210 pAdapter = pAdapterNode->pAdapter;
6211 netif_tx_disable(pAdapter->dev);
6212 netif_carrier_off(pAdapter->dev);
6213
6214 hdd_stop_adapter( pHddCtx, pAdapter );
6215
6216 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6217 pAdapterNode = pNext;
6218 }
6219
6220 EXIT();
6221
6222 return VOS_STATUS_SUCCESS;
6223}
6224
6225VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6226{
6227 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6228 VOS_STATUS status;
6229 hdd_adapter_t *pAdapter;
6230
6231 ENTER();
6232
6233 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6234
6235 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6236 {
6237 pAdapter = pAdapterNode->pAdapter;
6238 netif_tx_disable(pAdapter->dev);
6239 netif_carrier_off(pAdapter->dev);
6240
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006241 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6242
Jeff Johnson295189b2012-06-20 16:38:30 -07006243 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306244 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6245 {
6246 hdd_wmm_adapter_close( pAdapter );
6247 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6248 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006249
6250 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6251 pAdapterNode = pNext;
6252 }
6253
6254 EXIT();
6255
6256 return VOS_STATUS_SUCCESS;
6257}
6258
6259VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6260{
6261 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6262 VOS_STATUS status;
6263 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306264 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006265
6266 ENTER();
6267
6268 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6269
6270 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6271 {
6272 pAdapter = pAdapterNode->pAdapter;
6273
6274 switch(pAdapter->device_mode)
6275 {
6276 case WLAN_HDD_INFRA_STATION:
6277 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006278 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306279
6280 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6281
Jeff Johnson295189b2012-06-20 16:38:30 -07006282 hdd_init_station_mode(pAdapter);
6283 /* Open the gates for HDD to receive Wext commands */
6284 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006285 pHddCtx->scan_info.mScanPending = FALSE;
6286 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006287
6288 //Trigger the initial scan
6289 hdd_wlan_initial_scan(pAdapter);
6290
6291 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306292 if (eConnectionState_Associated == connState ||
6293 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006294 {
6295 union iwreq_data wrqu;
6296 memset(&wrqu, '\0', sizeof(wrqu));
6297 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6298 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6299 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006300 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006301
Jeff Johnson295189b2012-06-20 16:38:30 -07006302 /* indicate disconnected event to nl80211 */
6303 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6304 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006305 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306306 else if (eConnectionState_Connecting == connState)
6307 {
6308 /*
6309 * Indicate connect failure to supplicant if we were in the
6310 * process of connecting
6311 */
6312 cfg80211_connect_result(pAdapter->dev, NULL,
6313 NULL, 0, NULL, 0,
6314 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6315 GFP_KERNEL);
6316 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006317 break;
6318
6319 case WLAN_HDD_SOFTAP:
6320 /* softAP can handle SSR */
6321 break;
6322
6323 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006324 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006325 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006326 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006327 break;
6328
6329 case WLAN_HDD_MONITOR:
6330 /* monitor interface start */
6331 break;
6332 default:
6333 break;
6334 }
6335
6336 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6337 pAdapterNode = pNext;
6338 }
6339
6340 EXIT();
6341
6342 return VOS_STATUS_SUCCESS;
6343}
6344
6345VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6346{
6347 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6348 hdd_adapter_t *pAdapter;
6349 VOS_STATUS status;
6350 v_U32_t roamId;
6351
6352 ENTER();
6353
6354 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6355
6356 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6357 {
6358 pAdapter = pAdapterNode->pAdapter;
6359
6360 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6361 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6362 {
6363 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6364 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6365
6366 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6367 init_completion(&pAdapter->disconnect_comp_var);
6368 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6369 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6370
6371 wait_for_completion_interruptible_timeout(
6372 &pAdapter->disconnect_comp_var,
6373 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6374
6375 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6376 pHddCtx->isAmpAllowed = VOS_FALSE;
6377 sme_RoamConnect(pHddCtx->hHal,
6378 pAdapter->sessionId, &(pWextState->roamProfile),
6379 &roamId);
6380 }
6381
6382 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6383 pAdapterNode = pNext;
6384 }
6385
6386 EXIT();
6387
6388 return VOS_STATUS_SUCCESS;
6389}
6390
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006391void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6392{
6393 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6394 VOS_STATUS status;
6395 hdd_adapter_t *pAdapter;
6396 hdd_station_ctx_t *pHddStaCtx;
6397 hdd_ap_ctx_t *pHddApCtx;
6398 hdd_hostapd_state_t * pHostapdState;
6399 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6400 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6401 const char *p2pMode = "DEV";
6402 const char *ccMode = "Standalone";
6403 int n;
6404
6405 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6406 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6407 {
6408 pAdapter = pAdapterNode->pAdapter;
6409 switch (pAdapter->device_mode) {
6410 case WLAN_HDD_INFRA_STATION:
6411 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6412 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6413 staChannel = pHddStaCtx->conn_info.operationChannel;
6414 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6415 }
6416 break;
6417 case WLAN_HDD_P2P_CLIENT:
6418 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6419 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6420 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6421 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6422 p2pMode = "CLI";
6423 }
6424 break;
6425 case WLAN_HDD_P2P_GO:
6426 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6427 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6428 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6429 p2pChannel = pHddApCtx->operatingChannel;
6430 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6431 }
6432 p2pMode = "GO";
6433 break;
6434 case WLAN_HDD_SOFTAP:
6435 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6436 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6437 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6438 apChannel = pHddApCtx->operatingChannel;
6439 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6440 }
6441 break;
6442 default:
6443 break;
6444 }
6445 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6446 pAdapterNode = pNext;
6447 }
6448 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6449 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6450 }
6451 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6452 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6453 if (p2pChannel > 0) {
6454 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6455 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6456 }
6457 if (apChannel > 0) {
6458 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6459 apChannel, MAC_ADDR_ARRAY(apBssid));
6460 }
6461
6462 if (p2pChannel > 0 && apChannel > 0) {
6463 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6464 }
6465}
6466
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006467bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006468{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006469 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006470}
6471
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006472/* Once SSR is disabled then it cannot be set. */
6473void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006474{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006475 if (HDD_SSR_DISABLED == isSsrRequired)
6476 return;
6477
Jeff Johnson295189b2012-06-20 16:38:30 -07006478 isSsrRequired = value;
6479}
6480
6481VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6482 hdd_adapter_list_node_t** ppAdapterNode)
6483{
6484 VOS_STATUS status;
6485 spin_lock(&pHddCtx->hddAdapters.lock);
6486 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6487 (hdd_list_node_t**) ppAdapterNode );
6488 spin_unlock(&pHddCtx->hddAdapters.lock);
6489 return status;
6490}
6491
6492VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6493 hdd_adapter_list_node_t* pAdapterNode,
6494 hdd_adapter_list_node_t** pNextAdapterNode)
6495{
6496 VOS_STATUS status;
6497 spin_lock(&pHddCtx->hddAdapters.lock);
6498 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6499 (hdd_list_node_t*) pAdapterNode,
6500 (hdd_list_node_t**)pNextAdapterNode );
6501
6502 spin_unlock(&pHddCtx->hddAdapters.lock);
6503 return status;
6504}
6505
6506VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6507 hdd_adapter_list_node_t* pAdapterNode)
6508{
6509 VOS_STATUS status;
6510 spin_lock(&pHddCtx->hddAdapters.lock);
6511 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6512 &pAdapterNode->node );
6513 spin_unlock(&pHddCtx->hddAdapters.lock);
6514 return status;
6515}
6516
6517VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6518 hdd_adapter_list_node_t** ppAdapterNode)
6519{
6520 VOS_STATUS status;
6521 spin_lock(&pHddCtx->hddAdapters.lock);
6522 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6523 (hdd_list_node_t**) ppAdapterNode );
6524 spin_unlock(&pHddCtx->hddAdapters.lock);
6525 return status;
6526}
6527
6528VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6529 hdd_adapter_list_node_t* pAdapterNode)
6530{
6531 VOS_STATUS status;
6532 spin_lock(&pHddCtx->hddAdapters.lock);
6533 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6534 (hdd_list_node_t*) pAdapterNode );
6535 spin_unlock(&pHddCtx->hddAdapters.lock);
6536 return status;
6537}
6538
6539VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6540 hdd_adapter_list_node_t* pAdapterNode)
6541{
6542 VOS_STATUS status;
6543 spin_lock(&pHddCtx->hddAdapters.lock);
6544 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6545 (hdd_list_node_t*) pAdapterNode );
6546 spin_unlock(&pHddCtx->hddAdapters.lock);
6547 return status;
6548}
6549
6550hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6551 tSirMacAddr macAddr )
6552{
6553 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6554 hdd_adapter_t *pAdapter;
6555 VOS_STATUS status;
6556
6557 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6558
6559 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6560 {
6561 pAdapter = pAdapterNode->pAdapter;
6562
6563 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6564 macAddr, sizeof(tSirMacAddr) ) )
6565 {
6566 return pAdapter;
6567 }
6568 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6569 pAdapterNode = pNext;
6570 }
6571
6572 return NULL;
6573
6574}
6575
6576hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6577{
6578 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6579 hdd_adapter_t *pAdapter;
6580 VOS_STATUS status;
6581
6582 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6583
6584 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6585 {
6586 pAdapter = pAdapterNode->pAdapter;
6587
6588 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6589 IFNAMSIZ ) )
6590 {
6591 return pAdapter;
6592 }
6593 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6594 pAdapterNode = pNext;
6595 }
6596
6597 return NULL;
6598
6599}
6600
6601hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6602{
6603 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6604 hdd_adapter_t *pAdapter;
6605 VOS_STATUS status;
6606
6607 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6608
6609 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6610 {
6611 pAdapter = pAdapterNode->pAdapter;
6612
6613 if( pAdapter && (mode == pAdapter->device_mode) )
6614 {
6615 return pAdapter;
6616 }
6617 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6618 pAdapterNode = pNext;
6619 }
6620
6621 return NULL;
6622
6623}
6624
6625//Remove this function later
6626hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6627{
6628 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6629 hdd_adapter_t *pAdapter;
6630 VOS_STATUS status;
6631
6632 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6633
6634 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6635 {
6636 pAdapter = pAdapterNode->pAdapter;
6637
6638 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6639 {
6640 return pAdapter;
6641 }
6642
6643 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6644 pAdapterNode = pNext;
6645 }
6646
6647 return NULL;
6648
6649}
6650
Jeff Johnson295189b2012-06-20 16:38:30 -07006651/**---------------------------------------------------------------------------
6652
6653 \brief hdd_set_monitor_tx_adapter() -
6654
6655 This API initializes the adapter to be used while transmitting on monitor
6656 adapter.
6657
6658 \param - pHddCtx - Pointer to the HDD context.
6659 pAdapter - Adapter that will used for TX. This can be NULL.
6660 \return - None.
6661 --------------------------------------------------------------------------*/
6662void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6663{
6664 hdd_adapter_t *pMonAdapter;
6665
6666 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6667
6668 if( NULL != pMonAdapter )
6669 {
6670 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6671 }
6672}
Jeff Johnson295189b2012-06-20 16:38:30 -07006673/**---------------------------------------------------------------------------
6674
6675 \brief hdd_select_queue() -
6676
6677 This API returns the operating channel of the requested device mode
6678
6679 \param - pHddCtx - Pointer to the HDD context.
6680 - mode - Device mode for which operating channel is required
6681 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6682 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6683 \return - channel number. "0" id the requested device is not found OR it is not connected.
6684 --------------------------------------------------------------------------*/
6685v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6686{
6687 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6688 VOS_STATUS status;
6689 hdd_adapter_t *pAdapter;
6690 v_U8_t operatingChannel = 0;
6691
6692 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6693
6694 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6695 {
6696 pAdapter = pAdapterNode->pAdapter;
6697
6698 if( mode == pAdapter->device_mode )
6699 {
6700 switch(pAdapter->device_mode)
6701 {
6702 case WLAN_HDD_INFRA_STATION:
6703 case WLAN_HDD_P2P_CLIENT:
6704 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6705 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6706 break;
6707 case WLAN_HDD_SOFTAP:
6708 case WLAN_HDD_P2P_GO:
6709 /*softap connection info */
6710 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6711 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6712 break;
6713 default:
6714 break;
6715 }
6716
6717 break; //Found the device of interest. break the loop
6718 }
6719
6720 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6721 pAdapterNode = pNext;
6722 }
6723 return operatingChannel;
6724}
6725
6726#ifdef WLAN_FEATURE_PACKET_FILTERING
6727/**---------------------------------------------------------------------------
6728
6729 \brief hdd_set_multicast_list() -
6730
6731 This used to set the multicast address list.
6732
6733 \param - dev - Pointer to the WLAN device.
6734 - skb - Pointer to OS packet (sk_buff).
6735 \return - success/fail
6736
6737 --------------------------------------------------------------------------*/
6738static void hdd_set_multicast_list(struct net_device *dev)
6739{
6740 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006741 int mc_count;
6742 int i = 0;
6743 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306744
6745 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006746 {
6747 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306748 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006749 return;
6750 }
6751
6752 if (dev->flags & IFF_ALLMULTI)
6753 {
6754 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006755 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306756 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006757 }
6758 else
6759 {
6760 mc_count = netdev_mc_count(dev);
6761 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006762 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006763 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6764 {
6765 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006766 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306767 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006768 return;
6769 }
6770
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306771 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006772
6773 netdev_for_each_mc_addr(ha, dev) {
6774 if (i == mc_count)
6775 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306776 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6777 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
6778 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006779 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306780 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006781 i++;
6782 }
6783 }
6784 return;
6785}
6786#endif
6787
6788/**---------------------------------------------------------------------------
6789
6790 \brief hdd_select_queue() -
6791
6792 This function is registered with the Linux OS for network
6793 core to decide which queue to use first.
6794
6795 \param - dev - Pointer to the WLAN device.
6796 - skb - Pointer to OS packet (sk_buff).
6797 \return - ac, Queue Index/access category corresponding to UP in IP header
6798
6799 --------------------------------------------------------------------------*/
6800v_U16_t hdd_select_queue(struct net_device *dev,
6801 struct sk_buff *skb)
6802{
6803 return hdd_wmm_select_queue(dev, skb);
6804}
6805
6806
6807/**---------------------------------------------------------------------------
6808
6809 \brief hdd_wlan_initial_scan() -
6810
6811 This function triggers the initial scan
6812
6813 \param - pAdapter - Pointer to the HDD adapter.
6814
6815 --------------------------------------------------------------------------*/
6816void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6817{
6818 tCsrScanRequest scanReq;
6819 tCsrChannelInfo channelInfo;
6820 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006821 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006822 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6823
6824 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6825 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6826 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6827
6828 if(sme_Is11dSupported(pHddCtx->hHal))
6829 {
6830 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6831 if ( HAL_STATUS_SUCCESS( halStatus ) )
6832 {
6833 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6834 if( !scanReq.ChannelInfo.ChannelList )
6835 {
6836 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6837 vos_mem_free(channelInfo.ChannelList);
6838 return;
6839 }
6840 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6841 channelInfo.numOfChannels);
6842 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6843 vos_mem_free(channelInfo.ChannelList);
6844 }
6845
6846 scanReq.scanType = eSIR_PASSIVE_SCAN;
6847 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6848 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6849 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6850 }
6851 else
6852 {
6853 scanReq.scanType = eSIR_ACTIVE_SCAN;
6854 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6855 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6856 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6857 }
6858
6859 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6860 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6861 {
6862 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6863 __func__, halStatus );
6864 }
6865
6866 if(sme_Is11dSupported(pHddCtx->hHal))
6867 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6868}
6869
6870struct fullPowerContext
6871{
6872 struct completion completion;
6873 unsigned int magic;
6874};
6875#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6876
6877/**---------------------------------------------------------------------------
6878
6879 \brief hdd_full_power_callback() - HDD full power callback function
6880
6881 This is the function invoked by SME to inform the result of a full power
6882 request issued by HDD
6883
6884 \param - callbackcontext - Pointer to cookie
6885 \param - status - result of request
6886
6887 \return - None
6888
6889 --------------------------------------------------------------------------*/
6890static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6891{
6892 struct fullPowerContext *pContext = callbackContext;
6893
6894 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306895 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006896
6897 if (NULL == callbackContext)
6898 {
6899 hddLog(VOS_TRACE_LEVEL_ERROR,
6900 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006901 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006902 return;
6903 }
6904
6905 /* there is a race condition that exists between this callback function
6906 and the caller since the caller could time out either before or
6907 while this code is executing. we'll assume the timeout hasn't
6908 occurred, but we'll verify that right before we save our work */
6909
6910 if (POWER_CONTEXT_MAGIC != pContext->magic)
6911 {
6912 /* the caller presumably timed out so there is nothing we can do */
6913 hddLog(VOS_TRACE_LEVEL_WARN,
6914 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006915 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006916 return;
6917 }
6918
6919 /* the race is on. caller could have timed out immediately after
6920 we verified the magic, but if so, caller will wait a short time
6921 for us to notify the caller, so the context will stay valid */
6922 complete(&pContext->completion);
6923}
6924
6925/**---------------------------------------------------------------------------
6926
6927 \brief hdd_wlan_exit() - HDD WLAN exit function
6928
6929 This is the driver exit point (invoked during rmmod)
6930
6931 \param - pHddCtx - Pointer to the HDD Context
6932
6933 \return - None
6934
6935 --------------------------------------------------------------------------*/
6936void hdd_wlan_exit(hdd_context_t *pHddCtx)
6937{
6938 eHalStatus halStatus;
6939 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6940 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306941 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006942 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006943 struct fullPowerContext powerContext;
6944 long lrc;
6945
6946 ENTER();
6947
Jeff Johnson88ba7742013-02-27 14:36:02 -08006948 if (VOS_FTM_MODE != hdd_get_conparam())
6949 {
6950 // Unloading, restart logic is no more required.
6951 wlan_hdd_restart_deinit(pHddCtx);
6952 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006953
Jeff Johnson295189b2012-06-20 16:38:30 -07006954 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006955 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006956 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006957 {
6958 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6959 WLAN_HDD_INFRA_STATION);
6960 if (pAdapter == NULL)
6961 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6962
6963 if (pAdapter != NULL)
6964 {
6965 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6966 hdd_UnregisterWext(pAdapter->dev);
6967 }
6968 }
6969 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006970
Jeff Johnson295189b2012-06-20 16:38:30 -07006971 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006972 {
6973 wlan_hdd_ftm_close(pHddCtx);
6974 goto free_hdd_ctx;
6975 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006976 //Stop the Interface TX queue.
6977 //netif_tx_disable(pWlanDev);
6978 //netif_carrier_off(pWlanDev);
6979
Jeff Johnson295189b2012-06-20 16:38:30 -07006980 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6981 {
6982 pAdapter = hdd_get_adapter(pHddCtx,
6983 WLAN_HDD_SOFTAP);
6984 }
6985 else
6986 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006987 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006988 {
6989 pAdapter = hdd_get_adapter(pHddCtx,
6990 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006991 if (pAdapter == NULL)
6992 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07006993 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006994 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006995 /* DeRegister with platform driver as client for Suspend/Resume */
6996 vosStatus = hddDeregisterPmOps(pHddCtx);
6997 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6998 {
6999 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7000 VOS_ASSERT(0);
7001 }
7002
7003 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7004 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7005 {
7006 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7007 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007008
7009 // Cancel any outstanding scan requests. We are about to close all
7010 // of our adapters, but an adapter structure is what SME passes back
7011 // to our callback function. Hence if there are any outstanding scan
7012 // requests then there is a race condition between when the adapter
7013 // is closed and when the callback is invoked. We try to resolve that
7014 // race condition here by canceling any outstanding scans before we
7015 // close the adapters.
7016 // Note that the scans may be cancelled in an asynchronous manner, so
7017 // ideally there needs to be some kind of synchronization. Rather than
7018 // introduce a new synchronization here, we will utilize the fact that
7019 // we are about to Request Full Power, and since that is synchronized,
7020 // the expectation is that by the time Request Full Power has completed,
7021 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007022 if (NULL != pAdapter)
7023 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
7024 else
7025 hddLog(VOS_TRACE_LEVEL_ERROR,
7026 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007027
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007028 //Stop the traffic monitor timer
7029 if ( VOS_TIMER_STATE_RUNNING ==
7030 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7031 {
7032 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7033 }
7034
7035 // Destroy the traffic monitor timer
7036 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7037 &pHddCtx->tx_rx_trafficTmr)))
7038 {
7039 hddLog(VOS_TRACE_LEVEL_ERROR,
7040 "%s: Cannot deallocate Traffic monitor timer", __func__);
7041 }
7042
Jeff Johnson295189b2012-06-20 16:38:30 -07007043 //Disable IMPS/BMPS as we do not want the device to enter any power
7044 //save mode during shutdown
7045 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7046 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7047 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7048
7049 //Ensure that device is in full power as we will touch H/W during vos_Stop
7050 init_completion(&powerContext.completion);
7051 powerContext.magic = POWER_CONTEXT_MAGIC;
7052
7053 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7054 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7055
7056 if (eHAL_STATUS_SUCCESS != halStatus)
7057 {
7058 if (eHAL_STATUS_PMC_PENDING == halStatus)
7059 {
7060 /* request was sent -- wait for the response */
7061 lrc = wait_for_completion_interruptible_timeout(
7062 &powerContext.completion,
7063 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
7064 /* either we have a response or we timed out
7065 either way, first invalidate our magic */
7066 powerContext.magic = 0;
7067 if (lrc <= 0)
7068 {
7069 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007070 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007071 /* there is a race condition such that the callback
7072 function could be executing at the same time we are. of
7073 primary concern is if the callback function had already
7074 verified the "magic" but hasn't yet set the completion
7075 variable. Since the completion variable is on our
7076 stack, we'll delay just a bit to make sure the data is
7077 still valid if that is the case */
7078 msleep(50);
7079 }
7080 }
7081 else
7082 {
7083 hddLog(VOS_TRACE_LEVEL_ERROR,
7084 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007085 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007086 VOS_ASSERT(0);
7087 /* continue -- need to clean up as much as possible */
7088 }
7089 }
7090
Yue Ma0d4891e2013-08-06 17:01:45 -07007091 hdd_debugfs_exit(pHddCtx);
7092
Jeff Johnson295189b2012-06-20 16:38:30 -07007093 // Unregister the Net Device Notifier
7094 unregister_netdevice_notifier(&hdd_netdev_notifier);
7095
Jeff Johnson295189b2012-06-20 16:38:30 -07007096 hdd_stop_all_adapters( pHddCtx );
7097
Jeff Johnson295189b2012-06-20 16:38:30 -07007098#ifdef WLAN_BTAMP_FEATURE
7099 vosStatus = WLANBAP_Stop(pVosContext);
7100 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7101 {
7102 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7103 "%s: Failed to stop BAP",__func__);
7104 }
7105#endif //WLAN_BTAMP_FEATURE
7106
7107 //Stop all the modules
7108 vosStatus = vos_stop( pVosContext );
7109 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7110 {
7111 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7112 "%s: Failed to stop VOSS",__func__);
7113 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7114 }
7115
Jeff Johnson295189b2012-06-20 16:38:30 -07007116 //Assert Deep sleep signal now to put Libra HW in lowest power state
7117 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7118 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7119
7120 //Vote off any PMIC voltage supplies
7121 vos_chipPowerDown(NULL, NULL, NULL);
7122
7123 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7124
Leo Chang59cdc7e2013-07-10 10:08:21 -07007125
Jeff Johnson295189b2012-06-20 16:38:30 -07007126 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007127 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007128
7129 //Close the scheduler before calling vos_close to make sure no thread is
7130 // scheduled after the each module close is called i.e after all the data
7131 // structures are freed.
7132 vosStatus = vos_sched_close( pVosContext );
7133 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7134 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7135 "%s: Failed to close VOSS Scheduler",__func__);
7136 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7137 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007138#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007139#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7140 /* Destroy the wake lock */
7141 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7142#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007143 /* Destroy the wake lock */
7144 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007145#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007146
7147 //Close VOSS
7148 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7149 vos_close(pVosContext);
7150
Jeff Johnson295189b2012-06-20 16:38:30 -07007151 //Close Watchdog
7152 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7153 vos_watchdog_close(pVosContext);
7154
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307155 //Clean up HDD Nlink Service
7156 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007157#ifdef WLAN_KD_READY_NOTIFIER
7158 nl_srv_exit(pHddCtx->ptt_pid);
7159#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307160 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007161#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307162
Jeff Johnson295189b2012-06-20 16:38:30 -07007163 /* Cancel the vote for XO Core ON.
7164 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7165 * exited at this point
7166 */
7167 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
7168 " when WLAN is turned OFF\n");
7169 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7170 {
7171 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7172 " Not returning failure."
7173 " Power consumed will be high\n");
7174 }
7175
7176 hdd_close_all_adapters( pHddCtx );
7177
7178
7179 //Free up dynamically allocated members inside HDD Adapter
7180 kfree(pHddCtx->cfg_ini);
7181 pHddCtx->cfg_ini= NULL;
7182
7183 /* free the power on lock from platform driver */
7184 if (free_riva_power_on_lock("wlan"))
7185 {
7186 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7187 __func__);
7188 }
7189
Jeff Johnson88ba7742013-02-27 14:36:02 -08007190free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007191 /* FTM mode, WIPHY did not registered
7192 If un-register here, system crash will happen */
7193 if (VOS_FTM_MODE != hdd_get_conparam())
7194 {
7195 wiphy_unregister(wiphy) ;
7196 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007197 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007198 if (hdd_is_ssr_required())
7199 {
7200 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007201 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007202 msleep(5000);
7203 }
7204 hdd_set_ssr_required (VOS_FALSE);
7205}
7206
7207
7208/**---------------------------------------------------------------------------
7209
7210 \brief hdd_update_config_from_nv() - Function to update the contents of
7211 the running configuration with parameters taken from NV storage
7212
7213 \param - pHddCtx - Pointer to the HDD global context
7214
7215 \return - VOS_STATUS_SUCCESS if successful
7216
7217 --------------------------------------------------------------------------*/
7218static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7219{
Jeff Johnson295189b2012-06-20 16:38:30 -07007220 v_BOOL_t itemIsValid = VOS_FALSE;
7221 VOS_STATUS status;
7222 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7223 v_U8_t macLoop;
7224
7225 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7226 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7227 if(status != VOS_STATUS_SUCCESS)
7228 {
7229 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
7230 return VOS_STATUS_E_FAILURE;
7231 }
7232
7233 if (itemIsValid == VOS_TRUE)
7234 {
7235 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
7236 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7237 VOS_MAX_CONCURRENCY_PERSONA);
7238 if(status != VOS_STATUS_SUCCESS)
7239 {
7240 /* Get MAC from NV fail, not update CFG info
7241 * INI MAC value will be used for MAC setting */
7242 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
7243 return VOS_STATUS_E_FAILURE;
7244 }
7245
7246 /* If first MAC is not valid, treat all others are not valid
7247 * Then all MACs will be got from ini file */
7248 if(vos_is_macaddr_zero(&macFromNV[0]))
7249 {
7250 /* MAC address in NV file is not configured yet */
7251 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7252 return VOS_STATUS_E_INVAL;
7253 }
7254
7255 /* Get MAC address from NV, update CFG info */
7256 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7257 {
7258 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7259 {
7260 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
7261 /* This MAC is not valid, skip it
7262 * This MAC will be got from ini file */
7263 }
7264 else
7265 {
7266 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7267 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7268 VOS_MAC_ADDR_SIZE);
7269 }
7270 }
7271 }
7272 else
7273 {
7274 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7275 return VOS_STATUS_E_FAILURE;
7276 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007277
Jeff Johnson295189b2012-06-20 16:38:30 -07007278
7279 return VOS_STATUS_SUCCESS;
7280}
7281
7282/**---------------------------------------------------------------------------
7283
7284 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7285
7286 \param - pAdapter - Pointer to the HDD
7287
7288 \return - None
7289
7290 --------------------------------------------------------------------------*/
7291VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7292{
7293 eHalStatus halStatus;
7294 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307295 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007296
Jeff Johnson295189b2012-06-20 16:38:30 -07007297
7298 // Send ready indication to the HDD. This will kick off the MAC
7299 // into a 'running' state and should kick off an initial scan.
7300 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7301 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7302 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307303 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007304 "code %08d [x%08x]",__func__, halStatus, halStatus );
7305 return VOS_STATUS_E_FAILURE;
7306 }
7307
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307308 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007309 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7310 // And RIVA will crash
7311 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7312 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307313 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7314 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7315
7316
Jeff Johnson295189b2012-06-20 16:38:30 -07007317 return VOS_STATUS_SUCCESS;
7318}
7319
Jeff Johnson295189b2012-06-20 16:38:30 -07007320/* wake lock APIs for HDD */
7321void hdd_prevent_suspend(void)
7322{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007323#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007324 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007325#else
7326 wcnss_prevent_suspend();
7327#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007328}
7329
7330void hdd_allow_suspend(void)
7331{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007332#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007333 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007334#else
7335 wcnss_allow_suspend();
7336#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007337}
7338
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007339void hdd_allow_suspend_timeout(v_U32_t timeout)
7340{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007341#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007342 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007343#else
7344 /* Do nothing as there is no API in wcnss for timeout*/
7345#endif
7346}
7347
Jeff Johnson295189b2012-06-20 16:38:30 -07007348/**---------------------------------------------------------------------------
7349
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007350 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7351 information between Host and Riva
7352
7353 This function gets reported version of FW
7354 It also finds the version of Riva headers used to compile the host
7355 It compares the above two and prints a warning if they are different
7356 It gets the SW and HW version string
7357 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7358 indicating the features they support through a bitmap
7359
7360 \param - pHddCtx - Pointer to HDD context
7361
7362 \return - void
7363
7364 --------------------------------------------------------------------------*/
7365
7366void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7367{
7368
7369 tSirVersionType versionCompiled;
7370 tSirVersionType versionReported;
7371 tSirVersionString versionString;
7372 tANI_U8 fwFeatCapsMsgSupported = 0;
7373 VOS_STATUS vstatus;
7374
7375 /* retrieve and display WCNSS version information */
7376 do {
7377
7378 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7379 &versionCompiled);
7380 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7381 {
7382 hddLog(VOS_TRACE_LEVEL_FATAL,
7383 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007384 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007385 break;
7386 }
7387
7388 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7389 &versionReported);
7390 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7391 {
7392 hddLog(VOS_TRACE_LEVEL_FATAL,
7393 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007394 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007395 break;
7396 }
7397
7398 if ((versionCompiled.major != versionReported.major) ||
7399 (versionCompiled.minor != versionReported.minor) ||
7400 (versionCompiled.version != versionReported.version) ||
7401 (versionCompiled.revision != versionReported.revision))
7402 {
7403 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7404 "Host expected %u.%u.%u.%u\n",
7405 WLAN_MODULE_NAME,
7406 (int)versionReported.major,
7407 (int)versionReported.minor,
7408 (int)versionReported.version,
7409 (int)versionReported.revision,
7410 (int)versionCompiled.major,
7411 (int)versionCompiled.minor,
7412 (int)versionCompiled.version,
7413 (int)versionCompiled.revision);
7414 }
7415 else
7416 {
7417 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7418 WLAN_MODULE_NAME,
7419 (int)versionReported.major,
7420 (int)versionReported.minor,
7421 (int)versionReported.version,
7422 (int)versionReported.revision);
7423 }
7424
7425 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7426 versionString,
7427 sizeof(versionString));
7428 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7429 {
7430 hddLog(VOS_TRACE_LEVEL_FATAL,
7431 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007432 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007433 break;
7434 }
7435
7436 pr_info("%s: WCNSS software version %s\n",
7437 WLAN_MODULE_NAME, versionString);
7438
7439 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7440 versionString,
7441 sizeof(versionString));
7442 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7443 {
7444 hddLog(VOS_TRACE_LEVEL_FATAL,
7445 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007446 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007447 break;
7448 }
7449
7450 pr_info("%s: WCNSS hardware version %s\n",
7451 WLAN_MODULE_NAME, versionString);
7452
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007453 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7454 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007455 send the message only if it the riva is 1.1
7456 minor numbers for different riva branches:
7457 0 -> (1.0)Mainline Build
7458 1 -> (1.1)Mainline Build
7459 2->(1.04) Stability Build
7460 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007461 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007462 ((versionReported.minor>=1) && (versionReported.version>=1)))
7463 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7464 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007465
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007466 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007467 {
7468#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7469 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7470 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7471#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007472 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7473 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7474 {
7475 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7476 }
7477
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007478 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007479 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007480
7481 } while (0);
7482
7483}
7484
7485/**---------------------------------------------------------------------------
7486
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307487 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7488
7489 \param - pHddCtx - Pointer to the hdd context
7490
7491 \return - true if hardware supports 5GHz
7492
7493 --------------------------------------------------------------------------*/
7494static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7495{
7496 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7497 * then hardware support 5Ghz.
7498 */
7499 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7500 {
7501 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7502 return true;
7503 }
7504 else
7505 {
7506 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7507 __func__);
7508 return false;
7509 }
7510}
7511
7512
7513/**---------------------------------------------------------------------------
7514
Jeff Johnson295189b2012-06-20 16:38:30 -07007515 \brief hdd_wlan_startup() - HDD init function
7516
7517 This is the driver startup code executed once a WLAN device has been detected
7518
7519 \param - dev - Pointer to the underlying device
7520
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007521 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007522
7523 --------------------------------------------------------------------------*/
7524
7525int hdd_wlan_startup(struct device *dev )
7526{
7527 VOS_STATUS status;
7528 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007529 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007530 hdd_context_t *pHddCtx = NULL;
7531 v_CONTEXT_t pVosContext= NULL;
7532#ifdef WLAN_BTAMP_FEATURE
7533 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7534 WLANBAP_ConfigType btAmpConfig;
7535 hdd_config_t *pConfig;
7536#endif
7537 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007538 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007539
7540 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007541 /*
7542 * cfg80211: wiphy allocation
7543 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307544 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007545
7546 if(wiphy == NULL)
7547 {
7548 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007549 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007550 }
7551
7552 pHddCtx = wiphy_priv(wiphy);
7553
Jeff Johnson295189b2012-06-20 16:38:30 -07007554 //Initialize the adapter context to zeros.
7555 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7556
Jeff Johnson295189b2012-06-20 16:38:30 -07007557 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007558 hdd_prevent_suspend();
7559 pHddCtx->isLoadUnloadInProgress = TRUE;
7560
7561 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7562
7563 /*Get vos context here bcoz vos_open requires it*/
7564 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7565
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007566 if(pVosContext == NULL)
7567 {
7568 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7569 goto err_free_hdd_context;
7570 }
7571
Jeff Johnson295189b2012-06-20 16:38:30 -07007572 //Save the Global VOSS context in adapter context for future.
7573 pHddCtx->pvosContext = pVosContext;
7574
7575 //Save the adapter context in global context for future.
7576 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7577
Jeff Johnson295189b2012-06-20 16:38:30 -07007578 pHddCtx->parent_dev = dev;
7579
7580 init_completion(&pHddCtx->full_pwr_comp_var);
7581 init_completion(&pHddCtx->standby_comp_var);
7582 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007583 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007584 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307585 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007586
7587#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007588 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007589#else
7590 init_completion(&pHddCtx->driver_crda_req);
7591#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007592
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307593 spin_lock_init(&pHddCtx->schedScan_lock);
7594
Jeff Johnson295189b2012-06-20 16:38:30 -07007595 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7596
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307597#ifdef FEATURE_WLAN_TDLS
7598 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7599 * invoked by other instances also) to protect the concurrent
7600 * access for the Adapters by TDLS module.
7601 */
7602 mutex_init(&pHddCtx->tdls_lock);
7603#endif
7604
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307605 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007606 // Load all config first as TL config is needed during vos_open
7607 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7608 if(pHddCtx->cfg_ini == NULL)
7609 {
7610 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7611 goto err_free_hdd_context;
7612 }
7613
7614 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7615
7616 // Read and parse the qcom_cfg.ini file
7617 status = hdd_parse_config_ini( pHddCtx );
7618 if ( VOS_STATUS_SUCCESS != status )
7619 {
7620 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7621 __func__, WLAN_INI_FILE);
7622 goto err_config;
7623 }
7624
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307625 /* INI has been read, initialise the configuredMcastBcastFilter with
7626 * INI value as this will serve as the default value
7627 */
7628 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7629 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7630 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307631
7632 if (false == hdd_is_5g_supported(pHddCtx))
7633 {
7634 //5Ghz is not supported.
7635 if (1 != pHddCtx->cfg_ini->nBandCapability)
7636 {
7637 hddLog(VOS_TRACE_LEVEL_INFO,
7638 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7639 pHddCtx->cfg_ini->nBandCapability = 1;
7640 }
7641 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307642
7643 /* If SNR Monitoring is enabled, FW has to parse all beacons
7644 * for calcaluting and storing the average SNR, so set Nth beacon
7645 * filter to 1 to enable FW to parse all the beaocons
7646 */
7647 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7648 {
7649 /* The log level is deliberately set to WARN as overriding
7650 * nthBeaconFilter to 1 will increase power cosumption and this
7651 * might just prove helpful to detect the power issue.
7652 */
7653 hddLog(VOS_TRACE_LEVEL_WARN,
7654 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7655 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7656 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007657 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307658 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007659 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307660 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007661 {
7662 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307663 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7664 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007665 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007666
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007667 // Update VOS trace levels based upon the cfg.ini
7668 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7669 pHddCtx->cfg_ini->vosTraceEnableBAP);
7670 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7671 pHddCtx->cfg_ini->vosTraceEnableTL);
7672 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7673 pHddCtx->cfg_ini->vosTraceEnableWDI);
7674 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7675 pHddCtx->cfg_ini->vosTraceEnableHDD);
7676 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7677 pHddCtx->cfg_ini->vosTraceEnableSME);
7678 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7679 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307680 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7681 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007682 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7683 pHddCtx->cfg_ini->vosTraceEnableWDA);
7684 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7685 pHddCtx->cfg_ini->vosTraceEnableSYS);
7686 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7687 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007688 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7689 pHddCtx->cfg_ini->vosTraceEnableSAP);
7690 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7691 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007692
Jeff Johnson295189b2012-06-20 16:38:30 -07007693 // Update WDI trace levels based upon the cfg.ini
7694 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7695 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7696 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7697 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7698 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7699 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7700 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7701 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007702
Jeff Johnson88ba7742013-02-27 14:36:02 -08007703 if (VOS_FTM_MODE == hdd_get_conparam())
7704 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007705 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7706 {
7707 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7708 goto err_free_hdd_context;
7709 }
7710 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7711 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007712 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007713
Jeff Johnson88ba7742013-02-27 14:36:02 -08007714 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007715 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7716 {
7717 status = vos_watchdog_open(pVosContext,
7718 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7719
7720 if(!VOS_IS_STATUS_SUCCESS( status ))
7721 {
7722 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307723 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007724 }
7725 }
7726
7727 pHddCtx->isLogpInProgress = FALSE;
7728 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7729
Jeff Johnson295189b2012-06-20 16:38:30 -07007730 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7731 if(!VOS_IS_STATUS_SUCCESS(status))
7732 {
7733 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007734 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007735 }
7736
Amar Singhala49cbc52013-10-08 18:37:44 -07007737#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007738 /* initialize the NV module. This is required so that
7739 we can initialize the channel information in wiphy
7740 from the NV.bin data. The channel information in
7741 wiphy needs to be initialized before wiphy registration */
7742
7743 status = vos_nv_open();
7744 if (!VOS_IS_STATUS_SUCCESS(status))
7745 {
7746 /* NV module cannot be initialized */
7747 hddLog( VOS_TRACE_LEVEL_FATAL,
7748 "%s: vos_nv_open failed", __func__);
7749 goto err_clkvote;
7750 }
7751
7752 status = vos_init_wiphy_from_nv_bin();
7753 if (!VOS_IS_STATUS_SUCCESS(status))
7754 {
7755 /* NV module cannot be initialized */
7756 hddLog( VOS_TRACE_LEVEL_FATAL,
7757 "%s: vos_init_wiphy failed", __func__);
7758 goto err_vos_nv_close;
7759 }
7760
Amar Singhala49cbc52013-10-08 18:37:44 -07007761 /* registration of wiphy dev with cfg80211 */
7762 if (0 > wlan_hdd_cfg80211_register(wiphy))
7763 {
7764 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07007765 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07007766 }
7767#endif
7768
Jeff Johnson295189b2012-06-20 16:38:30 -07007769 status = vos_open( &pVosContext, 0);
7770 if ( !VOS_IS_STATUS_SUCCESS( status ))
7771 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007772 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007773 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007774 }
7775
Jeff Johnson295189b2012-06-20 16:38:30 -07007776 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7777
7778 if ( NULL == pHddCtx->hHal )
7779 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007780 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007781 goto err_vosclose;
7782 }
7783
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007784 status = vos_preStart( pHddCtx->pvosContext );
7785 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7786 {
7787 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7788 goto err_vosclose;
7789 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007790
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007791 /* Note that the vos_preStart() sequence triggers the cfg download.
7792 The cfg download must occur before we update the SME config
7793 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007794 status = hdd_set_sme_config( pHddCtx );
7795
7796 if ( VOS_STATUS_SUCCESS != status )
7797 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007798 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7799 goto err_vosclose;
7800 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007801
7802 //Initialize the WMM module
7803 status = hdd_wmm_init(pHddCtx);
7804 if (!VOS_IS_STATUS_SUCCESS(status))
7805 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007806 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007807 goto err_vosclose;
7808 }
7809
Jeff Johnson295189b2012-06-20 16:38:30 -07007810 /* In the integrated architecture we update the configuration from
7811 the INI file and from NV before vOSS has been started so that
7812 the final contents are available to send down to the cCPU */
7813
7814 // Apply the cfg.ini to cfg.dat
7815 if (FALSE == hdd_update_config_dat(pHddCtx))
7816 {
7817 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7818 goto err_vosclose;
7819 }
7820
7821 // Apply the NV to cfg.dat
7822 /* Prima Update MAC address only at here */
7823 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7824 {
7825#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7826 /* There was not a valid set of MAC Addresses in NV. See if the
7827 default addresses were modified by the cfg.ini settings. If so,
7828 we'll use them, but if not, we'll autogenerate a set of MAC
7829 addresses based upon the device serial number */
7830
7831 static const v_MACADDR_t default_address =
7832 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7833 unsigned int serialno;
7834 int i;
7835
7836 serialno = wcnss_get_serial_number();
7837 if ((0 != serialno) &&
7838 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7839 sizeof(default_address))))
7840 {
7841 /* cfg.ini has the default address, invoke autogen logic */
7842
7843 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7844 bytes of the serial number that can be used to generate
7845 the other 3 bytes of the MAC address. Mask off all but
7846 the lower 3 bytes (this will also make sure we don't
7847 overflow in the next step) */
7848 serialno &= 0x00FFFFFF;
7849
7850 /* we need a unique address for each session */
7851 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7852
7853 /* autogen all addresses */
7854 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7855 {
7856 /* start with the entire default address */
7857 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7858 /* then replace the lower 3 bytes */
7859 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7860 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7861 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7862
7863 serialno++;
7864 }
7865
7866 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7867 MAC_ADDRESS_STR,
7868 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7869 }
7870 else
7871#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7872 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007873 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007874 "%s: Invalid MAC address in NV, using MAC from ini file "
7875 MAC_ADDRESS_STR, __func__,
7876 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7877 }
7878 }
7879 {
7880 eHalStatus halStatus;
7881 // Set the MAC Address
7882 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7883 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7884 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7885 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7886
7887 if (!HAL_STATUS_SUCCESS( halStatus ))
7888 {
7889 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7890 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007891 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007892 }
7893 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007894
7895 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7896 Note: Firmware image will be read and downloaded inside vos_start API */
7897 status = vos_start( pHddCtx->pvosContext );
7898 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7899 {
7900 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7901 goto err_vosclose;
7902 }
7903
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007904 /* Exchange capability info between Host and FW and also get versioning info from FW */
7905 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007906
7907 status = hdd_post_voss_start_config( pHddCtx );
7908 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7909 {
7910 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7911 __func__);
7912 goto err_vosstop;
7913 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007914
7915#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307916 wlan_hdd_cfg80211_update_reg_info( wiphy );
7917
7918 /* registration of wiphy dev with cfg80211 */
7919 if (0 > wlan_hdd_cfg80211_register(wiphy))
7920 {
7921 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7922 goto err_vosstop;
7923 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007924#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007925
Jeff Johnson295189b2012-06-20 16:38:30 -07007926 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7927 {
7928 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7929 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7930 }
7931 else
7932 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007933 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7934 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7935 if (pAdapter != NULL)
7936 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307937 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007938 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307939 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7940 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7941 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007942
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307943 /* Generate the P2P Device Address. This consists of the device's
7944 * primary MAC address with the locally administered bit set.
7945 */
7946 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007947 }
7948 else
7949 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307950 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7951 if (p2p_dev_addr != NULL)
7952 {
7953 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7954 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7955 }
7956 else
7957 {
7958 hddLog(VOS_TRACE_LEVEL_FATAL,
7959 "%s: Failed to allocate mac_address for p2p_device",
7960 __func__);
7961 goto err_close_adapter;
7962 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007963 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007964
7965 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7966 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7967 if ( NULL == pP2pAdapter )
7968 {
7969 hddLog(VOS_TRACE_LEVEL_FATAL,
7970 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007971 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007972 goto err_close_adapter;
7973 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007974 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007975 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007976
7977 if( pAdapter == NULL )
7978 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007979 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7980 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007981 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007982
Jeff Johnson295189b2012-06-20 16:38:30 -07007983#ifdef WLAN_BTAMP_FEATURE
7984 vStatus = WLANBAP_Open(pVosContext);
7985 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7986 {
7987 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7988 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007989 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007990 }
7991
7992 vStatus = BSL_Init(pVosContext);
7993 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7994 {
7995 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7996 "%s: Failed to Init BSL",__func__);
7997 goto err_bap_close;
7998 }
7999 vStatus = WLANBAP_Start(pVosContext);
8000 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8001 {
8002 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8003 "%s: Failed to start TL",__func__);
8004 goto err_bap_close;
8005 }
8006
8007 pConfig = pHddCtx->cfg_ini;
8008 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8009 status = WLANBAP_SetConfig(&btAmpConfig);
8010
8011#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008012
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008013#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8014 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8015 {
8016 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8017 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8018 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8019 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8020 }
8021#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008022#ifdef FEATURE_WLAN_SCAN_PNO
8023 /*SME must send channel update configuration to RIVA*/
8024 sme_UpdateChannelConfig(pHddCtx->hHal);
8025#endif
8026
Jeff Johnson295189b2012-06-20 16:38:30 -07008027 /* Register with platform driver as client for Suspend/Resume */
8028 status = hddRegisterPmOps(pHddCtx);
8029 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8030 {
8031 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8032#ifdef WLAN_BTAMP_FEATURE
8033 goto err_bap_stop;
8034#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008035 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008036#endif //WLAN_BTAMP_FEATURE
8037 }
8038
Yue Ma0d4891e2013-08-06 17:01:45 -07008039 /* Open debugfs interface */
8040 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8041 {
8042 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8043 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008044 }
8045
Jeff Johnson295189b2012-06-20 16:38:30 -07008046 /* Register TM level change handler function to the platform */
8047 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8048 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8049 {
8050 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8051 goto err_unregister_pmops;
8052 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008053
8054 /* register for riva power on lock to platform driver */
8055 if (req_riva_power_on_lock("wlan"))
8056 {
8057 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8058 __func__);
8059 goto err_unregister_pmops;
8060 }
8061
Jeff Johnson295189b2012-06-20 16:38:30 -07008062 // register net device notifier for device change notification
8063 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8064
8065 if(ret < 0)
8066 {
8067 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8068 goto err_free_power_on_lock;
8069 }
8070
8071 //Initialize the nlink service
8072 if(nl_srv_init() != 0)
8073 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308074 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008075 goto err_reg_netdev;
8076 }
8077
Leo Chang4ce1cc52013-10-21 18:27:15 -07008078#ifdef WLAN_KD_READY_NOTIFIER
8079 pHddCtx->kd_nl_init = 1;
8080#endif /* WLAN_KD_READY_NOTIFIER */
8081
Jeff Johnson295189b2012-06-20 16:38:30 -07008082 //Initialize the BTC service
8083 if(btc_activate_service(pHddCtx) != 0)
8084 {
8085 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8086 goto err_nl_srv;
8087 }
8088
8089#ifdef PTT_SOCK_SVC_ENABLE
8090 //Initialize the PTT service
8091 if(ptt_sock_activate_svc(pHddCtx) != 0)
8092 {
8093 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8094 goto err_nl_srv;
8095 }
8096#endif
8097
Jeff Johnson295189b2012-06-20 16:38:30 -07008098 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008099 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008100 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008101 /* Action frame registered in one adapter which will
8102 * applicable to all interfaces
8103 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008104 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008105 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008106
8107 mutex_init(&pHddCtx->sap_lock);
8108
8109 pHddCtx->isLoadUnloadInProgress = FALSE;
8110
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008111#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008112#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8113 /* Initialize the wake lcok */
8114 wake_lock_init(&pHddCtx->rx_wake_lock,
8115 WAKE_LOCK_SUSPEND,
8116 "qcom_rx_wakelock");
8117#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008118 /* Initialize the wake lcok */
8119 wake_lock_init(&pHddCtx->sap_wake_lock,
8120 WAKE_LOCK_SUSPEND,
8121 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008122#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008123
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008124 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8125 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008126
8127 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8128 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05308129
Jeff Johnsone7245742012-09-05 17:12:55 -07008130 // Initialize the restart logic
8131 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308132
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008133 //Register the traffic monitor timer now
8134 if ( pHddCtx->cfg_ini->dynSplitscan)
8135 {
8136 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8137 VOS_TIMER_TYPE_SW,
8138 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8139 (void *)pHddCtx);
8140 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008141 goto success;
8142
8143err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008144#ifdef WLAN_KD_READY_NOTIFIER
8145 nl_srv_exit(pHddCtx->ptt_pid);
8146#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008147 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008148#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008149err_reg_netdev:
8150 unregister_netdevice_notifier(&hdd_netdev_notifier);
8151
8152err_free_power_on_lock:
8153 free_riva_power_on_lock("wlan");
8154
8155err_unregister_pmops:
8156 hddDevTmUnregisterNotifyCallback(pHddCtx);
8157 hddDeregisterPmOps(pHddCtx);
8158
Yue Ma0d4891e2013-08-06 17:01:45 -07008159 hdd_debugfs_exit(pHddCtx);
8160
Jeff Johnson295189b2012-06-20 16:38:30 -07008161#ifdef WLAN_BTAMP_FEATURE
8162err_bap_stop:
8163 WLANBAP_Stop(pVosContext);
8164#endif
8165
8166#ifdef WLAN_BTAMP_FEATURE
8167err_bap_close:
8168 WLANBAP_Close(pVosContext);
8169#endif
8170
Jeff Johnson295189b2012-06-20 16:38:30 -07008171err_close_adapter:
8172 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008173
8174#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308175 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008176#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008177
8178err_vosstop:
8179 vos_stop(pVosContext);
8180
Amar Singhala49cbc52013-10-08 18:37:44 -07008181err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008182 status = vos_sched_close( pVosContext );
8183 if (!VOS_IS_STATUS_SUCCESS(status)) {
8184 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8185 "%s: Failed to close VOSS Scheduler", __func__);
8186 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8187 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008188 vos_close(pVosContext );
8189
8190err_wiphy_unregister:
8191
8192#ifdef CONFIG_ENABLE_LINUX_REG
8193 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07008194
Amar Singhal0a402232013-10-11 20:57:16 -07008195err_vos_nv_close:
8196
8197 vos_nv_close();
8198
Jeff Johnson295189b2012-06-20 16:38:30 -07008199err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008200#endif
8201
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008202 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008203
8204err_wdclose:
8205 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8206 vos_watchdog_close(pVosContext);
8207
Jeff Johnson295189b2012-06-20 16:38:30 -07008208err_config:
8209 kfree(pHddCtx->cfg_ini);
8210 pHddCtx->cfg_ini= NULL;
8211
8212err_free_hdd_context:
8213 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008214 wiphy_free(wiphy) ;
8215 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008216 VOS_BUG(1);
8217
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008218 if (hdd_is_ssr_required())
8219 {
8220 /* WDI timeout had happened during load, so SSR is needed here */
8221 subsystem_restart("wcnss");
8222 msleep(5000);
8223 }
8224 hdd_set_ssr_required (VOS_FALSE);
8225
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008226 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008227
8228success:
8229 EXIT();
8230 return 0;
8231}
8232
8233/**---------------------------------------------------------------------------
8234
Jeff Johnson32d95a32012-09-10 13:15:23 -07008235 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008236
Jeff Johnson32d95a32012-09-10 13:15:23 -07008237 This is the driver entry point - called in different timeline depending
8238 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008239
8240 \param - None
8241
8242 \return - 0 for success, non zero for failure
8243
8244 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008245static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008246{
8247 VOS_STATUS status;
8248 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008249 struct device *dev = NULL;
8250 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008251#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8252 int max_retries = 0;
8253#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008254
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308255#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8256 vos_wconn_trace_init();
8257#endif
8258
Jeff Johnson295189b2012-06-20 16:38:30 -07008259 ENTER();
8260
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008261#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008262 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008263#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008264
8265 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8266 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8267
8268 //Power Up Libra WLAN card first if not already powered up
8269 status = vos_chipPowerUp(NULL,NULL,NULL);
8270 if (!VOS_IS_STATUS_SUCCESS(status))
8271 {
8272 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8273 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308274#ifdef WLAN_OPEN_SOURCE
8275 wake_lock_destroy(&wlan_wake_lock);
8276#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008277 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008278 }
8279
Jeff Johnson295189b2012-06-20 16:38:30 -07008280#ifdef ANI_BUS_TYPE_PCI
8281
8282 dev = wcnss_wlan_get_device();
8283
8284#endif // ANI_BUS_TYPE_PCI
8285
8286#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008287
8288#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8289 /* wait until WCNSS driver downloads NV */
8290 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8291 msleep(1000);
8292 }
8293 if (max_retries >= 5) {
8294 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308295#ifdef WLAN_OPEN_SOURCE
8296 wake_lock_destroy(&wlan_wake_lock);
8297#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008298 return -ENODEV;
8299 }
8300#endif
8301
Jeff Johnson295189b2012-06-20 16:38:30 -07008302 dev = wcnss_wlan_get_device();
8303#endif // ANI_BUS_TYPE_PLATFORM
8304
8305
8306 do {
8307 if (NULL == dev) {
8308 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8309 ret_status = -1;
8310 break;
8311 }
8312
8313#ifdef MEMORY_DEBUG
8314 vos_mem_init();
8315#endif
8316
8317#ifdef TIMER_MANAGER
8318 vos_timer_manager_init();
8319#endif
8320
8321 /* Preopen VOSS so that it is ready to start at least SAL */
8322 status = vos_preOpen(&pVosContext);
8323
8324 if (!VOS_IS_STATUS_SUCCESS(status))
8325 {
8326 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8327 ret_status = -1;
8328 break;
8329 }
8330
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008331#ifndef MODULE
8332 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8333 */
8334 hdd_set_conparam((v_UINT_t)con_mode);
8335#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008336
8337 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008338 if (hdd_wlan_startup(dev))
8339 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008340 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008341 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008342 vos_preClose( &pVosContext );
8343 ret_status = -1;
8344 break;
8345 }
8346
8347 /* Cancel the vote for XO Core ON
8348 * This is done here for safety purposes in case we re-initialize without turning
8349 * it OFF in any error scenario.
8350 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008351 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008352 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008353 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008354 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8355 {
8356 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
8357 " Power consumed will be high\n");
8358 }
8359 } while (0);
8360
8361 if (0 != ret_status)
8362 {
8363 //Assert Deep sleep signal now to put Libra HW in lowest power state
8364 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8365 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8366
8367 //Vote off any PMIC voltage supplies
8368 vos_chipPowerDown(NULL, NULL, NULL);
8369#ifdef TIMER_MANAGER
8370 vos_timer_exit();
8371#endif
8372#ifdef MEMORY_DEBUG
8373 vos_mem_exit();
8374#endif
8375
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008376#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008377 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008378#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008379 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8380 }
8381 else
8382 {
8383 //Send WLAN UP indication to Nlink Service
8384 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8385
8386 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008387 }
8388
8389 EXIT();
8390
8391 return ret_status;
8392}
8393
Jeff Johnson32d95a32012-09-10 13:15:23 -07008394/**---------------------------------------------------------------------------
8395
8396 \brief hdd_module_init() - Init Function
8397
8398 This is the driver entry point (invoked when module is loaded using insmod)
8399
8400 \param - None
8401
8402 \return - 0 for success, non zero for failure
8403
8404 --------------------------------------------------------------------------*/
8405#ifdef MODULE
8406static int __init hdd_module_init ( void)
8407{
8408 return hdd_driver_init();
8409}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008410#else /* #ifdef MODULE */
8411static int __init hdd_module_init ( void)
8412{
8413 /* Driver initialization is delayed to fwpath_changed_handler */
8414 return 0;
8415}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008416#endif /* #ifdef MODULE */
8417
Jeff Johnson295189b2012-06-20 16:38:30 -07008418
8419/**---------------------------------------------------------------------------
8420
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008421 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008422
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008423 This is the driver exit point (invoked when module is unloaded using rmmod
8424 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008425
8426 \param - None
8427
8428 \return - None
8429
8430 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008431static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008432{
8433 hdd_context_t *pHddCtx = NULL;
8434 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008435 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008436
8437 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8438
8439 //Get the global vos context
8440 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8441
8442 if(!pVosContext)
8443 {
8444 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8445 goto done;
8446 }
8447
8448 //Get the HDD context.
8449 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8450
8451 if(!pHddCtx)
8452 {
8453 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8454 }
8455 else
8456 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008457 while(isWDresetInProgress()) {
8458 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8459 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008460 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008461
8462 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8463 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8464 "%s:SSR never completed, fatal error", __func__);
8465 VOS_BUG(0);
8466 }
8467 }
8468
Jeff Johnson295189b2012-06-20 16:38:30 -07008469
8470 pHddCtx->isLoadUnloadInProgress = TRUE;
8471 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8472
8473 //Do all the cleanup before deregistering the driver
8474 hdd_wlan_exit(pHddCtx);
8475 }
8476
Jeff Johnson295189b2012-06-20 16:38:30 -07008477 vos_preClose( &pVosContext );
8478
8479#ifdef TIMER_MANAGER
8480 vos_timer_exit();
8481#endif
8482#ifdef MEMORY_DEBUG
8483 vos_mem_exit();
8484#endif
8485
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308486#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8487 vos_wconn_trace_exit();
8488#endif
8489
Jeff Johnson295189b2012-06-20 16:38:30 -07008490done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008491#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008492 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008493#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008494 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8495}
8496
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008497/**---------------------------------------------------------------------------
8498
8499 \brief hdd_module_exit() - Exit function
8500
8501 This is the driver exit point (invoked when module is unloaded using rmmod)
8502
8503 \param - None
8504
8505 \return - None
8506
8507 --------------------------------------------------------------------------*/
8508static void __exit hdd_module_exit(void)
8509{
8510 hdd_driver_exit();
8511}
8512
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008513#ifdef MODULE
8514static int fwpath_changed_handler(const char *kmessage,
8515 struct kernel_param *kp)
8516{
Jeff Johnson76052702013-04-16 13:55:05 -07008517 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008518}
8519
8520static int con_mode_handler(const char *kmessage,
8521 struct kernel_param *kp)
8522{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008523 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008524}
8525#else /* #ifdef MODULE */
8526/**---------------------------------------------------------------------------
8527
Jeff Johnson76052702013-04-16 13:55:05 -07008528 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008529
Jeff Johnson76052702013-04-16 13:55:05 -07008530 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008531 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008532 - invoked when module parameter fwpath is modified from userspace to signal
8533 initializing the WLAN driver or when con_mode is modified from userspace
8534 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008535
8536 \return - 0 for success, non zero for failure
8537
8538 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008539static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008540{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008541 int ret_status;
8542
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008543 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008544 ret_status = hdd_driver_init();
8545 wlan_hdd_inited = ret_status ? 0 : 1;
8546 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008547 }
8548
8549 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008550
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008551 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008552
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008553 ret_status = hdd_driver_init();
8554 wlan_hdd_inited = ret_status ? 0 : 1;
8555 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008556}
8557
Jeff Johnson295189b2012-06-20 16:38:30 -07008558/**---------------------------------------------------------------------------
8559
Jeff Johnson76052702013-04-16 13:55:05 -07008560 \brief fwpath_changed_handler() - Handler Function
8561
8562 Handle changes to the fwpath parameter
8563
8564 \return - 0 for success, non zero for failure
8565
8566 --------------------------------------------------------------------------*/
8567static int fwpath_changed_handler(const char *kmessage,
8568 struct kernel_param *kp)
8569{
8570 int ret;
8571
8572 ret = param_set_copystring(kmessage, kp);
8573 if (0 == ret)
8574 ret = kickstart_driver();
8575 return ret;
8576}
8577
8578/**---------------------------------------------------------------------------
8579
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008580 \brief con_mode_handler() -
8581
8582 Handler function for module param con_mode when it is changed by userspace
8583 Dynamically linked - do nothing
8584 Statically linked - exit and init driver, as in rmmod and insmod
8585
Jeff Johnson76052702013-04-16 13:55:05 -07008586 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008587
Jeff Johnson76052702013-04-16 13:55:05 -07008588 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008589
8590 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008591static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008592{
Jeff Johnson76052702013-04-16 13:55:05 -07008593 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008594
Jeff Johnson76052702013-04-16 13:55:05 -07008595 ret = param_set_int(kmessage, kp);
8596 if (0 == ret)
8597 ret = kickstart_driver();
8598 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008599}
8600#endif /* #ifdef MODULE */
8601
8602/**---------------------------------------------------------------------------
8603
Jeff Johnson295189b2012-06-20 16:38:30 -07008604 \brief hdd_get_conparam() -
8605
8606 This is the driver exit point (invoked when module is unloaded using rmmod)
8607
8608 \param - None
8609
8610 \return - tVOS_CON_MODE
8611
8612 --------------------------------------------------------------------------*/
8613tVOS_CON_MODE hdd_get_conparam ( void )
8614{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008615#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008616 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008617#else
8618 return (tVOS_CON_MODE)curr_con_mode;
8619#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008620}
8621void hdd_set_conparam ( v_UINT_t newParam )
8622{
8623 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008624#ifndef MODULE
8625 curr_con_mode = con_mode;
8626#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008627}
8628/**---------------------------------------------------------------------------
8629
8630 \brief hdd_softap_sta_deauth() - function
8631
8632 This to take counter measure to handle deauth req from HDD
8633
8634 \param - pAdapter - Pointer to the HDD
8635
8636 \param - enable - boolean value
8637
8638 \return - None
8639
8640 --------------------------------------------------------------------------*/
8641
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008642VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008643{
Jeff Johnson295189b2012-06-20 16:38:30 -07008644 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008645 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008646
8647 ENTER();
8648
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008649 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8650 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008651
8652 //Ignore request to deauth bcmc station
8653 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008654 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008655
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008656 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008657
8658 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008659 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008660}
8661
8662/**---------------------------------------------------------------------------
8663
8664 \brief hdd_softap_sta_disassoc() - function
8665
8666 This to take counter measure to handle deauth req from HDD
8667
8668 \param - pAdapter - Pointer to the HDD
8669
8670 \param - enable - boolean value
8671
8672 \return - None
8673
8674 --------------------------------------------------------------------------*/
8675
8676void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8677{
8678 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8679
8680 ENTER();
8681
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308682 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008683
8684 //Ignore request to disassoc bcmc station
8685 if( pDestMacAddress[0] & 0x1 )
8686 return;
8687
8688 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8689}
8690
8691void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8692{
8693 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8694
8695 ENTER();
8696
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308697 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008698
8699 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8700}
8701
Jeff Johnson295189b2012-06-20 16:38:30 -07008702/**---------------------------------------------------------------------------
8703 *
8704 * \brief hdd_get__concurrency_mode() -
8705 *
8706 *
8707 * \param - None
8708 *
8709 * \return - CONCURRENCY MODE
8710 *
8711 * --------------------------------------------------------------------------*/
8712tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8713{
8714 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8715 hdd_context_t *pHddCtx;
8716
8717 if (NULL != pVosContext)
8718 {
8719 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8720 if (NULL != pHddCtx)
8721 {
8722 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8723 }
8724 }
8725
8726 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008727 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008728 return VOS_STA;
8729}
8730
8731/* Decide whether to allow/not the apps power collapse.
8732 * Allow apps power collapse if we are in connected state.
8733 * if not, allow only if we are in IMPS */
8734v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8735{
8736 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008737 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008738 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008739 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8740 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8741 hdd_adapter_t *pAdapter = NULL;
8742 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008743 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008744
Jeff Johnson295189b2012-06-20 16:38:30 -07008745 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8746 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008747
Yathish9f22e662012-12-10 14:21:35 -08008748 concurrent_state = hdd_get_concurrency_mode();
8749
8750#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8751 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8752 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8753 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8754 return TRUE;
8755#endif
8756
Jeff Johnson295189b2012-06-20 16:38:30 -07008757 /*loop through all adapters. TBD fix for Concurrency */
8758 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8759 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8760 {
8761 pAdapter = pAdapterNode->pAdapter;
8762 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8763 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8764 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008765 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008766 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008767 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008768 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8769 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008770 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008771 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008772 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8773 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008774 return FALSE;
8775 }
8776 }
8777 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8778 pAdapterNode = pNext;
8779 }
8780 return TRUE;
8781}
8782
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008783/* Decides whether to send suspend notification to Riva
8784 * if any adapter is in BMPS; then it is required */
8785v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8786{
8787 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8788 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8789
8790 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8791 {
8792 return TRUE;
8793 }
8794 return FALSE;
8795}
8796
Jeff Johnson295189b2012-06-20 16:38:30 -07008797void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8798{
8799 switch(mode)
8800 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008801 case VOS_STA_MODE:
8802 case VOS_P2P_CLIENT_MODE:
8803 case VOS_P2P_GO_MODE:
8804 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008805 pHddCtx->concurrency_mode |= (1 << mode);
8806 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008807 break;
8808 default:
8809 break;
8810
8811 }
8812 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8813 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8814}
8815
8816
8817void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8818{
8819 switch(mode)
8820 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008821 case VOS_STA_MODE:
8822 case VOS_P2P_CLIENT_MODE:
8823 case VOS_P2P_GO_MODE:
8824 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008825 pHddCtx->no_of_sessions[mode]--;
8826 if (!(pHddCtx->no_of_sessions[mode]))
8827 pHddCtx->concurrency_mode &= (~(1 << mode));
8828 break;
8829 default:
8830 break;
8831 }
8832 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8833 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8834}
8835
Jeff Johnsone7245742012-09-05 17:12:55 -07008836/**---------------------------------------------------------------------------
8837 *
8838 * \brief wlan_hdd_restart_init
8839 *
8840 * This function initalizes restart timer/flag. An internal function.
8841 *
8842 * \param - pHddCtx
8843 *
8844 * \return - None
8845 *
8846 * --------------------------------------------------------------------------*/
8847
8848static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8849{
8850 /* Initialize */
8851 pHddCtx->hdd_restart_retries = 0;
8852 atomic_set(&pHddCtx->isRestartInProgress, 0);
8853 vos_timer_init(&pHddCtx->hdd_restart_timer,
8854 VOS_TIMER_TYPE_SW,
8855 wlan_hdd_restart_timer_cb,
8856 pHddCtx);
8857}
8858/**---------------------------------------------------------------------------
8859 *
8860 * \brief wlan_hdd_restart_deinit
8861 *
8862 * This function cleans up the resources used. An internal function.
8863 *
8864 * \param - pHddCtx
8865 *
8866 * \return - None
8867 *
8868 * --------------------------------------------------------------------------*/
8869
8870static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8871{
8872
8873 VOS_STATUS vos_status;
8874 /* Block any further calls */
8875 atomic_set(&pHddCtx->isRestartInProgress, 1);
8876 /* Cleanup */
8877 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8878 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008879 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008880 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8881 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008882 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008883
8884}
8885
8886/**---------------------------------------------------------------------------
8887 *
8888 * \brief wlan_hdd_framework_restart
8889 *
8890 * This function uses a cfg80211 API to start a framework initiated WLAN
8891 * driver module unload/load.
8892 *
8893 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8894 *
8895 *
8896 * \param - pHddCtx
8897 *
8898 * \return - VOS_STATUS_SUCCESS: Success
8899 * VOS_STATUS_E_EMPTY: Adapter is Empty
8900 * VOS_STATUS_E_NOMEM: No memory
8901
8902 * --------------------------------------------------------------------------*/
8903
8904static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8905{
8906 VOS_STATUS status = VOS_STATUS_SUCCESS;
8907 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008908 int len = (sizeof (struct ieee80211_mgmt));
8909 struct ieee80211_mgmt *mgmt = NULL;
8910
8911 /* Prepare the DEAUTH managment frame with reason code */
8912 mgmt = kzalloc(len, GFP_KERNEL);
8913 if(mgmt == NULL)
8914 {
8915 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8916 "%s: memory allocation failed (%d bytes)", __func__, len);
8917 return VOS_STATUS_E_NOMEM;
8918 }
8919 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008920
8921 /* Iterate over all adapters/devices */
8922 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8923 do
8924 {
8925 if( (status == VOS_STATUS_SUCCESS) &&
8926 pAdapterNode &&
8927 pAdapterNode->pAdapter)
8928 {
8929 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8930 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8931 pAdapterNode->pAdapter->dev->name,
8932 pAdapterNode->pAdapter->device_mode,
8933 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008934 /*
8935 * CFG80211 event to restart the driver
8936 *
8937 * 'cfg80211_send_unprot_deauth' sends a
8938 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8939 * of SME(Linux Kernel) state machine.
8940 *
8941 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8942 * the driver.
8943 *
8944 */
8945
8946 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008947 }
8948 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8949 pAdapterNode = pNext;
8950 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8951
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008952
8953 /* Free the allocated management frame */
8954 kfree(mgmt);
8955
Jeff Johnsone7245742012-09-05 17:12:55 -07008956 /* Retry until we unload or reach max count */
8957 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
8958 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
8959
8960 return status;
8961
8962}
8963/**---------------------------------------------------------------------------
8964 *
8965 * \brief wlan_hdd_restart_timer_cb
8966 *
8967 * Restart timer callback. An internal function.
8968 *
8969 * \param - User data:
8970 *
8971 * \return - None
8972 *
8973 * --------------------------------------------------------------------------*/
8974
8975void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
8976{
8977 hdd_context_t *pHddCtx = usrDataForCallback;
8978 wlan_hdd_framework_restart(pHddCtx);
8979 return;
8980
8981}
8982
8983
8984/**---------------------------------------------------------------------------
8985 *
8986 * \brief wlan_hdd_restart_driver
8987 *
8988 * This function sends an event to supplicant to restart the WLAN driver.
8989 *
8990 * This function is called from vos_wlanRestart.
8991 *
8992 * \param - pHddCtx
8993 *
8994 * \return - VOS_STATUS_SUCCESS: Success
8995 * VOS_STATUS_E_EMPTY: Adapter is Empty
8996 * VOS_STATUS_E_ALREADY: Request already in progress
8997
8998 * --------------------------------------------------------------------------*/
8999VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9000{
9001 VOS_STATUS status = VOS_STATUS_SUCCESS;
9002
9003 /* A tight check to make sure reentrancy */
9004 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9005 {
9006 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9007 "%s: WLAN restart is already in progress", __func__);
9008
9009 return VOS_STATUS_E_ALREADY;
9010 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009011 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009012#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009013 wcnss_reset_intr();
9014#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009015
Jeff Johnsone7245742012-09-05 17:12:55 -07009016 return status;
9017}
9018
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009019/*
9020 * API to find if there is any STA or P2P-Client is connected
9021 */
9022VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9023{
9024 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9025}
Jeff Johnsone7245742012-09-05 17:12:55 -07009026
Jeff Johnson295189b2012-06-20 16:38:30 -07009027//Register the module init/exit functions
9028module_init(hdd_module_init);
9029module_exit(hdd_module_exit);
9030
9031MODULE_LICENSE("Dual BSD/GPL");
9032MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9033MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9034
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009035module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9036 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009037
Jeff Johnson76052702013-04-16 13:55:05 -07009038module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009039 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);