blob: 5cc84d90ecbb9ee5183bbd93fe987ee20318da2b [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);
Kiet Lambe150c22013-11-21 16:30:32 +05304088 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
4089 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004090
4091 *pChannel = tempInt;
4092
4093 /* point to the next argument */
4094 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4095 /*no argument after the command*/
4096 if (NULL == inPtr) return -EINVAL;
4097 /*removing empty spaces*/
4098 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4099
4100 /*no argument followed by spaces*/
4101 if ('\0' == *inPtr)
4102 {
4103 return -EINVAL;
4104 }
4105
4106 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004107 v = sscanf(inPtr, "%32s ", tempBuf);
4108 if (1 != v) return -EINVAL;
4109
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004110 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304111 if ( v < 0 || tempInt <= 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004112
4113 *pDwellTime = tempInt;
4114
4115 /* point to the next argument */
4116 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4117 /*no argument after the command*/
4118 if (NULL == inPtr) return -EINVAL;
4119 /*removing empty spaces*/
4120 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4121
4122 /*no argument followed by spaces*/
4123 if ('\0' == *inPtr)
4124 {
4125 return -EINVAL;
4126 }
4127
4128 /* find the length of data */
4129 dataEnd = inPtr;
4130 while(('\0' != *dataEnd) )
4131 {
4132 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004133 }
Kiet Lambe150c22013-11-21 16:30:32 +05304134 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004135 if ( *pBufLen <= 0) return -EINVAL;
4136
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004137 /* Allocate the number of bytes based on the number of input characters
4138 whether it is even or odd.
4139 if the number of input characters are even, then we need N/2 byte.
4140 if the number of input characters are odd, then we need do (N+1)/2 to
4141 compensate rounding off.
4142 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4143 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4144 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004145 if (NULL == *pBuf)
4146 {
4147 hddLog(VOS_TRACE_LEVEL_FATAL,
4148 "%s: vos_mem_alloc failed ", __func__);
4149 return -EINVAL;
4150 }
4151
4152 /* the buffer received from the upper layer is character buffer,
4153 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4154 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4155 and f0 in 3rd location */
4156 for (i = 0, j = 0; j < *pBufLen; j += 2)
4157 {
Kiet Lambe150c22013-11-21 16:30:32 +05304158 if( j+1 == *pBufLen)
4159 {
4160 tempByte = hdd_parse_hex(inPtr[j]);
4161 }
4162 else
4163 {
4164 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4165 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004166 (*pBuf)[i++] = tempByte;
4167 }
4168 *pBufLen = i;
4169 return VOS_STATUS_SUCCESS;
4170}
4171
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004172/**---------------------------------------------------------------------------
4173
Srinivas Girigowdade697412013-02-14 16:31:48 -08004174 \brief hdd_parse_channellist() - HDD Parse channel list
4175
4176 This function parses the channel list passed in the format
4177 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004178 if the Number of channels (N) does not match with the actual number of channels passed
4179 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4180 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4181 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4182 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004183
4184 \param - pValue Pointer to input channel list
4185 \param - ChannelList Pointer to local output array to record channel list
4186 \param - pNumChannels Pointer to number of roam scan channels
4187
4188 \return - 0 for success non-zero for failure
4189
4190 --------------------------------------------------------------------------*/
4191VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4192{
4193 tANI_U8 *inPtr = pValue;
4194 int tempInt;
4195 int j = 0;
4196 int v = 0;
4197 char buf[32];
4198
4199 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4200 /*no argument after the command*/
4201 if (NULL == inPtr)
4202 {
4203 return -EINVAL;
4204 }
4205
4206 /*no space after the command*/
4207 else if (SPACE_ASCII_VALUE != *inPtr)
4208 {
4209 return -EINVAL;
4210 }
4211
4212 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004213 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004214
4215 /*no argument followed by spaces*/
4216 if ('\0' == *inPtr)
4217 {
4218 return -EINVAL;
4219 }
4220
4221 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004222 v = sscanf(inPtr, "%32s ", buf);
4223 if (1 != v) return -EINVAL;
4224
Srinivas Girigowdade697412013-02-14 16:31:48 -08004225 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004226 if ((v < 0) ||
4227 (tempInt <= 0) ||
4228 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4229 {
4230 return -EINVAL;
4231 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004232
4233 *pNumChannels = tempInt;
4234
4235 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4236 "Number of channels are: %d", *pNumChannels);
4237
4238 for (j = 0; j < (*pNumChannels); j++)
4239 {
4240 /*inPtr pointing to the beginning of first space after number of channels*/
4241 inPtr = strpbrk( inPtr, " " );
4242 /*no channel list after the number of channels argument*/
4243 if (NULL == inPtr)
4244 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004245 if (0 != j)
4246 {
4247 *pNumChannels = j;
4248 return VOS_STATUS_SUCCESS;
4249 }
4250 else
4251 {
4252 return -EINVAL;
4253 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004254 }
4255
4256 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004257 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004258
4259 /*no channel list after the number of channels argument and spaces*/
4260 if ( '\0' == *inPtr )
4261 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004262 if (0 != j)
4263 {
4264 *pNumChannels = j;
4265 return VOS_STATUS_SUCCESS;
4266 }
4267 else
4268 {
4269 return -EINVAL;
4270 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004271 }
4272
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004273 v = sscanf(inPtr, "%32s ", buf);
4274 if (1 != v) return -EINVAL;
4275
Srinivas Girigowdade697412013-02-14 16:31:48 -08004276 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004277 if ((v < 0) ||
4278 (tempInt <= 0) ||
4279 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4280 {
4281 return -EINVAL;
4282 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004283 pChannelList[j] = tempInt;
4284
4285 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4286 "Channel %d added to preferred channel list",
4287 pChannelList[j] );
4288 }
4289
Srinivas Girigowdade697412013-02-14 16:31:48 -08004290 return VOS_STATUS_SUCCESS;
4291}
4292
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004293
4294/**---------------------------------------------------------------------------
4295
4296 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4297
4298 This function parses the reasoc command data passed in the format
4299 REASSOC<space><bssid><space><channel>
4300
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004301 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004302 \param - pTargetApBssid Pointer to target Ap bssid
4303 \param - pChannel Pointer to the Target AP channel
4304
4305 \return - 0 for success non-zero for failure
4306
4307 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004308VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4309 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004310{
4311 tANI_U8 *inPtr = pValue;
4312 int tempInt;
4313 int v = 0;
4314 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004315 /* 12 hexa decimal digits and 5 ':' */
4316 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004317
4318 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4319 /*no argument after the command*/
4320 if (NULL == inPtr)
4321 {
4322 return -EINVAL;
4323 }
4324
4325 /*no space after the command*/
4326 else if (SPACE_ASCII_VALUE != *inPtr)
4327 {
4328 return -EINVAL;
4329 }
4330
4331 /*removing empty spaces*/
4332 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4333
4334 /*no argument followed by spaces*/
4335 if ('\0' == *inPtr)
4336 {
4337 return -EINVAL;
4338 }
4339
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004340 v = sscanf(inPtr, "%17s", macAddress);
4341 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004342 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4344 "Invalid MAC address or All hex inputs are not read (%d)", v);
4345 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004346 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004347
4348 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4349 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4350 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4351 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4352 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4353 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004354
4355 /* point to the next argument */
4356 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4357 /*no argument after the command*/
4358 if (NULL == inPtr) return -EINVAL;
4359
4360 /*removing empty spaces*/
4361 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4362
4363 /*no argument followed by spaces*/
4364 if ('\0' == *inPtr)
4365 {
4366 return -EINVAL;
4367 }
4368
4369 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004370 v = sscanf(inPtr, "%32s ", tempBuf);
4371 if (1 != v) return -EINVAL;
4372
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004373 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004374 if ((v < 0) ||
4375 (tempInt <= 0) ||
4376 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4377 {
4378 return -EINVAL;
4379 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004380
4381 *pChannel = tempInt;
4382 return VOS_STATUS_SUCCESS;
4383}
4384
4385#endif
4386
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004387#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4388/**---------------------------------------------------------------------------
4389
4390 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4391
4392 This function parses the SETCCKM IE command
4393 SETCCKMIE<space><ie data>
4394
4395 \param - pValue Pointer to input data
4396 \param - pCckmIe Pointer to output cckm Ie
4397 \param - pCckmIeLen Pointer to output cckm ie length
4398
4399 \return - 0 for success non-zero for failure
4400
4401 --------------------------------------------------------------------------*/
4402VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4403 tANI_U8 *pCckmIeLen)
4404{
4405 tANI_U8 *inPtr = pValue;
4406 tANI_U8 *dataEnd;
4407 int j = 0;
4408 int i = 0;
4409 tANI_U8 tempByte = 0;
4410
4411 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4412 /*no argument after the command*/
4413 if (NULL == inPtr)
4414 {
4415 return -EINVAL;
4416 }
4417
4418 /*no space after the command*/
4419 else if (SPACE_ASCII_VALUE != *inPtr)
4420 {
4421 return -EINVAL;
4422 }
4423
4424 /*removing empty spaces*/
4425 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4426
4427 /*no argument followed by spaces*/
4428 if ('\0' == *inPtr)
4429 {
4430 return -EINVAL;
4431 }
4432
4433 /* find the length of data */
4434 dataEnd = inPtr;
4435 while(('\0' != *dataEnd) )
4436 {
4437 dataEnd++;
4438 ++(*pCckmIeLen);
4439 }
4440 if ( *pCckmIeLen <= 0) return -EINVAL;
4441
4442 /* Allocate the number of bytes based on the number of input characters
4443 whether it is even or odd.
4444 if the number of input characters are even, then we need N/2 byte.
4445 if the number of input characters are odd, then we need do (N+1)/2 to
4446 compensate rounding off.
4447 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4448 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4449 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4450 if (NULL == *pCckmIe)
4451 {
4452 hddLog(VOS_TRACE_LEVEL_FATAL,
4453 "%s: vos_mem_alloc failed ", __func__);
4454 return -EINVAL;
4455 }
4456 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4457 /* the buffer received from the upper layer is character buffer,
4458 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4459 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4460 and f0 in 3rd location */
4461 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4462 {
4463 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4464 (*pCckmIe)[i++] = tempByte;
4465 }
4466 *pCckmIeLen = i;
4467
4468 return VOS_STATUS_SUCCESS;
4469}
4470#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4471
Jeff Johnson295189b2012-06-20 16:38:30 -07004472/**---------------------------------------------------------------------------
4473
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004474 \brief hdd_is_valid_mac_address() - Validate MAC address
4475
4476 This function validates whether the given MAC address is valid or not
4477 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4478 where X is the hexa decimal digit character and separated by ':'
4479 This algorithm works even if MAC address is not separated by ':'
4480
4481 This code checks given input string mac contains exactly 12 hexadecimal digits.
4482 and a separator colon : appears in the input string only after
4483 an even number of hex digits.
4484
4485 \param - pMacAddr pointer to the input MAC address
4486 \return - 1 for valid and 0 for invalid
4487
4488 --------------------------------------------------------------------------*/
4489
4490v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4491{
4492 int xdigit = 0;
4493 int separator = 0;
4494 while (*pMacAddr)
4495 {
4496 if (isxdigit(*pMacAddr))
4497 {
4498 xdigit++;
4499 }
4500 else if (':' == *pMacAddr)
4501 {
4502 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4503 break;
4504
4505 ++separator;
4506 }
4507 else
4508 {
4509 separator = -1;
4510 /* Invalid MAC found */
4511 return 0;
4512 }
4513 ++pMacAddr;
4514 }
4515 return (xdigit == 12 && (separator == 5 || separator == 0));
4516}
4517
4518/**---------------------------------------------------------------------------
4519
Jeff Johnson295189b2012-06-20 16:38:30 -07004520 \brief hdd_open() - HDD Open function
4521
4522 This is called in response to ifconfig up
4523
4524 \param - dev Pointer to net_device structure
4525
4526 \return - 0 for success non-zero for failure
4527
4528 --------------------------------------------------------------------------*/
4529int hdd_open (struct net_device *dev)
4530{
4531 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4532 hdd_context_t *pHddCtx;
4533 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4534 VOS_STATUS status;
4535 v_BOOL_t in_standby = TRUE;
4536
4537 if (NULL == pAdapter)
4538 {
4539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004540 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004541 return -ENODEV;
4542 }
4543
4544 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4545 if (NULL == pHddCtx)
4546 {
4547 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004548 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004549 return -ENODEV;
4550 }
4551
4552 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4553 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4554 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004555 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4556 {
4557 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304558 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004559 in_standby = FALSE;
4560 break;
4561 }
4562 else
4563 {
4564 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4565 pAdapterNode = pNext;
4566 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004567 }
4568
4569 if (TRUE == in_standby)
4570 {
4571 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4572 {
4573 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4574 "wlan out of power save", __func__);
4575 return -EINVAL;
4576 }
4577 }
4578
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004579 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004580 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4581 {
4582 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004583 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004584 /* Enable TX queues only when we are connected */
4585 netif_tx_start_all_queues(dev);
4586 }
4587
4588 return 0;
4589}
4590
4591int hdd_mon_open (struct net_device *dev)
4592{
4593 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4594
4595 if(pAdapter == NULL) {
4596 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004597 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004598 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004599 }
4600
4601 netif_start_queue(dev);
4602
4603 return 0;
4604}
4605/**---------------------------------------------------------------------------
4606
4607 \brief hdd_stop() - HDD stop function
4608
4609 This is called in response to ifconfig down
4610
4611 \param - dev Pointer to net_device structure
4612
4613 \return - 0 for success non-zero for failure
4614
4615 --------------------------------------------------------------------------*/
4616
4617int hdd_stop (struct net_device *dev)
4618{
4619 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4620 hdd_context_t *pHddCtx;
4621 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4622 VOS_STATUS status;
4623 v_BOOL_t enter_standby = TRUE;
4624
4625 ENTER();
4626
4627 if (NULL == pAdapter)
4628 {
4629 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004630 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004631 return -ENODEV;
4632 }
4633
4634 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4635 if (NULL == pHddCtx)
4636 {
4637 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004638 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004639 return -ENODEV;
4640 }
4641
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004642 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004643 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4644 netif_tx_disable(pAdapter->dev);
4645 netif_carrier_off(pAdapter->dev);
4646
4647
4648 /* SoftAP ifaces should never go in power save mode
4649 making sure same here. */
4650 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4651 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004652 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004653 )
4654 {
4655 /* SoftAP mode, so return from here */
4656 EXIT();
4657 return 0;
4658 }
4659
4660 /* Find if any iface is up then
4661 if any iface is up then can't put device to sleep/ power save mode. */
4662 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4663 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4664 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004665 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4666 {
4667 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304668 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004669 enter_standby = FALSE;
4670 break;
4671 }
4672 else
4673 {
4674 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4675 pAdapterNode = pNext;
4676 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004677 }
4678
4679 if (TRUE == enter_standby)
4680 {
4681 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4682 "entering standby", __func__);
4683 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4684 {
4685 /*log and return success*/
4686 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4687 "wlan in power save", __func__);
4688 }
4689 }
4690
4691 EXIT();
4692 return 0;
4693}
4694
4695/**---------------------------------------------------------------------------
4696
4697 \brief hdd_uninit() - HDD uninit function
4698
4699 This is called during the netdev unregister to uninitialize all data
4700associated with the device
4701
4702 \param - dev Pointer to net_device structure
4703
4704 \return - void
4705
4706 --------------------------------------------------------------------------*/
4707static void hdd_uninit (struct net_device *dev)
4708{
4709 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4710
4711 ENTER();
4712
4713 do
4714 {
4715 if (NULL == pAdapter)
4716 {
4717 hddLog(VOS_TRACE_LEVEL_FATAL,
4718 "%s: NULL pAdapter", __func__);
4719 break;
4720 }
4721
4722 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4723 {
4724 hddLog(VOS_TRACE_LEVEL_FATAL,
4725 "%s: Invalid magic", __func__);
4726 break;
4727 }
4728
4729 if (NULL == pAdapter->pHddCtx)
4730 {
4731 hddLog(VOS_TRACE_LEVEL_FATAL,
4732 "%s: NULL pHddCtx", __func__);
4733 break;
4734 }
4735
4736 if (dev != pAdapter->dev)
4737 {
4738 hddLog(VOS_TRACE_LEVEL_FATAL,
4739 "%s: Invalid device reference", __func__);
4740 /* we haven't validated all cases so let this go for now */
4741 }
4742
4743 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4744
4745 /* after uninit our adapter structure will no longer be valid */
4746 pAdapter->dev = NULL;
4747 pAdapter->magic = 0;
4748 } while (0);
4749
4750 EXIT();
4751}
4752
4753/**---------------------------------------------------------------------------
4754
4755 \brief hdd_release_firmware() -
4756
4757 This function calls the release firmware API to free the firmware buffer.
4758
4759 \param - pFileName Pointer to the File Name.
4760 pCtx - Pointer to the adapter .
4761
4762
4763 \return - 0 for success, non zero for failure
4764
4765 --------------------------------------------------------------------------*/
4766
4767VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4768{
4769 VOS_STATUS status = VOS_STATUS_SUCCESS;
4770 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4771 ENTER();
4772
4773
4774 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4775
4776 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4777
4778 if(pHddCtx->fw) {
4779 release_firmware(pHddCtx->fw);
4780 pHddCtx->fw = NULL;
4781 }
4782 else
4783 status = VOS_STATUS_E_FAILURE;
4784 }
4785 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4786 if(pHddCtx->nv) {
4787 release_firmware(pHddCtx->nv);
4788 pHddCtx->nv = NULL;
4789 }
4790 else
4791 status = VOS_STATUS_E_FAILURE;
4792
4793 }
4794
4795 EXIT();
4796 return status;
4797}
4798
4799/**---------------------------------------------------------------------------
4800
4801 \brief hdd_request_firmware() -
4802
4803 This function reads the firmware file using the request firmware
4804 API and returns the the firmware data and the firmware file size.
4805
4806 \param - pfileName - Pointer to the file name.
4807 - pCtx - Pointer to the adapter .
4808 - ppfw_data - Pointer to the pointer of the firmware data.
4809 - pSize - Pointer to the file size.
4810
4811 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4812
4813 --------------------------------------------------------------------------*/
4814
4815
4816VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4817{
4818 int status;
4819 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4820 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4821 ENTER();
4822
4823 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4824
4825 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4826
4827 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4828 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4829 __func__, pfileName);
4830 retval = VOS_STATUS_E_FAILURE;
4831 }
4832
4833 else {
4834 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4835 *pSize = pHddCtx->fw->size;
4836 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4837 __func__, *pSize);
4838 }
4839 }
4840 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4841
4842 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4843
4844 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4845 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4846 __func__, pfileName);
4847 retval = VOS_STATUS_E_FAILURE;
4848 }
4849
4850 else {
4851 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4852 *pSize = pHddCtx->nv->size;
4853 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4854 __func__, *pSize);
4855 }
4856 }
4857
4858 EXIT();
4859 return retval;
4860}
4861/**---------------------------------------------------------------------------
4862 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4863
4864 This is the function invoked by SME to inform the result of a full power
4865 request issued by HDD
4866
4867 \param - callbackcontext - Pointer to cookie
4868 status - result of request
4869
4870 \return - None
4871
4872--------------------------------------------------------------------------*/
4873void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4874{
4875 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4876
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004877 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004878 if(&pHddCtx->full_pwr_comp_var)
4879 {
4880 complete(&pHddCtx->full_pwr_comp_var);
4881 }
4882}
4883
4884/**---------------------------------------------------------------------------
4885
4886 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4887
4888 This is the function invoked by SME to inform the result of BMPS
4889 request issued by HDD
4890
4891 \param - callbackcontext - Pointer to cookie
4892 status - result of request
4893
4894 \return - None
4895
4896--------------------------------------------------------------------------*/
4897void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4898{
4899
4900 struct completion *completion_var = (struct completion*) callbackContext;
4901
4902 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
4903 if(completion_var != NULL)
4904 {
4905 complete(completion_var);
4906 }
4907}
4908
4909/**---------------------------------------------------------------------------
4910
4911 \brief hdd_get_cfg_file_size() -
4912
4913 This function reads the configuration file using the request firmware
4914 API and returns the configuration file size.
4915
4916 \param - pCtx - Pointer to the adapter .
4917 - pFileName - Pointer to the file name.
4918 - pBufSize - Pointer to the buffer size.
4919
4920 \return - 0 for success, non zero for failure
4921
4922 --------------------------------------------------------------------------*/
4923
4924VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4925{
4926 int status;
4927 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4928
4929 ENTER();
4930
4931 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4932
4933 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4934 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4935 status = VOS_STATUS_E_FAILURE;
4936 }
4937 else {
4938 *pBufSize = pHddCtx->fw->size;
4939 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4940 release_firmware(pHddCtx->fw);
4941 pHddCtx->fw = NULL;
4942 }
4943
4944 EXIT();
4945 return VOS_STATUS_SUCCESS;
4946}
4947
4948/**---------------------------------------------------------------------------
4949
4950 \brief hdd_read_cfg_file() -
4951
4952 This function reads the configuration file using the request firmware
4953 API and returns the cfg data and the buffer size of the configuration file.
4954
4955 \param - pCtx - Pointer to the adapter .
4956 - pFileName - Pointer to the file name.
4957 - pBuffer - Pointer to the data buffer.
4958 - pBufSize - Pointer to the buffer size.
4959
4960 \return - 0 for success, non zero for failure
4961
4962 --------------------------------------------------------------------------*/
4963
4964VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4965 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4966{
4967 int status;
4968 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4969
4970 ENTER();
4971
4972 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4973
4974 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4975 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4976 return VOS_STATUS_E_FAILURE;
4977 }
4978 else {
4979 if(*pBufSize != pHddCtx->fw->size) {
4980 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4981 "file size", __func__);
4982 release_firmware(pHddCtx->fw);
4983 pHddCtx->fw = NULL;
4984 return VOS_STATUS_E_FAILURE;
4985 }
4986 else {
4987 if(pBuffer) {
4988 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4989 }
4990 release_firmware(pHddCtx->fw);
4991 pHddCtx->fw = NULL;
4992 }
4993 }
4994
4995 EXIT();
4996
4997 return VOS_STATUS_SUCCESS;
4998}
4999
5000/**---------------------------------------------------------------------------
5001
Jeff Johnson295189b2012-06-20 16:38:30 -07005002 \brief hdd_set_mac_address() -
5003
5004 This function sets the user specified mac address using
5005 the command ifconfig wlanX hw ether <mac adress>.
5006
5007 \param - dev - Pointer to the net device.
5008 - addr - Pointer to the sockaddr.
5009 \return - 0 for success, non zero for failure
5010
5011 --------------------------------------------------------------------------*/
5012
5013static int hdd_set_mac_address(struct net_device *dev, void *addr)
5014{
5015 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5016 struct sockaddr *psta_mac_addr = addr;
5017 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5018
5019 ENTER();
5020
5021 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5022
5023#ifdef HDD_SESSIONIZE
5024 // set the MAC address though the STA ID CFG.
5025 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5026 (v_U8_t *)&pAdapter->macAddressCurrent,
5027 sizeof( pAdapter->macAddressCurrent ),
5028 hdd_set_mac_addr_cb, VOS_FALSE );
5029#endif
5030
5031 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5032
5033 EXIT();
5034 return halStatus;
5035}
5036
5037tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5038{
5039 int i;
5040 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5041 {
5042 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
5043 break;
5044 }
5045
5046 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5047 return NULL;
5048
5049 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5050 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5051}
5052
5053void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5054{
5055 int i;
5056 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5057 {
5058 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5059 {
5060 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5061 break;
5062 }
5063 }
5064 return;
5065}
5066
5067#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5068 static struct net_device_ops wlan_drv_ops = {
5069 .ndo_open = hdd_open,
5070 .ndo_stop = hdd_stop,
5071 .ndo_uninit = hdd_uninit,
5072 .ndo_start_xmit = hdd_hard_start_xmit,
5073 .ndo_tx_timeout = hdd_tx_timeout,
5074 .ndo_get_stats = hdd_stats,
5075 .ndo_do_ioctl = hdd_ioctl,
5076 .ndo_set_mac_address = hdd_set_mac_address,
5077 .ndo_select_queue = hdd_select_queue,
5078#ifdef WLAN_FEATURE_PACKET_FILTERING
5079#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5080 .ndo_set_rx_mode = hdd_set_multicast_list,
5081#else
5082 .ndo_set_multicast_list = hdd_set_multicast_list,
5083#endif //LINUX_VERSION_CODE
5084#endif
5085 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005086 static struct net_device_ops wlan_mon_drv_ops = {
5087 .ndo_open = hdd_mon_open,
5088 .ndo_stop = hdd_stop,
5089 .ndo_uninit = hdd_uninit,
5090 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5091 .ndo_tx_timeout = hdd_tx_timeout,
5092 .ndo_get_stats = hdd_stats,
5093 .ndo_do_ioctl = hdd_ioctl,
5094 .ndo_set_mac_address = hdd_set_mac_address,
5095 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005096
5097#endif
5098
5099void hdd_set_station_ops( struct net_device *pWlanDev )
5100{
5101#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005102 pWlanDev->netdev_ops = &wlan_drv_ops;
5103#else
5104 pWlanDev->open = hdd_open;
5105 pWlanDev->stop = hdd_stop;
5106 pWlanDev->uninit = hdd_uninit;
5107 pWlanDev->hard_start_xmit = NULL;
5108 pWlanDev->tx_timeout = hdd_tx_timeout;
5109 pWlanDev->get_stats = hdd_stats;
5110 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005111 pWlanDev->set_mac_address = hdd_set_mac_address;
5112#endif
5113}
5114
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005115static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005116{
5117 struct net_device *pWlanDev = NULL;
5118 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005119 /*
5120 * cfg80211 initialization and registration....
5121 */
5122 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5123
Jeff Johnson295189b2012-06-20 16:38:30 -07005124 if(pWlanDev != NULL)
5125 {
5126
5127 //Save the pointer to the net_device in the HDD adapter
5128 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5129
Jeff Johnson295189b2012-06-20 16:38:30 -07005130 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5131
5132 pAdapter->dev = pWlanDev;
5133 pAdapter->pHddCtx = pHddCtx;
5134 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5135
5136 init_completion(&pAdapter->session_open_comp_var);
5137 init_completion(&pAdapter->session_close_comp_var);
5138 init_completion(&pAdapter->disconnect_comp_var);
5139 init_completion(&pAdapter->linkup_event_var);
5140 init_completion(&pAdapter->cancel_rem_on_chan_var);
5141 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005142#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5143 init_completion(&pAdapter->offchannel_tx_event);
5144#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005145 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005146#ifdef FEATURE_WLAN_TDLS
5147 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005148 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005149 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305150 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005151#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005152 init_completion(&pHddCtx->mc_sus_event_var);
5153 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305154 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005155 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005156 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005157
Rajeev79dbe4c2013-10-05 11:03:42 +05305158#ifdef FEATURE_WLAN_BATCH_SCAN
5159 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5160 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5161 pAdapter->pBatchScanRsp = NULL;
5162 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005163 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08005164 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305165 mutex_init(&pAdapter->hdd_batch_scan_lock);
5166#endif
5167
Jeff Johnson295189b2012-06-20 16:38:30 -07005168 pAdapter->isLinkUpSvcNeeded = FALSE;
5169 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5170 //Init the net_device structure
5171 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5172
5173 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5174 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5175 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5176 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5177
5178 hdd_set_station_ops( pAdapter->dev );
5179
5180 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005181 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5182 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5183 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005184 /* set pWlanDev's parent to underlying device */
5185 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5186 }
5187
5188 return pAdapter;
5189}
5190
5191VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5192{
5193 struct net_device *pWlanDev = pAdapter->dev;
5194 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5195 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5196 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5197
5198 if( rtnl_lock_held )
5199 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005200 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005201 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5202 {
5203 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5204 return VOS_STATUS_E_FAILURE;
5205 }
5206 }
5207 if (register_netdevice(pWlanDev))
5208 {
5209 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5210 return VOS_STATUS_E_FAILURE;
5211 }
5212 }
5213 else
5214 {
5215 if(register_netdev(pWlanDev))
5216 {
5217 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5218 return VOS_STATUS_E_FAILURE;
5219 }
5220 }
5221 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5222
5223 return VOS_STATUS_SUCCESS;
5224}
5225
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005226static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005227{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005228 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005229
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005230 if (NULL == pAdapter)
5231 {
5232 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5233 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005234 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005235
5236 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5237 {
5238 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5239 return eHAL_STATUS_NOT_INITIALIZED;
5240 }
5241
5242 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5243
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005244#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005245 /* need to make sure all of our scheduled work has completed.
5246 * This callback is called from MC thread context, so it is safe to
5247 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005248 *
5249 * Even though this is called from MC thread context, if there is a faulty
5250 * work item in the system, that can hang this call forever. So flushing
5251 * this global work queue is not safe; and now we make sure that
5252 * individual work queues are stopped correctly. But the cancel work queue
5253 * is a GPL only API, so the proprietary version of the driver would still
5254 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005255 */
5256 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005257#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005258
5259 /* We can be blocked while waiting for scheduled work to be
5260 * flushed, and the adapter structure can potentially be freed, in
5261 * which case the magic will have been reset. So make sure the
5262 * magic is still good, and hence the adapter structure is still
5263 * valid, before signaling completion */
5264 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5265 {
5266 complete(&pAdapter->session_close_comp_var);
5267 }
5268
Jeff Johnson295189b2012-06-20 16:38:30 -07005269 return eHAL_STATUS_SUCCESS;
5270}
5271
5272VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5273{
5274 struct net_device *pWlanDev = pAdapter->dev;
5275 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5276 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5277 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5278 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5279 int rc = 0;
5280
5281 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005282 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005283 //Open a SME session for future operation
5284 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005285 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005286 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5287 {
5288 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005289 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005290 halStatus, halStatus );
5291 status = VOS_STATUS_E_FAILURE;
5292 goto error_sme_open;
5293 }
5294
5295 //Block on a completion variable. Can't wait forever though.
5296 rc = wait_for_completion_interruptible_timeout(
5297 &pAdapter->session_open_comp_var,
5298 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5299 if (!rc)
5300 {
5301 hddLog(VOS_TRACE_LEVEL_FATAL,
5302 "Session is not opened within timeout period code %08d", rc );
5303 status = VOS_STATUS_E_FAILURE;
5304 goto error_sme_open;
5305 }
5306
5307 // Register wireless extensions
5308 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5309 {
5310 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005311 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005312 halStatus, halStatus );
5313 status = VOS_STATUS_E_FAILURE;
5314 goto error_register_wext;
5315 }
5316 //Safe to register the hard_start_xmit function again
5317#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5318 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5319#else
5320 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5321#endif
5322
5323 //Set the Connection State to Not Connected
5324 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5325
5326 //Set the default operation channel
5327 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5328
5329 /* Make the default Auth Type as OPEN*/
5330 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5331
5332 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5333 {
5334 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005335 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005336 status, status );
5337 goto error_init_txrx;
5338 }
5339
5340 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5341
5342 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5343 {
5344 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005345 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005346 status, status );
5347 goto error_wmm_init;
5348 }
5349
5350 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5351
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005352#ifdef FEATURE_WLAN_TDLS
5353 if(0 != wlan_hdd_tdls_init(pAdapter))
5354 {
5355 status = VOS_STATUS_E_FAILURE;
5356 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5357 goto error_tdls_init;
5358 }
5359 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5360#endif
5361
Jeff Johnson295189b2012-06-20 16:38:30 -07005362 return VOS_STATUS_SUCCESS;
5363
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005364#ifdef FEATURE_WLAN_TDLS
5365error_tdls_init:
5366 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5367 hdd_wmm_adapter_close(pAdapter);
5368#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005369error_wmm_init:
5370 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5371 hdd_deinit_tx_rx(pAdapter);
5372error_init_txrx:
5373 hdd_UnregisterWext(pWlanDev);
5374error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005375 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005376 {
5377 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005378 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005379 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005380 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005381 {
5382 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005383 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005384 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005385 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005386 }
5387}
5388error_sme_open:
5389 return status;
5390}
5391
Jeff Johnson295189b2012-06-20 16:38:30 -07005392void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5393{
5394 hdd_cfg80211_state_t *cfgState;
5395
5396 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5397
5398 if( NULL != cfgState->buf )
5399 {
5400 int rc;
5401 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5402 rc = wait_for_completion_interruptible_timeout(
5403 &pAdapter->tx_action_cnf_event,
5404 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5405 if(!rc)
5406 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005407 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005408 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
5409 }
5410 }
5411 return;
5412}
Jeff Johnson295189b2012-06-20 16:38:30 -07005413
5414void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5415{
5416 ENTER();
5417 switch ( pAdapter->device_mode )
5418 {
5419 case WLAN_HDD_INFRA_STATION:
5420 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005421 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005422 {
5423 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5424 {
5425 hdd_deinit_tx_rx( pAdapter );
5426 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5427 }
5428
5429 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5430 {
5431 hdd_wmm_adapter_close( pAdapter );
5432 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5433 }
5434
Jeff Johnson295189b2012-06-20 16:38:30 -07005435 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005436#ifdef FEATURE_WLAN_TDLS
5437 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5438 {
5439 wlan_hdd_tdls_exit(pAdapter);
5440 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5441 }
5442#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005443
5444 break;
5445 }
5446
5447 case WLAN_HDD_SOFTAP:
5448 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005449 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305450
5451 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5452 {
5453 hdd_wmm_adapter_close( pAdapter );
5454 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5455 }
5456
Jeff Johnson295189b2012-06-20 16:38:30 -07005457 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005458
5459 hdd_unregister_hostapd(pAdapter);
5460 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005461 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005462 break;
5463 }
5464
5465 case WLAN_HDD_MONITOR:
5466 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005467 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005468 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5469 {
5470 hdd_deinit_tx_rx( pAdapter );
5471 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5472 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005473 if(NULL != pAdapterforTx)
5474 {
5475 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5476 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005477 break;
5478 }
5479
5480
5481 default:
5482 break;
5483 }
5484
5485 EXIT();
5486}
5487
5488void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5489{
5490 struct net_device *pWlanDev = pAdapter->dev;
5491
Rajeev79dbe4c2013-10-05 11:03:42 +05305492#ifdef FEATURE_WLAN_BATCH_SCAN
5493 tHddBatchScanRsp *pNode;
5494 tHddBatchScanRsp *pPrev;
5495 if (pAdapter)
5496 {
5497 mutex_lock(&pAdapter->hdd_batch_scan_lock);
5498 pNode = pAdapter->pBatchScanRsp;
5499 while (pNode)
5500 {
5501 pPrev = pNode;
5502 pNode = pNode->pNext;
5503 vos_mem_free((v_VOID_t * )pPrev);
5504 }
5505 pAdapter->pBatchScanRsp = NULL;
5506 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
5507 }
5508#endif
5509
Jeff Johnson295189b2012-06-20 16:38:30 -07005510 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5511 if( rtnl_held )
5512 {
5513 unregister_netdevice(pWlanDev);
5514 }
5515 else
5516 {
5517 unregister_netdev(pWlanDev);
5518 }
5519 // note that the pAdapter is no longer valid at this point
5520 // since the memory has been reclaimed
5521 }
5522
5523}
5524
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005525void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5526{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305527 VOS_STATUS status;
5528 hdd_adapter_t *pAdapter = NULL;
5529 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005530
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305531 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005532
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305533 /*loop through all adapters.*/
5534 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005535 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305536 pAdapter = pAdapterNode->pAdapter;
5537 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5538 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005539
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305540 { // we skip this registration for modes other than STA and P2P client modes.
5541 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5542 pAdapterNode = pNext;
5543 continue;
5544 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005545
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305546 //Apply Dynamic DTIM For P2P
5547 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5548 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5549 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5550 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5551 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5552 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5553 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5554 (eConnectionState_Associated ==
5555 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5556 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5557 {
5558 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005559
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305560 powerRequest.uIgnoreDTIM = 1;
5561 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5562
5563 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5564 {
5565 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5566 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5567 }
5568 else
5569 {
5570 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5571 }
5572
5573 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5574 * specified during Enter/Exit BMPS when LCD off*/
5575 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5576 NULL, eANI_BOOLEAN_FALSE);
5577 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5578 NULL, eANI_BOOLEAN_FALSE);
5579
5580 /* switch to the DTIM specified in cfg.ini */
5581 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5582 "Switch to DTIM %d", powerRequest.uListenInterval);
5583 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5584 break;
5585
5586 }
5587
5588 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5589 pAdapterNode = pNext;
5590 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005591}
5592
5593void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5594{
5595 /*Switch back to DTIM 1*/
5596 tSirSetPowerParamsReq powerRequest = { 0 };
5597
5598 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5599 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005600 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005601
5602 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5603 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5604 NULL, eANI_BOOLEAN_FALSE);
5605 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5606 NULL, eANI_BOOLEAN_FALSE);
5607
5608 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5609 "Switch to DTIM%d",powerRequest.uListenInterval);
5610 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5611
5612}
5613
Jeff Johnson295189b2012-06-20 16:38:30 -07005614VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5615{
5616 VOS_STATUS status = VOS_STATUS_SUCCESS;
5617
5618 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5619 {
5620 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5621 }
5622
5623 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5624 {
5625 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5626 }
5627
5628 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5629 {
5630 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5631 }
5632
5633 return status;
5634}
5635
5636VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5637{
5638 hdd_adapter_t *pAdapter = NULL;
5639 eHalStatus halStatus;
5640 VOS_STATUS status = VOS_STATUS_E_INVAL;
5641 v_BOOL_t disableBmps = FALSE;
5642 v_BOOL_t disableImps = FALSE;
5643
5644 switch(session_type)
5645 {
5646 case WLAN_HDD_INFRA_STATION:
5647 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005648 case WLAN_HDD_P2P_CLIENT:
5649 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005650 //Exit BMPS -> Is Sta/P2P Client is already connected
5651 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5652 if((NULL != pAdapter)&&
5653 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5654 {
5655 disableBmps = TRUE;
5656 }
5657
5658 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5659 if((NULL != pAdapter)&&
5660 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5661 {
5662 disableBmps = TRUE;
5663 }
5664
5665 //Exit both Bmps and Imps incase of Go/SAP Mode
5666 if((WLAN_HDD_SOFTAP == session_type) ||
5667 (WLAN_HDD_P2P_GO == session_type))
5668 {
5669 disableBmps = TRUE;
5670 disableImps = TRUE;
5671 }
5672
5673 if(TRUE == disableImps)
5674 {
5675 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5676 {
5677 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5678 }
5679 }
5680
5681 if(TRUE == disableBmps)
5682 {
5683 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5684 {
5685 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5686
5687 if(eHAL_STATUS_SUCCESS != halStatus)
5688 {
5689 status = VOS_STATUS_E_FAILURE;
5690 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
5691 VOS_ASSERT(0);
5692 return status;
5693 }
5694 }
5695
5696 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5697 {
5698 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5699
5700 if(eHAL_STATUS_SUCCESS != halStatus)
5701 {
5702 status = VOS_STATUS_E_FAILURE;
5703 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
5704 VOS_ASSERT(0);
5705 return status;
5706 }
5707 }
5708 }
5709
5710 if((TRUE == disableBmps) ||
5711 (TRUE == disableImps))
5712 {
5713 /* Now, get the chip into Full Power now */
5714 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5715 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5716 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5717
5718 if(halStatus != eHAL_STATUS_SUCCESS)
5719 {
5720 if(halStatus == eHAL_STATUS_PMC_PENDING)
5721 {
5722 //Block on a completion variable. Can't wait forever though
5723 wait_for_completion_interruptible_timeout(
5724 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5725 }
5726 else
5727 {
5728 status = VOS_STATUS_E_FAILURE;
5729 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
5730 VOS_ASSERT(0);
5731 return status;
5732 }
5733 }
5734
5735 status = VOS_STATUS_SUCCESS;
5736 }
5737
5738 break;
5739 }
5740 return status;
5741}
5742
5743hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005744 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005745 tANI_U8 rtnl_held )
5746{
5747 hdd_adapter_t *pAdapter = NULL;
5748 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5749 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5750 VOS_STATUS exitbmpsStatus;
5751
5752 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
5753
5754 //Disable BMPS incase of Concurrency
5755 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5756
5757 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5758 {
5759 //Fail to Exit BMPS
5760 VOS_ASSERT(0);
5761 return NULL;
5762 }
5763
5764 switch(session_type)
5765 {
5766 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005767 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005768 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005769 {
5770 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5771
5772 if( NULL == pAdapter )
5773 return NULL;
5774
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305775#ifdef FEATURE_WLAN_TDLS
5776 /* A Mutex Lock is introduced while changing/initializing the mode to
5777 * protect the concurrent access for the Adapters by TDLS module.
5778 */
5779 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5780 {
5781 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5782 "%s: unable to lock list", __func__);
5783 return NULL;
5784 }
5785#endif
5786
Jeff Johnsone7245742012-09-05 17:12:55 -07005787 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5788 NL80211_IFTYPE_P2P_CLIENT:
5789 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005790
Jeff Johnson295189b2012-06-20 16:38:30 -07005791 pAdapter->device_mode = session_type;
5792
5793 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305794#ifdef FEATURE_WLAN_TDLS
5795 mutex_unlock(&pHddCtx->tdls_lock);
5796#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005797 if( VOS_STATUS_SUCCESS != status )
5798 goto err_free_netdev;
5799
5800 status = hdd_register_interface( pAdapter, rtnl_held );
5801 if( VOS_STATUS_SUCCESS != status )
5802 {
5803 hdd_deinit_adapter(pHddCtx, pAdapter);
5804 goto err_free_netdev;
5805 }
5806 //Stop the Interface TX queue.
5807 netif_tx_disable(pAdapter->dev);
5808 //netif_tx_disable(pWlanDev);
5809 netif_carrier_off(pAdapter->dev);
5810
5811 break;
5812 }
5813
Jeff Johnson295189b2012-06-20 16:38:30 -07005814 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005815 case WLAN_HDD_SOFTAP:
5816 {
5817 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5818 if( NULL == pAdapter )
5819 return NULL;
5820
Jeff Johnson295189b2012-06-20 16:38:30 -07005821 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5822 NL80211_IFTYPE_AP:
5823 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005824 pAdapter->device_mode = session_type;
5825
5826 status = hdd_init_ap_mode(pAdapter);
5827 if( VOS_STATUS_SUCCESS != status )
5828 goto err_free_netdev;
5829
5830 status = hdd_register_hostapd( pAdapter, rtnl_held );
5831 if( VOS_STATUS_SUCCESS != status )
5832 {
5833 hdd_deinit_adapter(pHddCtx, pAdapter);
5834 goto err_free_netdev;
5835 }
5836
5837 netif_tx_disable(pAdapter->dev);
5838 netif_carrier_off(pAdapter->dev);
5839
5840 hdd_set_conparam( 1 );
5841 break;
5842 }
5843 case WLAN_HDD_MONITOR:
5844 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005845 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5846 if( NULL == pAdapter )
5847 return NULL;
5848
5849 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5850 pAdapter->device_mode = session_type;
5851 status = hdd_register_interface( pAdapter, rtnl_held );
5852#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5853 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5854#else
5855 pAdapter->dev->open = hdd_mon_open;
5856 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5857#endif
5858 hdd_init_tx_rx( pAdapter );
5859 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5860 //Set adapter to be used for data tx. It will use either GO or softap.
5861 pAdapter->sessionCtx.monitor.pAdapterForTx =
5862 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005863 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5864 {
5865 pAdapter->sessionCtx.monitor.pAdapterForTx =
5866 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5867 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005868 /* This workqueue will be used to transmit management packet over
5869 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005870 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5871 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5872 return NULL;
5873 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005874
Jeff Johnson295189b2012-06-20 16:38:30 -07005875 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5876 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005877 }
5878 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005879 case WLAN_HDD_FTM:
5880 {
5881 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5882
5883 if( NULL == pAdapter )
5884 return NULL;
5885 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5886 * message while loading driver in FTM mode. */
5887 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5888 pAdapter->device_mode = session_type;
5889 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305890
5891 hdd_init_tx_rx( pAdapter );
5892
5893 //Stop the Interface TX queue.
5894 netif_tx_disable(pAdapter->dev);
5895 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005896 }
5897 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005898 default:
5899 {
5900 VOS_ASSERT(0);
5901 return NULL;
5902 }
5903 }
5904
5905
5906 if( VOS_STATUS_SUCCESS == status )
5907 {
5908 //Add it to the hdd's session list.
5909 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5910 if( NULL == pHddAdapterNode )
5911 {
5912 status = VOS_STATUS_E_NOMEM;
5913 }
5914 else
5915 {
5916 pHddAdapterNode->pAdapter = pAdapter;
5917 status = hdd_add_adapter_back ( pHddCtx,
5918 pHddAdapterNode );
5919 }
5920 }
5921
5922 if( VOS_STATUS_SUCCESS != status )
5923 {
5924 if( NULL != pAdapter )
5925 {
5926 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5927 pAdapter = NULL;
5928 }
5929 if( NULL != pHddAdapterNode )
5930 {
5931 vos_mem_free( pHddAdapterNode );
5932 }
5933
5934 goto resume_bmps;
5935 }
5936
5937 if(VOS_STATUS_SUCCESS == status)
5938 {
5939 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5940
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005941 //Initialize the WoWL service
5942 if(!hdd_init_wowl(pAdapter))
5943 {
5944 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5945 goto err_free_netdev;
5946 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005947 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005948 return pAdapter;
5949
5950err_free_netdev:
5951 free_netdev(pAdapter->dev);
5952 wlan_hdd_release_intf_addr( pHddCtx,
5953 pAdapter->macAddressCurrent.bytes );
5954
5955resume_bmps:
5956 //If bmps disabled enable it
5957 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5958 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305959 if (pHddCtx->hdd_wlan_suspended)
5960 {
5961 hdd_set_pwrparams(pHddCtx);
5962 }
5963 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005964 }
5965 return NULL;
5966}
5967
5968VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5969 tANI_U8 rtnl_held )
5970{
5971 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5972 VOS_STATUS status;
5973
5974 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5975 if( VOS_STATUS_SUCCESS != status )
5976 return status;
5977
5978 while ( pCurrent->pAdapter != pAdapter )
5979 {
5980 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5981 if( VOS_STATUS_SUCCESS != status )
5982 break;
5983
5984 pCurrent = pNext;
5985 }
5986 pAdapterNode = pCurrent;
5987 if( VOS_STATUS_SUCCESS == status )
5988 {
5989 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5990 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305991
5992#ifdef FEATURE_WLAN_TDLS
5993
5994 /* A Mutex Lock is introduced while changing/initializing the mode to
5995 * protect the concurrent access for the Adapters by TDLS module.
5996 */
5997 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5998 {
5999 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6000 "%s: unable to lock list", __func__);
6001 return VOS_STATUS_E_FAILURE;
6002 }
6003#endif
6004
Jeff Johnson295189b2012-06-20 16:38:30 -07006005 hdd_remove_adapter( pHddCtx, pAdapterNode );
6006 vos_mem_free( pAdapterNode );
6007
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306008#ifdef FEATURE_WLAN_TDLS
6009 mutex_unlock(&pHddCtx->tdls_lock);
6010#endif
6011
Jeff Johnson295189b2012-06-20 16:38:30 -07006012
6013 /* If there is a single session of STA/P2P client, re-enable BMPS */
6014 if ((!vos_concurrent_sessions_running()) &&
6015 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6016 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6017 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306018 if (pHddCtx->hdd_wlan_suspended)
6019 {
6020 hdd_set_pwrparams(pHddCtx);
6021 }
6022 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006023 }
6024
6025 return VOS_STATUS_SUCCESS;
6026 }
6027
6028 return VOS_STATUS_E_FAILURE;
6029}
6030
6031VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6032{
6033 hdd_adapter_list_node_t *pHddAdapterNode;
6034 VOS_STATUS status;
6035
6036 ENTER();
6037
6038 do
6039 {
6040 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6041 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6042 {
6043 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6044 vos_mem_free( pHddAdapterNode );
6045 }
6046 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6047
6048 EXIT();
6049
6050 return VOS_STATUS_SUCCESS;
6051}
6052
6053void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6054{
6055 v_U8_t addIE[1] = {0};
6056
6057 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6058 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6059 eANI_BOOLEAN_FALSE) )
6060 {
6061 hddLog(LOGE,
6062 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
6063 }
6064
6065 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6066 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6067 eANI_BOOLEAN_FALSE) )
6068 {
6069 hddLog(LOGE,
6070 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
6071 }
6072
6073 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6074 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6075 eANI_BOOLEAN_FALSE) )
6076 {
6077 hddLog(LOGE,
6078 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
6079 }
6080}
6081
6082VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6083{
6084 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6085 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6086 union iwreq_data wrqu;
6087
6088 ENTER();
6089
6090 switch(pAdapter->device_mode)
6091 {
6092 case WLAN_HDD_INFRA_STATION:
6093 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006094 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006095 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6096 {
6097 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6098 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6099 pAdapter->sessionId,
6100 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6101 else
6102 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6103 pAdapter->sessionId,
6104 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6105 //success implies disconnect command got queued up successfully
6106 if(halStatus == eHAL_STATUS_SUCCESS)
6107 {
6108 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
6109 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6110 }
6111 memset(&wrqu, '\0', sizeof(wrqu));
6112 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6113 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6114 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6115 }
6116 else
6117 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306118 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006119 }
6120
6121 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6122 {
6123 INIT_COMPLETION(pAdapter->session_close_comp_var);
6124 if (eHAL_STATUS_SUCCESS ==
6125 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6126 hdd_smeCloseSessionCallback, pAdapter))
6127 {
6128 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006129 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006130 &pAdapter->session_close_comp_var,
6131 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
6132 }
6133 }
6134
6135 break;
6136
6137 case WLAN_HDD_SOFTAP:
6138 case WLAN_HDD_P2P_GO:
6139 //Any softap specific cleanup here...
6140 mutex_lock(&pHddCtx->sap_lock);
6141 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6142 {
6143 VOS_STATUS status;
6144 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6145
6146 //Stop Bss.
6147 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6148 if (VOS_IS_STATUS_SUCCESS(status))
6149 {
6150 hdd_hostapd_state_t *pHostapdState =
6151 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6152
6153 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6154
6155 if (!VOS_IS_STATUS_SUCCESS(status))
6156 {
6157 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006158 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006159 }
6160 }
6161 else
6162 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006163 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006164 }
6165 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6166
6167 if (eHAL_STATUS_FAILURE ==
6168 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6169 0, NULL, eANI_BOOLEAN_FALSE))
6170 {
6171 hddLog(LOGE,
6172 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006173 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006174 }
6175
6176 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6177 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6178 eANI_BOOLEAN_FALSE) )
6179 {
6180 hddLog(LOGE,
6181 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6182 }
6183
6184 // Reset WNI_CFG_PROBE_RSP Flags
6185 wlan_hdd_reset_prob_rspies(pAdapter);
6186 kfree(pAdapter->sessionCtx.ap.beacon);
6187 pAdapter->sessionCtx.ap.beacon = NULL;
6188 }
6189 mutex_unlock(&pHddCtx->sap_lock);
6190 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006191
Jeff Johnson295189b2012-06-20 16:38:30 -07006192 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006193#ifdef WLAN_OPEN_SOURCE
6194 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6195#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006196 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006197
Jeff Johnson295189b2012-06-20 16:38:30 -07006198 default:
6199 break;
6200 }
6201
6202 EXIT();
6203 return VOS_STATUS_SUCCESS;
6204}
6205
6206VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6207{
6208 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6209 VOS_STATUS status;
6210 hdd_adapter_t *pAdapter;
6211
6212 ENTER();
6213
6214 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6215
6216 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6217 {
6218 pAdapter = pAdapterNode->pAdapter;
6219 netif_tx_disable(pAdapter->dev);
6220 netif_carrier_off(pAdapter->dev);
6221
6222 hdd_stop_adapter( pHddCtx, pAdapter );
6223
6224 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6225 pAdapterNode = pNext;
6226 }
6227
6228 EXIT();
6229
6230 return VOS_STATUS_SUCCESS;
6231}
6232
6233VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6234{
6235 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6236 VOS_STATUS status;
6237 hdd_adapter_t *pAdapter;
6238
6239 ENTER();
6240
6241 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6242
6243 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6244 {
6245 pAdapter = pAdapterNode->pAdapter;
6246 netif_tx_disable(pAdapter->dev);
6247 netif_carrier_off(pAdapter->dev);
6248
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006249 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6250
Jeff Johnson295189b2012-06-20 16:38:30 -07006251 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306252 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6253 {
6254 hdd_wmm_adapter_close( pAdapter );
6255 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6256 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006257
6258 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6259 pAdapterNode = pNext;
6260 }
6261
6262 EXIT();
6263
6264 return VOS_STATUS_SUCCESS;
6265}
6266
6267VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6268{
6269 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6270 VOS_STATUS status;
6271 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306272 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006273
6274 ENTER();
6275
6276 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6277
6278 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6279 {
6280 pAdapter = pAdapterNode->pAdapter;
6281
6282 switch(pAdapter->device_mode)
6283 {
6284 case WLAN_HDD_INFRA_STATION:
6285 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006286 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306287
6288 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6289
Jeff Johnson295189b2012-06-20 16:38:30 -07006290 hdd_init_station_mode(pAdapter);
6291 /* Open the gates for HDD to receive Wext commands */
6292 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006293 pHddCtx->scan_info.mScanPending = FALSE;
6294 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006295
6296 //Trigger the initial scan
6297 hdd_wlan_initial_scan(pAdapter);
6298
6299 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306300 if (eConnectionState_Associated == connState ||
6301 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006302 {
6303 union iwreq_data wrqu;
6304 memset(&wrqu, '\0', sizeof(wrqu));
6305 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6306 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6307 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006308 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006309
Jeff Johnson295189b2012-06-20 16:38:30 -07006310 /* indicate disconnected event to nl80211 */
6311 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6312 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006313 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306314 else if (eConnectionState_Connecting == connState)
6315 {
6316 /*
6317 * Indicate connect failure to supplicant if we were in the
6318 * process of connecting
6319 */
6320 cfg80211_connect_result(pAdapter->dev, NULL,
6321 NULL, 0, NULL, 0,
6322 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6323 GFP_KERNEL);
6324 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006325 break;
6326
6327 case WLAN_HDD_SOFTAP:
6328 /* softAP can handle SSR */
6329 break;
6330
6331 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006332 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006333 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006334 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006335 break;
6336
6337 case WLAN_HDD_MONITOR:
6338 /* monitor interface start */
6339 break;
6340 default:
6341 break;
6342 }
6343
6344 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6345 pAdapterNode = pNext;
6346 }
6347
6348 EXIT();
6349
6350 return VOS_STATUS_SUCCESS;
6351}
6352
6353VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6354{
6355 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6356 hdd_adapter_t *pAdapter;
6357 VOS_STATUS status;
6358 v_U32_t roamId;
6359
6360 ENTER();
6361
6362 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6363
6364 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6365 {
6366 pAdapter = pAdapterNode->pAdapter;
6367
6368 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6369 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6370 {
6371 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6372 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6373
6374 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6375 init_completion(&pAdapter->disconnect_comp_var);
6376 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6377 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6378
6379 wait_for_completion_interruptible_timeout(
6380 &pAdapter->disconnect_comp_var,
6381 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6382
6383 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6384 pHddCtx->isAmpAllowed = VOS_FALSE;
6385 sme_RoamConnect(pHddCtx->hHal,
6386 pAdapter->sessionId, &(pWextState->roamProfile),
6387 &roamId);
6388 }
6389
6390 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6391 pAdapterNode = pNext;
6392 }
6393
6394 EXIT();
6395
6396 return VOS_STATUS_SUCCESS;
6397}
6398
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006399void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6400{
6401 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6402 VOS_STATUS status;
6403 hdd_adapter_t *pAdapter;
6404 hdd_station_ctx_t *pHddStaCtx;
6405 hdd_ap_ctx_t *pHddApCtx;
6406 hdd_hostapd_state_t * pHostapdState;
6407 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6408 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6409 const char *p2pMode = "DEV";
6410 const char *ccMode = "Standalone";
6411 int n;
6412
6413 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6414 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6415 {
6416 pAdapter = pAdapterNode->pAdapter;
6417 switch (pAdapter->device_mode) {
6418 case WLAN_HDD_INFRA_STATION:
6419 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6420 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6421 staChannel = pHddStaCtx->conn_info.operationChannel;
6422 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6423 }
6424 break;
6425 case WLAN_HDD_P2P_CLIENT:
6426 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6427 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6428 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6429 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6430 p2pMode = "CLI";
6431 }
6432 break;
6433 case WLAN_HDD_P2P_GO:
6434 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6435 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6436 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6437 p2pChannel = pHddApCtx->operatingChannel;
6438 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6439 }
6440 p2pMode = "GO";
6441 break;
6442 case WLAN_HDD_SOFTAP:
6443 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6444 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6445 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6446 apChannel = pHddApCtx->operatingChannel;
6447 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6448 }
6449 break;
6450 default:
6451 break;
6452 }
6453 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6454 pAdapterNode = pNext;
6455 }
6456 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6457 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6458 }
6459 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6460 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6461 if (p2pChannel > 0) {
6462 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6463 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6464 }
6465 if (apChannel > 0) {
6466 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6467 apChannel, MAC_ADDR_ARRAY(apBssid));
6468 }
6469
6470 if (p2pChannel > 0 && apChannel > 0) {
6471 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6472 }
6473}
6474
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006475bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006476{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006477 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006478}
6479
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006480/* Once SSR is disabled then it cannot be set. */
6481void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006482{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006483 if (HDD_SSR_DISABLED == isSsrRequired)
6484 return;
6485
Jeff Johnson295189b2012-06-20 16:38:30 -07006486 isSsrRequired = value;
6487}
6488
6489VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6490 hdd_adapter_list_node_t** ppAdapterNode)
6491{
6492 VOS_STATUS status;
6493 spin_lock(&pHddCtx->hddAdapters.lock);
6494 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6495 (hdd_list_node_t**) ppAdapterNode );
6496 spin_unlock(&pHddCtx->hddAdapters.lock);
6497 return status;
6498}
6499
6500VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6501 hdd_adapter_list_node_t* pAdapterNode,
6502 hdd_adapter_list_node_t** pNextAdapterNode)
6503{
6504 VOS_STATUS status;
6505 spin_lock(&pHddCtx->hddAdapters.lock);
6506 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6507 (hdd_list_node_t*) pAdapterNode,
6508 (hdd_list_node_t**)pNextAdapterNode );
6509
6510 spin_unlock(&pHddCtx->hddAdapters.lock);
6511 return status;
6512}
6513
6514VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6515 hdd_adapter_list_node_t* pAdapterNode)
6516{
6517 VOS_STATUS status;
6518 spin_lock(&pHddCtx->hddAdapters.lock);
6519 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6520 &pAdapterNode->node );
6521 spin_unlock(&pHddCtx->hddAdapters.lock);
6522 return status;
6523}
6524
6525VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6526 hdd_adapter_list_node_t** ppAdapterNode)
6527{
6528 VOS_STATUS status;
6529 spin_lock(&pHddCtx->hddAdapters.lock);
6530 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6531 (hdd_list_node_t**) ppAdapterNode );
6532 spin_unlock(&pHddCtx->hddAdapters.lock);
6533 return status;
6534}
6535
6536VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6537 hdd_adapter_list_node_t* pAdapterNode)
6538{
6539 VOS_STATUS status;
6540 spin_lock(&pHddCtx->hddAdapters.lock);
6541 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6542 (hdd_list_node_t*) pAdapterNode );
6543 spin_unlock(&pHddCtx->hddAdapters.lock);
6544 return status;
6545}
6546
6547VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6548 hdd_adapter_list_node_t* pAdapterNode)
6549{
6550 VOS_STATUS status;
6551 spin_lock(&pHddCtx->hddAdapters.lock);
6552 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6553 (hdd_list_node_t*) pAdapterNode );
6554 spin_unlock(&pHddCtx->hddAdapters.lock);
6555 return status;
6556}
6557
6558hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6559 tSirMacAddr macAddr )
6560{
6561 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6562 hdd_adapter_t *pAdapter;
6563 VOS_STATUS status;
6564
6565 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6566
6567 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6568 {
6569 pAdapter = pAdapterNode->pAdapter;
6570
6571 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6572 macAddr, sizeof(tSirMacAddr) ) )
6573 {
6574 return pAdapter;
6575 }
6576 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6577 pAdapterNode = pNext;
6578 }
6579
6580 return NULL;
6581
6582}
6583
6584hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6585{
6586 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6587 hdd_adapter_t *pAdapter;
6588 VOS_STATUS status;
6589
6590 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6591
6592 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6593 {
6594 pAdapter = pAdapterNode->pAdapter;
6595
6596 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6597 IFNAMSIZ ) )
6598 {
6599 return pAdapter;
6600 }
6601 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6602 pAdapterNode = pNext;
6603 }
6604
6605 return NULL;
6606
6607}
6608
6609hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6610{
6611 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6612 hdd_adapter_t *pAdapter;
6613 VOS_STATUS status;
6614
6615 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6616
6617 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6618 {
6619 pAdapter = pAdapterNode->pAdapter;
6620
6621 if( pAdapter && (mode == pAdapter->device_mode) )
6622 {
6623 return pAdapter;
6624 }
6625 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6626 pAdapterNode = pNext;
6627 }
6628
6629 return NULL;
6630
6631}
6632
6633//Remove this function later
6634hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6635{
6636 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6637 hdd_adapter_t *pAdapter;
6638 VOS_STATUS status;
6639
6640 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6641
6642 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6643 {
6644 pAdapter = pAdapterNode->pAdapter;
6645
6646 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6647 {
6648 return pAdapter;
6649 }
6650
6651 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6652 pAdapterNode = pNext;
6653 }
6654
6655 return NULL;
6656
6657}
6658
Jeff Johnson295189b2012-06-20 16:38:30 -07006659/**---------------------------------------------------------------------------
6660
6661 \brief hdd_set_monitor_tx_adapter() -
6662
6663 This API initializes the adapter to be used while transmitting on monitor
6664 adapter.
6665
6666 \param - pHddCtx - Pointer to the HDD context.
6667 pAdapter - Adapter that will used for TX. This can be NULL.
6668 \return - None.
6669 --------------------------------------------------------------------------*/
6670void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6671{
6672 hdd_adapter_t *pMonAdapter;
6673
6674 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6675
6676 if( NULL != pMonAdapter )
6677 {
6678 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6679 }
6680}
Jeff Johnson295189b2012-06-20 16:38:30 -07006681/**---------------------------------------------------------------------------
6682
6683 \brief hdd_select_queue() -
6684
6685 This API returns the operating channel of the requested device mode
6686
6687 \param - pHddCtx - Pointer to the HDD context.
6688 - mode - Device mode for which operating channel is required
6689 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6690 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6691 \return - channel number. "0" id the requested device is not found OR it is not connected.
6692 --------------------------------------------------------------------------*/
6693v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6694{
6695 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6696 VOS_STATUS status;
6697 hdd_adapter_t *pAdapter;
6698 v_U8_t operatingChannel = 0;
6699
6700 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6701
6702 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6703 {
6704 pAdapter = pAdapterNode->pAdapter;
6705
6706 if( mode == pAdapter->device_mode )
6707 {
6708 switch(pAdapter->device_mode)
6709 {
6710 case WLAN_HDD_INFRA_STATION:
6711 case WLAN_HDD_P2P_CLIENT:
6712 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6713 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6714 break;
6715 case WLAN_HDD_SOFTAP:
6716 case WLAN_HDD_P2P_GO:
6717 /*softap connection info */
6718 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6719 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6720 break;
6721 default:
6722 break;
6723 }
6724
6725 break; //Found the device of interest. break the loop
6726 }
6727
6728 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6729 pAdapterNode = pNext;
6730 }
6731 return operatingChannel;
6732}
6733
6734#ifdef WLAN_FEATURE_PACKET_FILTERING
6735/**---------------------------------------------------------------------------
6736
6737 \brief hdd_set_multicast_list() -
6738
6739 This used to set the multicast address list.
6740
6741 \param - dev - Pointer to the WLAN device.
6742 - skb - Pointer to OS packet (sk_buff).
6743 \return - success/fail
6744
6745 --------------------------------------------------------------------------*/
6746static void hdd_set_multicast_list(struct net_device *dev)
6747{
6748 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006749 int mc_count;
6750 int i = 0;
6751 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306752
6753 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006754 {
6755 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306756 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006757 return;
6758 }
6759
6760 if (dev->flags & IFF_ALLMULTI)
6761 {
6762 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006763 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306764 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006765 }
6766 else
6767 {
6768 mc_count = netdev_mc_count(dev);
6769 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006770 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006771 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6772 {
6773 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006774 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306775 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006776 return;
6777 }
6778
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306779 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006780
6781 netdev_for_each_mc_addr(ha, dev) {
6782 if (i == mc_count)
6783 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306784 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6785 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
6786 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006787 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306788 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006789 i++;
6790 }
6791 }
6792 return;
6793}
6794#endif
6795
6796/**---------------------------------------------------------------------------
6797
6798 \brief hdd_select_queue() -
6799
6800 This function is registered with the Linux OS for network
6801 core to decide which queue to use first.
6802
6803 \param - dev - Pointer to the WLAN device.
6804 - skb - Pointer to OS packet (sk_buff).
6805 \return - ac, Queue Index/access category corresponding to UP in IP header
6806
6807 --------------------------------------------------------------------------*/
6808v_U16_t hdd_select_queue(struct net_device *dev,
6809 struct sk_buff *skb)
6810{
6811 return hdd_wmm_select_queue(dev, skb);
6812}
6813
6814
6815/**---------------------------------------------------------------------------
6816
6817 \brief hdd_wlan_initial_scan() -
6818
6819 This function triggers the initial scan
6820
6821 \param - pAdapter - Pointer to the HDD adapter.
6822
6823 --------------------------------------------------------------------------*/
6824void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6825{
6826 tCsrScanRequest scanReq;
6827 tCsrChannelInfo channelInfo;
6828 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006829 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006830 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6831
6832 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6833 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6834 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6835
6836 if(sme_Is11dSupported(pHddCtx->hHal))
6837 {
6838 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6839 if ( HAL_STATUS_SUCCESS( halStatus ) )
6840 {
6841 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6842 if( !scanReq.ChannelInfo.ChannelList )
6843 {
6844 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6845 vos_mem_free(channelInfo.ChannelList);
6846 return;
6847 }
6848 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6849 channelInfo.numOfChannels);
6850 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6851 vos_mem_free(channelInfo.ChannelList);
6852 }
6853
6854 scanReq.scanType = eSIR_PASSIVE_SCAN;
6855 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6856 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6857 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6858 }
6859 else
6860 {
6861 scanReq.scanType = eSIR_ACTIVE_SCAN;
6862 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6863 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6864 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6865 }
6866
6867 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6868 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6869 {
6870 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6871 __func__, halStatus );
6872 }
6873
6874 if(sme_Is11dSupported(pHddCtx->hHal))
6875 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6876}
6877
6878struct fullPowerContext
6879{
6880 struct completion completion;
6881 unsigned int magic;
6882};
6883#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6884
6885/**---------------------------------------------------------------------------
6886
6887 \brief hdd_full_power_callback() - HDD full power callback function
6888
6889 This is the function invoked by SME to inform the result of a full power
6890 request issued by HDD
6891
6892 \param - callbackcontext - Pointer to cookie
6893 \param - status - result of request
6894
6895 \return - None
6896
6897 --------------------------------------------------------------------------*/
6898static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6899{
6900 struct fullPowerContext *pContext = callbackContext;
6901
6902 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306903 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006904
6905 if (NULL == callbackContext)
6906 {
6907 hddLog(VOS_TRACE_LEVEL_ERROR,
6908 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006909 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006910 return;
6911 }
6912
6913 /* there is a race condition that exists between this callback function
6914 and the caller since the caller could time out either before or
6915 while this code is executing. we'll assume the timeout hasn't
6916 occurred, but we'll verify that right before we save our work */
6917
6918 if (POWER_CONTEXT_MAGIC != pContext->magic)
6919 {
6920 /* the caller presumably timed out so there is nothing we can do */
6921 hddLog(VOS_TRACE_LEVEL_WARN,
6922 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006923 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006924 return;
6925 }
6926
6927 /* the race is on. caller could have timed out immediately after
6928 we verified the magic, but if so, caller will wait a short time
6929 for us to notify the caller, so the context will stay valid */
6930 complete(&pContext->completion);
6931}
6932
6933/**---------------------------------------------------------------------------
6934
6935 \brief hdd_wlan_exit() - HDD WLAN exit function
6936
6937 This is the driver exit point (invoked during rmmod)
6938
6939 \param - pHddCtx - Pointer to the HDD Context
6940
6941 \return - None
6942
6943 --------------------------------------------------------------------------*/
6944void hdd_wlan_exit(hdd_context_t *pHddCtx)
6945{
6946 eHalStatus halStatus;
6947 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6948 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306949 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006950 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006951 struct fullPowerContext powerContext;
6952 long lrc;
6953
6954 ENTER();
6955
Jeff Johnson88ba7742013-02-27 14:36:02 -08006956 if (VOS_FTM_MODE != hdd_get_conparam())
6957 {
6958 // Unloading, restart logic is no more required.
6959 wlan_hdd_restart_deinit(pHddCtx);
6960 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006961
Jeff Johnson295189b2012-06-20 16:38:30 -07006962 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006963 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006964 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006965 {
6966 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6967 WLAN_HDD_INFRA_STATION);
6968 if (pAdapter == NULL)
6969 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6970
6971 if (pAdapter != NULL)
6972 {
6973 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6974 hdd_UnregisterWext(pAdapter->dev);
6975 }
6976 }
6977 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006978
Jeff Johnson295189b2012-06-20 16:38:30 -07006979 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006980 {
6981 wlan_hdd_ftm_close(pHddCtx);
6982 goto free_hdd_ctx;
6983 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006984 //Stop the Interface TX queue.
6985 //netif_tx_disable(pWlanDev);
6986 //netif_carrier_off(pWlanDev);
6987
Jeff Johnson295189b2012-06-20 16:38:30 -07006988 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6989 {
6990 pAdapter = hdd_get_adapter(pHddCtx,
6991 WLAN_HDD_SOFTAP);
6992 }
6993 else
6994 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006995 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006996 {
6997 pAdapter = hdd_get_adapter(pHddCtx,
6998 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006999 if (pAdapter == NULL)
7000 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07007001 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007002 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007003 /* DeRegister with platform driver as client for Suspend/Resume */
7004 vosStatus = hddDeregisterPmOps(pHddCtx);
7005 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7006 {
7007 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7008 VOS_ASSERT(0);
7009 }
7010
7011 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7012 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7013 {
7014 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7015 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007016
7017 // Cancel any outstanding scan requests. We are about to close all
7018 // of our adapters, but an adapter structure is what SME passes back
7019 // to our callback function. Hence if there are any outstanding scan
7020 // requests then there is a race condition between when the adapter
7021 // is closed and when the callback is invoked. We try to resolve that
7022 // race condition here by canceling any outstanding scans before we
7023 // close the adapters.
7024 // Note that the scans may be cancelled in an asynchronous manner, so
7025 // ideally there needs to be some kind of synchronization. Rather than
7026 // introduce a new synchronization here, we will utilize the fact that
7027 // we are about to Request Full Power, and since that is synchronized,
7028 // the expectation is that by the time Request Full Power has completed,
7029 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007030 if (NULL != pAdapter)
7031 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
7032 else
7033 hddLog(VOS_TRACE_LEVEL_ERROR,
7034 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007035
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007036 //Stop the traffic monitor timer
7037 if ( VOS_TIMER_STATE_RUNNING ==
7038 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7039 {
7040 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7041 }
7042
7043 // Destroy the traffic monitor timer
7044 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7045 &pHddCtx->tx_rx_trafficTmr)))
7046 {
7047 hddLog(VOS_TRACE_LEVEL_ERROR,
7048 "%s: Cannot deallocate Traffic monitor timer", __func__);
7049 }
7050
Jeff Johnson295189b2012-06-20 16:38:30 -07007051 //Disable IMPS/BMPS as we do not want the device to enter any power
7052 //save mode during shutdown
7053 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7054 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7055 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7056
7057 //Ensure that device is in full power as we will touch H/W during vos_Stop
7058 init_completion(&powerContext.completion);
7059 powerContext.magic = POWER_CONTEXT_MAGIC;
7060
7061 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7062 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7063
7064 if (eHAL_STATUS_SUCCESS != halStatus)
7065 {
7066 if (eHAL_STATUS_PMC_PENDING == halStatus)
7067 {
7068 /* request was sent -- wait for the response */
7069 lrc = wait_for_completion_interruptible_timeout(
7070 &powerContext.completion,
7071 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
7072 /* either we have a response or we timed out
7073 either way, first invalidate our magic */
7074 powerContext.magic = 0;
7075 if (lrc <= 0)
7076 {
7077 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007078 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007079 /* there is a race condition such that the callback
7080 function could be executing at the same time we are. of
7081 primary concern is if the callback function had already
7082 verified the "magic" but hasn't yet set the completion
7083 variable. Since the completion variable is on our
7084 stack, we'll delay just a bit to make sure the data is
7085 still valid if that is the case */
7086 msleep(50);
7087 }
7088 }
7089 else
7090 {
7091 hddLog(VOS_TRACE_LEVEL_ERROR,
7092 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007093 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007094 VOS_ASSERT(0);
7095 /* continue -- need to clean up as much as possible */
7096 }
7097 }
7098
Yue Ma0d4891e2013-08-06 17:01:45 -07007099 hdd_debugfs_exit(pHddCtx);
7100
Jeff Johnson295189b2012-06-20 16:38:30 -07007101 // Unregister the Net Device Notifier
7102 unregister_netdevice_notifier(&hdd_netdev_notifier);
7103
Jeff Johnson295189b2012-06-20 16:38:30 -07007104 hdd_stop_all_adapters( pHddCtx );
7105
Jeff Johnson295189b2012-06-20 16:38:30 -07007106#ifdef WLAN_BTAMP_FEATURE
7107 vosStatus = WLANBAP_Stop(pVosContext);
7108 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7109 {
7110 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7111 "%s: Failed to stop BAP",__func__);
7112 }
7113#endif //WLAN_BTAMP_FEATURE
7114
7115 //Stop all the modules
7116 vosStatus = vos_stop( pVosContext );
7117 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7118 {
7119 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7120 "%s: Failed to stop VOSS",__func__);
7121 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7122 }
7123
Jeff Johnson295189b2012-06-20 16:38:30 -07007124 //Assert Deep sleep signal now to put Libra HW in lowest power state
7125 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7126 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7127
7128 //Vote off any PMIC voltage supplies
7129 vos_chipPowerDown(NULL, NULL, NULL);
7130
7131 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7132
Leo Chang59cdc7e2013-07-10 10:08:21 -07007133
Jeff Johnson295189b2012-06-20 16:38:30 -07007134 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007135 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007136
7137 //Close the scheduler before calling vos_close to make sure no thread is
7138 // scheduled after the each module close is called i.e after all the data
7139 // structures are freed.
7140 vosStatus = vos_sched_close( pVosContext );
7141 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7142 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7143 "%s: Failed to close VOSS Scheduler",__func__);
7144 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7145 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007146#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007147#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7148 /* Destroy the wake lock */
7149 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7150#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007151 /* Destroy the wake lock */
7152 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007153#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007154
7155 //Close VOSS
7156 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7157 vos_close(pVosContext);
7158
Jeff Johnson295189b2012-06-20 16:38:30 -07007159 //Close Watchdog
7160 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7161 vos_watchdog_close(pVosContext);
7162
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307163 //Clean up HDD Nlink Service
7164 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007165#ifdef WLAN_KD_READY_NOTIFIER
7166 nl_srv_exit(pHddCtx->ptt_pid);
7167#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307168 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007169#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307170
Jeff Johnson295189b2012-06-20 16:38:30 -07007171 /* Cancel the vote for XO Core ON.
7172 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7173 * exited at this point
7174 */
7175 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
7176 " when WLAN is turned OFF\n");
7177 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7178 {
7179 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7180 " Not returning failure."
7181 " Power consumed will be high\n");
7182 }
7183
7184 hdd_close_all_adapters( pHddCtx );
7185
7186
7187 //Free up dynamically allocated members inside HDD Adapter
7188 kfree(pHddCtx->cfg_ini);
7189 pHddCtx->cfg_ini= NULL;
7190
7191 /* free the power on lock from platform driver */
7192 if (free_riva_power_on_lock("wlan"))
7193 {
7194 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7195 __func__);
7196 }
7197
Jeff Johnson88ba7742013-02-27 14:36:02 -08007198free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007199 /* FTM mode, WIPHY did not registered
7200 If un-register here, system crash will happen */
7201 if (VOS_FTM_MODE != hdd_get_conparam())
7202 {
7203 wiphy_unregister(wiphy) ;
7204 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007205 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007206 if (hdd_is_ssr_required())
7207 {
7208 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007209 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007210 msleep(5000);
7211 }
7212 hdd_set_ssr_required (VOS_FALSE);
7213}
7214
7215
7216/**---------------------------------------------------------------------------
7217
7218 \brief hdd_update_config_from_nv() - Function to update the contents of
7219 the running configuration with parameters taken from NV storage
7220
7221 \param - pHddCtx - Pointer to the HDD global context
7222
7223 \return - VOS_STATUS_SUCCESS if successful
7224
7225 --------------------------------------------------------------------------*/
7226static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7227{
Jeff Johnson295189b2012-06-20 16:38:30 -07007228 v_BOOL_t itemIsValid = VOS_FALSE;
7229 VOS_STATUS status;
7230 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7231 v_U8_t macLoop;
7232
7233 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7234 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7235 if(status != VOS_STATUS_SUCCESS)
7236 {
7237 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
7238 return VOS_STATUS_E_FAILURE;
7239 }
7240
7241 if (itemIsValid == VOS_TRUE)
7242 {
7243 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
7244 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7245 VOS_MAX_CONCURRENCY_PERSONA);
7246 if(status != VOS_STATUS_SUCCESS)
7247 {
7248 /* Get MAC from NV fail, not update CFG info
7249 * INI MAC value will be used for MAC setting */
7250 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
7251 return VOS_STATUS_E_FAILURE;
7252 }
7253
7254 /* If first MAC is not valid, treat all others are not valid
7255 * Then all MACs will be got from ini file */
7256 if(vos_is_macaddr_zero(&macFromNV[0]))
7257 {
7258 /* MAC address in NV file is not configured yet */
7259 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7260 return VOS_STATUS_E_INVAL;
7261 }
7262
7263 /* Get MAC address from NV, update CFG info */
7264 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7265 {
7266 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7267 {
7268 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
7269 /* This MAC is not valid, skip it
7270 * This MAC will be got from ini file */
7271 }
7272 else
7273 {
7274 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7275 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7276 VOS_MAC_ADDR_SIZE);
7277 }
7278 }
7279 }
7280 else
7281 {
7282 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7283 return VOS_STATUS_E_FAILURE;
7284 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007285
Jeff Johnson295189b2012-06-20 16:38:30 -07007286
7287 return VOS_STATUS_SUCCESS;
7288}
7289
7290/**---------------------------------------------------------------------------
7291
7292 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7293
7294 \param - pAdapter - Pointer to the HDD
7295
7296 \return - None
7297
7298 --------------------------------------------------------------------------*/
7299VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7300{
7301 eHalStatus halStatus;
7302 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307303 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007304
Jeff Johnson295189b2012-06-20 16:38:30 -07007305
7306 // Send ready indication to the HDD. This will kick off the MAC
7307 // into a 'running' state and should kick off an initial scan.
7308 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7309 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7310 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307311 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007312 "code %08d [x%08x]",__func__, halStatus, halStatus );
7313 return VOS_STATUS_E_FAILURE;
7314 }
7315
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307316 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007317 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7318 // And RIVA will crash
7319 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7320 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307321 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7322 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7323
7324
Jeff Johnson295189b2012-06-20 16:38:30 -07007325 return VOS_STATUS_SUCCESS;
7326}
7327
Jeff Johnson295189b2012-06-20 16:38:30 -07007328/* wake lock APIs for HDD */
7329void hdd_prevent_suspend(void)
7330{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007331#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007332 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007333#else
7334 wcnss_prevent_suspend();
7335#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007336}
7337
7338void hdd_allow_suspend(void)
7339{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007340#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007341 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007342#else
7343 wcnss_allow_suspend();
7344#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007345}
7346
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007347void hdd_allow_suspend_timeout(v_U32_t timeout)
7348{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007349#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007350 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007351#else
7352 /* Do nothing as there is no API in wcnss for timeout*/
7353#endif
7354}
7355
Jeff Johnson295189b2012-06-20 16:38:30 -07007356/**---------------------------------------------------------------------------
7357
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007358 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7359 information between Host and Riva
7360
7361 This function gets reported version of FW
7362 It also finds the version of Riva headers used to compile the host
7363 It compares the above two and prints a warning if they are different
7364 It gets the SW and HW version string
7365 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7366 indicating the features they support through a bitmap
7367
7368 \param - pHddCtx - Pointer to HDD context
7369
7370 \return - void
7371
7372 --------------------------------------------------------------------------*/
7373
7374void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7375{
7376
7377 tSirVersionType versionCompiled;
7378 tSirVersionType versionReported;
7379 tSirVersionString versionString;
7380 tANI_U8 fwFeatCapsMsgSupported = 0;
7381 VOS_STATUS vstatus;
7382
7383 /* retrieve and display WCNSS version information */
7384 do {
7385
7386 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7387 &versionCompiled);
7388 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7389 {
7390 hddLog(VOS_TRACE_LEVEL_FATAL,
7391 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007392 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007393 break;
7394 }
7395
7396 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7397 &versionReported);
7398 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7399 {
7400 hddLog(VOS_TRACE_LEVEL_FATAL,
7401 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007402 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007403 break;
7404 }
7405
7406 if ((versionCompiled.major != versionReported.major) ||
7407 (versionCompiled.minor != versionReported.minor) ||
7408 (versionCompiled.version != versionReported.version) ||
7409 (versionCompiled.revision != versionReported.revision))
7410 {
7411 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7412 "Host expected %u.%u.%u.%u\n",
7413 WLAN_MODULE_NAME,
7414 (int)versionReported.major,
7415 (int)versionReported.minor,
7416 (int)versionReported.version,
7417 (int)versionReported.revision,
7418 (int)versionCompiled.major,
7419 (int)versionCompiled.minor,
7420 (int)versionCompiled.version,
7421 (int)versionCompiled.revision);
7422 }
7423 else
7424 {
7425 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7426 WLAN_MODULE_NAME,
7427 (int)versionReported.major,
7428 (int)versionReported.minor,
7429 (int)versionReported.version,
7430 (int)versionReported.revision);
7431 }
7432
7433 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7434 versionString,
7435 sizeof(versionString));
7436 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7437 {
7438 hddLog(VOS_TRACE_LEVEL_FATAL,
7439 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007440 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007441 break;
7442 }
7443
7444 pr_info("%s: WCNSS software version %s\n",
7445 WLAN_MODULE_NAME, versionString);
7446
7447 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7448 versionString,
7449 sizeof(versionString));
7450 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7451 {
7452 hddLog(VOS_TRACE_LEVEL_FATAL,
7453 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007454 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007455 break;
7456 }
7457
7458 pr_info("%s: WCNSS hardware version %s\n",
7459 WLAN_MODULE_NAME, versionString);
7460
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007461 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7462 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007463 send the message only if it the riva is 1.1
7464 minor numbers for different riva branches:
7465 0 -> (1.0)Mainline Build
7466 1 -> (1.1)Mainline Build
7467 2->(1.04) Stability Build
7468 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007469 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007470 ((versionReported.minor>=1) && (versionReported.version>=1)))
7471 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7472 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007473
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007474 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007475 {
7476#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7477 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7478 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7479#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007480 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7481 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7482 {
7483 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7484 }
7485
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007486 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007487 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007488
7489 } while (0);
7490
7491}
7492
7493/**---------------------------------------------------------------------------
7494
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307495 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7496
7497 \param - pHddCtx - Pointer to the hdd context
7498
7499 \return - true if hardware supports 5GHz
7500
7501 --------------------------------------------------------------------------*/
7502static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7503{
7504 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7505 * then hardware support 5Ghz.
7506 */
7507 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7508 {
7509 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7510 return true;
7511 }
7512 else
7513 {
7514 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7515 __func__);
7516 return false;
7517 }
7518}
7519
7520
7521/**---------------------------------------------------------------------------
7522
Jeff Johnson295189b2012-06-20 16:38:30 -07007523 \brief hdd_wlan_startup() - HDD init function
7524
7525 This is the driver startup code executed once a WLAN device has been detected
7526
7527 \param - dev - Pointer to the underlying device
7528
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007529 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007530
7531 --------------------------------------------------------------------------*/
7532
7533int hdd_wlan_startup(struct device *dev )
7534{
7535 VOS_STATUS status;
7536 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007537 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007538 hdd_context_t *pHddCtx = NULL;
7539 v_CONTEXT_t pVosContext= NULL;
7540#ifdef WLAN_BTAMP_FEATURE
7541 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7542 WLANBAP_ConfigType btAmpConfig;
7543 hdd_config_t *pConfig;
7544#endif
7545 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007546 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007547
7548 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007549 /*
7550 * cfg80211: wiphy allocation
7551 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307552 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007553
7554 if(wiphy == NULL)
7555 {
7556 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007557 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007558 }
7559
7560 pHddCtx = wiphy_priv(wiphy);
7561
Jeff Johnson295189b2012-06-20 16:38:30 -07007562 //Initialize the adapter context to zeros.
7563 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7564
Jeff Johnson295189b2012-06-20 16:38:30 -07007565 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007566 hdd_prevent_suspend();
7567 pHddCtx->isLoadUnloadInProgress = TRUE;
7568
7569 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7570
7571 /*Get vos context here bcoz vos_open requires it*/
7572 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7573
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007574 if(pVosContext == NULL)
7575 {
7576 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7577 goto err_free_hdd_context;
7578 }
7579
Jeff Johnson295189b2012-06-20 16:38:30 -07007580 //Save the Global VOSS context in adapter context for future.
7581 pHddCtx->pvosContext = pVosContext;
7582
7583 //Save the adapter context in global context for future.
7584 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7585
Jeff Johnson295189b2012-06-20 16:38:30 -07007586 pHddCtx->parent_dev = dev;
7587
7588 init_completion(&pHddCtx->full_pwr_comp_var);
7589 init_completion(&pHddCtx->standby_comp_var);
7590 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007591 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007592 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307593 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007594
7595#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007596 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007597#else
7598 init_completion(&pHddCtx->driver_crda_req);
7599#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007600
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307601 spin_lock_init(&pHddCtx->schedScan_lock);
7602
Jeff Johnson295189b2012-06-20 16:38:30 -07007603 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7604
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307605#ifdef FEATURE_WLAN_TDLS
7606 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7607 * invoked by other instances also) to protect the concurrent
7608 * access for the Adapters by TDLS module.
7609 */
7610 mutex_init(&pHddCtx->tdls_lock);
7611#endif
7612
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307613 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007614 // Load all config first as TL config is needed during vos_open
7615 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7616 if(pHddCtx->cfg_ini == NULL)
7617 {
7618 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7619 goto err_free_hdd_context;
7620 }
7621
7622 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7623
7624 // Read and parse the qcom_cfg.ini file
7625 status = hdd_parse_config_ini( pHddCtx );
7626 if ( VOS_STATUS_SUCCESS != status )
7627 {
7628 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7629 __func__, WLAN_INI_FILE);
7630 goto err_config;
7631 }
7632
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307633 /* INI has been read, initialise the configuredMcastBcastFilter with
7634 * INI value as this will serve as the default value
7635 */
7636 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7637 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7638 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307639
7640 if (false == hdd_is_5g_supported(pHddCtx))
7641 {
7642 //5Ghz is not supported.
7643 if (1 != pHddCtx->cfg_ini->nBandCapability)
7644 {
7645 hddLog(VOS_TRACE_LEVEL_INFO,
7646 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7647 pHddCtx->cfg_ini->nBandCapability = 1;
7648 }
7649 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307650
7651 /* If SNR Monitoring is enabled, FW has to parse all beacons
7652 * for calcaluting and storing the average SNR, so set Nth beacon
7653 * filter to 1 to enable FW to parse all the beaocons
7654 */
7655 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7656 {
7657 /* The log level is deliberately set to WARN as overriding
7658 * nthBeaconFilter to 1 will increase power cosumption and this
7659 * might just prove helpful to detect the power issue.
7660 */
7661 hddLog(VOS_TRACE_LEVEL_WARN,
7662 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7663 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7664 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007665 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307666 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007667 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307668 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007669 {
7670 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307671 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7672 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007673 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007674
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007675 // Update VOS trace levels based upon the cfg.ini
7676 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7677 pHddCtx->cfg_ini->vosTraceEnableBAP);
7678 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7679 pHddCtx->cfg_ini->vosTraceEnableTL);
7680 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7681 pHddCtx->cfg_ini->vosTraceEnableWDI);
7682 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7683 pHddCtx->cfg_ini->vosTraceEnableHDD);
7684 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7685 pHddCtx->cfg_ini->vosTraceEnableSME);
7686 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7687 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307688 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7689 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007690 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7691 pHddCtx->cfg_ini->vosTraceEnableWDA);
7692 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7693 pHddCtx->cfg_ini->vosTraceEnableSYS);
7694 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7695 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007696 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7697 pHddCtx->cfg_ini->vosTraceEnableSAP);
7698 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7699 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007700
Jeff Johnson295189b2012-06-20 16:38:30 -07007701 // Update WDI trace levels based upon the cfg.ini
7702 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7703 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7704 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7705 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7706 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7707 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7708 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7709 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007710
Jeff Johnson88ba7742013-02-27 14:36:02 -08007711 if (VOS_FTM_MODE == hdd_get_conparam())
7712 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007713 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7714 {
7715 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7716 goto err_free_hdd_context;
7717 }
7718 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7719 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007720 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007721
Jeff Johnson88ba7742013-02-27 14:36:02 -08007722 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007723 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7724 {
7725 status = vos_watchdog_open(pVosContext,
7726 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7727
7728 if(!VOS_IS_STATUS_SUCCESS( status ))
7729 {
7730 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307731 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007732 }
7733 }
7734
7735 pHddCtx->isLogpInProgress = FALSE;
7736 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7737
Jeff Johnson295189b2012-06-20 16:38:30 -07007738 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7739 if(!VOS_IS_STATUS_SUCCESS(status))
7740 {
7741 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007742 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007743 }
7744
Amar Singhala49cbc52013-10-08 18:37:44 -07007745#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007746 /* initialize the NV module. This is required so that
7747 we can initialize the channel information in wiphy
7748 from the NV.bin data. The channel information in
7749 wiphy needs to be initialized before wiphy registration */
7750
7751 status = vos_nv_open();
7752 if (!VOS_IS_STATUS_SUCCESS(status))
7753 {
7754 /* NV module cannot be initialized */
7755 hddLog( VOS_TRACE_LEVEL_FATAL,
7756 "%s: vos_nv_open failed", __func__);
7757 goto err_clkvote;
7758 }
7759
7760 status = vos_init_wiphy_from_nv_bin();
7761 if (!VOS_IS_STATUS_SUCCESS(status))
7762 {
7763 /* NV module cannot be initialized */
7764 hddLog( VOS_TRACE_LEVEL_FATAL,
7765 "%s: vos_init_wiphy failed", __func__);
7766 goto err_vos_nv_close;
7767 }
7768
Amar Singhala49cbc52013-10-08 18:37:44 -07007769 /* registration of wiphy dev with cfg80211 */
7770 if (0 > wlan_hdd_cfg80211_register(wiphy))
7771 {
7772 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07007773 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07007774 }
7775#endif
7776
Jeff Johnson295189b2012-06-20 16:38:30 -07007777 status = vos_open( &pVosContext, 0);
7778 if ( !VOS_IS_STATUS_SUCCESS( status ))
7779 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007780 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007781 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007782 }
7783
Jeff Johnson295189b2012-06-20 16:38:30 -07007784 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7785
7786 if ( NULL == pHddCtx->hHal )
7787 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007788 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007789 goto err_vosclose;
7790 }
7791
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007792 status = vos_preStart( pHddCtx->pvosContext );
7793 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7794 {
7795 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7796 goto err_vosclose;
7797 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007798
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007799 /* Note that the vos_preStart() sequence triggers the cfg download.
7800 The cfg download must occur before we update the SME config
7801 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007802 status = hdd_set_sme_config( pHddCtx );
7803
7804 if ( VOS_STATUS_SUCCESS != status )
7805 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007806 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7807 goto err_vosclose;
7808 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007809
7810 //Initialize the WMM module
7811 status = hdd_wmm_init(pHddCtx);
7812 if (!VOS_IS_STATUS_SUCCESS(status))
7813 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007814 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007815 goto err_vosclose;
7816 }
7817
Jeff Johnson295189b2012-06-20 16:38:30 -07007818 /* In the integrated architecture we update the configuration from
7819 the INI file and from NV before vOSS has been started so that
7820 the final contents are available to send down to the cCPU */
7821
7822 // Apply the cfg.ini to cfg.dat
7823 if (FALSE == hdd_update_config_dat(pHddCtx))
7824 {
7825 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7826 goto err_vosclose;
7827 }
7828
7829 // Apply the NV to cfg.dat
7830 /* Prima Update MAC address only at here */
7831 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7832 {
7833#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7834 /* There was not a valid set of MAC Addresses in NV. See if the
7835 default addresses were modified by the cfg.ini settings. If so,
7836 we'll use them, but if not, we'll autogenerate a set of MAC
7837 addresses based upon the device serial number */
7838
7839 static const v_MACADDR_t default_address =
7840 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7841 unsigned int serialno;
7842 int i;
7843
7844 serialno = wcnss_get_serial_number();
7845 if ((0 != serialno) &&
7846 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7847 sizeof(default_address))))
7848 {
7849 /* cfg.ini has the default address, invoke autogen logic */
7850
7851 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7852 bytes of the serial number that can be used to generate
7853 the other 3 bytes of the MAC address. Mask off all but
7854 the lower 3 bytes (this will also make sure we don't
7855 overflow in the next step) */
7856 serialno &= 0x00FFFFFF;
7857
7858 /* we need a unique address for each session */
7859 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7860
7861 /* autogen all addresses */
7862 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7863 {
7864 /* start with the entire default address */
7865 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7866 /* then replace the lower 3 bytes */
7867 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7868 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7869 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7870
7871 serialno++;
7872 }
7873
7874 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7875 MAC_ADDRESS_STR,
7876 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7877 }
7878 else
7879#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7880 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007881 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007882 "%s: Invalid MAC address in NV, using MAC from ini file "
7883 MAC_ADDRESS_STR, __func__,
7884 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7885 }
7886 }
7887 {
7888 eHalStatus halStatus;
7889 // Set the MAC Address
7890 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7891 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7892 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7893 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7894
7895 if (!HAL_STATUS_SUCCESS( halStatus ))
7896 {
7897 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7898 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007899 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007900 }
7901 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007902
7903 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7904 Note: Firmware image will be read and downloaded inside vos_start API */
7905 status = vos_start( pHddCtx->pvosContext );
7906 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7907 {
7908 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7909 goto err_vosclose;
7910 }
7911
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007912 /* Exchange capability info between Host and FW and also get versioning info from FW */
7913 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007914
7915 status = hdd_post_voss_start_config( pHddCtx );
7916 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7917 {
7918 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7919 __func__);
7920 goto err_vosstop;
7921 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007922
7923#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307924 wlan_hdd_cfg80211_update_reg_info( wiphy );
7925
7926 /* registration of wiphy dev with cfg80211 */
7927 if (0 > wlan_hdd_cfg80211_register(wiphy))
7928 {
7929 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7930 goto err_vosstop;
7931 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007932#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007933
Jeff Johnson295189b2012-06-20 16:38:30 -07007934 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7935 {
7936 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7937 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7938 }
7939 else
7940 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007941 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7942 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7943 if (pAdapter != NULL)
7944 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307945 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007946 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307947 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7948 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7949 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007950
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307951 /* Generate the P2P Device Address. This consists of the device's
7952 * primary MAC address with the locally administered bit set.
7953 */
7954 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007955 }
7956 else
7957 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307958 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7959 if (p2p_dev_addr != NULL)
7960 {
7961 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7962 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7963 }
7964 else
7965 {
7966 hddLog(VOS_TRACE_LEVEL_FATAL,
7967 "%s: Failed to allocate mac_address for p2p_device",
7968 __func__);
7969 goto err_close_adapter;
7970 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007971 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007972
7973 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7974 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7975 if ( NULL == pP2pAdapter )
7976 {
7977 hddLog(VOS_TRACE_LEVEL_FATAL,
7978 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007979 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007980 goto err_close_adapter;
7981 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007982 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007983 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007984
7985 if( pAdapter == NULL )
7986 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007987 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7988 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007989 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007990
Jeff Johnson295189b2012-06-20 16:38:30 -07007991#ifdef WLAN_BTAMP_FEATURE
7992 vStatus = WLANBAP_Open(pVosContext);
7993 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7994 {
7995 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7996 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007997 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007998 }
7999
8000 vStatus = BSL_Init(pVosContext);
8001 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8002 {
8003 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8004 "%s: Failed to Init BSL",__func__);
8005 goto err_bap_close;
8006 }
8007 vStatus = WLANBAP_Start(pVosContext);
8008 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8009 {
8010 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8011 "%s: Failed to start TL",__func__);
8012 goto err_bap_close;
8013 }
8014
8015 pConfig = pHddCtx->cfg_ini;
8016 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8017 status = WLANBAP_SetConfig(&btAmpConfig);
8018
8019#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008020
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008021#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8022 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8023 {
8024 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8025 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8026 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8027 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8028 }
8029#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008030#ifdef FEATURE_WLAN_SCAN_PNO
8031 /*SME must send channel update configuration to RIVA*/
8032 sme_UpdateChannelConfig(pHddCtx->hHal);
8033#endif
8034
Jeff Johnson295189b2012-06-20 16:38:30 -07008035 /* Register with platform driver as client for Suspend/Resume */
8036 status = hddRegisterPmOps(pHddCtx);
8037 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8038 {
8039 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8040#ifdef WLAN_BTAMP_FEATURE
8041 goto err_bap_stop;
8042#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008043 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008044#endif //WLAN_BTAMP_FEATURE
8045 }
8046
Yue Ma0d4891e2013-08-06 17:01:45 -07008047 /* Open debugfs interface */
8048 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8049 {
8050 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8051 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008052 }
8053
Jeff Johnson295189b2012-06-20 16:38:30 -07008054 /* Register TM level change handler function to the platform */
8055 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8056 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8057 {
8058 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8059 goto err_unregister_pmops;
8060 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008061
8062 /* register for riva power on lock to platform driver */
8063 if (req_riva_power_on_lock("wlan"))
8064 {
8065 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8066 __func__);
8067 goto err_unregister_pmops;
8068 }
8069
Jeff Johnson295189b2012-06-20 16:38:30 -07008070 // register net device notifier for device change notification
8071 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8072
8073 if(ret < 0)
8074 {
8075 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8076 goto err_free_power_on_lock;
8077 }
8078
8079 //Initialize the nlink service
8080 if(nl_srv_init() != 0)
8081 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308082 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008083 goto err_reg_netdev;
8084 }
8085
Leo Chang4ce1cc52013-10-21 18:27:15 -07008086#ifdef WLAN_KD_READY_NOTIFIER
8087 pHddCtx->kd_nl_init = 1;
8088#endif /* WLAN_KD_READY_NOTIFIER */
8089
Jeff Johnson295189b2012-06-20 16:38:30 -07008090 //Initialize the BTC service
8091 if(btc_activate_service(pHddCtx) != 0)
8092 {
8093 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8094 goto err_nl_srv;
8095 }
8096
8097#ifdef PTT_SOCK_SVC_ENABLE
8098 //Initialize the PTT service
8099 if(ptt_sock_activate_svc(pHddCtx) != 0)
8100 {
8101 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8102 goto err_nl_srv;
8103 }
8104#endif
8105
Jeff Johnson295189b2012-06-20 16:38:30 -07008106 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008107 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008108 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008109 /* Action frame registered in one adapter which will
8110 * applicable to all interfaces
8111 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008112 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008113 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008114
8115 mutex_init(&pHddCtx->sap_lock);
8116
8117 pHddCtx->isLoadUnloadInProgress = FALSE;
8118
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008119#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008120#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8121 /* Initialize the wake lcok */
8122 wake_lock_init(&pHddCtx->rx_wake_lock,
8123 WAKE_LOCK_SUSPEND,
8124 "qcom_rx_wakelock");
8125#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008126 /* Initialize the wake lcok */
8127 wake_lock_init(&pHddCtx->sap_wake_lock,
8128 WAKE_LOCK_SUSPEND,
8129 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008130#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008131
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008132 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8133 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008134
8135 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8136 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05308137
Jeff Johnsone7245742012-09-05 17:12:55 -07008138 // Initialize the restart logic
8139 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308140
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008141 //Register the traffic monitor timer now
8142 if ( pHddCtx->cfg_ini->dynSplitscan)
8143 {
8144 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8145 VOS_TIMER_TYPE_SW,
8146 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8147 (void *)pHddCtx);
8148 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008149 goto success;
8150
8151err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008152#ifdef WLAN_KD_READY_NOTIFIER
8153 nl_srv_exit(pHddCtx->ptt_pid);
8154#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008155 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008156#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008157err_reg_netdev:
8158 unregister_netdevice_notifier(&hdd_netdev_notifier);
8159
8160err_free_power_on_lock:
8161 free_riva_power_on_lock("wlan");
8162
8163err_unregister_pmops:
8164 hddDevTmUnregisterNotifyCallback(pHddCtx);
8165 hddDeregisterPmOps(pHddCtx);
8166
Yue Ma0d4891e2013-08-06 17:01:45 -07008167 hdd_debugfs_exit(pHddCtx);
8168
Jeff Johnson295189b2012-06-20 16:38:30 -07008169#ifdef WLAN_BTAMP_FEATURE
8170err_bap_stop:
8171 WLANBAP_Stop(pVosContext);
8172#endif
8173
8174#ifdef WLAN_BTAMP_FEATURE
8175err_bap_close:
8176 WLANBAP_Close(pVosContext);
8177#endif
8178
Jeff Johnson295189b2012-06-20 16:38:30 -07008179err_close_adapter:
8180 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008181
8182#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308183 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008184#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008185
8186err_vosstop:
8187 vos_stop(pVosContext);
8188
Amar Singhala49cbc52013-10-08 18:37:44 -07008189err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008190 status = vos_sched_close( pVosContext );
8191 if (!VOS_IS_STATUS_SUCCESS(status)) {
8192 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8193 "%s: Failed to close VOSS Scheduler", __func__);
8194 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8195 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008196 vos_close(pVosContext );
8197
8198err_wiphy_unregister:
8199
8200#ifdef CONFIG_ENABLE_LINUX_REG
8201 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07008202
Amar Singhal0a402232013-10-11 20:57:16 -07008203err_vos_nv_close:
8204
8205 vos_nv_close();
8206
Jeff Johnson295189b2012-06-20 16:38:30 -07008207err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008208#endif
8209
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008210 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008211
8212err_wdclose:
8213 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8214 vos_watchdog_close(pVosContext);
8215
Jeff Johnson295189b2012-06-20 16:38:30 -07008216err_config:
8217 kfree(pHddCtx->cfg_ini);
8218 pHddCtx->cfg_ini= NULL;
8219
8220err_free_hdd_context:
8221 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008222 wiphy_free(wiphy) ;
8223 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008224 VOS_BUG(1);
8225
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008226 if (hdd_is_ssr_required())
8227 {
8228 /* WDI timeout had happened during load, so SSR is needed here */
8229 subsystem_restart("wcnss");
8230 msleep(5000);
8231 }
8232 hdd_set_ssr_required (VOS_FALSE);
8233
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008234 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008235
8236success:
8237 EXIT();
8238 return 0;
8239}
8240
8241/**---------------------------------------------------------------------------
8242
Jeff Johnson32d95a32012-09-10 13:15:23 -07008243 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008244
Jeff Johnson32d95a32012-09-10 13:15:23 -07008245 This is the driver entry point - called in different timeline depending
8246 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008247
8248 \param - None
8249
8250 \return - 0 for success, non zero for failure
8251
8252 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008253static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008254{
8255 VOS_STATUS status;
8256 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008257 struct device *dev = NULL;
8258 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008259#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8260 int max_retries = 0;
8261#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008262
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308263#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8264 vos_wconn_trace_init();
8265#endif
8266
Jeff Johnson295189b2012-06-20 16:38:30 -07008267 ENTER();
8268
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008269#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008270 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008271#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008272
8273 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8274 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8275
8276 //Power Up Libra WLAN card first if not already powered up
8277 status = vos_chipPowerUp(NULL,NULL,NULL);
8278 if (!VOS_IS_STATUS_SUCCESS(status))
8279 {
8280 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8281 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308282#ifdef WLAN_OPEN_SOURCE
8283 wake_lock_destroy(&wlan_wake_lock);
8284#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008285 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008286 }
8287
Jeff Johnson295189b2012-06-20 16:38:30 -07008288#ifdef ANI_BUS_TYPE_PCI
8289
8290 dev = wcnss_wlan_get_device();
8291
8292#endif // ANI_BUS_TYPE_PCI
8293
8294#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008295
8296#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8297 /* wait until WCNSS driver downloads NV */
8298 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8299 msleep(1000);
8300 }
8301 if (max_retries >= 5) {
8302 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308303#ifdef WLAN_OPEN_SOURCE
8304 wake_lock_destroy(&wlan_wake_lock);
8305#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008306 return -ENODEV;
8307 }
8308#endif
8309
Jeff Johnson295189b2012-06-20 16:38:30 -07008310 dev = wcnss_wlan_get_device();
8311#endif // ANI_BUS_TYPE_PLATFORM
8312
8313
8314 do {
8315 if (NULL == dev) {
8316 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8317 ret_status = -1;
8318 break;
8319 }
8320
8321#ifdef MEMORY_DEBUG
8322 vos_mem_init();
8323#endif
8324
8325#ifdef TIMER_MANAGER
8326 vos_timer_manager_init();
8327#endif
8328
8329 /* Preopen VOSS so that it is ready to start at least SAL */
8330 status = vos_preOpen(&pVosContext);
8331
8332 if (!VOS_IS_STATUS_SUCCESS(status))
8333 {
8334 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8335 ret_status = -1;
8336 break;
8337 }
8338
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008339#ifndef MODULE
8340 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8341 */
8342 hdd_set_conparam((v_UINT_t)con_mode);
8343#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008344
8345 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008346 if (hdd_wlan_startup(dev))
8347 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008348 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008349 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008350 vos_preClose( &pVosContext );
8351 ret_status = -1;
8352 break;
8353 }
8354
8355 /* Cancel the vote for XO Core ON
8356 * This is done here for safety purposes in case we re-initialize without turning
8357 * it OFF in any error scenario.
8358 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008359 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008360 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008361 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008362 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8363 {
8364 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
8365 " Power consumed will be high\n");
8366 }
8367 } while (0);
8368
8369 if (0 != ret_status)
8370 {
8371 //Assert Deep sleep signal now to put Libra HW in lowest power state
8372 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8373 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8374
8375 //Vote off any PMIC voltage supplies
8376 vos_chipPowerDown(NULL, NULL, NULL);
8377#ifdef TIMER_MANAGER
8378 vos_timer_exit();
8379#endif
8380#ifdef MEMORY_DEBUG
8381 vos_mem_exit();
8382#endif
8383
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008384#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008385 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008386#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008387 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8388 }
8389 else
8390 {
8391 //Send WLAN UP indication to Nlink Service
8392 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8393
8394 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008395 }
8396
8397 EXIT();
8398
8399 return ret_status;
8400}
8401
Jeff Johnson32d95a32012-09-10 13:15:23 -07008402/**---------------------------------------------------------------------------
8403
8404 \brief hdd_module_init() - Init Function
8405
8406 This is the driver entry point (invoked when module is loaded using insmod)
8407
8408 \param - None
8409
8410 \return - 0 for success, non zero for failure
8411
8412 --------------------------------------------------------------------------*/
8413#ifdef MODULE
8414static int __init hdd_module_init ( void)
8415{
8416 return hdd_driver_init();
8417}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008418#else /* #ifdef MODULE */
8419static int __init hdd_module_init ( void)
8420{
8421 /* Driver initialization is delayed to fwpath_changed_handler */
8422 return 0;
8423}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008424#endif /* #ifdef MODULE */
8425
Jeff Johnson295189b2012-06-20 16:38:30 -07008426
8427/**---------------------------------------------------------------------------
8428
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008429 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008430
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008431 This is the driver exit point (invoked when module is unloaded using rmmod
8432 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008433
8434 \param - None
8435
8436 \return - None
8437
8438 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008439static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008440{
8441 hdd_context_t *pHddCtx = NULL;
8442 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008443 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008444
8445 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8446
8447 //Get the global vos context
8448 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8449
8450 if(!pVosContext)
8451 {
8452 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8453 goto done;
8454 }
8455
8456 //Get the HDD context.
8457 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8458
8459 if(!pHddCtx)
8460 {
8461 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8462 }
8463 else
8464 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008465 while(isWDresetInProgress()) {
8466 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8467 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008468 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008469
8470 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8471 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8472 "%s:SSR never completed, fatal error", __func__);
8473 VOS_BUG(0);
8474 }
8475 }
8476
Jeff Johnson295189b2012-06-20 16:38:30 -07008477
8478 pHddCtx->isLoadUnloadInProgress = TRUE;
8479 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8480
8481 //Do all the cleanup before deregistering the driver
8482 hdd_wlan_exit(pHddCtx);
8483 }
8484
Jeff Johnson295189b2012-06-20 16:38:30 -07008485 vos_preClose( &pVosContext );
8486
8487#ifdef TIMER_MANAGER
8488 vos_timer_exit();
8489#endif
8490#ifdef MEMORY_DEBUG
8491 vos_mem_exit();
8492#endif
8493
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308494#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8495 vos_wconn_trace_exit();
8496#endif
8497
Jeff Johnson295189b2012-06-20 16:38:30 -07008498done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008499#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008500 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008501#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008502 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8503}
8504
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008505/**---------------------------------------------------------------------------
8506
8507 \brief hdd_module_exit() - Exit function
8508
8509 This is the driver exit point (invoked when module is unloaded using rmmod)
8510
8511 \param - None
8512
8513 \return - None
8514
8515 --------------------------------------------------------------------------*/
8516static void __exit hdd_module_exit(void)
8517{
8518 hdd_driver_exit();
8519}
8520
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008521#ifdef MODULE
8522static int fwpath_changed_handler(const char *kmessage,
8523 struct kernel_param *kp)
8524{
Jeff Johnson76052702013-04-16 13:55:05 -07008525 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008526}
8527
8528static int con_mode_handler(const char *kmessage,
8529 struct kernel_param *kp)
8530{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008531 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008532}
8533#else /* #ifdef MODULE */
8534/**---------------------------------------------------------------------------
8535
Jeff Johnson76052702013-04-16 13:55:05 -07008536 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008537
Jeff Johnson76052702013-04-16 13:55:05 -07008538 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008539 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008540 - invoked when module parameter fwpath is modified from userspace to signal
8541 initializing the WLAN driver or when con_mode is modified from userspace
8542 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008543
8544 \return - 0 for success, non zero for failure
8545
8546 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008547static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008548{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008549 int ret_status;
8550
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008551 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008552 ret_status = hdd_driver_init();
8553 wlan_hdd_inited = ret_status ? 0 : 1;
8554 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008555 }
8556
8557 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008558
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008559 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008560
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008561 ret_status = hdd_driver_init();
8562 wlan_hdd_inited = ret_status ? 0 : 1;
8563 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008564}
8565
Jeff Johnson295189b2012-06-20 16:38:30 -07008566/**---------------------------------------------------------------------------
8567
Jeff Johnson76052702013-04-16 13:55:05 -07008568 \brief fwpath_changed_handler() - Handler Function
8569
8570 Handle changes to the fwpath parameter
8571
8572 \return - 0 for success, non zero for failure
8573
8574 --------------------------------------------------------------------------*/
8575static int fwpath_changed_handler(const char *kmessage,
8576 struct kernel_param *kp)
8577{
8578 int ret;
8579
8580 ret = param_set_copystring(kmessage, kp);
8581 if (0 == ret)
8582 ret = kickstart_driver();
8583 return ret;
8584}
8585
8586/**---------------------------------------------------------------------------
8587
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008588 \brief con_mode_handler() -
8589
8590 Handler function for module param con_mode when it is changed by userspace
8591 Dynamically linked - do nothing
8592 Statically linked - exit and init driver, as in rmmod and insmod
8593
Jeff Johnson76052702013-04-16 13:55:05 -07008594 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008595
Jeff Johnson76052702013-04-16 13:55:05 -07008596 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008597
8598 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008599static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008600{
Jeff Johnson76052702013-04-16 13:55:05 -07008601 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008602
Jeff Johnson76052702013-04-16 13:55:05 -07008603 ret = param_set_int(kmessage, kp);
8604 if (0 == ret)
8605 ret = kickstart_driver();
8606 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008607}
8608#endif /* #ifdef MODULE */
8609
8610/**---------------------------------------------------------------------------
8611
Jeff Johnson295189b2012-06-20 16:38:30 -07008612 \brief hdd_get_conparam() -
8613
8614 This is the driver exit point (invoked when module is unloaded using rmmod)
8615
8616 \param - None
8617
8618 \return - tVOS_CON_MODE
8619
8620 --------------------------------------------------------------------------*/
8621tVOS_CON_MODE hdd_get_conparam ( void )
8622{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008623#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008624 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008625#else
8626 return (tVOS_CON_MODE)curr_con_mode;
8627#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008628}
8629void hdd_set_conparam ( v_UINT_t newParam )
8630{
8631 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008632#ifndef MODULE
8633 curr_con_mode = con_mode;
8634#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008635}
8636/**---------------------------------------------------------------------------
8637
8638 \brief hdd_softap_sta_deauth() - function
8639
8640 This to take counter measure to handle deauth req from HDD
8641
8642 \param - pAdapter - Pointer to the HDD
8643
8644 \param - enable - boolean value
8645
8646 \return - None
8647
8648 --------------------------------------------------------------------------*/
8649
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008650VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008651{
Jeff Johnson295189b2012-06-20 16:38:30 -07008652 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008653 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008654
8655 ENTER();
8656
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008657 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8658 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008659
8660 //Ignore request to deauth bcmc station
8661 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008662 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008663
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008664 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008665
8666 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008667 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008668}
8669
8670/**---------------------------------------------------------------------------
8671
8672 \brief hdd_softap_sta_disassoc() - function
8673
8674 This to take counter measure to handle deauth req from HDD
8675
8676 \param - pAdapter - Pointer to the HDD
8677
8678 \param - enable - boolean value
8679
8680 \return - None
8681
8682 --------------------------------------------------------------------------*/
8683
8684void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8685{
8686 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8687
8688 ENTER();
8689
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308690 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008691
8692 //Ignore request to disassoc bcmc station
8693 if( pDestMacAddress[0] & 0x1 )
8694 return;
8695
8696 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8697}
8698
8699void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8700{
8701 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8702
8703 ENTER();
8704
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308705 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008706
8707 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8708}
8709
Jeff Johnson295189b2012-06-20 16:38:30 -07008710/**---------------------------------------------------------------------------
8711 *
8712 * \brief hdd_get__concurrency_mode() -
8713 *
8714 *
8715 * \param - None
8716 *
8717 * \return - CONCURRENCY MODE
8718 *
8719 * --------------------------------------------------------------------------*/
8720tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8721{
8722 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8723 hdd_context_t *pHddCtx;
8724
8725 if (NULL != pVosContext)
8726 {
8727 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8728 if (NULL != pHddCtx)
8729 {
8730 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8731 }
8732 }
8733
8734 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008735 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008736 return VOS_STA;
8737}
8738
8739/* Decide whether to allow/not the apps power collapse.
8740 * Allow apps power collapse if we are in connected state.
8741 * if not, allow only if we are in IMPS */
8742v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8743{
8744 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008745 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008746 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008747 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8748 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8749 hdd_adapter_t *pAdapter = NULL;
8750 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008751 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008752
Jeff Johnson295189b2012-06-20 16:38:30 -07008753 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8754 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008755
Yathish9f22e662012-12-10 14:21:35 -08008756 concurrent_state = hdd_get_concurrency_mode();
8757
8758#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8759 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8760 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8761 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8762 return TRUE;
8763#endif
8764
Jeff Johnson295189b2012-06-20 16:38:30 -07008765 /*loop through all adapters. TBD fix for Concurrency */
8766 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8767 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8768 {
8769 pAdapter = pAdapterNode->pAdapter;
8770 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8771 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8772 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008773 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008774 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008775 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008776 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8777 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008778 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008779 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008780 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8781 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008782 return FALSE;
8783 }
8784 }
8785 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8786 pAdapterNode = pNext;
8787 }
8788 return TRUE;
8789}
8790
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008791/* Decides whether to send suspend notification to Riva
8792 * if any adapter is in BMPS; then it is required */
8793v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8794{
8795 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8796 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8797
8798 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8799 {
8800 return TRUE;
8801 }
8802 return FALSE;
8803}
8804
Jeff Johnson295189b2012-06-20 16:38:30 -07008805void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8806{
8807 switch(mode)
8808 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008809 case VOS_STA_MODE:
8810 case VOS_P2P_CLIENT_MODE:
8811 case VOS_P2P_GO_MODE:
8812 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008813 pHddCtx->concurrency_mode |= (1 << mode);
8814 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008815 break;
8816 default:
8817 break;
8818
8819 }
8820 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8821 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8822}
8823
8824
8825void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8826{
8827 switch(mode)
8828 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008829 case VOS_STA_MODE:
8830 case VOS_P2P_CLIENT_MODE:
8831 case VOS_P2P_GO_MODE:
8832 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008833 pHddCtx->no_of_sessions[mode]--;
8834 if (!(pHddCtx->no_of_sessions[mode]))
8835 pHddCtx->concurrency_mode &= (~(1 << mode));
8836 break;
8837 default:
8838 break;
8839 }
8840 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8841 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8842}
8843
Jeff Johnsone7245742012-09-05 17:12:55 -07008844/**---------------------------------------------------------------------------
8845 *
8846 * \brief wlan_hdd_restart_init
8847 *
8848 * This function initalizes restart timer/flag. An internal function.
8849 *
8850 * \param - pHddCtx
8851 *
8852 * \return - None
8853 *
8854 * --------------------------------------------------------------------------*/
8855
8856static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8857{
8858 /* Initialize */
8859 pHddCtx->hdd_restart_retries = 0;
8860 atomic_set(&pHddCtx->isRestartInProgress, 0);
8861 vos_timer_init(&pHddCtx->hdd_restart_timer,
8862 VOS_TIMER_TYPE_SW,
8863 wlan_hdd_restart_timer_cb,
8864 pHddCtx);
8865}
8866/**---------------------------------------------------------------------------
8867 *
8868 * \brief wlan_hdd_restart_deinit
8869 *
8870 * This function cleans up the resources used. An internal function.
8871 *
8872 * \param - pHddCtx
8873 *
8874 * \return - None
8875 *
8876 * --------------------------------------------------------------------------*/
8877
8878static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8879{
8880
8881 VOS_STATUS vos_status;
8882 /* Block any further calls */
8883 atomic_set(&pHddCtx->isRestartInProgress, 1);
8884 /* Cleanup */
8885 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8886 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008887 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008888 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8889 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008890 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008891
8892}
8893
8894/**---------------------------------------------------------------------------
8895 *
8896 * \brief wlan_hdd_framework_restart
8897 *
8898 * This function uses a cfg80211 API to start a framework initiated WLAN
8899 * driver module unload/load.
8900 *
8901 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8902 *
8903 *
8904 * \param - pHddCtx
8905 *
8906 * \return - VOS_STATUS_SUCCESS: Success
8907 * VOS_STATUS_E_EMPTY: Adapter is Empty
8908 * VOS_STATUS_E_NOMEM: No memory
8909
8910 * --------------------------------------------------------------------------*/
8911
8912static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8913{
8914 VOS_STATUS status = VOS_STATUS_SUCCESS;
8915 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008916 int len = (sizeof (struct ieee80211_mgmt));
8917 struct ieee80211_mgmt *mgmt = NULL;
8918
8919 /* Prepare the DEAUTH managment frame with reason code */
8920 mgmt = kzalloc(len, GFP_KERNEL);
8921 if(mgmt == NULL)
8922 {
8923 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8924 "%s: memory allocation failed (%d bytes)", __func__, len);
8925 return VOS_STATUS_E_NOMEM;
8926 }
8927 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008928
8929 /* Iterate over all adapters/devices */
8930 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8931 do
8932 {
8933 if( (status == VOS_STATUS_SUCCESS) &&
8934 pAdapterNode &&
8935 pAdapterNode->pAdapter)
8936 {
8937 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8938 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8939 pAdapterNode->pAdapter->dev->name,
8940 pAdapterNode->pAdapter->device_mode,
8941 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008942 /*
8943 * CFG80211 event to restart the driver
8944 *
8945 * 'cfg80211_send_unprot_deauth' sends a
8946 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8947 * of SME(Linux Kernel) state machine.
8948 *
8949 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8950 * the driver.
8951 *
8952 */
8953
8954 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008955 }
8956 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8957 pAdapterNode = pNext;
8958 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8959
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008960
8961 /* Free the allocated management frame */
8962 kfree(mgmt);
8963
Jeff Johnsone7245742012-09-05 17:12:55 -07008964 /* Retry until we unload or reach max count */
8965 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
8966 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
8967
8968 return status;
8969
8970}
8971/**---------------------------------------------------------------------------
8972 *
8973 * \brief wlan_hdd_restart_timer_cb
8974 *
8975 * Restart timer callback. An internal function.
8976 *
8977 * \param - User data:
8978 *
8979 * \return - None
8980 *
8981 * --------------------------------------------------------------------------*/
8982
8983void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
8984{
8985 hdd_context_t *pHddCtx = usrDataForCallback;
8986 wlan_hdd_framework_restart(pHddCtx);
8987 return;
8988
8989}
8990
8991
8992/**---------------------------------------------------------------------------
8993 *
8994 * \brief wlan_hdd_restart_driver
8995 *
8996 * This function sends an event to supplicant to restart the WLAN driver.
8997 *
8998 * This function is called from vos_wlanRestart.
8999 *
9000 * \param - pHddCtx
9001 *
9002 * \return - VOS_STATUS_SUCCESS: Success
9003 * VOS_STATUS_E_EMPTY: Adapter is Empty
9004 * VOS_STATUS_E_ALREADY: Request already in progress
9005
9006 * --------------------------------------------------------------------------*/
9007VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9008{
9009 VOS_STATUS status = VOS_STATUS_SUCCESS;
9010
9011 /* A tight check to make sure reentrancy */
9012 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9013 {
9014 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9015 "%s: WLAN restart is already in progress", __func__);
9016
9017 return VOS_STATUS_E_ALREADY;
9018 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009019 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009020#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009021 wcnss_reset_intr();
9022#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009023
Jeff Johnsone7245742012-09-05 17:12:55 -07009024 return status;
9025}
9026
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009027/*
9028 * API to find if there is any STA or P2P-Client is connected
9029 */
9030VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9031{
9032 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9033}
Jeff Johnsone7245742012-09-05 17:12:55 -07009034
Jeff Johnson295189b2012-06-20 16:38:30 -07009035//Register the module init/exit functions
9036module_init(hdd_module_init);
9037module_exit(hdd_module_exit);
9038
9039MODULE_LICENSE("Dual BSD/GPL");
9040MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9041MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9042
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009043module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9044 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009045
Jeff Johnson76052702013-04-16 13:55:05 -07009046module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009047 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);