blob: aab14e14f530a128f180a257d6b72fb27c1e50fb [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;
807
808 /*initialize default values*/
809 pHddSetBatchScanReq->scanFrequency = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
810 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
811 pHddSetBatchScanReq->rtt = 0;
812 pHddSetBatchScanReq->bestNetwork = HDD_SET_BATCH_SCAN_BEST_NETWORK;
813
814 /*go to space after WLS_BATCHING_SET command*/
815 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
816 /*no argument after the command*/
817 if (NULL == inPtr)
818 {
819 return -EINVAL;
820 }
821
822 /*no space after the command*/
823 else if (SPACE_ASCII_VALUE != *inPtr)
824 {
825 return -EINVAL;
826 }
827
828 /*removing empty spaces*/
829 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
830
831 /*no argument followed by spaces*/
832 if ('\0' == *inPtr)
833 {
834 return -EINVAL;
835 }
836
837 /*check and parse SCANFREQ*/
838 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
839 {
840 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
841 &pHddSetBatchScanReq->scanFrequency, &lastArg);
842 if ( (NULL == inPtr) || (TRUE == lastArg))
843 {
844 return -EINVAL;
845 }
846 }
847
848 /*check and parse MSCAN*/
849 if ((strncmp(inPtr, "MSCAN", 5) == 0))
850 {
851 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
852 &pHddSetBatchScanReq->numberOfScansToBatch, &lastArg);
853 if (TRUE == lastArg)
854 {
855 goto done;
856 }
857 else if (NULL == inPtr)
858 {
859 return -EINVAL;
860 }
861 }
862 else
863 {
864 return -EINVAL;
865 }
866
867 /*check and parse BESTN*/
868 if ((strncmp(inPtr, "BESTN", 5) == 0))
869 {
870 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
871 &pHddSetBatchScanReq->bestNetwork, &lastArg);
872 if (TRUE == lastArg)
873 {
874 goto done;
875 }
876 else if (NULL == inPtr)
877 {
878 return -EINVAL;
879 }
880 }
881
882 /*check and parse CHANNEL*/
883 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
884 {
885 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
886 if (TRUE == lastArg)
887 {
888 goto done;
889 }
890 else if (NULL == inPtr)
891 {
892 return -EINVAL;
893 }
894 if (('A' == val) || ('a' == val))
895 {
896 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
897 }
898 else if (('B' == val) || ('b' == val))
899 {
900 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
901 }
902 else
903 {
904 return -EINVAL;
905 }
906 }
907
908 /*check and parse RTT*/
909 if ((strncmp(inPtr, "RTT", 3) == 0))
910 {
911 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
912 &pHddSetBatchScanReq->rtt, &lastArg);
913 if (TRUE == lastArg)
914 {
915 goto done;
916 }
917 if (NULL == inPtr)
918 {
919 return -EINVAL;
920 }
921 }
922
923
924done:
925
926 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
927 "Received WLS_BATCHING_SET with SCANFREQ=%d "
928 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
929 pHddSetBatchScanReq->scanFrequency,
930 pHddSetBatchScanReq->numberOfScansToBatch,
931 pHddSetBatchScanReq->bestNetwork,
932 pHddSetBatchScanReq->rfBand,
933 pHddSetBatchScanReq->rtt);
934
935 return 0;
936}/*End of hdd_parse_set_batchscan_command*/
937
938/**---------------------------------------------------------------------------
939
940 \brief hdd_set_batch_scan_req_callback () - This function is called after
941 receiving set batch scan response from FW and it saves set batch scan
942 response data FW to HDD context and sets the completion event on
943 which hdd_ioctl is waiting
944
945 \param - callbackContext Pointer to HDD adapter
946 \param - pRsp Pointer to set batch scan response data received from FW
947
948 \return - nothing
949
950 --------------------------------------------------------------------------*/
951static void hdd_set_batch_scan_req_callback
952(
953 void *callbackContext,
954 tSirSetBatchScanRsp *pRsp
955)
956{
957 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
958 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
959
960 /*sanity check*/
961 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
962 {
963 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
964 "%s: Invalid pAdapter magic", __func__);
965 VOS_ASSERT(0);
966 return;
967 }
968 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
969
970 /*save set batch scan response*/
971 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
972
973 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
974 "Received set batch scan rsp from FW with nScansToBatch=%d",
975 pHddSetBatchScanRsp->nScansToBatch);
976
977 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
978 complete(&pAdapter->hdd_set_batch_scan_req_var);
979
980 return;
981}/*End of hdd_set_batch_scan_req_callback*/
982
983
984/**---------------------------------------------------------------------------
985
986 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
987 info in hdd batch scan response queue
988
989 \param - pAdapter Pointer to hdd adapter
990 \param - pAPMetaInfo Pointer to access point meta info
991 \param - scanId scan ID of batch scan response
992 \param - isLastAp tells whether AP is last AP in batch scan response or not
993
994 \return - nothing
995
996 --------------------------------------------------------------------------*/
997static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
998 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
999{
1000 tHddBatchScanRsp *pHead;
1001 tHddBatchScanRsp *pNode;
1002 tHddBatchScanRsp *pPrev;
1003 tHddBatchScanRsp *pTemp;
1004 tANI_U8 ssidLen;
1005
1006 /*head of hdd batch scan response queue*/
1007 pHead = pAdapter->pBatchScanRsp;
1008
1009 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1010 if (NULL == pNode)
1011 {
1012 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1013 "%s: Could not allocate memory", __func__);
1014 VOS_ASSERT(0);
1015 return;
1016 }
1017
1018 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1019 sizeof(pNode->ApInfo.bssid));
1020 ssidLen = strlen(pApMetaInfo->ssid);
1021 if (SIR_MAX_SSID_SIZE < ssidLen)
1022 {
1023 /*invalid scan result*/
1024 vos_mem_free(pNode);
1025 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1026 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1027 return;
1028 }
1029 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1030 /*null terminate ssid*/
1031 pNode->ApInfo.ssid[ssidLen] = '\0';
1032 pNode->ApInfo.ch = pApMetaInfo->ch;
1033 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1034 pNode->ApInfo.age = pApMetaInfo->timestamp;
1035 pNode->ApInfo.batchId = scanId;
1036 pNode->ApInfo.isLastAp = isLastAp;
1037
1038 pNode->pNext = NULL;
1039 if (NULL == pHead)
1040 {
1041 pAdapter->pBatchScanRsp = pNode;
1042 }
1043 else
1044 {
1045 pTemp = pHead;
1046 while (NULL != pTemp)
1047 {
1048 pPrev = pTemp;
1049 pTemp = pTemp->pNext;
1050 }
1051 pPrev->pNext = pNode;
1052 }
1053
1054 return;
1055}/*End of hdd_populate_batch_scan_rsp_queue*/
1056
1057/**---------------------------------------------------------------------------
1058
1059 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1060 receiving batch scan response indication from FW. It saves get batch scan
1061 response data in HDD batch scan response queue. This callback sets the
1062 completion event on which hdd_ioctl is waiting only after getting complete
1063 batch scan response data from FW
1064
1065 \param - callbackContext Pointer to HDD adapter
1066 \param - pRsp Pointer to get batch scan response data received from FW
1067
1068 \return - nothing
1069
1070 --------------------------------------------------------------------------*/
1071static void hdd_batch_scan_result_ind_callback
1072(
1073 void *callbackContext,
1074 void *pRsp
1075)
1076{
1077 v_BOOL_t isLastAp;
1078 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001079 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301080 tANI_U32 numberScanList;
1081 tANI_U32 nextScanListOffset;
1082 tANI_U32 nextApMetaInfoOffset;
1083 hdd_adapter_t* pAdapter;
1084 tpSirBatchScanList pScanList;
1085 tpSirBatchScanNetworkInfo pApMetaInfo;
1086 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1087 tSirSetBatchScanReq *pReq;
1088
1089 pAdapter = (hdd_adapter_t *)callbackContext;
1090 /*sanity check*/
1091 if ((NULL != pAdapter) && (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
1092 {
1093 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1094 "%s: Invalid pAdapter magic", __func__);
1095 VOS_ASSERT(0);
1096 return;
1097 }
1098
1099 /*initialize locals*/
1100 pReq = &pAdapter->hddSetBatchScanReq;
1101 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1102 isLastAp = FALSE;
1103 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001104 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301105 numberScanList = 0;
1106 nextScanListOffset = 0;
1107 nextApMetaInfoOffset = 0;
1108 pScanList = NULL;
1109 pApMetaInfo = NULL;
1110
1111 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1112 {
1113 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1114 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1115 isLastAp = TRUE;
1116 goto done;
1117 }
1118
1119 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1120 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1121 "Batch scan rsp: numberScalList %d", numberScanList);
1122
1123 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1124 {
1125 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1126 "%s: numberScanList %d", __func__, numberScanList);
1127 isLastAp = TRUE;
1128 goto done;
1129 }
1130
1131 while (numberScanList)
1132 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001133 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301134 nextScanListOffset);
1135 if (NULL == pScanList)
1136 {
1137 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1138 "%s: pScanList is %p", __func__, pScanList);
1139 isLastAp = TRUE;
1140 goto done;
1141 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001142 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301143 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001144 "Batch scan rsp: numApMetaInfo %d scanId %d",
1145 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301146
1147 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1148 {
1149 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1150 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1151 isLastAp = TRUE;
1152 goto done;
1153 }
1154
Rajeev Kumarce651e42013-10-21 18:57:15 -07001155 /*Initialize next AP meta info offset for next scan list*/
1156 nextApMetaInfoOffset = 0;
1157
Rajeev79dbe4c2013-10-05 11:03:42 +05301158 while (numApMetaInfo)
1159 {
1160 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1161 nextApMetaInfoOffset);
1162 if (NULL == pApMetaInfo)
1163 {
1164 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1165 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1166 isLastAp = TRUE;
1167 goto done;
1168 }
1169 /*calculate AP age*/
1170 pApMetaInfo->timestamp =
1171 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1172
1173 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1174 "%s: bssId 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x "
1175 "ch %d rssi %d timestamp %d", __func__,
1176 pApMetaInfo->bssid[0],pApMetaInfo->bssid[1],
1177 pApMetaInfo->bssid[2],pApMetaInfo->bssid[3],
1178 pApMetaInfo->bssid[4],pApMetaInfo->bssid[5],
1179 pApMetaInfo->ch, pApMetaInfo->rssi,
1180 pApMetaInfo->timestamp);
1181
1182 /*mark last AP in batch scan response*/
1183 if ((TRUE == pBatchScanRsp->isLastResult) &&
1184 (1 == numberScanList) && (1 == numApMetaInfo))
1185 {
1186 isLastAp = TRUE;
1187 }
1188
1189 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1190 /*store batch scan repsonse in hdd queue*/
1191 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1192 pScanList->scanId, isLastAp);
1193 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1194
1195 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1196 numApMetaInfo--;
1197 }
1198
Rajeev Kumarce651e42013-10-21 18:57:15 -07001199 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1200 + (sizeof(tSirBatchScanNetworkInfo)
1201 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301202 numberScanList--;
1203 }
1204
1205done:
1206
1207 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1208 requested from hdd_ioctl*/
1209 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1210 (TRUE == isLastAp))
1211 {
1212 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1213 complete(&pAdapter->hdd_get_batch_scan_req_var);
1214 }
1215
1216 return;
1217}/*End of hdd_batch_scan_result_ind_callback*/
1218
1219/**---------------------------------------------------------------------------
1220
1221 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1222 response as per batch scan FR request format by putting proper markers
1223
1224 \param - pDest pointer to destination buffer
1225 \param - cur_len current length
1226 \param - tot_len total remaining size which can be written to user space
1227 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1228 \param - pAdapter Pointer to HDD adapter
1229
1230 \return - ret no of characters written
1231
1232 --------------------------------------------------------------------------*/
1233static tANI_U32
1234hdd_format_batch_scan_rsp
1235(
1236 tANI_U8 *pDest,
1237 tANI_U32 cur_len,
1238 tANI_U32 tot_len,
1239 tHddBatchScanRsp *pApMetaInfo,
1240 hdd_adapter_t* pAdapter
1241)
1242{
1243 tANI_U32 ret = 0;
1244 tANI_U32 rem_len = 0;
1245 tANI_U8 temp_len = 0;
1246 tANI_U8 temp_total_len = 0;
1247 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1248 tANI_U8 *pTemp = temp;
1249
1250 /*Batch scan reponse needs to be returned to user space in
1251 following format:
1252 "scancount=X\n" where X is the number of scans in current batch
1253 batch
1254 "trunc\n" optional present if current scan truncated
1255 "bssid=XX:XX:XX:XX:XX:XX\n"
1256 "ssid=XXXX\n"
1257 "freq=X\n" frequency in Mhz
1258 "level=XX\n"
1259 "age=X\n" ms
1260 "dist=X\n" cm (-1 if not available)
1261 "errror=X\n" (-1if not available)
1262 "====\n" (end of ap marker)
1263 "####\n" (end of scan marker)
1264 "----\n" (end of results)*/
1265 /*send scan result in above format to user space based on
1266 available length*/
1267 /*The GET response may have more data than the driver can return in its
1268 buffer. In that case the buffer should be filled to the nearest complete
1269 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1270 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1271 The final buffer should end with "----\n"*/
1272
1273 /*sanity*/
1274 if (cur_len > tot_len)
1275 {
1276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1277 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1278 return 0;
1279 }
1280 else
1281 {
1282 rem_len = (tot_len - cur_len);
1283 }
1284
1285 /*end scan marker*/
1286 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1287 {
1288 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1289 pTemp += temp_len;
1290 temp_total_len += temp_len;
1291 }
1292
1293 /*bssid*/
1294 temp_len = snprintf(pTemp, sizeof(temp),
1295 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1296 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1297 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1298 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1299 pTemp += temp_len;
1300 temp_total_len += temp_len;
1301
1302 /*ssid*/
1303 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1304 pApMetaInfo->ApInfo.ssid);
1305 pTemp += temp_len;
1306 temp_total_len += temp_len;
1307
1308 /*freq*/
1309 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001310 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301311 pTemp += temp_len;
1312 temp_total_len += temp_len;
1313
1314 /*level*/
1315 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1316 pApMetaInfo->ApInfo.rssi);
1317 pTemp += temp_len;
1318 temp_total_len += temp_len;
1319
1320 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001321 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301322 pApMetaInfo->ApInfo.age);
1323 pTemp += temp_len;
1324 temp_total_len += temp_len;
1325
1326 /*dist*/
1327 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1328 pTemp += temp_len;
1329 temp_total_len += temp_len;
1330
1331 /*error*/
1332 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1333 pTemp += temp_len;
1334 temp_total_len += temp_len;
1335
1336 /*end AP marker*/
1337 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1338 pTemp += temp_len;
1339 temp_total_len += temp_len;
1340
1341 /*last AP in batch scan response*/
1342 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1343 {
1344 /*end scan marker*/
1345 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1346 pTemp += temp_len;
1347 temp_total_len += temp_len;
1348
1349 /*end batch scan result marker*/
1350 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1351 pTemp += temp_len;
1352 temp_total_len += temp_len;
1353 }
1354
1355 if (temp_total_len < rem_len)
1356 {
1357 ret = temp_total_len + 1;
1358 strlcpy(pDest, temp, ret);
1359 pAdapter->isTruncated = FALSE;
1360 }
1361 else
1362 {
1363 pAdapter->isTruncated = TRUE;
1364 if (rem_len >= strlen("%%%%"))
1365 {
1366 ret = snprintf(pDest, strlen("%%%%"), "%%%%");
1367 }
1368 {
1369 ret = 0;
1370 }
1371 }
1372
1373 return ret;
1374
1375}/*End of hdd_format_batch_scan_rsp*/
1376
1377/**---------------------------------------------------------------------------
1378
1379 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1380 buffer starting with head of hdd batch scan response queue
1381
1382 \param - pAdapter Pointer to HDD adapter
1383 \param - pDest Pointer to user data buffer
1384 \param - cur_len current offset in user buffer
1385 \param - rem_len remaining no of bytes in user buffer
1386
1387 \return - number of bytes written in user buffer
1388
1389 --------------------------------------------------------------------------*/
1390
1391tANI_U32 hdd_populate_user_batch_scan_rsp
1392(
1393 hdd_adapter_t* pAdapter,
1394 tANI_U8 *pDest,
1395 tANI_U32 cur_len,
1396 tANI_U32 rem_len
1397)
1398{
1399 tHddBatchScanRsp *pHead;
1400 tHddBatchScanRsp *pPrev;
1401 tANI_U32 len;
1402
1403 pAdapter->prev_batch_id = 0;
1404 pAdapter->isTruncated = FALSE;
1405
1406 /*head of hdd batch scan response queue*/
1407 pHead = pAdapter->pBatchScanRsp;
1408 while (pHead)
1409 {
1410 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1411 pAdapter);
1412 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001413 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301414 cur_len += len;
1415 if(TRUE == pAdapter->isTruncated)
1416 {
1417 /*result is truncated return rest of scan rsp in next req*/
1418 cur_len = rem_len;
1419 break;
1420 }
1421 pPrev = pHead;
1422 pHead = pHead->pNext;
1423 pAdapter->pBatchScanRsp = pHead;
1424 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1425 vos_mem_free(pPrev);
1426 }
1427
1428 return cur_len;
1429}/*End of hdd_populate_user_batch_scan_rsp*/
1430
1431/**---------------------------------------------------------------------------
1432
1433 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1434 scan response data from HDD queue to user space
1435 It does following in detail:
1436 a) if HDD has enough data in its queue then it 1st copies data to user
1437 space and then send get batch scan indication message to FW. In this
1438 case it does not wait on any event and batch scan response data will
1439 be populated in HDD response queue in MC thread context after receiving
1440 indication from FW
1441 b) else send get batch scan indication message to FW and wait on an event
1442 which will be set once HDD receives complete batch scan response from
1443 FW and then this function returns batch scan response to user space
1444
1445 \param - pAdapter Pointer to HDD adapter
1446 \param - pPrivData Pointer to priv_data
1447
1448 \return - 0 for success -EFAULT for failure
1449
1450 --------------------------------------------------------------------------*/
1451
1452int hdd_return_batch_scan_rsp_to_user
1453(
1454 hdd_adapter_t* pAdapter,
1455 hdd_priv_data_t *pPrivData,
1456 tANI_U8 *command
1457)
1458{
1459 tANI_U8 *pDest;
1460 tANI_U32 count = 0;
1461 tANI_U32 len = 0;
1462 tANI_U32 cur_len = 0;
1463 tANI_U32 rem_len = 0;
1464 eHalStatus halStatus;
1465 unsigned long rc;
1466 tSirTriggerBatchScanResultInd *pReq;
1467
1468 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1469 pReq->param = 0;/*batch scan client*/
1470 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1471 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1472
1473 cur_len = pPrivData->used_len;
1474 if (pPrivData->total_len > pPrivData->used_len)
1475 {
1476 rem_len = pPrivData->total_len - pPrivData->used_len;
1477 }
1478 else
1479 {
1480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1481 "%s: Invalid user data buffer total_len %d used_len %d",
1482 __func__, pPrivData->total_len, pPrivData->used_len);
1483 return -EFAULT;
1484 }
1485
1486 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1487 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1488 cur_len, rem_len);
1489 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1490
1491 /*enough scan result available in cache to return to user space or
1492 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001493 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301494 {
1495 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1496 halStatus = sme_TriggerBatchScanResultInd(
1497 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1498 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1499 pAdapter);
1500 if ( eHAL_STATUS_SUCCESS == halStatus )
1501 {
1502 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1503 {
1504 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1505 rc = wait_for_completion_timeout(
1506 &pAdapter->hdd_get_batch_scan_req_var,
1507 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1508 if (0 == rc)
1509 {
1510 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1511 "%s: Timeout waiting to fetch batch scan rsp from fw",
1512 __func__);
1513 return -EFAULT;
1514 }
1515 }
1516
1517 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001518 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301519 pDest += len;
1520 cur_len += len;
1521
1522 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1523 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1524 cur_len, rem_len);
1525 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1526
1527 count = 0;
1528 len = (len - pPrivData->used_len);
1529 pDest = (command + pPrivData->used_len);
1530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001531 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301532 while(count < len)
1533 {
1534 printk("%c", *(pDest + count));
1535 count++;
1536 }
1537 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1538 "%s: copy %d data to user buffer", __func__, len);
1539 if (copy_to_user(pPrivData->buf, pDest, len))
1540 {
1541 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1542 "%s: failed to copy data to user buffer", __func__);
1543 return -EFAULT;
1544 }
1545 }
1546 else
1547 {
1548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1549 "sme_GetBatchScanScan returned failure halStatus %d",
1550 halStatus);
1551 return -EINVAL;
1552 }
1553 }
1554 else
1555 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301556 count = 0;
1557 len = (len - pPrivData->used_len);
1558 pDest = (command + pPrivData->used_len);
1559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001560 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301561 while(count < len)
1562 {
1563 printk("%c", *(pDest + count));
1564 count++;
1565 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1567 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301568 if (copy_to_user(pPrivData->buf, pDest, len))
1569 {
1570 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1571 "%s: failed to copy data to user buffer", __func__);
1572 return -EFAULT;
1573 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301574 }
1575
1576 return 0;
1577} /*End of hdd_return_batch_scan_rsp_to_user*/
1578
1579#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1580
Jeff Johnson295189b2012-06-20 16:38:30 -07001581int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1582{
1583 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1584 hdd_priv_data_t priv_data;
1585 tANI_U8 *command = NULL;
1586 int ret = 0;
1587
1588 if (NULL == pAdapter)
1589 {
1590 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001591 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001592 ret = -ENODEV;
1593 goto exit;
1594 }
1595
Jeff Johnsone7245742012-09-05 17:12:55 -07001596 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001597 {
1598 ret = -EINVAL;
1599 goto exit;
1600 }
1601
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001602 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1603 {
1604 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1605 "%s:LOGP in Progress. Ignore!!!", __func__);
1606 ret = -EBUSY;
1607 goto exit;
1608 }
1609
Jeff Johnson295189b2012-06-20 16:38:30 -07001610 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1611 {
1612 ret = -EFAULT;
1613 goto exit;
1614 }
1615
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001616 if (priv_data.total_len <= 0)
1617 {
1618 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1619 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1620 priv_data.total_len);
1621 ret = -EINVAL;
1622 goto exit;
1623 }
1624
1625 /* Allocate +1 for '\0' */
1626 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001627 if (!command)
1628 {
1629 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001630 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001631 ret = -ENOMEM;
1632 goto exit;
1633 }
1634
1635 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1636 {
1637 ret = -EFAULT;
1638 goto exit;
1639 }
1640
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001641 /* Making sure the command is NUL-terminated */
1642 command[priv_data.total_len] = '\0';
1643
Jeff Johnson295189b2012-06-20 16:38:30 -07001644 if ((SIOCDEVPRIVATE + 1) == cmd)
1645 {
1646 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1647
1648 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001649 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001650
1651 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1652 {
1653 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1654 sizeof(tSirMacAddr)))
1655 {
1656 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001657 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001658 ret = -EFAULT;
1659 }
1660 }
Amar Singhal0974e402013-02-12 14:27:46 -08001661 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001662 {
Amar Singhal0974e402013-02-12 14:27:46 -08001663 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001664 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001665
Jeff Johnson295189b2012-06-20 16:38:30 -07001666 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001667
1668 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001669 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001670 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001671 "%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 -07001672 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001673 ret = hdd_setBand_helper(dev, ptr);
1674 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001675 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1676 {
1677 char *country_code;
1678
1679 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001680
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001681 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001682 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001683#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301684 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001685#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001686 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1687 (void *)(tSmeChangeCountryCallback)
1688 wlan_hdd_change_country_code_callback,
1689 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
1690 if (eHAL_STATUS_SUCCESS == ret)
1691 {
1692 ret = wait_for_completion_interruptible_timeout(
1693 &pAdapter->change_country_code,
1694 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1695 if (0 >= ret)
1696 {
1697 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1698 __func__);
1699 }
1700 }
1701 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001702 {
1703 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001704 "%s: SME Change Country code fail ret=%d", __func__, ret);
1705 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001706 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001707
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001708 }
1709 /*
1710 command should be a string having format
1711 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1712 */
Amar Singhal0974e402013-02-12 14:27:46 -08001713 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001714 {
Amar Singhal0974e402013-02-12 14:27:46 -08001715 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001716
1717 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001718 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001719
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001720 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001721 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001722 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1723 {
1724 int suspend = 0;
1725 tANI_U8 *ptr = (tANI_U8*)command + 15;
1726
1727 suspend = *ptr - '0';
1728 hdd_set_wlan_suspend_mode(suspend);
1729 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001730#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1731 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1732 {
1733 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001734 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001735 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1736 eHalStatus status = eHAL_STATUS_SUCCESS;
1737
1738 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1739 value = value + 15;
1740
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001741 /* Convert the value from ascii to integer */
1742 ret = kstrtos8(value, 10, &rssi);
1743 if (ret < 0)
1744 {
1745 /* If the input value is greater than max value of datatype, then also
1746 kstrtou8 fails */
1747 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1748 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07001749 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001750 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1751 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1752 ret = -EINVAL;
1753 goto exit;
1754 }
1755
Srinivas Girigowdade697412013-02-14 16:31:48 -08001756 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001757
Srinivas Girigowdade697412013-02-14 16:31:48 -08001758 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1759 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1760 {
1761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1762 "Neighbor lookup threshold value %d is out of range"
1763 " (Min: %d Max: %d)", lookUpThreshold,
1764 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1765 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1766 ret = -EINVAL;
1767 goto exit;
1768 }
1769
1770 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1771 "%s: Received Command to Set Roam trigger"
1772 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1773
1774 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1775 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1776 if (eHAL_STATUS_SUCCESS != status)
1777 {
1778 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1779 "%s: Failed to set roam trigger, try again", __func__);
1780 ret = -EPERM;
1781 goto exit;
1782 }
1783
1784 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1785 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1786 }
1787 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1788 {
1789 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1790 int rssi = (-1) * lookUpThreshold;
1791 char extra[32];
1792 tANI_U8 len = 0;
1793
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001794 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001795 if (copy_to_user(priv_data.buf, &extra, len + 1))
1796 {
1797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1798 "%s: failed to copy data to user buffer", __func__);
1799 ret = -EFAULT;
1800 goto exit;
1801 }
1802 }
1803 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1804 {
1805 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001806 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001807 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001808
Srinivas Girigowdade697412013-02-14 16:31:48 -08001809 /* input refresh period is in terms of seconds */
1810 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1811 value = value + 18;
1812 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001813 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001814 if (ret < 0)
1815 {
1816 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001817 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001818 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001819 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001820 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001821 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1822 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001823 ret = -EINVAL;
1824 goto exit;
1825 }
1826
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001827 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1828 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001829 {
1830 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001831 "Roam scan period value %d is out of range"
1832 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001833 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1834 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001835 ret = -EINVAL;
1836 goto exit;
1837 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001838 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001839
1840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1841 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001842 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001843
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001844 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1845 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001846 }
1847 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1848 {
1849 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1850 char extra[32];
1851 tANI_U8 len = 0;
1852
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001853 len = scnprintf(extra, sizeof(extra), "%s %d",
1854 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001855 /* Returned value is in units of seconds */
1856 if (copy_to_user(priv_data.buf, &extra, len + 1))
1857 {
1858 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1859 "%s: failed to copy data to user buffer", __func__);
1860 ret = -EFAULT;
1861 goto exit;
1862 }
1863 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001864 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1865 {
1866 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001867 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001868 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001869
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001870 /* input refresh period is in terms of seconds */
1871 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1872 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001873
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001874 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001875 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001876 if (ret < 0)
1877 {
1878 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001879 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001881 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001882 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001883 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1884 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1885 ret = -EINVAL;
1886 goto exit;
1887 }
1888
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001889 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1890 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1891 {
1892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1893 "Neighbor scan results refresh period value %d is out of range"
1894 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1895 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1896 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1897 ret = -EINVAL;
1898 goto exit;
1899 }
1900 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1901
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001902 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1903 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001904 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001905
1906 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1907 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1908 }
1909 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1910 {
1911 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1912 char extra[32];
1913 tANI_U8 len = 0;
1914
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001915 len = scnprintf(extra, sizeof(extra), "%s %d",
1916 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001917 /* Returned value is in units of seconds */
1918 if (copy_to_user(priv_data.buf, &extra, len + 1))
1919 {
1920 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1921 "%s: failed to copy data to user buffer", __func__);
1922 ret = -EFAULT;
1923 goto exit;
1924 }
1925 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001926#ifdef FEATURE_WLAN_LFR
1927 /* SETROAMMODE */
1928 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1929 {
1930 tANI_U8 *value = command;
1931 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1932
1933 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1934 value = value + SIZE_OF_SETROAMMODE + 1;
1935
1936 /* Convert the value from ascii to integer */
1937 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1938 if (ret < 0)
1939 {
1940 /* If the input value is greater than max value of datatype, then also
1941 kstrtou8 fails */
1942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1943 "%s: kstrtou8 failed range [%d - %d]", __func__,
1944 CFG_LFR_FEATURE_ENABLED_MIN,
1945 CFG_LFR_FEATURE_ENABLED_MAX);
1946 ret = -EINVAL;
1947 goto exit;
1948 }
1949 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1950 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
1951 {
1952 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1953 "Roam Mode value %d is out of range"
1954 " (Min: %d Max: %d)", roamMode,
1955 CFG_LFR_FEATURE_ENABLED_MIN,
1956 CFG_LFR_FEATURE_ENABLED_MAX);
1957 ret = -EINVAL;
1958 goto exit;
1959 }
1960
1961 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1962 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
1963 /*
1964 * Note that
1965 * SETROAMMODE 0 is to enable LFR while
1966 * SETROAMMODE 1 is to disable LFR, but
1967 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
1968 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
1969 */
1970 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1971 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
1972 else
1973 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
1974
1975 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
1976 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
1977 }
1978 /* GETROAMMODE */
1979 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
1980 {
1981 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1982 char extra[32];
1983 tANI_U8 len = 0;
1984
1985 /*
1986 * roamMode value shall be inverted because the sementics is different.
1987 */
1988 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1989 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
1990 else
1991 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
1992
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001993 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001994 if (copy_to_user(priv_data.buf, &extra, len + 1))
1995 {
1996 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1997 "%s: failed to copy data to user buffer", __func__);
1998 ret = -EFAULT;
1999 goto exit;
2000 }
2001 }
2002#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002003#endif
2004#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2005 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2006 {
2007 tANI_U8 *value = command;
2008 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2009
2010 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2011 value = value + 13;
2012 /* Convert the value from ascii to integer */
2013 ret = kstrtou8(value, 10, &roamRssiDiff);
2014 if (ret < 0)
2015 {
2016 /* If the input value is greater than max value of datatype, then also
2017 kstrtou8 fails */
2018 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2019 "%s: kstrtou8 failed range [%d - %d]", __func__,
2020 CFG_ROAM_RSSI_DIFF_MIN,
2021 CFG_ROAM_RSSI_DIFF_MAX);
2022 ret = -EINVAL;
2023 goto exit;
2024 }
2025
2026 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2027 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2028 {
2029 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2030 "Roam rssi diff value %d is out of range"
2031 " (Min: %d Max: %d)", roamRssiDiff,
2032 CFG_ROAM_RSSI_DIFF_MIN,
2033 CFG_ROAM_RSSI_DIFF_MAX);
2034 ret = -EINVAL;
2035 goto exit;
2036 }
2037
2038 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2039 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2040
2041 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2042 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2043 }
2044 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2045 {
2046 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2047 char extra[32];
2048 tANI_U8 len = 0;
2049
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002050 len = scnprintf(extra, sizeof(extra), "%s %d",
2051 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002052 if (copy_to_user(priv_data.buf, &extra, len + 1))
2053 {
2054 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2055 "%s: failed to copy data to user buffer", __func__);
2056 ret = -EFAULT;
2057 goto exit;
2058 }
2059 }
2060#endif
2061#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2062 else if (strncmp(command, "GETBAND", 7) == 0)
2063 {
2064 int band = -1;
2065 char extra[32];
2066 tANI_U8 len = 0;
2067 hdd_getBand_helper(pHddCtx, &band);
2068
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002069 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002070 if (copy_to_user(priv_data.buf, &extra, len + 1))
2071 {
2072 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2073 "%s: failed to copy data to user buffer", __func__);
2074 ret = -EFAULT;
2075 goto exit;
2076 }
2077 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002078 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2079 {
2080 tANI_U8 *value = command;
2081 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2082 tANI_U8 numChannels = 0;
2083 eHalStatus status = eHAL_STATUS_SUCCESS;
2084
2085 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2086 if (eHAL_STATUS_SUCCESS != status)
2087 {
2088 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2089 "%s: Failed to parse channel list information", __func__);
2090 ret = -EINVAL;
2091 goto exit;
2092 }
2093
2094 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2095 {
2096 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2097 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2098 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2099 ret = -EINVAL;
2100 goto exit;
2101 }
2102 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2103 numChannels);
2104 if (eHAL_STATUS_SUCCESS != status)
2105 {
2106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2107 "%s: Failed to update channel list information", __func__);
2108 ret = -EINVAL;
2109 goto exit;
2110 }
2111 }
2112 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2113 {
2114 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2115 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002116 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002117 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002118 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002119
2120 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2121 ChannelList, &numChannels ))
2122 {
2123 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2124 "%s: failed to get roam scan channel list", __func__);
2125 ret = -EFAULT;
2126 goto exit;
2127 }
2128 /* output channel list is of the format
2129 [Number of roam scan channels][Channel1][Channel2]... */
2130 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002131 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002132 for (j = 0; (j < numChannels); j++)
2133 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002134 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2135 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002136 }
2137
2138 if (copy_to_user(priv_data.buf, &extra, len + 1))
2139 {
2140 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2141 "%s: failed to copy data to user buffer", __func__);
2142 ret = -EFAULT;
2143 goto exit;
2144 }
2145 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002146 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2147 {
2148 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2149 char extra[32];
2150 tANI_U8 len = 0;
2151
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002152 /* Check if the features OKC/CCX/11R are supported simultaneously,
2153 then this operation is not permitted (return FAILURE) */
2154 if (ccxMode &&
2155 hdd_is_okc_mode_enabled(pHddCtx) &&
2156 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2157 {
2158 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2159 "%s: OKC/CCX/11R are supported simultaneously"
2160 " hence this operation is not permitted!", __func__);
2161 ret = -EPERM;
2162 goto exit;
2163 }
2164
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002165 len = scnprintf(extra, sizeof(extra), "%s %d",
2166 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002167 if (copy_to_user(priv_data.buf, &extra, len + 1))
2168 {
2169 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2170 "%s: failed to copy data to user buffer", __func__);
2171 ret = -EFAULT;
2172 goto exit;
2173 }
2174 }
2175 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2176 {
2177 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2178 char extra[32];
2179 tANI_U8 len = 0;
2180
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002181 /* Check if the features OKC/CCX/11R are supported simultaneously,
2182 then this operation is not permitted (return FAILURE) */
2183 if (okcMode &&
2184 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2185 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2186 {
2187 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2188 "%s: OKC/CCX/11R are supported simultaneously"
2189 " hence this operation is not permitted!", __func__);
2190 ret = -EPERM;
2191 goto exit;
2192 }
2193
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002194 len = scnprintf(extra, sizeof(extra), "%s %d",
2195 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002196 if (copy_to_user(priv_data.buf, &extra, len + 1))
2197 {
2198 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2199 "%s: failed to copy data to user buffer", __func__);
2200 ret = -EFAULT;
2201 goto exit;
2202 }
2203 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002204 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002205 {
2206 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2207 char extra[32];
2208 tANI_U8 len = 0;
2209
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002210 len = scnprintf(extra, sizeof(extra), "%s %d",
2211 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002212 if (copy_to_user(priv_data.buf, &extra, len + 1))
2213 {
2214 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2215 "%s: failed to copy data to user buffer", __func__);
2216 ret = -EFAULT;
2217 goto exit;
2218 }
2219 }
2220 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2221 {
2222 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2223 char extra[32];
2224 tANI_U8 len = 0;
2225
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002226 len = scnprintf(extra, sizeof(extra), "%s %d",
2227 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002228 if (copy_to_user(priv_data.buf, &extra, len + 1))
2229 {
2230 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2231 "%s: failed to copy data to user buffer", __func__);
2232 ret = -EFAULT;
2233 goto exit;
2234 }
2235 }
2236 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2237 {
2238 tANI_U8 *value = command;
2239 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2240
2241 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2242 value = value + 26;
2243 /* Convert the value from ascii to integer */
2244 ret = kstrtou8(value, 10, &minTime);
2245 if (ret < 0)
2246 {
2247 /* If the input value is greater than max value of datatype, then also
2248 kstrtou8 fails */
2249 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2250 "%s: kstrtou8 failed range [%d - %d]", __func__,
2251 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2252 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2253 ret = -EINVAL;
2254 goto exit;
2255 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002256 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2257 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2258 {
2259 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2260 "scan min channel time value %d is out of range"
2261 " (Min: %d Max: %d)", minTime,
2262 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2263 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2264 ret = -EINVAL;
2265 goto exit;
2266 }
2267
2268 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2269 "%s: Received Command to change channel min time = %d", __func__, minTime);
2270
2271 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2272 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2273 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002274 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2275 {
2276 tANI_U8 *value = command;
2277 tANI_U8 channel = 0;
2278 tANI_U8 dwellTime = 0;
2279 tANI_U8 bufLen = 0;
2280 tANI_U8 *buf = NULL;
2281 tSirMacAddr targetApBssid;
2282 eHalStatus status = eHAL_STATUS_SUCCESS;
2283 struct ieee80211_channel chan;
2284 tANI_U8 finalLen = 0;
2285 tANI_U8 *finalBuf = NULL;
2286 tANI_U8 temp = 0;
2287 u64 cookie;
2288 hdd_station_ctx_t *pHddStaCtx = NULL;
2289 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2290
2291 /* if not associated, no need to send action frame */
2292 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2293 {
2294 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2295 ret = -EINVAL;
2296 goto exit;
2297 }
2298
2299 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2300 &dwellTime, &buf, &bufLen);
2301 if (eHAL_STATUS_SUCCESS != status)
2302 {
2303 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2304 "%s: Failed to parse send action frame data", __func__);
2305 ret = -EINVAL;
2306 goto exit;
2307 }
2308
2309 /* if the target bssid is different from currently associated AP,
2310 then no need to send action frame */
2311 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2312 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2313 {
2314 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2315 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002316 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002317 goto exit;
2318 }
2319
2320 /* if the channel number is different from operating channel then
2321 no need to send action frame */
2322 if (channel != pHddStaCtx->conn_info.operationChannel)
2323 {
2324 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2325 "%s: channel(%d) is different from operating channel(%d)",
2326 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2327 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002328 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002329 goto exit;
2330 }
2331 chan.center_freq = sme_ChnToFreq(channel);
2332
2333 finalLen = bufLen + 24;
2334 finalBuf = vos_mem_malloc(finalLen);
2335 if (NULL == finalBuf)
2336 {
2337 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2338 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002339 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002340 goto exit;
2341 }
2342 vos_mem_zero(finalBuf, finalLen);
2343
2344 /* Fill subtype */
2345 temp = SIR_MAC_MGMT_ACTION << 4;
2346 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2347
2348 /* Fill type */
2349 temp = SIR_MAC_MGMT_FRAME;
2350 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2351
2352 /* Fill destination address (bssid of the AP) */
2353 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2354
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002355 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002356 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2357
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002358 /* Fill BSSID (AP mac address) */
2359 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002360
2361 /* Fill received buffer from 24th address */
2362 vos_mem_copy(finalBuf + 24, buf, bufLen);
2363
Jeff Johnson11c33152013-04-16 17:52:40 -07002364 /* done with the parsed buffer */
2365 vos_mem_free(buf);
2366
Yue Maf49ba872013-08-19 12:04:25 -07002367 wlan_hdd_action( NULL,
2368#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2369 &(pAdapter->wdev),
2370#else
2371 dev,
2372#endif
2373 &chan, 0,
2374#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2375 NL80211_CHAN_HT20, 1,
2376#endif
2377 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002378 1, &cookie );
2379 vos_mem_free(finalBuf);
2380 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002381 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2382 {
2383 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2384 char extra[32];
2385 tANI_U8 len = 0;
2386
2387 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002388 len = scnprintf(extra, sizeof(extra), "%s %d",
2389 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002390 if (copy_to_user(priv_data.buf, &extra, len + 1))
2391 {
2392 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2393 "%s: failed to copy data to user buffer", __func__);
2394 ret = -EFAULT;
2395 goto exit;
2396 }
2397 }
2398 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2399 {
2400 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002401 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002402 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002403
2404 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2405 value = value + 19;
2406 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002407 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002408 if (ret < 0)
2409 {
2410 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002411 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002412 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002413 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002414 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2415 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2416 ret = -EINVAL;
2417 goto exit;
2418 }
2419
2420 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2421 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2422 {
2423 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2424 "lfr mode value %d is out of range"
2425 " (Min: %d Max: %d)", maxTime,
2426 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2427 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2428 ret = -EINVAL;
2429 goto exit;
2430 }
2431
2432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2433 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2434
2435 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002436
2437 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2438 * where RFS is the RF Switching time. It is twice RFS to consider the
2439 * time to go off channel and return to the home channel. */
2440 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2441 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2442 {
2443 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002444 "%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 -07002445 " Hence enforcing home away time to disable (0)",
2446 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2447 homeAwayTime = 0;
2448 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2449 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
2450 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002451 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2452 }
2453 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2454 {
2455 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2456 char extra[32];
2457 tANI_U8 len = 0;
2458
2459 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002460 len = scnprintf(extra, sizeof(extra), "%s %d",
2461 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002462 if (copy_to_user(priv_data.buf, &extra, len + 1))
2463 {
2464 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2465 "%s: failed to copy data to user buffer", __func__);
2466 ret = -EFAULT;
2467 goto exit;
2468 }
2469 }
2470 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2471 {
2472 tANI_U8 *value = command;
2473 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2474
2475 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2476 value = value + 16;
2477 /* Convert the value from ascii to integer */
2478 ret = kstrtou16(value, 10, &val);
2479 if (ret < 0)
2480 {
2481 /* If the input value is greater than max value of datatype, then also
2482 kstrtou16 fails */
2483 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2484 "%s: kstrtou16 failed range [%d - %d]", __func__,
2485 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2486 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2487 ret = -EINVAL;
2488 goto exit;
2489 }
2490
2491 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2492 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2493 {
2494 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2495 "scan home time value %d is out of range"
2496 " (Min: %d Max: %d)", val,
2497 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2498 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2499 ret = -EINVAL;
2500 goto exit;
2501 }
2502
2503 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2504 "%s: Received Command to change scan home time = %d", __func__, val);
2505
2506 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2507 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2508 }
2509 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2510 {
2511 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2512 char extra[32];
2513 tANI_U8 len = 0;
2514
2515 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002516 len = scnprintf(extra, sizeof(extra), "%s %d",
2517 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002518 if (copy_to_user(priv_data.buf, &extra, len + 1))
2519 {
2520 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2521 "%s: failed to copy data to user buffer", __func__);
2522 ret = -EFAULT;
2523 goto exit;
2524 }
2525 }
2526 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2527 {
2528 tANI_U8 *value = command;
2529 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2530
2531 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2532 value = value + 17;
2533 /* Convert the value from ascii to integer */
2534 ret = kstrtou8(value, 10, &val);
2535 if (ret < 0)
2536 {
2537 /* If the input value is greater than max value of datatype, then also
2538 kstrtou8 fails */
2539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2540 "%s: kstrtou8 failed range [%d - %d]", __func__,
2541 CFG_ROAM_INTRA_BAND_MIN,
2542 CFG_ROAM_INTRA_BAND_MAX);
2543 ret = -EINVAL;
2544 goto exit;
2545 }
2546
2547 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2548 (val > CFG_ROAM_INTRA_BAND_MAX))
2549 {
2550 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2551 "intra band mode value %d is out of range"
2552 " (Min: %d Max: %d)", val,
2553 CFG_ROAM_INTRA_BAND_MIN,
2554 CFG_ROAM_INTRA_BAND_MAX);
2555 ret = -EINVAL;
2556 goto exit;
2557 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002558 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2559 "%s: Received Command to change intra band = %d", __func__, val);
2560
2561 pHddCtx->cfg_ini->nRoamIntraBand = val;
2562 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2563 }
2564 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2565 {
2566 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2567 char extra[32];
2568 tANI_U8 len = 0;
2569
2570 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002571 len = scnprintf(extra, sizeof(extra), "%s %d",
2572 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002573 if (copy_to_user(priv_data.buf, &extra, len + 1))
2574 {
2575 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2576 "%s: failed to copy data to user buffer", __func__);
2577 ret = -EFAULT;
2578 goto exit;
2579 }
2580 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002581 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2582 {
2583 tANI_U8 *value = command;
2584 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2585
2586 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2587 value = value + 15;
2588 /* Convert the value from ascii to integer */
2589 ret = kstrtou8(value, 10, &nProbes);
2590 if (ret < 0)
2591 {
2592 /* If the input value is greater than max value of datatype, then also
2593 kstrtou8 fails */
2594 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2595 "%s: kstrtou8 failed range [%d - %d]", __func__,
2596 CFG_ROAM_SCAN_N_PROBES_MIN,
2597 CFG_ROAM_SCAN_N_PROBES_MAX);
2598 ret = -EINVAL;
2599 goto exit;
2600 }
2601
2602 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2603 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2604 {
2605 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2606 "NProbes value %d is out of range"
2607 " (Min: %d Max: %d)", nProbes,
2608 CFG_ROAM_SCAN_N_PROBES_MIN,
2609 CFG_ROAM_SCAN_N_PROBES_MAX);
2610 ret = -EINVAL;
2611 goto exit;
2612 }
2613
2614 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2615 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2616
2617 pHddCtx->cfg_ini->nProbes = nProbes;
2618 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2619 }
2620 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2621 {
2622 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2623 char extra[32];
2624 tANI_U8 len = 0;
2625
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002626 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002627 if (copy_to_user(priv_data.buf, &extra, len + 1))
2628 {
2629 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2630 "%s: failed to copy data to user buffer", __func__);
2631 ret = -EFAULT;
2632 goto exit;
2633 }
2634 }
2635 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2636 {
2637 tANI_U8 *value = command;
2638 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002639 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002640
2641 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2642 /* input value is in units of msec */
2643 value = value + 20;
2644 /* Convert the value from ascii to integer */
2645 ret = kstrtou16(value, 10, &homeAwayTime);
2646 if (ret < 0)
2647 {
2648 /* If the input value is greater than max value of datatype, then also
2649 kstrtou8 fails */
2650 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2651 "%s: kstrtou8 failed range [%d - %d]", __func__,
2652 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2653 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2654 ret = -EINVAL;
2655 goto exit;
2656 }
2657
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002658 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2659 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2660 {
2661 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2662 "homeAwayTime value %d is out of range"
2663 " (Min: %d Max: %d)", homeAwayTime,
2664 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2665 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2666 ret = -EINVAL;
2667 goto exit;
2668 }
2669
2670 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2671 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
2672
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002673 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2674 * where RFS is the RF Switching time. It is twice RFS to consider the
2675 * time to go off channel and return to the home channel. */
2676 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2677 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2678 {
2679 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002680 "%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 -07002681 " Hence enforcing home away time to disable (0)",
2682 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2683 homeAwayTime = 0;
2684 }
2685
2686 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2687 {
2688 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2689 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2690 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002691 }
2692 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2693 {
2694 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2695 char extra[32];
2696 tANI_U8 len = 0;
2697
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002698 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002699 if (copy_to_user(priv_data.buf, &extra, len + 1))
2700 {
2701 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2702 "%s: failed to copy data to user buffer", __func__);
2703 ret = -EFAULT;
2704 goto exit;
2705 }
2706 }
2707 else if (strncmp(command, "REASSOC", 7) == 0)
2708 {
2709 tANI_U8 *value = command;
2710 tANI_U8 channel = 0;
2711 tSirMacAddr targetApBssid;
2712 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002713#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2714 tCsrHandoffRequest handoffInfo;
2715#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002716 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002717 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2718
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002719 /* if not associated, no need to proceed with reassoc */
2720 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2721 {
2722 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2723 ret = -EINVAL;
2724 goto exit;
2725 }
2726
2727 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2728 if (eHAL_STATUS_SUCCESS != status)
2729 {
2730 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2731 "%s: Failed to parse reassoc command data", __func__);
2732 ret = -EINVAL;
2733 goto exit;
2734 }
2735
2736 /* if the target bssid is same as currently associated AP,
2737 then no need to proceed with reassoc */
2738 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2739 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2740 {
2741 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2742 ret = -EINVAL;
2743 goto exit;
2744 }
2745
2746 /* Check channel number is a valid channel number */
2747 if(VOS_STATUS_SUCCESS !=
2748 wlan_hdd_validate_operation_channel(pAdapter, channel))
2749 {
2750 hddLog(VOS_TRACE_LEVEL_ERROR,
2751 "%s: Invalid Channel [%d] \n", __func__, channel);
2752 return -EINVAL;
2753 }
2754
2755 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002756#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2757 handoffInfo.channel = channel;
2758 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2759 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2760#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002761 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002762 else if (strncmp(command, "SETWESMODE", 10) == 0)
2763 {
2764 tANI_U8 *value = command;
2765 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
2766
2767 /* Move pointer to ahead of SETWESMODE<delimiter> */
2768 value = value + 11;
2769 /* Convert the value from ascii to integer */
2770 ret = kstrtou8(value, 10, &wesMode);
2771 if (ret < 0)
2772 {
2773 /* If the input value is greater than max value of datatype, then also
2774 kstrtou8 fails */
2775 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2776 "%s: kstrtou8 failed range [%d - %d]", __func__,
2777 CFG_ENABLE_WES_MODE_NAME_MIN,
2778 CFG_ENABLE_WES_MODE_NAME_MAX);
2779 ret = -EINVAL;
2780 goto exit;
2781 }
2782
2783 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
2784 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
2785 {
2786 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2787 "WES Mode value %d is out of range"
2788 " (Min: %d Max: %d)", wesMode,
2789 CFG_ENABLE_WES_MODE_NAME_MIN,
2790 CFG_ENABLE_WES_MODE_NAME_MAX);
2791 ret = -EINVAL;
2792 goto exit;
2793 }
2794 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2795 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
2796
2797 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
2798 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
2799 }
2800 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
2801 {
2802 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
2803 char extra[32];
2804 tANI_U8 len = 0;
2805
Arif Hussain826d9412013-11-12 16:44:54 -08002806 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002807 if (copy_to_user(priv_data.buf, &extra, len + 1))
2808 {
2809 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2810 "%s: failed to copy data to user buffer", __func__);
2811 ret = -EFAULT;
2812 goto exit;
2813 }
2814 }
2815#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002816#ifdef FEATURE_WLAN_LFR
2817 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2818 {
2819 tANI_U8 *value = command;
2820 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2821
2822 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2823 value = value + 12;
2824 /* Convert the value from ascii to integer */
2825 ret = kstrtou8(value, 10, &lfrMode);
2826 if (ret < 0)
2827 {
2828 /* If the input value is greater than max value of datatype, then also
2829 kstrtou8 fails */
2830 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2831 "%s: kstrtou8 failed range [%d - %d]", __func__,
2832 CFG_LFR_FEATURE_ENABLED_MIN,
2833 CFG_LFR_FEATURE_ENABLED_MAX);
2834 ret = -EINVAL;
2835 goto exit;
2836 }
2837
2838 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2839 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2840 {
2841 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2842 "lfr mode value %d is out of range"
2843 " (Min: %d Max: %d)", lfrMode,
2844 CFG_LFR_FEATURE_ENABLED_MIN,
2845 CFG_LFR_FEATURE_ENABLED_MAX);
2846 ret = -EINVAL;
2847 goto exit;
2848 }
2849
2850 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2851 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2852
2853 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2854 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2855 }
2856#endif
2857#ifdef WLAN_FEATURE_VOWIFI_11R
2858 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2859 {
2860 tANI_U8 *value = command;
2861 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2862
2863 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2864 value = value + 18;
2865 /* Convert the value from ascii to integer */
2866 ret = kstrtou8(value, 10, &ft);
2867 if (ret < 0)
2868 {
2869 /* If the input value is greater than max value of datatype, then also
2870 kstrtou8 fails */
2871 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2872 "%s: kstrtou8 failed range [%d - %d]", __func__,
2873 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2874 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2875 ret = -EINVAL;
2876 goto exit;
2877 }
2878
2879 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2880 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2881 {
2882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2883 "ft mode value %d is out of range"
2884 " (Min: %d Max: %d)", ft,
2885 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2886 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2887 ret = -EINVAL;
2888 goto exit;
2889 }
2890
2891 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2892 "%s: Received Command to change ft mode = %d", __func__, ft);
2893
2894 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2895 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2896 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302897
2898 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2899 {
2900 tANI_U8 *value = command;
2901 tSirMacAddr targetApBssid;
2902 tANI_U8 trigger = 0;
2903 eHalStatus status = eHAL_STATUS_SUCCESS;
2904 hdd_station_ctx_t *pHddStaCtx = NULL;
2905 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2906
2907 /* if not associated, no need to proceed with reassoc */
2908 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2909 {
2910 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2911 ret = -EINVAL;
2912 goto exit;
2913 }
2914
2915 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2916 if (eHAL_STATUS_SUCCESS != status)
2917 {
2918 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2919 "%s: Failed to parse reassoc command data", __func__);
2920 ret = -EINVAL;
2921 goto exit;
2922 }
2923
2924 /* if the target bssid is same as currently associated AP,
2925 then no need to proceed with reassoc */
2926 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2927 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2928 {
2929 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2930 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2931 __func__);
2932 ret = -EINVAL;
2933 goto exit;
2934 }
2935
2936 /* Proceed with scan/roam */
2937 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2938 &targetApBssid[0],
2939 (tSmeFastRoamTrigger)(trigger));
2940 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002941#endif
2942#ifdef FEATURE_WLAN_CCX
2943 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2944 {
2945 tANI_U8 *value = command;
2946 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2947
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002948 /* Check if the features OKC/CCX/11R are supported simultaneously,
2949 then this operation is not permitted (return FAILURE) */
2950 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2951 hdd_is_okc_mode_enabled(pHddCtx) &&
2952 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2953 {
2954 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2955 "%s: OKC/CCX/11R are supported simultaneously"
2956 " hence this operation is not permitted!", __func__);
2957 ret = -EPERM;
2958 goto exit;
2959 }
2960
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002961 /* Move pointer to ahead of SETCCXMODE<delimiter> */
2962 value = value + 11;
2963 /* Convert the value from ascii to integer */
2964 ret = kstrtou8(value, 10, &ccxMode);
2965 if (ret < 0)
2966 {
2967 /* If the input value is greater than max value of datatype, then also
2968 kstrtou8 fails */
2969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2970 "%s: kstrtou8 failed range [%d - %d]", __func__,
2971 CFG_CCX_FEATURE_ENABLED_MIN,
2972 CFG_CCX_FEATURE_ENABLED_MAX);
2973 ret = -EINVAL;
2974 goto exit;
2975 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002976 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
2977 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
2978 {
2979 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2980 "Ccx mode value %d is out of range"
2981 " (Min: %d Max: %d)", ccxMode,
2982 CFG_CCX_FEATURE_ENABLED_MIN,
2983 CFG_CCX_FEATURE_ENABLED_MAX);
2984 ret = -EINVAL;
2985 goto exit;
2986 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002987 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2988 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
2989
2990 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
2991 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
2992 }
2993#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002994 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
2995 {
2996 tANI_U8 *value = command;
2997 tANI_BOOLEAN roamScanControl = 0;
2998
2999 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3000 value = value + 19;
3001 /* Convert the value from ascii to integer */
3002 ret = kstrtou8(value, 10, &roamScanControl);
3003 if (ret < 0)
3004 {
3005 /* If the input value is greater than max value of datatype, then also
3006 kstrtou8 fails */
3007 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3008 "%s: kstrtou8 failed ", __func__);
3009 ret = -EINVAL;
3010 goto exit;
3011 }
3012
3013 if (0 != roamScanControl)
3014 {
3015 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3016 "roam scan control invalid value = %d",
3017 roamScanControl);
3018 ret = -EINVAL;
3019 goto exit;
3020 }
3021 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3022 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3023
3024 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3025 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003026#ifdef FEATURE_WLAN_OKC
3027 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3028 {
3029 tANI_U8 *value = command;
3030 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3031
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003032 /* Check if the features OKC/CCX/11R are supported simultaneously,
3033 then this operation is not permitted (return FAILURE) */
3034 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3035 hdd_is_okc_mode_enabled(pHddCtx) &&
3036 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3037 {
3038 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3039 "%s: OKC/CCX/11R are supported simultaneously"
3040 " hence this operation is not permitted!", __func__);
3041 ret = -EPERM;
3042 goto exit;
3043 }
3044
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003045 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3046 value = value + 11;
3047 /* Convert the value from ascii to integer */
3048 ret = kstrtou8(value, 10, &okcMode);
3049 if (ret < 0)
3050 {
3051 /* If the input value is greater than max value of datatype, then also
3052 kstrtou8 fails */
3053 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3054 "%s: kstrtou8 failed range [%d - %d]", __func__,
3055 CFG_OKC_FEATURE_ENABLED_MIN,
3056 CFG_OKC_FEATURE_ENABLED_MAX);
3057 ret = -EINVAL;
3058 goto exit;
3059 }
3060
3061 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3062 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3063 {
3064 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3065 "Okc mode value %d is out of range"
3066 " (Min: %d Max: %d)", okcMode,
3067 CFG_OKC_FEATURE_ENABLED_MIN,
3068 CFG_OKC_FEATURE_ENABLED_MAX);
3069 ret = -EINVAL;
3070 goto exit;
3071 }
3072
3073 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3074 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3075
3076 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3077 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003078#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003079 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3080 {
3081 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3082 char extra[32];
3083 tANI_U8 len = 0;
3084
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003085 len = scnprintf(extra, sizeof(extra), "%s %d",
3086 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003087 if (copy_to_user(priv_data.buf, &extra, len + 1))
3088 {
3089 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3090 "%s: failed to copy data to user buffer", __func__);
3091 ret = -EFAULT;
3092 goto exit;
3093 }
3094 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303095#ifdef WLAN_FEATURE_PACKET_FILTERING
3096 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3097 {
3098 tANI_U8 filterType = 0;
3099 tANI_U8 *value = command;
3100
3101 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3102 value = value + 22;
3103
3104 /* Convert the value from ascii to integer */
3105 ret = kstrtou8(value, 10, &filterType);
3106 if (ret < 0)
3107 {
3108 /* If the input value is greater than max value of datatype,
3109 * then also kstrtou8 fails
3110 */
3111 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3112 "%s: kstrtou8 failed range ", __func__);
3113 ret = -EINVAL;
3114 goto exit;
3115 }
3116
3117 if (filterType != 0 && filterType != 1)
3118 {
3119 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3120 "%s: Accepted Values are 0 and 1 ", __func__);
3121 ret = -EINVAL;
3122 goto exit;
3123 }
3124 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3125 pAdapter->sessionId);
3126 }
3127#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303128 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3129 {
3130 char *dhcpPhase;
3131 dhcpPhase = command + 12;
3132 if ('1' == *dhcpPhase)
3133 {
3134 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3135 pAdapter->macAddressCurrent.bytes);
3136 }
3137 else if ('2' == *dhcpPhase)
3138 {
3139 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3140 pAdapter->macAddressCurrent.bytes);
3141 }
3142 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003143 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3144 {
3145 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3146 }
3147 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3148 {
3149 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3150 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303151 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3152 {
3153 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3154 char extra[32];
3155 tANI_U8 len = 0;
3156
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003157 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303158 (int)pCfg->nActiveMaxChnTime);
3159 if (copy_to_user(priv_data.buf, &extra, len + 1))
3160 {
3161 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3162 "%s: failed to copy data to user buffer", __func__);
3163 ret = -EFAULT;
3164 goto exit;
3165 }
3166 ret = len;
3167 }
3168 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3169 {
3170 tANI_U8 *value = command;
3171 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3172 int val = 0, temp;
3173
3174 value = value + 13;
3175 temp = kstrtou32(value, 10, &val);
3176 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3177 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3178 {
3179 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3180 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3181 ret = -EFAULT;
3182 goto exit;
3183 }
3184 pCfg->nActiveMaxChnTime = val;
3185 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003186 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3187 {
3188 tANI_U8 filterType = 0;
3189 tANI_U8 *value;
3190 value = command + 9;
3191
3192 /* Convert the value from ascii to integer */
3193 ret = kstrtou8(value, 10, &filterType);
3194 if (ret < 0)
3195 {
3196 /* If the input value is greater than max value of datatype,
3197 * then also kstrtou8 fails
3198 */
3199 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3200 "%s: kstrtou8 failed range ", __func__);
3201 ret = -EINVAL;
3202 goto exit;
3203 }
3204 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3205 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3206 {
3207 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3208 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3209 " 2-Sink ", __func__);
3210 ret = -EINVAL;
3211 goto exit;
3212 }
3213 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3214 pHddCtx->drvr_miracast = filterType;
3215 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3216 }
Leo Chang614d2072013-08-22 14:59:44 -07003217 else if (strncmp(command, "SETMCRATE", 9) == 0)
3218 {
Leo Chang614d2072013-08-22 14:59:44 -07003219 tANI_U8 *value = command;
3220 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003221 tSirRateUpdateInd *rateUpdate;
3222 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003223
3224 /* Only valid for SAP mode */
3225 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3226 {
3227 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3228 "%s: SAP mode is not running", __func__);
3229 ret = -EFAULT;
3230 goto exit;
3231 }
3232
3233 /* Move pointer to ahead of SETMCRATE<delimiter> */
3234 /* input value is in units of hundred kbps */
3235 value = value + 10;
3236 /* Convert the value from ascii to integer, decimal base */
3237 ret = kstrtouint(value, 10, &targetRate);
3238
Leo Chang1f98cbd2013-10-17 15:03:52 -07003239 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3240 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003241 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003242 hddLog(VOS_TRACE_LEVEL_ERROR,
3243 "%s: SETMCRATE indication alloc fail", __func__);
3244 ret = -EFAULT;
3245 goto exit;
3246 }
3247 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3248
3249 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3250 "MC Target rate %d", targetRate);
3251 /* Ignore unicast */
3252 rateUpdate->ucastDataRate = -1;
3253 rateUpdate->mcastDataRate24GHz = targetRate;
3254 rateUpdate->mcastDataRate5GHz = targetRate;
3255 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3256 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3257 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3258 if (eHAL_STATUS_SUCCESS != status)
3259 {
3260 hddLog(VOS_TRACE_LEVEL_ERROR,
3261 "%s: SET_MC_RATE failed", __func__);
3262 vos_mem_free(rateUpdate);
3263 ret = -EFAULT;
3264 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003265 }
3266 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303267#ifdef FEATURE_WLAN_BATCH_SCAN
3268 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3269 {
3270 char extra[32];
3271 tANI_U8 len = 0;
3272 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3273
3274 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3275 {
3276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3277 "%s: Batch scan feature is not supported by FW", __func__);
3278 ret = -EINVAL;
3279 goto exit;
3280 }
3281
3282 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3283 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3284 {
3285 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3286 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3287 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3288 " mode",
3289 pAdapter->device_mode);
3290 ret = -EINVAL;
3291 goto exit;
3292 }
3293
Arif Hussain826d9412013-11-12 16:44:54 -08003294 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
Rajeev79dbe4c2013-10-05 11:03:42 +05303295 version);
3296 if (copy_to_user(priv_data.buf, &extra, len + 1))
3297 {
3298 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3299 "%s: failed to copy data to user buffer", __func__);
3300 ret = -EFAULT;
3301 goto exit;
3302 }
3303 ret = HDD_BATCH_SCAN_VERSION;
3304 }
3305 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3306 {
3307 int status;
3308 tANI_U8 *value = (command + 16);
3309 eHalStatus halStatus;
3310 unsigned long rc;
3311 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3312 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3313
3314 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3315 {
3316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3317 "%s: Batch scan feature is not supported by FW", __func__);
3318 ret = -EINVAL;
3319 goto exit;
3320 }
3321
Rajeev Kumar20140c12013-10-21 19:39:02 -07003322
Rajeev79dbe4c2013-10-05 11:03:42 +05303323 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3324 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3325 {
3326 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003327 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303328 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3329 pAdapter->device_mode);
3330 ret = -EINVAL;
3331 goto exit;
3332 }
3333
Rajeev Kumar20140c12013-10-21 19:39:02 -07003334
Rajeev79dbe4c2013-10-05 11:03:42 +05303335 status = hdd_parse_set_batchscan_command(value, pReq);
3336 if (status)
3337 {
3338 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003339 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303340 ret = -EINVAL;
3341 goto exit;
3342 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003343
3344
Rajeev79dbe4c2013-10-05 11:03:42 +05303345 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3346 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3347 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3348 pAdapter);
3349
3350 if ( eHAL_STATUS_SUCCESS == halStatus )
3351 {
3352 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3353 "sme_SetBatchScanReq returned success halStatus %d",
3354 halStatus);
3355 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3356 {
3357 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3358 rc = wait_for_completion_timeout(
3359 &pAdapter->hdd_set_batch_scan_req_var,
3360 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3361 if (0 == rc)
3362 {
3363 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3364 "%s: Timeout waiting for set batch scan to complete",
3365 __func__);
3366 ret = -EINVAL;
3367 goto exit;
3368 }
3369 }
3370 if ( !pRsp->nScansToBatch )
3371 {
3372 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3373 "%s: Received set batch scan failure response from FW",
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003374 __func__);
Rajeev79dbe4c2013-10-05 11:03:42 +05303375 ret = -EINVAL;
3376 goto exit;
3377 }
3378 /*As per the Batch Scan Framework API we should return the MIN of
3379 either MSCAN or the max # of scans firmware can cache*/
3380 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3381
Rajeev Kumar20140c12013-10-21 19:39:02 -07003382 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3383
Rajeev79dbe4c2013-10-05 11:03:42 +05303384 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3385 "%s: request MSCAN %d response MSCAN %d ret %d",
3386 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3387 }
3388 else
3389 {
3390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3391 "sme_SetBatchScanReq returned failure halStatus %d",
3392 halStatus);
3393 ret = -EINVAL;
3394 goto exit;
3395 }
3396 }
3397 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3398 {
3399 eHalStatus halStatus;
3400 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3401 pInd->param = 0;
3402
3403 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3404 {
3405 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3406 "%s: Batch scan feature is not supported by FW", __func__);
3407 ret = -EINVAL;
3408 goto exit;
3409 }
3410
Rajeev Kumar20140c12013-10-21 19:39:02 -07003411 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303412 {
3413 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003414 "Batch scan is not yet enabled batch scan state %d",
3415 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303416 ret = -EINVAL;
3417 goto exit;
3418 }
3419
Rajeev Kumar20140c12013-10-21 19:39:02 -07003420 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3421
Rajeev79dbe4c2013-10-05 11:03:42 +05303422 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3423 pAdapter->sessionId);
3424 if ( eHAL_STATUS_SUCCESS == halStatus )
3425 {
3426 ret = 0;
3427 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3428 "sme_StopBatchScanInd returned success halStatus %d",
3429 halStatus);
3430 }
3431 else
3432 {
3433 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3434 "sme_StopBatchScanInd returned failure halStatus %d",
3435 halStatus);
3436 ret = -EINVAL;
3437 goto exit;
3438 }
3439 }
3440 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3441 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003442 tANI_U32 remain_len;
3443
Rajeev79dbe4c2013-10-05 11:03:42 +05303444 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3445 {
3446 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3447 "%s: Batch scan feature is not supported by FW", __func__);
3448 ret = -EINVAL;
3449 goto exit;
3450 }
3451
Rajeev Kumar20140c12013-10-21 19:39:02 -07003452 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303453 {
3454 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003455 "Batch scan is not yet enabled could not return results"
3456 "Batch Scan state %d",
3457 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303458 ret = -EINVAL;
3459 goto exit;
3460 }
3461
3462 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003463 remain_len = priv_data.total_len - priv_data.used_len;
3464 if (remain_len < priv_data.total_len)
3465 {
3466 /*Clear previous batch scan response data if any*/
3467 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3468 }
3469 else
3470 {
3471 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3472 "Invalid total length from user space can't fetch batch"
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003473 " scan response total_len %d used_len %d remain len %d",
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003474 priv_data.total_len, priv_data.used_len, remain_len);
3475 ret = -EINVAL;
3476 goto exit;
3477 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303478 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3479 }
3480#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003481#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3482 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3483 {
3484 tANI_U8 *value = command;
3485 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3486 tANI_U8 numChannels = 0;
3487 eHalStatus status = eHAL_STATUS_SUCCESS;
3488
3489 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3490 if (eHAL_STATUS_SUCCESS != status)
3491 {
3492 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3493 "%s: Failed to parse channel list information", __func__);
3494 ret = -EINVAL;
3495 goto exit;
3496 }
3497
3498 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3499 {
3500 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3501 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3502 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3503 ret = -EINVAL;
3504 goto exit;
3505 }
3506 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3507 ChannelList,
3508 numChannels);
3509 if (eHAL_STATUS_SUCCESS != status)
3510 {
3511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3512 "%s: Failed to update channel list information", __func__);
3513 ret = -EINVAL;
3514 goto exit;
3515 }
3516 }
3517 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3518 {
3519 tANI_U8 *value = command;
3520 char extra[128] = {0};
3521 int len = 0;
3522 tANI_U8 tid = 0;
3523 hdd_station_ctx_t *pHddStaCtx = NULL;
3524 tAniTrafStrmMetrics tsmMetrics;
3525 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3526
3527 /* if not associated, return error */
3528 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3529 {
3530 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3531 ret = -EINVAL;
3532 goto exit;
3533 }
3534
3535 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3536 value = value + 12;
3537 /* Convert the value from ascii to integer */
3538 ret = kstrtou8(value, 10, &tid);
3539 if (ret < 0)
3540 {
3541 /* If the input value is greater than max value of datatype, then also
3542 kstrtou8 fails */
3543 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3544 "%s: kstrtou8 failed range [%d - %d]", __func__,
3545 TID_MIN_VALUE,
3546 TID_MAX_VALUE);
3547 ret = -EINVAL;
3548 goto exit;
3549 }
3550
3551 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3552 {
3553 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3554 "tid value %d is out of range"
3555 " (Min: %d Max: %d)", tid,
3556 TID_MIN_VALUE,
3557 TID_MAX_VALUE);
3558 ret = -EINVAL;
3559 goto exit;
3560 }
3561
3562 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3563 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3564
3565 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3566 {
3567 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3568 "%s: failed to get tsm stats", __func__);
3569 ret = -EFAULT;
3570 goto exit;
3571 }
3572
3573 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3574 "UplinkPktQueueDly(%d)\n"
3575 "UplinkPktQueueDlyHist[0](%d)\n"
3576 "UplinkPktQueueDlyHist[1](%d)\n"
3577 "UplinkPktQueueDlyHist[2](%d)\n"
3578 "UplinkPktQueueDlyHist[3](%d)\n"
3579 "UplinkPktTxDly(%lu)\n"
3580 "UplinkPktLoss(%d)\n"
3581 "UplinkPktCount(%d)\n"
3582 "RoamingCount(%d)\n"
3583 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3584 tsmMetrics.UplinkPktQueueDlyHist[0],
3585 tsmMetrics.UplinkPktQueueDlyHist[1],
3586 tsmMetrics.UplinkPktQueueDlyHist[2],
3587 tsmMetrics.UplinkPktQueueDlyHist[3],
3588 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3589 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3590
3591 /* Output TSM stats is of the format
3592 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3593 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003594 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003595 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3596 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3597 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3598 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3599 tsmMetrics.RoamingDly);
3600
3601 if (copy_to_user(priv_data.buf, &extra, len + 1))
3602 {
3603 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3604 "%s: failed to copy data to user buffer", __func__);
3605 ret = -EFAULT;
3606 goto exit;
3607 }
3608 }
3609 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3610 {
3611 tANI_U8 *value = command;
3612 tANI_U8 *cckmIe = NULL;
3613 tANI_U8 cckmIeLen = 0;
3614 eHalStatus status = eHAL_STATUS_SUCCESS;
3615
3616 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3617 if (eHAL_STATUS_SUCCESS != status)
3618 {
3619 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3620 "%s: Failed to parse cckm ie data", __func__);
3621 ret = -EINVAL;
3622 goto exit;
3623 }
3624
3625 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3626 {
3627 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3628 "%s: CCKM Ie input length is more than max[%d]", __func__,
3629 DOT11F_IE_RSN_MAX_LEN);
3630 if (NULL != cckmIe)
3631 {
3632 vos_mem_free(cckmIe);
3633 }
3634 ret = -EINVAL;
3635 goto exit;
3636 }
3637 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
3638 if (NULL != cckmIe)
3639 {
3640 vos_mem_free(cckmIe);
3641 }
3642 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003643 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3644 {
3645 tANI_U8 *value = command;
3646 tCsrCcxBeaconReq ccxBcnReq;
3647 eHalStatus status = eHAL_STATUS_SUCCESS;
3648 status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
3649 if (eHAL_STATUS_SUCCESS != status)
3650 {
3651 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3652 "%s: Failed to parse ccx beacon req", __func__);
3653 ret = -EINVAL;
3654 goto exit;
3655 }
3656
3657 sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
3658 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003659#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003660 else {
3661 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3662 __func__, command);
3663 }
3664
Jeff Johnson295189b2012-06-20 16:38:30 -07003665 }
3666exit:
3667 if (command)
3668 {
3669 kfree(command);
3670 }
3671 return ret;
3672}
3673
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003674
3675
3676#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003677/**---------------------------------------------------------------------------
3678
3679 \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
3680
3681 This function parses the ccx beacon request passed in the format
3682 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3683 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3684 <space>Scan Mode N<space>Meas Duration N
3685 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3686 then take N.
3687 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3688 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3689 This function does not take care of removing duplicate channels from the list
3690
3691 \param - pValue Pointer to data
3692 \param - pCcxBcnReq output pointer to store parsed ie information
3693
3694 \return - 0 for success non-zero for failure
3695
3696 --------------------------------------------------------------------------*/
3697static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
3698 tCsrCcxBeaconReq *pCcxBcnReq)
3699{
3700 tANI_U8 *inPtr = pValue;
3701 int tempInt = 0;
3702 int j = 0, i = 0, v = 0;
3703 char buf[32];
3704
3705 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3706 /*no argument after the command*/
3707 if (NULL == inPtr)
3708 {
3709 return -EINVAL;
3710 }
3711 /*no space after the command*/
3712 else if (SPACE_ASCII_VALUE != *inPtr)
3713 {
3714 return -EINVAL;
3715 }
3716
3717 /*removing empty spaces*/
3718 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3719
3720 /*no argument followed by spaces*/
3721 if ('\0' == *inPtr) return -EINVAL;
3722
3723 /*getting the first argument ie measurement token*/
3724 v = sscanf(inPtr, "%32s ", buf);
3725 if (1 != v) return -EINVAL;
3726
3727 v = kstrtos32(buf, 10, &tempInt);
3728 if ( v < 0) return -EINVAL;
3729
3730 pCcxBcnReq->numBcnReqIe = tempInt;
3731
3732 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3733 "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
3734
3735 for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
3736 {
3737 for (i = 0; i < 4; i++)
3738 {
3739 /*inPtr pointing to the beginning of first space after number of ie fields*/
3740 inPtr = strpbrk( inPtr, " " );
3741 /*no ie data after the number of ie fields argument*/
3742 if (NULL == inPtr) return -EINVAL;
3743
3744 /*removing empty space*/
3745 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3746
3747 /*no ie data after the number of ie fields argument and spaces*/
3748 if ( '\0' == *inPtr ) return -EINVAL;
3749
3750 v = sscanf(inPtr, "%32s ", buf);
3751 if (1 != v) return -EINVAL;
3752
3753 v = kstrtos32(buf, 10, &tempInt);
3754 if (v < 0) return -EINVAL;
3755
3756 switch (i)
3757 {
3758 case 0: /* Measurement token */
3759 if (tempInt <= 0)
3760 {
3761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3762 "Invalid Measurement Token(%d)", tempInt);
3763 return -EINVAL;
3764 }
3765 pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
3766 break;
3767
3768 case 1: /* Channel number */
3769 if ((tempInt <= 0) ||
3770 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3771 {
3772 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3773 "Invalid Channel Number(%d)", tempInt);
3774 return -EINVAL;
3775 }
3776 pCcxBcnReq->bcnReq[j].channel = tempInt;
3777 break;
3778
3779 case 2: /* Scan mode */
3780 if ((tempInt < 0) || (tempInt > 2))
3781 {
3782 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3783 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
3784 return -EINVAL;
3785 }
3786 pCcxBcnReq->bcnReq[j].scanMode= tempInt;
3787 break;
3788
3789 case 3: /* Measurement duration */
3790 if (tempInt <= 0)
3791 {
3792 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3793 "Invalid Measurement Duration(%d)", tempInt);
3794 return -EINVAL;
3795 }
3796 pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
3797 break;
3798 }
3799 }
3800 }
3801
3802 for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
3803 {
3804 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3805 "Index(%d) Measurement Token(%lu)Channel(%lu) Scan Mode(%lu) Measurement Duration(%lu)\n",
3806 j,
3807 pCcxBcnReq->bcnReq[j].measurementToken,
3808 pCcxBcnReq->bcnReq[j].channel,
3809 pCcxBcnReq->bcnReq[j].scanMode,
3810 pCcxBcnReq->bcnReq[j].measurementDuration);
3811 }
3812
3813 return VOS_STATUS_SUCCESS;
3814}
3815
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003816static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3817{
3818 struct statsContext *pStatsContext = NULL;
3819 hdd_adapter_t *pAdapter = NULL;
3820
3821 if (NULL == pContext)
3822 {
3823 hddLog(VOS_TRACE_LEVEL_ERROR,
3824 "%s: Bad param, pContext [%p]",
3825 __func__, pContext);
3826 return;
3827 }
3828
3829 /* there is a race condition that exists between this callback function
3830 and the caller since the caller could time out either before or
3831 while this code is executing. we'll assume the timeout hasn't
3832 occurred, but we'll verify that right before we save our work */
3833
3834 pStatsContext = pContext;
3835 pAdapter = pStatsContext->pAdapter;
3836 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3837 {
3838 /* the caller presumably timed out so there is nothing we can do */
3839 hddLog(VOS_TRACE_LEVEL_WARN,
3840 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3841 __func__, pAdapter, pStatsContext->magic);
3842 return;
3843 }
3844
3845 /* the race is on. caller could have timed out immediately after
3846 we verified the magic, but if so, caller will wait a short time
3847 for us to copy over the tsm stats */
3848 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3849 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3850 tsmMetrics.UplinkPktQueueDlyHist,
3851 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3852 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3853 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3854 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3855 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3856 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3857 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3858
3859 /* and notify the caller */
3860 complete(&pStatsContext->completion);
3861}
3862
3863
3864
3865static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3866 tAniTrafStrmMetrics* pTsmMetrics)
3867{
3868 hdd_station_ctx_t *pHddStaCtx = NULL;
3869 eHalStatus hstatus;
3870 long lrc;
3871 struct statsContext context;
3872 hdd_context_t *pHddCtx = NULL;
3873
3874 if (NULL == pAdapter)
3875 {
3876 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3877 return VOS_STATUS_E_FAULT;
3878 }
3879
3880 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3881 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3882
3883 /* we are connected prepare our callback context */
3884 init_completion(&context.completion);
3885 context.pAdapter = pAdapter;
3886 context.magic = STATS_CONTEXT_MAGIC;
3887
3888 /* query tsm stats */
3889 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3890 pHddStaCtx->conn_info.staId[ 0 ],
3891 pHddStaCtx->conn_info.bssId,
3892 &context, pHddCtx->pvosContext, tid);
3893
3894 if (eHAL_STATUS_SUCCESS != hstatus)
3895 {
3896 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics", __func__);
3897 return hstatus;
3898 }
3899 else
3900 {
3901 /* request was sent -- wait for the response */
3902 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3903 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
3904 /* either we have a response or we timed out
3905 either way, first invalidate our magic */
3906 context.magic = 0;
3907 if (lrc <= 0)
3908 {
3909 hddLog(VOS_TRACE_LEVEL_ERROR,
3910 "%s: SME %s while retrieving statistics",
3911 __func__, (0 == lrc) ? "timeout" : "interrupt");
3912 /* there is a race condition such that the callback
3913 function could be executing at the same time we are. of
3914 primary concern is if the callback function had already
3915 verified the "magic" but hasn't yet set the completion
3916 variable. Since the completion variable is on our
3917 stack, we'll delay just a bit to make sure the data is
3918 still valid if that is the case */
3919 msleep(50);
3920 return (VOS_STATUS_E_TIMEOUT);
3921 }
3922 }
3923 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
3924 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
3925 pAdapter->tsmStats.UplinkPktQueueDlyHist,
3926 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3927 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3928 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
3929 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
3930 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
3931 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
3932 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
3933
3934 return VOS_STATUS_SUCCESS;
3935}
3936#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
3937
Srinivas Girigowdade697412013-02-14 16:31:48 -08003938#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3939void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3940{
3941 eCsrBand band = -1;
3942 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3943 switch (band)
3944 {
3945 case eCSR_BAND_ALL:
3946 *pBand = WLAN_HDD_UI_BAND_AUTO;
3947 break;
3948
3949 case eCSR_BAND_24:
3950 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3951 break;
3952
3953 case eCSR_BAND_5G:
3954 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3955 break;
3956
3957 default:
3958 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3959 *pBand = -1;
3960 break;
3961 }
3962}
3963
3964/**---------------------------------------------------------------------------
3965
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003966 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
3967
3968 This function parses the send action frame data passed in the format
3969 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
3970
Srinivas Girigowda56076852013-08-20 14:00:50 -07003971 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003972 \param - pTargetApBssid Pointer to target Ap bssid
3973 \param - pChannel Pointer to the Target AP channel
3974 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
3975 \param - pBuf Pointer to data
3976 \param - pBufLen Pointer to data length
3977
3978 \return - 0 for success non-zero for failure
3979
3980 --------------------------------------------------------------------------*/
3981VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
3982 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
3983{
3984 tANI_U8 *inPtr = pValue;
3985 tANI_U8 *dataEnd;
3986 int tempInt;
3987 int j = 0;
3988 int i = 0;
3989 int v = 0;
3990 tANI_U8 tempBuf[32];
3991 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003992 /* 12 hexa decimal digits and 5 ':' */
3993 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003994
3995 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3996 /*no argument after the command*/
3997 if (NULL == inPtr)
3998 {
3999 return -EINVAL;
4000 }
4001
4002 /*no space after the command*/
4003 else if (SPACE_ASCII_VALUE != *inPtr)
4004 {
4005 return -EINVAL;
4006 }
4007
4008 /*removing empty spaces*/
4009 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4010
4011 /*no argument followed by spaces*/
4012 if ('\0' == *inPtr)
4013 {
4014 return -EINVAL;
4015 }
4016
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004017 v = sscanf(inPtr, "%17s", macAddress);
4018 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004019 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004020 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4021 "Invalid MAC address or All hex inputs are not read (%d)", v);
4022 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004023 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004024
4025 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4026 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4027 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4028 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4029 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4030 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004031
4032 /* point to the next argument */
4033 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4034 /*no argument after the command*/
4035 if (NULL == inPtr) return -EINVAL;
4036
4037 /*removing empty spaces*/
4038 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4039
4040 /*no argument followed by spaces*/
4041 if ('\0' == *inPtr)
4042 {
4043 return -EINVAL;
4044 }
4045
4046 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004047 v = sscanf(inPtr, "%32s ", tempBuf);
4048 if (1 != v) return -EINVAL;
4049
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004050 v = kstrtos32(tempBuf, 10, &tempInt);
4051 if ( v < 0) return -EINVAL;
4052
4053 *pChannel = tempInt;
4054
4055 /* point to the next argument */
4056 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4057 /*no argument after the command*/
4058 if (NULL == inPtr) return -EINVAL;
4059 /*removing empty spaces*/
4060 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4061
4062 /*no argument followed by spaces*/
4063 if ('\0' == *inPtr)
4064 {
4065 return -EINVAL;
4066 }
4067
4068 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004069 v = sscanf(inPtr, "%32s ", tempBuf);
4070 if (1 != v) return -EINVAL;
4071
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004072 v = kstrtos32(tempBuf, 10, &tempInt);
4073 if ( v < 0) return -EINVAL;
4074
4075 *pDwellTime = tempInt;
4076
4077 /* point to the next argument */
4078 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4079 /*no argument after the command*/
4080 if (NULL == inPtr) return -EINVAL;
4081 /*removing empty spaces*/
4082 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4083
4084 /*no argument followed by spaces*/
4085 if ('\0' == *inPtr)
4086 {
4087 return -EINVAL;
4088 }
4089
4090 /* find the length of data */
4091 dataEnd = inPtr;
4092 while(('\0' != *dataEnd) )
4093 {
4094 dataEnd++;
4095 ++(*pBufLen);
4096 }
4097 if ( *pBufLen <= 0) return -EINVAL;
4098
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004099 /* Allocate the number of bytes based on the number of input characters
4100 whether it is even or odd.
4101 if the number of input characters are even, then we need N/2 byte.
4102 if the number of input characters are odd, then we need do (N+1)/2 to
4103 compensate rounding off.
4104 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4105 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4106 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004107 if (NULL == *pBuf)
4108 {
4109 hddLog(VOS_TRACE_LEVEL_FATAL,
4110 "%s: vos_mem_alloc failed ", __func__);
4111 return -EINVAL;
4112 }
4113
4114 /* the buffer received from the upper layer is character buffer,
4115 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4116 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4117 and f0 in 3rd location */
4118 for (i = 0, j = 0; j < *pBufLen; j += 2)
4119 {
4120 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4121 (*pBuf)[i++] = tempByte;
4122 }
4123 *pBufLen = i;
4124 return VOS_STATUS_SUCCESS;
4125}
4126
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004127/**---------------------------------------------------------------------------
4128
Srinivas Girigowdade697412013-02-14 16:31:48 -08004129 \brief hdd_parse_channellist() - HDD Parse channel list
4130
4131 This function parses the channel list passed in the format
4132 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004133 if the Number of channels (N) does not match with the actual number of channels passed
4134 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4135 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4136 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4137 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004138
4139 \param - pValue Pointer to input channel list
4140 \param - ChannelList Pointer to local output array to record channel list
4141 \param - pNumChannels Pointer to number of roam scan channels
4142
4143 \return - 0 for success non-zero for failure
4144
4145 --------------------------------------------------------------------------*/
4146VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4147{
4148 tANI_U8 *inPtr = pValue;
4149 int tempInt;
4150 int j = 0;
4151 int v = 0;
4152 char buf[32];
4153
4154 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4155 /*no argument after the command*/
4156 if (NULL == inPtr)
4157 {
4158 return -EINVAL;
4159 }
4160
4161 /*no space after the command*/
4162 else if (SPACE_ASCII_VALUE != *inPtr)
4163 {
4164 return -EINVAL;
4165 }
4166
4167 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004168 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004169
4170 /*no argument followed by spaces*/
4171 if ('\0' == *inPtr)
4172 {
4173 return -EINVAL;
4174 }
4175
4176 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004177 v = sscanf(inPtr, "%32s ", buf);
4178 if (1 != v) return -EINVAL;
4179
Srinivas Girigowdade697412013-02-14 16:31:48 -08004180 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004181 if ((v < 0) ||
4182 (tempInt <= 0) ||
4183 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4184 {
4185 return -EINVAL;
4186 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004187
4188 *pNumChannels = tempInt;
4189
4190 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4191 "Number of channels are: %d", *pNumChannels);
4192
4193 for (j = 0; j < (*pNumChannels); j++)
4194 {
4195 /*inPtr pointing to the beginning of first space after number of channels*/
4196 inPtr = strpbrk( inPtr, " " );
4197 /*no channel list after the number of channels argument*/
4198 if (NULL == inPtr)
4199 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004200 if (0 != j)
4201 {
4202 *pNumChannels = j;
4203 return VOS_STATUS_SUCCESS;
4204 }
4205 else
4206 {
4207 return -EINVAL;
4208 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004209 }
4210
4211 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004212 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004213
4214 /*no channel list after the number of channels argument and spaces*/
4215 if ( '\0' == *inPtr )
4216 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004217 if (0 != j)
4218 {
4219 *pNumChannels = j;
4220 return VOS_STATUS_SUCCESS;
4221 }
4222 else
4223 {
4224 return -EINVAL;
4225 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004226 }
4227
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004228 v = sscanf(inPtr, "%32s ", buf);
4229 if (1 != v) return -EINVAL;
4230
Srinivas Girigowdade697412013-02-14 16:31:48 -08004231 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004232 if ((v < 0) ||
4233 (tempInt <= 0) ||
4234 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4235 {
4236 return -EINVAL;
4237 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004238 pChannelList[j] = tempInt;
4239
4240 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4241 "Channel %d added to preferred channel list",
4242 pChannelList[j] );
4243 }
4244
Srinivas Girigowdade697412013-02-14 16:31:48 -08004245 return VOS_STATUS_SUCCESS;
4246}
4247
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004248
4249/**---------------------------------------------------------------------------
4250
4251 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4252
4253 This function parses the reasoc command data passed in the format
4254 REASSOC<space><bssid><space><channel>
4255
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004256 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004257 \param - pTargetApBssid Pointer to target Ap bssid
4258 \param - pChannel Pointer to the Target AP channel
4259
4260 \return - 0 for success non-zero for failure
4261
4262 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004263VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4264 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004265{
4266 tANI_U8 *inPtr = pValue;
4267 int tempInt;
4268 int v = 0;
4269 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004270 /* 12 hexa decimal digits and 5 ':' */
4271 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004272
4273 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4274 /*no argument after the command*/
4275 if (NULL == inPtr)
4276 {
4277 return -EINVAL;
4278 }
4279
4280 /*no space after the command*/
4281 else if (SPACE_ASCII_VALUE != *inPtr)
4282 {
4283 return -EINVAL;
4284 }
4285
4286 /*removing empty spaces*/
4287 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4288
4289 /*no argument followed by spaces*/
4290 if ('\0' == *inPtr)
4291 {
4292 return -EINVAL;
4293 }
4294
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004295 v = sscanf(inPtr, "%17s", macAddress);
4296 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004297 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004298 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4299 "Invalid MAC address or All hex inputs are not read (%d)", v);
4300 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004301 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004302
4303 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4304 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4305 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4306 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4307 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4308 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004309
4310 /* point to the next argument */
4311 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4312 /*no argument after the command*/
4313 if (NULL == inPtr) return -EINVAL;
4314
4315 /*removing empty spaces*/
4316 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4317
4318 /*no argument followed by spaces*/
4319 if ('\0' == *inPtr)
4320 {
4321 return -EINVAL;
4322 }
4323
4324 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004325 v = sscanf(inPtr, "%32s ", tempBuf);
4326 if (1 != v) return -EINVAL;
4327
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004328 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004329 if ((v < 0) ||
4330 (tempInt <= 0) ||
4331 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4332 {
4333 return -EINVAL;
4334 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004335
4336 *pChannel = tempInt;
4337 return VOS_STATUS_SUCCESS;
4338}
4339
4340#endif
4341
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004342#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4343/**---------------------------------------------------------------------------
4344
4345 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4346
4347 This function parses the SETCCKM IE command
4348 SETCCKMIE<space><ie data>
4349
4350 \param - pValue Pointer to input data
4351 \param - pCckmIe Pointer to output cckm Ie
4352 \param - pCckmIeLen Pointer to output cckm ie length
4353
4354 \return - 0 for success non-zero for failure
4355
4356 --------------------------------------------------------------------------*/
4357VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4358 tANI_U8 *pCckmIeLen)
4359{
4360 tANI_U8 *inPtr = pValue;
4361 tANI_U8 *dataEnd;
4362 int j = 0;
4363 int i = 0;
4364 tANI_U8 tempByte = 0;
4365
4366 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4367 /*no argument after the command*/
4368 if (NULL == inPtr)
4369 {
4370 return -EINVAL;
4371 }
4372
4373 /*no space after the command*/
4374 else if (SPACE_ASCII_VALUE != *inPtr)
4375 {
4376 return -EINVAL;
4377 }
4378
4379 /*removing empty spaces*/
4380 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4381
4382 /*no argument followed by spaces*/
4383 if ('\0' == *inPtr)
4384 {
4385 return -EINVAL;
4386 }
4387
4388 /* find the length of data */
4389 dataEnd = inPtr;
4390 while(('\0' != *dataEnd) )
4391 {
4392 dataEnd++;
4393 ++(*pCckmIeLen);
4394 }
4395 if ( *pCckmIeLen <= 0) return -EINVAL;
4396
4397 /* Allocate the number of bytes based on the number of input characters
4398 whether it is even or odd.
4399 if the number of input characters are even, then we need N/2 byte.
4400 if the number of input characters are odd, then we need do (N+1)/2 to
4401 compensate rounding off.
4402 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4403 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4404 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4405 if (NULL == *pCckmIe)
4406 {
4407 hddLog(VOS_TRACE_LEVEL_FATAL,
4408 "%s: vos_mem_alloc failed ", __func__);
4409 return -EINVAL;
4410 }
4411 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4412 /* the buffer received from the upper layer is character buffer,
4413 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4414 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4415 and f0 in 3rd location */
4416 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4417 {
4418 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4419 (*pCckmIe)[i++] = tempByte;
4420 }
4421 *pCckmIeLen = i;
4422
4423 return VOS_STATUS_SUCCESS;
4424}
4425#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4426
Jeff Johnson295189b2012-06-20 16:38:30 -07004427/**---------------------------------------------------------------------------
4428
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004429 \brief hdd_is_valid_mac_address() - Validate MAC address
4430
4431 This function validates whether the given MAC address is valid or not
4432 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4433 where X is the hexa decimal digit character and separated by ':'
4434 This algorithm works even if MAC address is not separated by ':'
4435
4436 This code checks given input string mac contains exactly 12 hexadecimal digits.
4437 and a separator colon : appears in the input string only after
4438 an even number of hex digits.
4439
4440 \param - pMacAddr pointer to the input MAC address
4441 \return - 1 for valid and 0 for invalid
4442
4443 --------------------------------------------------------------------------*/
4444
4445v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4446{
4447 int xdigit = 0;
4448 int separator = 0;
4449 while (*pMacAddr)
4450 {
4451 if (isxdigit(*pMacAddr))
4452 {
4453 xdigit++;
4454 }
4455 else if (':' == *pMacAddr)
4456 {
4457 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4458 break;
4459
4460 ++separator;
4461 }
4462 else
4463 {
4464 separator = -1;
4465 /* Invalid MAC found */
4466 return 0;
4467 }
4468 ++pMacAddr;
4469 }
4470 return (xdigit == 12 && (separator == 5 || separator == 0));
4471}
4472
4473/**---------------------------------------------------------------------------
4474
Jeff Johnson295189b2012-06-20 16:38:30 -07004475 \brief hdd_open() - HDD Open function
4476
4477 This is called in response to ifconfig up
4478
4479 \param - dev Pointer to net_device structure
4480
4481 \return - 0 for success non-zero for failure
4482
4483 --------------------------------------------------------------------------*/
4484int hdd_open (struct net_device *dev)
4485{
4486 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4487 hdd_context_t *pHddCtx;
4488 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4489 VOS_STATUS status;
4490 v_BOOL_t in_standby = TRUE;
4491
4492 if (NULL == pAdapter)
4493 {
4494 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004495 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004496 return -ENODEV;
4497 }
4498
4499 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4500 if (NULL == pHddCtx)
4501 {
4502 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004503 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004504 return -ENODEV;
4505 }
4506
4507 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4508 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4509 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004510 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4511 {
4512 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304513 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004514 in_standby = FALSE;
4515 break;
4516 }
4517 else
4518 {
4519 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4520 pAdapterNode = pNext;
4521 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004522 }
4523
4524 if (TRUE == in_standby)
4525 {
4526 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4527 {
4528 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4529 "wlan out of power save", __func__);
4530 return -EINVAL;
4531 }
4532 }
4533
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004534 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004535 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4536 {
4537 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004538 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004539 /* Enable TX queues only when we are connected */
4540 netif_tx_start_all_queues(dev);
4541 }
4542
4543 return 0;
4544}
4545
4546int hdd_mon_open (struct net_device *dev)
4547{
4548 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4549
4550 if(pAdapter == NULL) {
4551 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004552 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004553 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004554 }
4555
4556 netif_start_queue(dev);
4557
4558 return 0;
4559}
4560/**---------------------------------------------------------------------------
4561
4562 \brief hdd_stop() - HDD stop function
4563
4564 This is called in response to ifconfig down
4565
4566 \param - dev Pointer to net_device structure
4567
4568 \return - 0 for success non-zero for failure
4569
4570 --------------------------------------------------------------------------*/
4571
4572int hdd_stop (struct net_device *dev)
4573{
4574 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4575 hdd_context_t *pHddCtx;
4576 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4577 VOS_STATUS status;
4578 v_BOOL_t enter_standby = TRUE;
4579
4580 ENTER();
4581
4582 if (NULL == pAdapter)
4583 {
4584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004585 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004586 return -ENODEV;
4587 }
4588
4589 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4590 if (NULL == pHddCtx)
4591 {
4592 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004593 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004594 return -ENODEV;
4595 }
4596
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004597 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004598 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4599 netif_tx_disable(pAdapter->dev);
4600 netif_carrier_off(pAdapter->dev);
4601
4602
4603 /* SoftAP ifaces should never go in power save mode
4604 making sure same here. */
4605 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4606 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004607 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004608 )
4609 {
4610 /* SoftAP mode, so return from here */
4611 EXIT();
4612 return 0;
4613 }
4614
4615 /* Find if any iface is up then
4616 if any iface is up then can't put device to sleep/ power save mode. */
4617 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4618 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4619 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004620 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4621 {
4622 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304623 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004624 enter_standby = FALSE;
4625 break;
4626 }
4627 else
4628 {
4629 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4630 pAdapterNode = pNext;
4631 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004632 }
4633
4634 if (TRUE == enter_standby)
4635 {
4636 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4637 "entering standby", __func__);
4638 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4639 {
4640 /*log and return success*/
4641 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4642 "wlan in power save", __func__);
4643 }
4644 }
4645
4646 EXIT();
4647 return 0;
4648}
4649
4650/**---------------------------------------------------------------------------
4651
4652 \brief hdd_uninit() - HDD uninit function
4653
4654 This is called during the netdev unregister to uninitialize all data
4655associated with the device
4656
4657 \param - dev Pointer to net_device structure
4658
4659 \return - void
4660
4661 --------------------------------------------------------------------------*/
4662static void hdd_uninit (struct net_device *dev)
4663{
4664 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4665
4666 ENTER();
4667
4668 do
4669 {
4670 if (NULL == pAdapter)
4671 {
4672 hddLog(VOS_TRACE_LEVEL_FATAL,
4673 "%s: NULL pAdapter", __func__);
4674 break;
4675 }
4676
4677 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4678 {
4679 hddLog(VOS_TRACE_LEVEL_FATAL,
4680 "%s: Invalid magic", __func__);
4681 break;
4682 }
4683
4684 if (NULL == pAdapter->pHddCtx)
4685 {
4686 hddLog(VOS_TRACE_LEVEL_FATAL,
4687 "%s: NULL pHddCtx", __func__);
4688 break;
4689 }
4690
4691 if (dev != pAdapter->dev)
4692 {
4693 hddLog(VOS_TRACE_LEVEL_FATAL,
4694 "%s: Invalid device reference", __func__);
4695 /* we haven't validated all cases so let this go for now */
4696 }
4697
4698 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4699
4700 /* after uninit our adapter structure will no longer be valid */
4701 pAdapter->dev = NULL;
4702 pAdapter->magic = 0;
4703 } while (0);
4704
4705 EXIT();
4706}
4707
4708/**---------------------------------------------------------------------------
4709
4710 \brief hdd_release_firmware() -
4711
4712 This function calls the release firmware API to free the firmware buffer.
4713
4714 \param - pFileName Pointer to the File Name.
4715 pCtx - Pointer to the adapter .
4716
4717
4718 \return - 0 for success, non zero for failure
4719
4720 --------------------------------------------------------------------------*/
4721
4722VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4723{
4724 VOS_STATUS status = VOS_STATUS_SUCCESS;
4725 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4726 ENTER();
4727
4728
4729 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4730
4731 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4732
4733 if(pHddCtx->fw) {
4734 release_firmware(pHddCtx->fw);
4735 pHddCtx->fw = NULL;
4736 }
4737 else
4738 status = VOS_STATUS_E_FAILURE;
4739 }
4740 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4741 if(pHddCtx->nv) {
4742 release_firmware(pHddCtx->nv);
4743 pHddCtx->nv = NULL;
4744 }
4745 else
4746 status = VOS_STATUS_E_FAILURE;
4747
4748 }
4749
4750 EXIT();
4751 return status;
4752}
4753
4754/**---------------------------------------------------------------------------
4755
4756 \brief hdd_request_firmware() -
4757
4758 This function reads the firmware file using the request firmware
4759 API and returns the the firmware data and the firmware file size.
4760
4761 \param - pfileName - Pointer to the file name.
4762 - pCtx - Pointer to the adapter .
4763 - ppfw_data - Pointer to the pointer of the firmware data.
4764 - pSize - Pointer to the file size.
4765
4766 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4767
4768 --------------------------------------------------------------------------*/
4769
4770
4771VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4772{
4773 int status;
4774 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4775 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4776 ENTER();
4777
4778 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4779
4780 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4781
4782 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4783 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4784 __func__, pfileName);
4785 retval = VOS_STATUS_E_FAILURE;
4786 }
4787
4788 else {
4789 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4790 *pSize = pHddCtx->fw->size;
4791 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4792 __func__, *pSize);
4793 }
4794 }
4795 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4796
4797 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4798
4799 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4800 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4801 __func__, pfileName);
4802 retval = VOS_STATUS_E_FAILURE;
4803 }
4804
4805 else {
4806 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4807 *pSize = pHddCtx->nv->size;
4808 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4809 __func__, *pSize);
4810 }
4811 }
4812
4813 EXIT();
4814 return retval;
4815}
4816/**---------------------------------------------------------------------------
4817 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4818
4819 This is the function invoked by SME to inform the result of a full power
4820 request issued by HDD
4821
4822 \param - callbackcontext - Pointer to cookie
4823 status - result of request
4824
4825 \return - None
4826
4827--------------------------------------------------------------------------*/
4828void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4829{
4830 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4831
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004832 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004833 if(&pHddCtx->full_pwr_comp_var)
4834 {
4835 complete(&pHddCtx->full_pwr_comp_var);
4836 }
4837}
4838
4839/**---------------------------------------------------------------------------
4840
4841 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4842
4843 This is the function invoked by SME to inform the result of BMPS
4844 request issued by HDD
4845
4846 \param - callbackcontext - Pointer to cookie
4847 status - result of request
4848
4849 \return - None
4850
4851--------------------------------------------------------------------------*/
4852void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4853{
4854
4855 struct completion *completion_var = (struct completion*) callbackContext;
4856
4857 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
4858 if(completion_var != NULL)
4859 {
4860 complete(completion_var);
4861 }
4862}
4863
4864/**---------------------------------------------------------------------------
4865
4866 \brief hdd_get_cfg_file_size() -
4867
4868 This function reads the configuration file using the request firmware
4869 API and returns the configuration file size.
4870
4871 \param - pCtx - Pointer to the adapter .
4872 - pFileName - Pointer to the file name.
4873 - pBufSize - Pointer to the buffer size.
4874
4875 \return - 0 for success, non zero for failure
4876
4877 --------------------------------------------------------------------------*/
4878
4879VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4880{
4881 int status;
4882 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4883
4884 ENTER();
4885
4886 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4887
4888 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4889 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4890 status = VOS_STATUS_E_FAILURE;
4891 }
4892 else {
4893 *pBufSize = pHddCtx->fw->size;
4894 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4895 release_firmware(pHddCtx->fw);
4896 pHddCtx->fw = NULL;
4897 }
4898
4899 EXIT();
4900 return VOS_STATUS_SUCCESS;
4901}
4902
4903/**---------------------------------------------------------------------------
4904
4905 \brief hdd_read_cfg_file() -
4906
4907 This function reads the configuration file using the request firmware
4908 API and returns the cfg data and the buffer size of the configuration file.
4909
4910 \param - pCtx - Pointer to the adapter .
4911 - pFileName - Pointer to the file name.
4912 - pBuffer - Pointer to the data buffer.
4913 - pBufSize - Pointer to the buffer size.
4914
4915 \return - 0 for success, non zero for failure
4916
4917 --------------------------------------------------------------------------*/
4918
4919VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4920 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4921{
4922 int status;
4923 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4924
4925 ENTER();
4926
4927 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4928
4929 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4930 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4931 return VOS_STATUS_E_FAILURE;
4932 }
4933 else {
4934 if(*pBufSize != pHddCtx->fw->size) {
4935 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4936 "file size", __func__);
4937 release_firmware(pHddCtx->fw);
4938 pHddCtx->fw = NULL;
4939 return VOS_STATUS_E_FAILURE;
4940 }
4941 else {
4942 if(pBuffer) {
4943 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4944 }
4945 release_firmware(pHddCtx->fw);
4946 pHddCtx->fw = NULL;
4947 }
4948 }
4949
4950 EXIT();
4951
4952 return VOS_STATUS_SUCCESS;
4953}
4954
4955/**---------------------------------------------------------------------------
4956
Jeff Johnson295189b2012-06-20 16:38:30 -07004957 \brief hdd_set_mac_address() -
4958
4959 This function sets the user specified mac address using
4960 the command ifconfig wlanX hw ether <mac adress>.
4961
4962 \param - dev - Pointer to the net device.
4963 - addr - Pointer to the sockaddr.
4964 \return - 0 for success, non zero for failure
4965
4966 --------------------------------------------------------------------------*/
4967
4968static int hdd_set_mac_address(struct net_device *dev, void *addr)
4969{
4970 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4971 struct sockaddr *psta_mac_addr = addr;
4972 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4973
4974 ENTER();
4975
4976 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
4977
4978#ifdef HDD_SESSIONIZE
4979 // set the MAC address though the STA ID CFG.
4980 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
4981 (v_U8_t *)&pAdapter->macAddressCurrent,
4982 sizeof( pAdapter->macAddressCurrent ),
4983 hdd_set_mac_addr_cb, VOS_FALSE );
4984#endif
4985
4986 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
4987
4988 EXIT();
4989 return halStatus;
4990}
4991
4992tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
4993{
4994 int i;
4995 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4996 {
4997 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
4998 break;
4999 }
5000
5001 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5002 return NULL;
5003
5004 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5005 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5006}
5007
5008void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5009{
5010 int i;
5011 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5012 {
5013 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5014 {
5015 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5016 break;
5017 }
5018 }
5019 return;
5020}
5021
5022#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5023 static struct net_device_ops wlan_drv_ops = {
5024 .ndo_open = hdd_open,
5025 .ndo_stop = hdd_stop,
5026 .ndo_uninit = hdd_uninit,
5027 .ndo_start_xmit = hdd_hard_start_xmit,
5028 .ndo_tx_timeout = hdd_tx_timeout,
5029 .ndo_get_stats = hdd_stats,
5030 .ndo_do_ioctl = hdd_ioctl,
5031 .ndo_set_mac_address = hdd_set_mac_address,
5032 .ndo_select_queue = hdd_select_queue,
5033#ifdef WLAN_FEATURE_PACKET_FILTERING
5034#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5035 .ndo_set_rx_mode = hdd_set_multicast_list,
5036#else
5037 .ndo_set_multicast_list = hdd_set_multicast_list,
5038#endif //LINUX_VERSION_CODE
5039#endif
5040 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005041 static struct net_device_ops wlan_mon_drv_ops = {
5042 .ndo_open = hdd_mon_open,
5043 .ndo_stop = hdd_stop,
5044 .ndo_uninit = hdd_uninit,
5045 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5046 .ndo_tx_timeout = hdd_tx_timeout,
5047 .ndo_get_stats = hdd_stats,
5048 .ndo_do_ioctl = hdd_ioctl,
5049 .ndo_set_mac_address = hdd_set_mac_address,
5050 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005051
5052#endif
5053
5054void hdd_set_station_ops( struct net_device *pWlanDev )
5055{
5056#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5057 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
5058 pWlanDev->netdev_ops = &wlan_drv_ops;
5059#else
5060 pWlanDev->open = hdd_open;
5061 pWlanDev->stop = hdd_stop;
5062 pWlanDev->uninit = hdd_uninit;
5063 pWlanDev->hard_start_xmit = NULL;
5064 pWlanDev->tx_timeout = hdd_tx_timeout;
5065 pWlanDev->get_stats = hdd_stats;
5066 pWlanDev->do_ioctl = hdd_ioctl;
5067 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
5068 pWlanDev->set_mac_address = hdd_set_mac_address;
5069#endif
5070}
5071
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005072static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005073{
5074 struct net_device *pWlanDev = NULL;
5075 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005076 /*
5077 * cfg80211 initialization and registration....
5078 */
5079 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5080
Jeff Johnson295189b2012-06-20 16:38:30 -07005081 if(pWlanDev != NULL)
5082 {
5083
5084 //Save the pointer to the net_device in the HDD adapter
5085 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5086
Jeff Johnson295189b2012-06-20 16:38:30 -07005087 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5088
5089 pAdapter->dev = pWlanDev;
5090 pAdapter->pHddCtx = pHddCtx;
5091 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5092
5093 init_completion(&pAdapter->session_open_comp_var);
5094 init_completion(&pAdapter->session_close_comp_var);
5095 init_completion(&pAdapter->disconnect_comp_var);
5096 init_completion(&pAdapter->linkup_event_var);
5097 init_completion(&pAdapter->cancel_rem_on_chan_var);
5098 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005099#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5100 init_completion(&pAdapter->offchannel_tx_event);
5101#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005102 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005103#ifdef FEATURE_WLAN_TDLS
5104 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005105 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005106 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305107 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005108#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005109 init_completion(&pHddCtx->mc_sus_event_var);
5110 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305111 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005112 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005113 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005114
Rajeev79dbe4c2013-10-05 11:03:42 +05305115#ifdef FEATURE_WLAN_BATCH_SCAN
5116 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5117 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5118 pAdapter->pBatchScanRsp = NULL;
5119 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005120 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev79dbe4c2013-10-05 11:03:42 +05305121 mutex_init(&pAdapter->hdd_batch_scan_lock);
5122#endif
5123
Jeff Johnson295189b2012-06-20 16:38:30 -07005124 pAdapter->isLinkUpSvcNeeded = FALSE;
5125 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5126 //Init the net_device structure
5127 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5128
5129 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5130 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5131 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5132 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5133
5134 hdd_set_station_ops( pAdapter->dev );
5135
5136 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005137 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5138 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5139 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005140 /* set pWlanDev's parent to underlying device */
5141 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5142 }
5143
5144 return pAdapter;
5145}
5146
5147VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5148{
5149 struct net_device *pWlanDev = pAdapter->dev;
5150 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5151 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5152 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5153
5154 if( rtnl_lock_held )
5155 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005156 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005157 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5158 {
5159 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5160 return VOS_STATUS_E_FAILURE;
5161 }
5162 }
5163 if (register_netdevice(pWlanDev))
5164 {
5165 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5166 return VOS_STATUS_E_FAILURE;
5167 }
5168 }
5169 else
5170 {
5171 if(register_netdev(pWlanDev))
5172 {
5173 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5174 return VOS_STATUS_E_FAILURE;
5175 }
5176 }
5177 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5178
5179 return VOS_STATUS_SUCCESS;
5180}
5181
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005182static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005183{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005184 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005185
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005186 if (NULL == pAdapter)
5187 {
5188 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5189 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005190 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005191
5192 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5193 {
5194 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5195 return eHAL_STATUS_NOT_INITIALIZED;
5196 }
5197
5198 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5199
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005200#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005201 /* need to make sure all of our scheduled work has completed.
5202 * This callback is called from MC thread context, so it is safe to
5203 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005204 *
5205 * Even though this is called from MC thread context, if there is a faulty
5206 * work item in the system, that can hang this call forever. So flushing
5207 * this global work queue is not safe; and now we make sure that
5208 * individual work queues are stopped correctly. But the cancel work queue
5209 * is a GPL only API, so the proprietary version of the driver would still
5210 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005211 */
5212 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005213#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005214
5215 /* We can be blocked while waiting for scheduled work to be
5216 * flushed, and the adapter structure can potentially be freed, in
5217 * which case the magic will have been reset. So make sure the
5218 * magic is still good, and hence the adapter structure is still
5219 * valid, before signaling completion */
5220 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5221 {
5222 complete(&pAdapter->session_close_comp_var);
5223 }
5224
Jeff Johnson295189b2012-06-20 16:38:30 -07005225 return eHAL_STATUS_SUCCESS;
5226}
5227
5228VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5229{
5230 struct net_device *pWlanDev = pAdapter->dev;
5231 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5232 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5233 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5234 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5235 int rc = 0;
5236
5237 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005238 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005239 //Open a SME session for future operation
5240 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005241 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005242 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5243 {
5244 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005245 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005246 halStatus, halStatus );
5247 status = VOS_STATUS_E_FAILURE;
5248 goto error_sme_open;
5249 }
5250
5251 //Block on a completion variable. Can't wait forever though.
5252 rc = wait_for_completion_interruptible_timeout(
5253 &pAdapter->session_open_comp_var,
5254 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5255 if (!rc)
5256 {
5257 hddLog(VOS_TRACE_LEVEL_FATAL,
5258 "Session is not opened within timeout period code %08d", rc );
5259 status = VOS_STATUS_E_FAILURE;
5260 goto error_sme_open;
5261 }
5262
5263 // Register wireless extensions
5264 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5265 {
5266 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005267 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005268 halStatus, halStatus );
5269 status = VOS_STATUS_E_FAILURE;
5270 goto error_register_wext;
5271 }
5272 //Safe to register the hard_start_xmit function again
5273#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5274 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5275#else
5276 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5277#endif
5278
5279 //Set the Connection State to Not Connected
5280 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5281
5282 //Set the default operation channel
5283 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5284
5285 /* Make the default Auth Type as OPEN*/
5286 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5287
5288 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5289 {
5290 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005291 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005292 status, status );
5293 goto error_init_txrx;
5294 }
5295
5296 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5297
5298 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5299 {
5300 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005301 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005302 status, status );
5303 goto error_wmm_init;
5304 }
5305
5306 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5307
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005308#ifdef FEATURE_WLAN_TDLS
5309 if(0 != wlan_hdd_tdls_init(pAdapter))
5310 {
5311 status = VOS_STATUS_E_FAILURE;
5312 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5313 goto error_tdls_init;
5314 }
5315 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5316#endif
5317
Jeff Johnson295189b2012-06-20 16:38:30 -07005318 return VOS_STATUS_SUCCESS;
5319
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005320#ifdef FEATURE_WLAN_TDLS
5321error_tdls_init:
5322 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5323 hdd_wmm_adapter_close(pAdapter);
5324#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005325error_wmm_init:
5326 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5327 hdd_deinit_tx_rx(pAdapter);
5328error_init_txrx:
5329 hdd_UnregisterWext(pWlanDev);
5330error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005331 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005332 {
5333 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005334 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005335 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005336 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005337 {
5338 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005339 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005340 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005341 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005342 }
5343}
5344error_sme_open:
5345 return status;
5346}
5347
Jeff Johnson295189b2012-06-20 16:38:30 -07005348void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5349{
5350 hdd_cfg80211_state_t *cfgState;
5351
5352 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5353
5354 if( NULL != cfgState->buf )
5355 {
5356 int rc;
5357 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5358 rc = wait_for_completion_interruptible_timeout(
5359 &pAdapter->tx_action_cnf_event,
5360 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5361 if(!rc)
5362 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005363 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005364 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
5365 }
5366 }
5367 return;
5368}
Jeff Johnson295189b2012-06-20 16:38:30 -07005369
5370void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5371{
5372 ENTER();
5373 switch ( pAdapter->device_mode )
5374 {
5375 case WLAN_HDD_INFRA_STATION:
5376 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005377 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005378 {
5379 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5380 {
5381 hdd_deinit_tx_rx( pAdapter );
5382 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5383 }
5384
5385 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5386 {
5387 hdd_wmm_adapter_close( pAdapter );
5388 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5389 }
5390
Jeff Johnson295189b2012-06-20 16:38:30 -07005391 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005392#ifdef FEATURE_WLAN_TDLS
5393 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5394 {
5395 wlan_hdd_tdls_exit(pAdapter);
5396 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5397 }
5398#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005399
5400 break;
5401 }
5402
5403 case WLAN_HDD_SOFTAP:
5404 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005405 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305406
5407 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5408 {
5409 hdd_wmm_adapter_close( pAdapter );
5410 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5411 }
5412
Jeff Johnson295189b2012-06-20 16:38:30 -07005413 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005414
5415 hdd_unregister_hostapd(pAdapter);
5416 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005417 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005418 break;
5419 }
5420
5421 case WLAN_HDD_MONITOR:
5422 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005423 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005424 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5425 {
5426 hdd_deinit_tx_rx( pAdapter );
5427 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5428 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005429 if(NULL != pAdapterforTx)
5430 {
5431 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5432 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005433 break;
5434 }
5435
5436
5437 default:
5438 break;
5439 }
5440
5441 EXIT();
5442}
5443
5444void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5445{
5446 struct net_device *pWlanDev = pAdapter->dev;
5447
Rajeev79dbe4c2013-10-05 11:03:42 +05305448#ifdef FEATURE_WLAN_BATCH_SCAN
5449 tHddBatchScanRsp *pNode;
5450 tHddBatchScanRsp *pPrev;
5451 if (pAdapter)
5452 {
5453 mutex_lock(&pAdapter->hdd_batch_scan_lock);
5454 pNode = pAdapter->pBatchScanRsp;
5455 while (pNode)
5456 {
5457 pPrev = pNode;
5458 pNode = pNode->pNext;
5459 vos_mem_free((v_VOID_t * )pPrev);
5460 }
5461 pAdapter->pBatchScanRsp = NULL;
5462 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
5463 }
5464#endif
5465
Jeff Johnson295189b2012-06-20 16:38:30 -07005466 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5467 if( rtnl_held )
5468 {
5469 unregister_netdevice(pWlanDev);
5470 }
5471 else
5472 {
5473 unregister_netdev(pWlanDev);
5474 }
5475 // note that the pAdapter is no longer valid at this point
5476 // since the memory has been reclaimed
5477 }
5478
5479}
5480
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005481void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5482{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305483 VOS_STATUS status;
5484 hdd_adapter_t *pAdapter = NULL;
5485 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005486
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305487 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005488
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305489 /*loop through all adapters.*/
5490 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005491 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305492 pAdapter = pAdapterNode->pAdapter;
5493 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5494 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005495
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305496 { // we skip this registration for modes other than STA and P2P client modes.
5497 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5498 pAdapterNode = pNext;
5499 continue;
5500 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005501
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305502 //Apply Dynamic DTIM For P2P
5503 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5504 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5505 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5506 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5507 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5508 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5509 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5510 (eConnectionState_Associated ==
5511 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5512 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5513 {
5514 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005515
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305516 powerRequest.uIgnoreDTIM = 1;
5517 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5518
5519 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5520 {
5521 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5522 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5523 }
5524 else
5525 {
5526 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5527 }
5528
5529 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5530 * specified during Enter/Exit BMPS when LCD off*/
5531 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5532 NULL, eANI_BOOLEAN_FALSE);
5533 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5534 NULL, eANI_BOOLEAN_FALSE);
5535
5536 /* switch to the DTIM specified in cfg.ini */
5537 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5538 "Switch to DTIM %d", powerRequest.uListenInterval);
5539 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5540 break;
5541
5542 }
5543
5544 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5545 pAdapterNode = pNext;
5546 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005547}
5548
5549void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5550{
5551 /*Switch back to DTIM 1*/
5552 tSirSetPowerParamsReq powerRequest = { 0 };
5553
5554 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5555 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005556 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005557
5558 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5559 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5560 NULL, eANI_BOOLEAN_FALSE);
5561 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5562 NULL, eANI_BOOLEAN_FALSE);
5563
5564 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5565 "Switch to DTIM%d",powerRequest.uListenInterval);
5566 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5567
5568}
5569
Jeff Johnson295189b2012-06-20 16:38:30 -07005570VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5571{
5572 VOS_STATUS status = VOS_STATUS_SUCCESS;
5573
5574 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5575 {
5576 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5577 }
5578
5579 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5580 {
5581 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5582 }
5583
5584 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5585 {
5586 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5587 }
5588
5589 return status;
5590}
5591
5592VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5593{
5594 hdd_adapter_t *pAdapter = NULL;
5595 eHalStatus halStatus;
5596 VOS_STATUS status = VOS_STATUS_E_INVAL;
5597 v_BOOL_t disableBmps = FALSE;
5598 v_BOOL_t disableImps = FALSE;
5599
5600 switch(session_type)
5601 {
5602 case WLAN_HDD_INFRA_STATION:
5603 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005604 case WLAN_HDD_P2P_CLIENT:
5605 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005606 //Exit BMPS -> Is Sta/P2P Client is already connected
5607 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5608 if((NULL != pAdapter)&&
5609 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5610 {
5611 disableBmps = TRUE;
5612 }
5613
5614 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5615 if((NULL != pAdapter)&&
5616 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5617 {
5618 disableBmps = TRUE;
5619 }
5620
5621 //Exit both Bmps and Imps incase of Go/SAP Mode
5622 if((WLAN_HDD_SOFTAP == session_type) ||
5623 (WLAN_HDD_P2P_GO == session_type))
5624 {
5625 disableBmps = TRUE;
5626 disableImps = TRUE;
5627 }
5628
5629 if(TRUE == disableImps)
5630 {
5631 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5632 {
5633 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5634 }
5635 }
5636
5637 if(TRUE == disableBmps)
5638 {
5639 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5640 {
5641 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5642
5643 if(eHAL_STATUS_SUCCESS != halStatus)
5644 {
5645 status = VOS_STATUS_E_FAILURE;
5646 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
5647 VOS_ASSERT(0);
5648 return status;
5649 }
5650 }
5651
5652 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5653 {
5654 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5655
5656 if(eHAL_STATUS_SUCCESS != halStatus)
5657 {
5658 status = VOS_STATUS_E_FAILURE;
5659 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
5660 VOS_ASSERT(0);
5661 return status;
5662 }
5663 }
5664 }
5665
5666 if((TRUE == disableBmps) ||
5667 (TRUE == disableImps))
5668 {
5669 /* Now, get the chip into Full Power now */
5670 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5671 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5672 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5673
5674 if(halStatus != eHAL_STATUS_SUCCESS)
5675 {
5676 if(halStatus == eHAL_STATUS_PMC_PENDING)
5677 {
5678 //Block on a completion variable. Can't wait forever though
5679 wait_for_completion_interruptible_timeout(
5680 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5681 }
5682 else
5683 {
5684 status = VOS_STATUS_E_FAILURE;
5685 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
5686 VOS_ASSERT(0);
5687 return status;
5688 }
5689 }
5690
5691 status = VOS_STATUS_SUCCESS;
5692 }
5693
5694 break;
5695 }
5696 return status;
5697}
5698
5699hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005700 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005701 tANI_U8 rtnl_held )
5702{
5703 hdd_adapter_t *pAdapter = NULL;
5704 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5705 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5706 VOS_STATUS exitbmpsStatus;
5707
5708 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
5709
5710 //Disable BMPS incase of Concurrency
5711 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5712
5713 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5714 {
5715 //Fail to Exit BMPS
5716 VOS_ASSERT(0);
5717 return NULL;
5718 }
5719
5720 switch(session_type)
5721 {
5722 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005723 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005724 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005725 {
5726 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5727
5728 if( NULL == pAdapter )
5729 return NULL;
5730
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305731#ifdef FEATURE_WLAN_TDLS
5732 /* A Mutex Lock is introduced while changing/initializing the mode to
5733 * protect the concurrent access for the Adapters by TDLS module.
5734 */
5735 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5736 {
5737 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5738 "%s: unable to lock list", __func__);
5739 return NULL;
5740 }
5741#endif
5742
Jeff Johnsone7245742012-09-05 17:12:55 -07005743 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5744 NL80211_IFTYPE_P2P_CLIENT:
5745 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005746
Jeff Johnson295189b2012-06-20 16:38:30 -07005747 pAdapter->device_mode = session_type;
5748
5749 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305750#ifdef FEATURE_WLAN_TDLS
5751 mutex_unlock(&pHddCtx->tdls_lock);
5752#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005753 if( VOS_STATUS_SUCCESS != status )
5754 goto err_free_netdev;
5755
5756 status = hdd_register_interface( pAdapter, rtnl_held );
5757 if( VOS_STATUS_SUCCESS != status )
5758 {
5759 hdd_deinit_adapter(pHddCtx, pAdapter);
5760 goto err_free_netdev;
5761 }
5762 //Stop the Interface TX queue.
5763 netif_tx_disable(pAdapter->dev);
5764 //netif_tx_disable(pWlanDev);
5765 netif_carrier_off(pAdapter->dev);
5766
5767 break;
5768 }
5769
Jeff Johnson295189b2012-06-20 16:38:30 -07005770 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005771 case WLAN_HDD_SOFTAP:
5772 {
5773 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5774 if( NULL == pAdapter )
5775 return NULL;
5776
Jeff Johnson295189b2012-06-20 16:38:30 -07005777 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5778 NL80211_IFTYPE_AP:
5779 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005780 pAdapter->device_mode = session_type;
5781
5782 status = hdd_init_ap_mode(pAdapter);
5783 if( VOS_STATUS_SUCCESS != status )
5784 goto err_free_netdev;
5785
5786 status = hdd_register_hostapd( pAdapter, rtnl_held );
5787 if( VOS_STATUS_SUCCESS != status )
5788 {
5789 hdd_deinit_adapter(pHddCtx, pAdapter);
5790 goto err_free_netdev;
5791 }
5792
5793 netif_tx_disable(pAdapter->dev);
5794 netif_carrier_off(pAdapter->dev);
5795
5796 hdd_set_conparam( 1 );
5797 break;
5798 }
5799 case WLAN_HDD_MONITOR:
5800 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005801 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5802 if( NULL == pAdapter )
5803 return NULL;
5804
5805 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5806 pAdapter->device_mode = session_type;
5807 status = hdd_register_interface( pAdapter, rtnl_held );
5808#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5809 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5810#else
5811 pAdapter->dev->open = hdd_mon_open;
5812 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5813#endif
5814 hdd_init_tx_rx( pAdapter );
5815 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5816 //Set adapter to be used for data tx. It will use either GO or softap.
5817 pAdapter->sessionCtx.monitor.pAdapterForTx =
5818 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005819 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5820 {
5821 pAdapter->sessionCtx.monitor.pAdapterForTx =
5822 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5823 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005824 /* This workqueue will be used to transmit management packet over
5825 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005826 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5827 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5828 return NULL;
5829 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005830
Jeff Johnson295189b2012-06-20 16:38:30 -07005831 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5832 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005833 }
5834 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005835 case WLAN_HDD_FTM:
5836 {
5837 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5838
5839 if( NULL == pAdapter )
5840 return NULL;
5841 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5842 * message while loading driver in FTM mode. */
5843 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5844 pAdapter->device_mode = session_type;
5845 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305846
5847 hdd_init_tx_rx( pAdapter );
5848
5849 //Stop the Interface TX queue.
5850 netif_tx_disable(pAdapter->dev);
5851 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005852 }
5853 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005854 default:
5855 {
5856 VOS_ASSERT(0);
5857 return NULL;
5858 }
5859 }
5860
5861
5862 if( VOS_STATUS_SUCCESS == status )
5863 {
5864 //Add it to the hdd's session list.
5865 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5866 if( NULL == pHddAdapterNode )
5867 {
5868 status = VOS_STATUS_E_NOMEM;
5869 }
5870 else
5871 {
5872 pHddAdapterNode->pAdapter = pAdapter;
5873 status = hdd_add_adapter_back ( pHddCtx,
5874 pHddAdapterNode );
5875 }
5876 }
5877
5878 if( VOS_STATUS_SUCCESS != status )
5879 {
5880 if( NULL != pAdapter )
5881 {
5882 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5883 pAdapter = NULL;
5884 }
5885 if( NULL != pHddAdapterNode )
5886 {
5887 vos_mem_free( pHddAdapterNode );
5888 }
5889
5890 goto resume_bmps;
5891 }
5892
5893 if(VOS_STATUS_SUCCESS == status)
5894 {
5895 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5896
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005897 //Initialize the WoWL service
5898 if(!hdd_init_wowl(pAdapter))
5899 {
5900 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5901 goto err_free_netdev;
5902 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005903 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005904 return pAdapter;
5905
5906err_free_netdev:
5907 free_netdev(pAdapter->dev);
5908 wlan_hdd_release_intf_addr( pHddCtx,
5909 pAdapter->macAddressCurrent.bytes );
5910
5911resume_bmps:
5912 //If bmps disabled enable it
5913 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5914 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305915 if (pHddCtx->hdd_wlan_suspended)
5916 {
5917 hdd_set_pwrparams(pHddCtx);
5918 }
5919 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005920 }
5921 return NULL;
5922}
5923
5924VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5925 tANI_U8 rtnl_held )
5926{
5927 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5928 VOS_STATUS status;
5929
5930 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5931 if( VOS_STATUS_SUCCESS != status )
5932 return status;
5933
5934 while ( pCurrent->pAdapter != pAdapter )
5935 {
5936 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5937 if( VOS_STATUS_SUCCESS != status )
5938 break;
5939
5940 pCurrent = pNext;
5941 }
5942 pAdapterNode = pCurrent;
5943 if( VOS_STATUS_SUCCESS == status )
5944 {
5945 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5946 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305947
5948#ifdef FEATURE_WLAN_TDLS
5949
5950 /* A Mutex Lock is introduced while changing/initializing the mode to
5951 * protect the concurrent access for the Adapters by TDLS module.
5952 */
5953 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5954 {
5955 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5956 "%s: unable to lock list", __func__);
5957 return VOS_STATUS_E_FAILURE;
5958 }
5959#endif
5960
Jeff Johnson295189b2012-06-20 16:38:30 -07005961 hdd_remove_adapter( pHddCtx, pAdapterNode );
5962 vos_mem_free( pAdapterNode );
5963
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305964#ifdef FEATURE_WLAN_TDLS
5965 mutex_unlock(&pHddCtx->tdls_lock);
5966#endif
5967
Jeff Johnson295189b2012-06-20 16:38:30 -07005968
5969 /* If there is a single session of STA/P2P client, re-enable BMPS */
5970 if ((!vos_concurrent_sessions_running()) &&
5971 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
5972 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
5973 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305974 if (pHddCtx->hdd_wlan_suspended)
5975 {
5976 hdd_set_pwrparams(pHddCtx);
5977 }
5978 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005979 }
5980
5981 return VOS_STATUS_SUCCESS;
5982 }
5983
5984 return VOS_STATUS_E_FAILURE;
5985}
5986
5987VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
5988{
5989 hdd_adapter_list_node_t *pHddAdapterNode;
5990 VOS_STATUS status;
5991
5992 ENTER();
5993
5994 do
5995 {
5996 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
5997 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
5998 {
5999 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6000 vos_mem_free( pHddAdapterNode );
6001 }
6002 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6003
6004 EXIT();
6005
6006 return VOS_STATUS_SUCCESS;
6007}
6008
6009void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6010{
6011 v_U8_t addIE[1] = {0};
6012
6013 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6014 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6015 eANI_BOOLEAN_FALSE) )
6016 {
6017 hddLog(LOGE,
6018 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
6019 }
6020
6021 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6022 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6023 eANI_BOOLEAN_FALSE) )
6024 {
6025 hddLog(LOGE,
6026 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
6027 }
6028
6029 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6030 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6031 eANI_BOOLEAN_FALSE) )
6032 {
6033 hddLog(LOGE,
6034 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
6035 }
6036}
6037
6038VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6039{
6040 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6041 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6042 union iwreq_data wrqu;
6043
6044 ENTER();
6045
6046 switch(pAdapter->device_mode)
6047 {
6048 case WLAN_HDD_INFRA_STATION:
6049 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006050 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006051 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6052 {
6053 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6054 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6055 pAdapter->sessionId,
6056 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6057 else
6058 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6059 pAdapter->sessionId,
6060 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6061 //success implies disconnect command got queued up successfully
6062 if(halStatus == eHAL_STATUS_SUCCESS)
6063 {
6064 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
6065 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6066 }
6067 memset(&wrqu, '\0', sizeof(wrqu));
6068 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6069 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6070 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6071 }
6072 else
6073 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306074 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006075 }
6076
6077 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6078 {
6079 INIT_COMPLETION(pAdapter->session_close_comp_var);
6080 if (eHAL_STATUS_SUCCESS ==
6081 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6082 hdd_smeCloseSessionCallback, pAdapter))
6083 {
6084 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006085 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006086 &pAdapter->session_close_comp_var,
6087 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
6088 }
6089 }
6090
6091 break;
6092
6093 case WLAN_HDD_SOFTAP:
6094 case WLAN_HDD_P2P_GO:
6095 //Any softap specific cleanup here...
6096 mutex_lock(&pHddCtx->sap_lock);
6097 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6098 {
6099 VOS_STATUS status;
6100 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6101
6102 //Stop Bss.
6103 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6104 if (VOS_IS_STATUS_SUCCESS(status))
6105 {
6106 hdd_hostapd_state_t *pHostapdState =
6107 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6108
6109 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6110
6111 if (!VOS_IS_STATUS_SUCCESS(status))
6112 {
6113 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006114 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006115 }
6116 }
6117 else
6118 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006119 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006120 }
6121 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6122
6123 if (eHAL_STATUS_FAILURE ==
6124 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6125 0, NULL, eANI_BOOLEAN_FALSE))
6126 {
6127 hddLog(LOGE,
6128 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006129 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006130 }
6131
6132 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6133 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6134 eANI_BOOLEAN_FALSE) )
6135 {
6136 hddLog(LOGE,
6137 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6138 }
6139
6140 // Reset WNI_CFG_PROBE_RSP Flags
6141 wlan_hdd_reset_prob_rspies(pAdapter);
6142 kfree(pAdapter->sessionCtx.ap.beacon);
6143 pAdapter->sessionCtx.ap.beacon = NULL;
6144 }
6145 mutex_unlock(&pHddCtx->sap_lock);
6146 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006147
Jeff Johnson295189b2012-06-20 16:38:30 -07006148 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006149#ifdef WLAN_OPEN_SOURCE
6150 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6151#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006152 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006153
Jeff Johnson295189b2012-06-20 16:38:30 -07006154 default:
6155 break;
6156 }
6157
6158 EXIT();
6159 return VOS_STATUS_SUCCESS;
6160}
6161
6162VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6163{
6164 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6165 VOS_STATUS status;
6166 hdd_adapter_t *pAdapter;
6167
6168 ENTER();
6169
6170 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6171
6172 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6173 {
6174 pAdapter = pAdapterNode->pAdapter;
6175 netif_tx_disable(pAdapter->dev);
6176 netif_carrier_off(pAdapter->dev);
6177
6178 hdd_stop_adapter( pHddCtx, pAdapter );
6179
6180 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6181 pAdapterNode = pNext;
6182 }
6183
6184 EXIT();
6185
6186 return VOS_STATUS_SUCCESS;
6187}
6188
6189VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6190{
6191 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6192 VOS_STATUS status;
6193 hdd_adapter_t *pAdapter;
6194
6195 ENTER();
6196
6197 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6198
6199 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6200 {
6201 pAdapter = pAdapterNode->pAdapter;
6202 netif_tx_disable(pAdapter->dev);
6203 netif_carrier_off(pAdapter->dev);
6204
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006205 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6206
Jeff Johnson295189b2012-06-20 16:38:30 -07006207 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306208 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6209 {
6210 hdd_wmm_adapter_close( pAdapter );
6211 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6212 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006213
6214 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6215 pAdapterNode = pNext;
6216 }
6217
6218 EXIT();
6219
6220 return VOS_STATUS_SUCCESS;
6221}
6222
6223VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6224{
6225 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6226 VOS_STATUS status;
6227 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306228 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006229
6230 ENTER();
6231
6232 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6233
6234 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6235 {
6236 pAdapter = pAdapterNode->pAdapter;
6237
6238 switch(pAdapter->device_mode)
6239 {
6240 case WLAN_HDD_INFRA_STATION:
6241 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006242 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306243
6244 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6245
Jeff Johnson295189b2012-06-20 16:38:30 -07006246 hdd_init_station_mode(pAdapter);
6247 /* Open the gates for HDD to receive Wext commands */
6248 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006249 pHddCtx->scan_info.mScanPending = FALSE;
6250 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006251
6252 //Trigger the initial scan
6253 hdd_wlan_initial_scan(pAdapter);
6254
6255 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306256 if (eConnectionState_Associated == connState ||
6257 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006258 {
6259 union iwreq_data wrqu;
6260 memset(&wrqu, '\0', sizeof(wrqu));
6261 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6262 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6263 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006264 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006265
Jeff Johnson295189b2012-06-20 16:38:30 -07006266 /* indicate disconnected event to nl80211 */
6267 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6268 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006269 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306270 else if (eConnectionState_Connecting == connState)
6271 {
6272 /*
6273 * Indicate connect failure to supplicant if we were in the
6274 * process of connecting
6275 */
6276 cfg80211_connect_result(pAdapter->dev, NULL,
6277 NULL, 0, NULL, 0,
6278 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6279 GFP_KERNEL);
6280 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006281 break;
6282
6283 case WLAN_HDD_SOFTAP:
6284 /* softAP can handle SSR */
6285 break;
6286
6287 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006288 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006289 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006290 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006291 break;
6292
6293 case WLAN_HDD_MONITOR:
6294 /* monitor interface start */
6295 break;
6296 default:
6297 break;
6298 }
6299
6300 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6301 pAdapterNode = pNext;
6302 }
6303
6304 EXIT();
6305
6306 return VOS_STATUS_SUCCESS;
6307}
6308
6309VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6310{
6311 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6312 hdd_adapter_t *pAdapter;
6313 VOS_STATUS status;
6314 v_U32_t roamId;
6315
6316 ENTER();
6317
6318 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6319
6320 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6321 {
6322 pAdapter = pAdapterNode->pAdapter;
6323
6324 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6325 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6326 {
6327 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6328 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6329
6330 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6331 init_completion(&pAdapter->disconnect_comp_var);
6332 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6333 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6334
6335 wait_for_completion_interruptible_timeout(
6336 &pAdapter->disconnect_comp_var,
6337 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6338
6339 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6340 pHddCtx->isAmpAllowed = VOS_FALSE;
6341 sme_RoamConnect(pHddCtx->hHal,
6342 pAdapter->sessionId, &(pWextState->roamProfile),
6343 &roamId);
6344 }
6345
6346 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6347 pAdapterNode = pNext;
6348 }
6349
6350 EXIT();
6351
6352 return VOS_STATUS_SUCCESS;
6353}
6354
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006355void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6356{
6357 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6358 VOS_STATUS status;
6359 hdd_adapter_t *pAdapter;
6360 hdd_station_ctx_t *pHddStaCtx;
6361 hdd_ap_ctx_t *pHddApCtx;
6362 hdd_hostapd_state_t * pHostapdState;
6363 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6364 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6365 const char *p2pMode = "DEV";
6366 const char *ccMode = "Standalone";
6367 int n;
6368
6369 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6370 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6371 {
6372 pAdapter = pAdapterNode->pAdapter;
6373 switch (pAdapter->device_mode) {
6374 case WLAN_HDD_INFRA_STATION:
6375 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6376 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6377 staChannel = pHddStaCtx->conn_info.operationChannel;
6378 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6379 }
6380 break;
6381 case WLAN_HDD_P2P_CLIENT:
6382 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6383 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6384 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6385 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6386 p2pMode = "CLI";
6387 }
6388 break;
6389 case WLAN_HDD_P2P_GO:
6390 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6391 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6392 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6393 p2pChannel = pHddApCtx->operatingChannel;
6394 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6395 }
6396 p2pMode = "GO";
6397 break;
6398 case WLAN_HDD_SOFTAP:
6399 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6400 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6401 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6402 apChannel = pHddApCtx->operatingChannel;
6403 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6404 }
6405 break;
6406 default:
6407 break;
6408 }
6409 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6410 pAdapterNode = pNext;
6411 }
6412 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6413 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6414 }
6415 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6416 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6417 if (p2pChannel > 0) {
6418 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6419 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6420 }
6421 if (apChannel > 0) {
6422 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6423 apChannel, MAC_ADDR_ARRAY(apBssid));
6424 }
6425
6426 if (p2pChannel > 0 && apChannel > 0) {
6427 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6428 }
6429}
6430
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006431bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006432{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006433 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006434}
6435
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006436/* Once SSR is disabled then it cannot be set. */
6437void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006438{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006439 if (HDD_SSR_DISABLED == isSsrRequired)
6440 return;
6441
Jeff Johnson295189b2012-06-20 16:38:30 -07006442 isSsrRequired = value;
6443}
6444
6445VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6446 hdd_adapter_list_node_t** ppAdapterNode)
6447{
6448 VOS_STATUS status;
6449 spin_lock(&pHddCtx->hddAdapters.lock);
6450 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6451 (hdd_list_node_t**) ppAdapterNode );
6452 spin_unlock(&pHddCtx->hddAdapters.lock);
6453 return status;
6454}
6455
6456VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6457 hdd_adapter_list_node_t* pAdapterNode,
6458 hdd_adapter_list_node_t** pNextAdapterNode)
6459{
6460 VOS_STATUS status;
6461 spin_lock(&pHddCtx->hddAdapters.lock);
6462 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6463 (hdd_list_node_t*) pAdapterNode,
6464 (hdd_list_node_t**)pNextAdapterNode );
6465
6466 spin_unlock(&pHddCtx->hddAdapters.lock);
6467 return status;
6468}
6469
6470VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6471 hdd_adapter_list_node_t* pAdapterNode)
6472{
6473 VOS_STATUS status;
6474 spin_lock(&pHddCtx->hddAdapters.lock);
6475 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6476 &pAdapterNode->node );
6477 spin_unlock(&pHddCtx->hddAdapters.lock);
6478 return status;
6479}
6480
6481VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6482 hdd_adapter_list_node_t** ppAdapterNode)
6483{
6484 VOS_STATUS status;
6485 spin_lock(&pHddCtx->hddAdapters.lock);
6486 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6487 (hdd_list_node_t**) ppAdapterNode );
6488 spin_unlock(&pHddCtx->hddAdapters.lock);
6489 return status;
6490}
6491
6492VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6493 hdd_adapter_list_node_t* pAdapterNode)
6494{
6495 VOS_STATUS status;
6496 spin_lock(&pHddCtx->hddAdapters.lock);
6497 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6498 (hdd_list_node_t*) pAdapterNode );
6499 spin_unlock(&pHddCtx->hddAdapters.lock);
6500 return status;
6501}
6502
6503VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6504 hdd_adapter_list_node_t* pAdapterNode)
6505{
6506 VOS_STATUS status;
6507 spin_lock(&pHddCtx->hddAdapters.lock);
6508 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6509 (hdd_list_node_t*) pAdapterNode );
6510 spin_unlock(&pHddCtx->hddAdapters.lock);
6511 return status;
6512}
6513
6514hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6515 tSirMacAddr macAddr )
6516{
6517 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6518 hdd_adapter_t *pAdapter;
6519 VOS_STATUS status;
6520
6521 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6522
6523 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6524 {
6525 pAdapter = pAdapterNode->pAdapter;
6526
6527 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6528 macAddr, sizeof(tSirMacAddr) ) )
6529 {
6530 return pAdapter;
6531 }
6532 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6533 pAdapterNode = pNext;
6534 }
6535
6536 return NULL;
6537
6538}
6539
6540hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6541{
6542 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6543 hdd_adapter_t *pAdapter;
6544 VOS_STATUS status;
6545
6546 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6547
6548 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6549 {
6550 pAdapter = pAdapterNode->pAdapter;
6551
6552 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6553 IFNAMSIZ ) )
6554 {
6555 return pAdapter;
6556 }
6557 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6558 pAdapterNode = pNext;
6559 }
6560
6561 return NULL;
6562
6563}
6564
6565hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6566{
6567 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6568 hdd_adapter_t *pAdapter;
6569 VOS_STATUS status;
6570
6571 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6572
6573 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6574 {
6575 pAdapter = pAdapterNode->pAdapter;
6576
6577 if( pAdapter && (mode == pAdapter->device_mode) )
6578 {
6579 return pAdapter;
6580 }
6581 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6582 pAdapterNode = pNext;
6583 }
6584
6585 return NULL;
6586
6587}
6588
6589//Remove this function later
6590hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6591{
6592 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6593 hdd_adapter_t *pAdapter;
6594 VOS_STATUS status;
6595
6596 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6597
6598 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6599 {
6600 pAdapter = pAdapterNode->pAdapter;
6601
6602 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6603 {
6604 return pAdapter;
6605 }
6606
6607 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6608 pAdapterNode = pNext;
6609 }
6610
6611 return NULL;
6612
6613}
6614
Jeff Johnson295189b2012-06-20 16:38:30 -07006615/**---------------------------------------------------------------------------
6616
6617 \brief hdd_set_monitor_tx_adapter() -
6618
6619 This API initializes the adapter to be used while transmitting on monitor
6620 adapter.
6621
6622 \param - pHddCtx - Pointer to the HDD context.
6623 pAdapter - Adapter that will used for TX. This can be NULL.
6624 \return - None.
6625 --------------------------------------------------------------------------*/
6626void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6627{
6628 hdd_adapter_t *pMonAdapter;
6629
6630 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6631
6632 if( NULL != pMonAdapter )
6633 {
6634 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6635 }
6636}
Jeff Johnson295189b2012-06-20 16:38:30 -07006637/**---------------------------------------------------------------------------
6638
6639 \brief hdd_select_queue() -
6640
6641 This API returns the operating channel of the requested device mode
6642
6643 \param - pHddCtx - Pointer to the HDD context.
6644 - mode - Device mode for which operating channel is required
6645 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6646 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6647 \return - channel number. "0" id the requested device is not found OR it is not connected.
6648 --------------------------------------------------------------------------*/
6649v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6650{
6651 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6652 VOS_STATUS status;
6653 hdd_adapter_t *pAdapter;
6654 v_U8_t operatingChannel = 0;
6655
6656 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6657
6658 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6659 {
6660 pAdapter = pAdapterNode->pAdapter;
6661
6662 if( mode == pAdapter->device_mode )
6663 {
6664 switch(pAdapter->device_mode)
6665 {
6666 case WLAN_HDD_INFRA_STATION:
6667 case WLAN_HDD_P2P_CLIENT:
6668 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6669 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6670 break;
6671 case WLAN_HDD_SOFTAP:
6672 case WLAN_HDD_P2P_GO:
6673 /*softap connection info */
6674 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6675 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6676 break;
6677 default:
6678 break;
6679 }
6680
6681 break; //Found the device of interest. break the loop
6682 }
6683
6684 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6685 pAdapterNode = pNext;
6686 }
6687 return operatingChannel;
6688}
6689
6690#ifdef WLAN_FEATURE_PACKET_FILTERING
6691/**---------------------------------------------------------------------------
6692
6693 \brief hdd_set_multicast_list() -
6694
6695 This used to set the multicast address list.
6696
6697 \param - dev - Pointer to the WLAN device.
6698 - skb - Pointer to OS packet (sk_buff).
6699 \return - success/fail
6700
6701 --------------------------------------------------------------------------*/
6702static void hdd_set_multicast_list(struct net_device *dev)
6703{
6704 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006705 int mc_count;
6706 int i = 0;
6707 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306708
6709 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006710 {
6711 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306712 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006713 return;
6714 }
6715
6716 if (dev->flags & IFF_ALLMULTI)
6717 {
6718 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006719 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306720 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006721 }
6722 else
6723 {
6724 mc_count = netdev_mc_count(dev);
6725 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006726 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006727 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6728 {
6729 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006730 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306731 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006732 return;
6733 }
6734
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306735 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006736
6737 netdev_for_each_mc_addr(ha, dev) {
6738 if (i == mc_count)
6739 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306740 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6741 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
6742 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006743 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306744 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006745 i++;
6746 }
6747 }
6748 return;
6749}
6750#endif
6751
6752/**---------------------------------------------------------------------------
6753
6754 \brief hdd_select_queue() -
6755
6756 This function is registered with the Linux OS for network
6757 core to decide which queue to use first.
6758
6759 \param - dev - Pointer to the WLAN device.
6760 - skb - Pointer to OS packet (sk_buff).
6761 \return - ac, Queue Index/access category corresponding to UP in IP header
6762
6763 --------------------------------------------------------------------------*/
6764v_U16_t hdd_select_queue(struct net_device *dev,
6765 struct sk_buff *skb)
6766{
6767 return hdd_wmm_select_queue(dev, skb);
6768}
6769
6770
6771/**---------------------------------------------------------------------------
6772
6773 \brief hdd_wlan_initial_scan() -
6774
6775 This function triggers the initial scan
6776
6777 \param - pAdapter - Pointer to the HDD adapter.
6778
6779 --------------------------------------------------------------------------*/
6780void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6781{
6782 tCsrScanRequest scanReq;
6783 tCsrChannelInfo channelInfo;
6784 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006785 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006786 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6787
6788 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6789 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6790 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6791
6792 if(sme_Is11dSupported(pHddCtx->hHal))
6793 {
6794 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6795 if ( HAL_STATUS_SUCCESS( halStatus ) )
6796 {
6797 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6798 if( !scanReq.ChannelInfo.ChannelList )
6799 {
6800 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6801 vos_mem_free(channelInfo.ChannelList);
6802 return;
6803 }
6804 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6805 channelInfo.numOfChannels);
6806 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6807 vos_mem_free(channelInfo.ChannelList);
6808 }
6809
6810 scanReq.scanType = eSIR_PASSIVE_SCAN;
6811 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6812 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6813 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6814 }
6815 else
6816 {
6817 scanReq.scanType = eSIR_ACTIVE_SCAN;
6818 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6819 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6820 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6821 }
6822
6823 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6824 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6825 {
6826 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6827 __func__, halStatus );
6828 }
6829
6830 if(sme_Is11dSupported(pHddCtx->hHal))
6831 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6832}
6833
6834struct fullPowerContext
6835{
6836 struct completion completion;
6837 unsigned int magic;
6838};
6839#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6840
6841/**---------------------------------------------------------------------------
6842
6843 \brief hdd_full_power_callback() - HDD full power callback function
6844
6845 This is the function invoked by SME to inform the result of a full power
6846 request issued by HDD
6847
6848 \param - callbackcontext - Pointer to cookie
6849 \param - status - result of request
6850
6851 \return - None
6852
6853 --------------------------------------------------------------------------*/
6854static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6855{
6856 struct fullPowerContext *pContext = callbackContext;
6857
6858 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306859 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006860
6861 if (NULL == callbackContext)
6862 {
6863 hddLog(VOS_TRACE_LEVEL_ERROR,
6864 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006865 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006866 return;
6867 }
6868
6869 /* there is a race condition that exists between this callback function
6870 and the caller since the caller could time out either before or
6871 while this code is executing. we'll assume the timeout hasn't
6872 occurred, but we'll verify that right before we save our work */
6873
6874 if (POWER_CONTEXT_MAGIC != pContext->magic)
6875 {
6876 /* the caller presumably timed out so there is nothing we can do */
6877 hddLog(VOS_TRACE_LEVEL_WARN,
6878 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006879 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006880 return;
6881 }
6882
6883 /* the race is on. caller could have timed out immediately after
6884 we verified the magic, but if so, caller will wait a short time
6885 for us to notify the caller, so the context will stay valid */
6886 complete(&pContext->completion);
6887}
6888
6889/**---------------------------------------------------------------------------
6890
6891 \brief hdd_wlan_exit() - HDD WLAN exit function
6892
6893 This is the driver exit point (invoked during rmmod)
6894
6895 \param - pHddCtx - Pointer to the HDD Context
6896
6897 \return - None
6898
6899 --------------------------------------------------------------------------*/
6900void hdd_wlan_exit(hdd_context_t *pHddCtx)
6901{
6902 eHalStatus halStatus;
6903 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6904 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306905 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006906 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006907 struct fullPowerContext powerContext;
6908 long lrc;
6909
6910 ENTER();
6911
Jeff Johnson88ba7742013-02-27 14:36:02 -08006912 if (VOS_FTM_MODE != hdd_get_conparam())
6913 {
6914 // Unloading, restart logic is no more required.
6915 wlan_hdd_restart_deinit(pHddCtx);
6916 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006917
Jeff Johnson295189b2012-06-20 16:38:30 -07006918 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006919 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006920 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006921 {
6922 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6923 WLAN_HDD_INFRA_STATION);
6924 if (pAdapter == NULL)
6925 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6926
6927 if (pAdapter != NULL)
6928 {
6929 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6930 hdd_UnregisterWext(pAdapter->dev);
6931 }
6932 }
6933 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006934
Jeff Johnson295189b2012-06-20 16:38:30 -07006935 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006936 {
6937 wlan_hdd_ftm_close(pHddCtx);
6938 goto free_hdd_ctx;
6939 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006940 //Stop the Interface TX queue.
6941 //netif_tx_disable(pWlanDev);
6942 //netif_carrier_off(pWlanDev);
6943
Jeff Johnson295189b2012-06-20 16:38:30 -07006944 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6945 {
6946 pAdapter = hdd_get_adapter(pHddCtx,
6947 WLAN_HDD_SOFTAP);
6948 }
6949 else
6950 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006951 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006952 {
6953 pAdapter = hdd_get_adapter(pHddCtx,
6954 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006955 if (pAdapter == NULL)
6956 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07006957 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006958 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006959 /* DeRegister with platform driver as client for Suspend/Resume */
6960 vosStatus = hddDeregisterPmOps(pHddCtx);
6961 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6962 {
6963 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
6964 VOS_ASSERT(0);
6965 }
6966
6967 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
6968 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6969 {
6970 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
6971 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006972
6973 // Cancel any outstanding scan requests. We are about to close all
6974 // of our adapters, but an adapter structure is what SME passes back
6975 // to our callback function. Hence if there are any outstanding scan
6976 // requests then there is a race condition between when the adapter
6977 // is closed and when the callback is invoked. We try to resolve that
6978 // race condition here by canceling any outstanding scans before we
6979 // close the adapters.
6980 // Note that the scans may be cancelled in an asynchronous manner, so
6981 // ideally there needs to be some kind of synchronization. Rather than
6982 // introduce a new synchronization here, we will utilize the fact that
6983 // we are about to Request Full Power, and since that is synchronized,
6984 // the expectation is that by the time Request Full Power has completed,
6985 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006986 if (NULL != pAdapter)
6987 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
6988 else
6989 hddLog(VOS_TRACE_LEVEL_ERROR,
6990 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006991
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07006992 //Stop the traffic monitor timer
6993 if ( VOS_TIMER_STATE_RUNNING ==
6994 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
6995 {
6996 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
6997 }
6998
6999 // Destroy the traffic monitor timer
7000 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7001 &pHddCtx->tx_rx_trafficTmr)))
7002 {
7003 hddLog(VOS_TRACE_LEVEL_ERROR,
7004 "%s: Cannot deallocate Traffic monitor timer", __func__);
7005 }
7006
Jeff Johnson295189b2012-06-20 16:38:30 -07007007 //Disable IMPS/BMPS as we do not want the device to enter any power
7008 //save mode during shutdown
7009 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7010 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7011 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7012
7013 //Ensure that device is in full power as we will touch H/W during vos_Stop
7014 init_completion(&powerContext.completion);
7015 powerContext.magic = POWER_CONTEXT_MAGIC;
7016
7017 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7018 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7019
7020 if (eHAL_STATUS_SUCCESS != halStatus)
7021 {
7022 if (eHAL_STATUS_PMC_PENDING == halStatus)
7023 {
7024 /* request was sent -- wait for the response */
7025 lrc = wait_for_completion_interruptible_timeout(
7026 &powerContext.completion,
7027 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
7028 /* either we have a response or we timed out
7029 either way, first invalidate our magic */
7030 powerContext.magic = 0;
7031 if (lrc <= 0)
7032 {
7033 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007034 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007035 /* there is a race condition such that the callback
7036 function could be executing at the same time we are. of
7037 primary concern is if the callback function had already
7038 verified the "magic" but hasn't yet set the completion
7039 variable. Since the completion variable is on our
7040 stack, we'll delay just a bit to make sure the data is
7041 still valid if that is the case */
7042 msleep(50);
7043 }
7044 }
7045 else
7046 {
7047 hddLog(VOS_TRACE_LEVEL_ERROR,
7048 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007049 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007050 VOS_ASSERT(0);
7051 /* continue -- need to clean up as much as possible */
7052 }
7053 }
7054
Yue Ma0d4891e2013-08-06 17:01:45 -07007055 hdd_debugfs_exit(pHddCtx);
7056
Jeff Johnson295189b2012-06-20 16:38:30 -07007057 // Unregister the Net Device Notifier
7058 unregister_netdevice_notifier(&hdd_netdev_notifier);
7059
Jeff Johnson295189b2012-06-20 16:38:30 -07007060 hdd_stop_all_adapters( pHddCtx );
7061
Jeff Johnson295189b2012-06-20 16:38:30 -07007062#ifdef WLAN_BTAMP_FEATURE
7063 vosStatus = WLANBAP_Stop(pVosContext);
7064 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7065 {
7066 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7067 "%s: Failed to stop BAP",__func__);
7068 }
7069#endif //WLAN_BTAMP_FEATURE
7070
7071 //Stop all the modules
7072 vosStatus = vos_stop( pVosContext );
7073 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7074 {
7075 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7076 "%s: Failed to stop VOSS",__func__);
7077 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7078 }
7079
Jeff Johnson295189b2012-06-20 16:38:30 -07007080 //Assert Deep sleep signal now to put Libra HW in lowest power state
7081 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7082 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7083
7084 //Vote off any PMIC voltage supplies
7085 vos_chipPowerDown(NULL, NULL, NULL);
7086
7087 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7088
Leo Chang59cdc7e2013-07-10 10:08:21 -07007089
Jeff Johnson295189b2012-06-20 16:38:30 -07007090 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007091 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007092
7093 //Close the scheduler before calling vos_close to make sure no thread is
7094 // scheduled after the each module close is called i.e after all the data
7095 // structures are freed.
7096 vosStatus = vos_sched_close( pVosContext );
7097 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7098 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7099 "%s: Failed to close VOSS Scheduler",__func__);
7100 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7101 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007102#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007103#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7104 /* Destroy the wake lock */
7105 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7106#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007107 /* Destroy the wake lock */
7108 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007109#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007110
7111 //Close VOSS
7112 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7113 vos_close(pVosContext);
7114
Jeff Johnson295189b2012-06-20 16:38:30 -07007115 //Close Watchdog
7116 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7117 vos_watchdog_close(pVosContext);
7118
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307119 //Clean up HDD Nlink Service
7120 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007121#ifdef WLAN_KD_READY_NOTIFIER
7122 nl_srv_exit(pHddCtx->ptt_pid);
7123#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307124 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007125#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307126
Jeff Johnson295189b2012-06-20 16:38:30 -07007127 /* Cancel the vote for XO Core ON.
7128 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7129 * exited at this point
7130 */
7131 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
7132 " when WLAN is turned OFF\n");
7133 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7134 {
7135 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7136 " Not returning failure."
7137 " Power consumed will be high\n");
7138 }
7139
7140 hdd_close_all_adapters( pHddCtx );
7141
7142
7143 //Free up dynamically allocated members inside HDD Adapter
7144 kfree(pHddCtx->cfg_ini);
7145 pHddCtx->cfg_ini= NULL;
7146
7147 /* free the power on lock from platform driver */
7148 if (free_riva_power_on_lock("wlan"))
7149 {
7150 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7151 __func__);
7152 }
7153
Jeff Johnson88ba7742013-02-27 14:36:02 -08007154free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007155 /* FTM mode, WIPHY did not registered
7156 If un-register here, system crash will happen */
7157 if (VOS_FTM_MODE != hdd_get_conparam())
7158 {
7159 wiphy_unregister(wiphy) ;
7160 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007161 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007162 if (hdd_is_ssr_required())
7163 {
7164 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007165 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007166 msleep(5000);
7167 }
7168 hdd_set_ssr_required (VOS_FALSE);
7169}
7170
7171
7172/**---------------------------------------------------------------------------
7173
7174 \brief hdd_update_config_from_nv() - Function to update the contents of
7175 the running configuration with parameters taken from NV storage
7176
7177 \param - pHddCtx - Pointer to the HDD global context
7178
7179 \return - VOS_STATUS_SUCCESS if successful
7180
7181 --------------------------------------------------------------------------*/
7182static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7183{
Jeff Johnson295189b2012-06-20 16:38:30 -07007184 v_BOOL_t itemIsValid = VOS_FALSE;
7185 VOS_STATUS status;
7186 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7187 v_U8_t macLoop;
7188
7189 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7190 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7191 if(status != VOS_STATUS_SUCCESS)
7192 {
7193 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
7194 return VOS_STATUS_E_FAILURE;
7195 }
7196
7197 if (itemIsValid == VOS_TRUE)
7198 {
7199 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
7200 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7201 VOS_MAX_CONCURRENCY_PERSONA);
7202 if(status != VOS_STATUS_SUCCESS)
7203 {
7204 /* Get MAC from NV fail, not update CFG info
7205 * INI MAC value will be used for MAC setting */
7206 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
7207 return VOS_STATUS_E_FAILURE;
7208 }
7209
7210 /* If first MAC is not valid, treat all others are not valid
7211 * Then all MACs will be got from ini file */
7212 if(vos_is_macaddr_zero(&macFromNV[0]))
7213 {
7214 /* MAC address in NV file is not configured yet */
7215 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7216 return VOS_STATUS_E_INVAL;
7217 }
7218
7219 /* Get MAC address from NV, update CFG info */
7220 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7221 {
7222 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7223 {
7224 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
7225 /* This MAC is not valid, skip it
7226 * This MAC will be got from ini file */
7227 }
7228 else
7229 {
7230 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7231 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7232 VOS_MAC_ADDR_SIZE);
7233 }
7234 }
7235 }
7236 else
7237 {
7238 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7239 return VOS_STATUS_E_FAILURE;
7240 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007241
Jeff Johnson295189b2012-06-20 16:38:30 -07007242
7243 return VOS_STATUS_SUCCESS;
7244}
7245
7246/**---------------------------------------------------------------------------
7247
7248 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7249
7250 \param - pAdapter - Pointer to the HDD
7251
7252 \return - None
7253
7254 --------------------------------------------------------------------------*/
7255VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7256{
7257 eHalStatus halStatus;
7258 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307259 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007260
Jeff Johnson295189b2012-06-20 16:38:30 -07007261
7262 // Send ready indication to the HDD. This will kick off the MAC
7263 // into a 'running' state and should kick off an initial scan.
7264 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7265 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7266 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307267 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007268 "code %08d [x%08x]",__func__, halStatus, halStatus );
7269 return VOS_STATUS_E_FAILURE;
7270 }
7271
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307272 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007273 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7274 // And RIVA will crash
7275 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7276 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307277 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7278 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7279
7280
Jeff Johnson295189b2012-06-20 16:38:30 -07007281 return VOS_STATUS_SUCCESS;
7282}
7283
Jeff Johnson295189b2012-06-20 16:38:30 -07007284/* wake lock APIs for HDD */
7285void hdd_prevent_suspend(void)
7286{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007287#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007288 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007289#else
7290 wcnss_prevent_suspend();
7291#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007292}
7293
7294void hdd_allow_suspend(void)
7295{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007296#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007297 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007298#else
7299 wcnss_allow_suspend();
7300#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007301}
7302
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007303void hdd_allow_suspend_timeout(v_U32_t timeout)
7304{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007305#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007306 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007307#else
7308 /* Do nothing as there is no API in wcnss for timeout*/
7309#endif
7310}
7311
Jeff Johnson295189b2012-06-20 16:38:30 -07007312/**---------------------------------------------------------------------------
7313
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007314 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7315 information between Host and Riva
7316
7317 This function gets reported version of FW
7318 It also finds the version of Riva headers used to compile the host
7319 It compares the above two and prints a warning if they are different
7320 It gets the SW and HW version string
7321 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7322 indicating the features they support through a bitmap
7323
7324 \param - pHddCtx - Pointer to HDD context
7325
7326 \return - void
7327
7328 --------------------------------------------------------------------------*/
7329
7330void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7331{
7332
7333 tSirVersionType versionCompiled;
7334 tSirVersionType versionReported;
7335 tSirVersionString versionString;
7336 tANI_U8 fwFeatCapsMsgSupported = 0;
7337 VOS_STATUS vstatus;
7338
7339 /* retrieve and display WCNSS version information */
7340 do {
7341
7342 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7343 &versionCompiled);
7344 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7345 {
7346 hddLog(VOS_TRACE_LEVEL_FATAL,
7347 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007348 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007349 break;
7350 }
7351
7352 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7353 &versionReported);
7354 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7355 {
7356 hddLog(VOS_TRACE_LEVEL_FATAL,
7357 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007358 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007359 break;
7360 }
7361
7362 if ((versionCompiled.major != versionReported.major) ||
7363 (versionCompiled.minor != versionReported.minor) ||
7364 (versionCompiled.version != versionReported.version) ||
7365 (versionCompiled.revision != versionReported.revision))
7366 {
7367 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7368 "Host expected %u.%u.%u.%u\n",
7369 WLAN_MODULE_NAME,
7370 (int)versionReported.major,
7371 (int)versionReported.minor,
7372 (int)versionReported.version,
7373 (int)versionReported.revision,
7374 (int)versionCompiled.major,
7375 (int)versionCompiled.minor,
7376 (int)versionCompiled.version,
7377 (int)versionCompiled.revision);
7378 }
7379 else
7380 {
7381 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7382 WLAN_MODULE_NAME,
7383 (int)versionReported.major,
7384 (int)versionReported.minor,
7385 (int)versionReported.version,
7386 (int)versionReported.revision);
7387 }
7388
7389 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7390 versionString,
7391 sizeof(versionString));
7392 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7393 {
7394 hddLog(VOS_TRACE_LEVEL_FATAL,
7395 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007396 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007397 break;
7398 }
7399
7400 pr_info("%s: WCNSS software version %s\n",
7401 WLAN_MODULE_NAME, versionString);
7402
7403 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7404 versionString,
7405 sizeof(versionString));
7406 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7407 {
7408 hddLog(VOS_TRACE_LEVEL_FATAL,
7409 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007410 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007411 break;
7412 }
7413
7414 pr_info("%s: WCNSS hardware version %s\n",
7415 WLAN_MODULE_NAME, versionString);
7416
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007417 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7418 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007419 send the message only if it the riva is 1.1
7420 minor numbers for different riva branches:
7421 0 -> (1.0)Mainline Build
7422 1 -> (1.1)Mainline Build
7423 2->(1.04) Stability Build
7424 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007425 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007426 ((versionReported.minor>=1) && (versionReported.version>=1)))
7427 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7428 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007429
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007430 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007431 {
7432#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7433 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7434 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7435#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007436 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7437 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7438 {
7439 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7440 }
7441
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007442 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007443 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007444
7445 } while (0);
7446
7447}
7448
7449/**---------------------------------------------------------------------------
7450
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307451 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7452
7453 \param - pHddCtx - Pointer to the hdd context
7454
7455 \return - true if hardware supports 5GHz
7456
7457 --------------------------------------------------------------------------*/
7458static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7459{
7460 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7461 * then hardware support 5Ghz.
7462 */
7463 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7464 {
7465 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7466 return true;
7467 }
7468 else
7469 {
7470 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7471 __func__);
7472 return false;
7473 }
7474}
7475
7476
7477/**---------------------------------------------------------------------------
7478
Jeff Johnson295189b2012-06-20 16:38:30 -07007479 \brief hdd_wlan_startup() - HDD init function
7480
7481 This is the driver startup code executed once a WLAN device has been detected
7482
7483 \param - dev - Pointer to the underlying device
7484
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007485 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007486
7487 --------------------------------------------------------------------------*/
7488
7489int hdd_wlan_startup(struct device *dev )
7490{
7491 VOS_STATUS status;
7492 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007493 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007494 hdd_context_t *pHddCtx = NULL;
7495 v_CONTEXT_t pVosContext= NULL;
7496#ifdef WLAN_BTAMP_FEATURE
7497 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7498 WLANBAP_ConfigType btAmpConfig;
7499 hdd_config_t *pConfig;
7500#endif
7501 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007502 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007503
7504 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007505 /*
7506 * cfg80211: wiphy allocation
7507 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307508 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007509
7510 if(wiphy == NULL)
7511 {
7512 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007513 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007514 }
7515
7516 pHddCtx = wiphy_priv(wiphy);
7517
Jeff Johnson295189b2012-06-20 16:38:30 -07007518 //Initialize the adapter context to zeros.
7519 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7520
Jeff Johnson295189b2012-06-20 16:38:30 -07007521 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007522 hdd_prevent_suspend();
7523 pHddCtx->isLoadUnloadInProgress = TRUE;
7524
7525 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7526
7527 /*Get vos context here bcoz vos_open requires it*/
7528 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7529
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007530 if(pVosContext == NULL)
7531 {
7532 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7533 goto err_free_hdd_context;
7534 }
7535
Jeff Johnson295189b2012-06-20 16:38:30 -07007536 //Save the Global VOSS context in adapter context for future.
7537 pHddCtx->pvosContext = pVosContext;
7538
7539 //Save the adapter context in global context for future.
7540 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7541
Jeff Johnson295189b2012-06-20 16:38:30 -07007542 pHddCtx->parent_dev = dev;
7543
7544 init_completion(&pHddCtx->full_pwr_comp_var);
7545 init_completion(&pHddCtx->standby_comp_var);
7546 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007547 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007548 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307549 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007550
7551#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007552 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007553#else
7554 init_completion(&pHddCtx->driver_crda_req);
7555#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007556
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307557 spin_lock_init(&pHddCtx->schedScan_lock);
7558
Jeff Johnson295189b2012-06-20 16:38:30 -07007559 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7560
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307561#ifdef FEATURE_WLAN_TDLS
7562 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7563 * invoked by other instances also) to protect the concurrent
7564 * access for the Adapters by TDLS module.
7565 */
7566 mutex_init(&pHddCtx->tdls_lock);
7567#endif
7568
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307569 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007570 // Load all config first as TL config is needed during vos_open
7571 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7572 if(pHddCtx->cfg_ini == NULL)
7573 {
7574 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7575 goto err_free_hdd_context;
7576 }
7577
7578 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7579
7580 // Read and parse the qcom_cfg.ini file
7581 status = hdd_parse_config_ini( pHddCtx );
7582 if ( VOS_STATUS_SUCCESS != status )
7583 {
7584 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7585 __func__, WLAN_INI_FILE);
7586 goto err_config;
7587 }
7588
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307589 /* INI has been read, initialise the configuredMcastBcastFilter with
7590 * INI value as this will serve as the default value
7591 */
7592 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7593 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7594 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307595
7596 if (false == hdd_is_5g_supported(pHddCtx))
7597 {
7598 //5Ghz is not supported.
7599 if (1 != pHddCtx->cfg_ini->nBandCapability)
7600 {
7601 hddLog(VOS_TRACE_LEVEL_INFO,
7602 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7603 pHddCtx->cfg_ini->nBandCapability = 1;
7604 }
7605 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307606
7607 /* If SNR Monitoring is enabled, FW has to parse all beacons
7608 * for calcaluting and storing the average SNR, so set Nth beacon
7609 * filter to 1 to enable FW to parse all the beaocons
7610 */
7611 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7612 {
7613 /* The log level is deliberately set to WARN as overriding
7614 * nthBeaconFilter to 1 will increase power cosumption and this
7615 * might just prove helpful to detect the power issue.
7616 */
7617 hddLog(VOS_TRACE_LEVEL_WARN,
7618 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7619 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7620 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007621 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307622 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007623 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307624 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007625 {
7626 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307627 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7628 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007629 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007630
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007631 // Update VOS trace levels based upon the cfg.ini
7632 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7633 pHddCtx->cfg_ini->vosTraceEnableBAP);
7634 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7635 pHddCtx->cfg_ini->vosTraceEnableTL);
7636 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7637 pHddCtx->cfg_ini->vosTraceEnableWDI);
7638 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7639 pHddCtx->cfg_ini->vosTraceEnableHDD);
7640 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7641 pHddCtx->cfg_ini->vosTraceEnableSME);
7642 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7643 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307644 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7645 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007646 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7647 pHddCtx->cfg_ini->vosTraceEnableWDA);
7648 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7649 pHddCtx->cfg_ini->vosTraceEnableSYS);
7650 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7651 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007652 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7653 pHddCtx->cfg_ini->vosTraceEnableSAP);
7654 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7655 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007656
Jeff Johnson295189b2012-06-20 16:38:30 -07007657 // Update WDI trace levels based upon the cfg.ini
7658 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7659 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7660 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7661 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7662 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7663 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7664 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7665 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007666
Jeff Johnson88ba7742013-02-27 14:36:02 -08007667 if (VOS_FTM_MODE == hdd_get_conparam())
7668 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007669 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7670 {
7671 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7672 goto err_free_hdd_context;
7673 }
7674 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7675 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007676 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007677
Jeff Johnson88ba7742013-02-27 14:36:02 -08007678 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007679 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7680 {
7681 status = vos_watchdog_open(pVosContext,
7682 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7683
7684 if(!VOS_IS_STATUS_SUCCESS( status ))
7685 {
7686 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307687 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007688 }
7689 }
7690
7691 pHddCtx->isLogpInProgress = FALSE;
7692 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7693
Jeff Johnson295189b2012-06-20 16:38:30 -07007694 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7695 if(!VOS_IS_STATUS_SUCCESS(status))
7696 {
7697 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007698 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007699 }
7700
Amar Singhala49cbc52013-10-08 18:37:44 -07007701#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007702 /* initialize the NV module. This is required so that
7703 we can initialize the channel information in wiphy
7704 from the NV.bin data. The channel information in
7705 wiphy needs to be initialized before wiphy registration */
7706
7707 status = vos_nv_open();
7708 if (!VOS_IS_STATUS_SUCCESS(status))
7709 {
7710 /* NV module cannot be initialized */
7711 hddLog( VOS_TRACE_LEVEL_FATAL,
7712 "%s: vos_nv_open failed", __func__);
7713 goto err_clkvote;
7714 }
7715
7716 status = vos_init_wiphy_from_nv_bin();
7717 if (!VOS_IS_STATUS_SUCCESS(status))
7718 {
7719 /* NV module cannot be initialized */
7720 hddLog( VOS_TRACE_LEVEL_FATAL,
7721 "%s: vos_init_wiphy failed", __func__);
7722 goto err_vos_nv_close;
7723 }
7724
Amar Singhala49cbc52013-10-08 18:37:44 -07007725 /* registration of wiphy dev with cfg80211 */
7726 if (0 > wlan_hdd_cfg80211_register(wiphy))
7727 {
7728 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07007729 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07007730 }
7731#endif
7732
Jeff Johnson295189b2012-06-20 16:38:30 -07007733 status = vos_open( &pVosContext, 0);
7734 if ( !VOS_IS_STATUS_SUCCESS( status ))
7735 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007736 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007737 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007738 }
7739
Jeff Johnson295189b2012-06-20 16:38:30 -07007740 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7741
7742 if ( NULL == pHddCtx->hHal )
7743 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007744 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007745 goto err_vosclose;
7746 }
7747
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007748 status = vos_preStart( pHddCtx->pvosContext );
7749 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7750 {
7751 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7752 goto err_vosclose;
7753 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007754
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007755 /* Note that the vos_preStart() sequence triggers the cfg download.
7756 The cfg download must occur before we update the SME config
7757 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007758 status = hdd_set_sme_config( pHddCtx );
7759
7760 if ( VOS_STATUS_SUCCESS != status )
7761 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007762 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7763 goto err_vosclose;
7764 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007765
7766 //Initialize the WMM module
7767 status = hdd_wmm_init(pHddCtx);
7768 if (!VOS_IS_STATUS_SUCCESS(status))
7769 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007770 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007771 goto err_vosclose;
7772 }
7773
Jeff Johnson295189b2012-06-20 16:38:30 -07007774 /* In the integrated architecture we update the configuration from
7775 the INI file and from NV before vOSS has been started so that
7776 the final contents are available to send down to the cCPU */
7777
7778 // Apply the cfg.ini to cfg.dat
7779 if (FALSE == hdd_update_config_dat(pHddCtx))
7780 {
7781 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7782 goto err_vosclose;
7783 }
7784
7785 // Apply the NV to cfg.dat
7786 /* Prima Update MAC address only at here */
7787 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7788 {
7789#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7790 /* There was not a valid set of MAC Addresses in NV. See if the
7791 default addresses were modified by the cfg.ini settings. If so,
7792 we'll use them, but if not, we'll autogenerate a set of MAC
7793 addresses based upon the device serial number */
7794
7795 static const v_MACADDR_t default_address =
7796 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7797 unsigned int serialno;
7798 int i;
7799
7800 serialno = wcnss_get_serial_number();
7801 if ((0 != serialno) &&
7802 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7803 sizeof(default_address))))
7804 {
7805 /* cfg.ini has the default address, invoke autogen logic */
7806
7807 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7808 bytes of the serial number that can be used to generate
7809 the other 3 bytes of the MAC address. Mask off all but
7810 the lower 3 bytes (this will also make sure we don't
7811 overflow in the next step) */
7812 serialno &= 0x00FFFFFF;
7813
7814 /* we need a unique address for each session */
7815 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7816
7817 /* autogen all addresses */
7818 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7819 {
7820 /* start with the entire default address */
7821 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7822 /* then replace the lower 3 bytes */
7823 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7824 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7825 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7826
7827 serialno++;
7828 }
7829
7830 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7831 MAC_ADDRESS_STR,
7832 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7833 }
7834 else
7835#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7836 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007837 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007838 "%s: Invalid MAC address in NV, using MAC from ini file "
7839 MAC_ADDRESS_STR, __func__,
7840 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7841 }
7842 }
7843 {
7844 eHalStatus halStatus;
7845 // Set the MAC Address
7846 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7847 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7848 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7849 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7850
7851 if (!HAL_STATUS_SUCCESS( halStatus ))
7852 {
7853 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7854 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007855 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007856 }
7857 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007858
7859 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7860 Note: Firmware image will be read and downloaded inside vos_start API */
7861 status = vos_start( pHddCtx->pvosContext );
7862 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7863 {
7864 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7865 goto err_vosclose;
7866 }
7867
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007868 /* Exchange capability info between Host and FW and also get versioning info from FW */
7869 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007870
7871 status = hdd_post_voss_start_config( pHddCtx );
7872 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7873 {
7874 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7875 __func__);
7876 goto err_vosstop;
7877 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007878
7879#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307880 wlan_hdd_cfg80211_update_reg_info( wiphy );
7881
7882 /* registration of wiphy dev with cfg80211 */
7883 if (0 > wlan_hdd_cfg80211_register(wiphy))
7884 {
7885 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7886 goto err_vosstop;
7887 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007888#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007889
Jeff Johnson295189b2012-06-20 16:38:30 -07007890 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7891 {
7892 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7893 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7894 }
7895 else
7896 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007897 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7898 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7899 if (pAdapter != NULL)
7900 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307901 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007902 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307903 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7904 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7905 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007906
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307907 /* Generate the P2P Device Address. This consists of the device's
7908 * primary MAC address with the locally administered bit set.
7909 */
7910 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007911 }
7912 else
7913 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307914 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7915 if (p2p_dev_addr != NULL)
7916 {
7917 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7918 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7919 }
7920 else
7921 {
7922 hddLog(VOS_TRACE_LEVEL_FATAL,
7923 "%s: Failed to allocate mac_address for p2p_device",
7924 __func__);
7925 goto err_close_adapter;
7926 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007927 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007928
7929 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7930 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7931 if ( NULL == pP2pAdapter )
7932 {
7933 hddLog(VOS_TRACE_LEVEL_FATAL,
7934 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007935 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007936 goto err_close_adapter;
7937 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007938 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007939 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007940
7941 if( pAdapter == NULL )
7942 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007943 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7944 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007945 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007946
Jeff Johnson295189b2012-06-20 16:38:30 -07007947#ifdef WLAN_BTAMP_FEATURE
7948 vStatus = WLANBAP_Open(pVosContext);
7949 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7950 {
7951 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7952 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007953 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007954 }
7955
7956 vStatus = BSL_Init(pVosContext);
7957 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7958 {
7959 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7960 "%s: Failed to Init BSL",__func__);
7961 goto err_bap_close;
7962 }
7963 vStatus = WLANBAP_Start(pVosContext);
7964 if (!VOS_IS_STATUS_SUCCESS(vStatus))
7965 {
7966 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7967 "%s: Failed to start TL",__func__);
7968 goto err_bap_close;
7969 }
7970
7971 pConfig = pHddCtx->cfg_ini;
7972 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
7973 status = WLANBAP_SetConfig(&btAmpConfig);
7974
7975#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07007976
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07007977#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
7978 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
7979 {
7980 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
7981 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
7982 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
7983 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
7984 }
7985#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007986#ifdef FEATURE_WLAN_SCAN_PNO
7987 /*SME must send channel update configuration to RIVA*/
7988 sme_UpdateChannelConfig(pHddCtx->hHal);
7989#endif
7990
Jeff Johnson295189b2012-06-20 16:38:30 -07007991 /* Register with platform driver as client for Suspend/Resume */
7992 status = hddRegisterPmOps(pHddCtx);
7993 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7994 {
7995 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
7996#ifdef WLAN_BTAMP_FEATURE
7997 goto err_bap_stop;
7998#else
Jeff Johnsone7245742012-09-05 17:12:55 -07007999 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008000#endif //WLAN_BTAMP_FEATURE
8001 }
8002
Yue Ma0d4891e2013-08-06 17:01:45 -07008003 /* Open debugfs interface */
8004 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8005 {
8006 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8007 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008008 }
8009
Jeff Johnson295189b2012-06-20 16:38:30 -07008010 /* Register TM level change handler function to the platform */
8011 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8012 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8013 {
8014 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8015 goto err_unregister_pmops;
8016 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008017
8018 /* register for riva power on lock to platform driver */
8019 if (req_riva_power_on_lock("wlan"))
8020 {
8021 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8022 __func__);
8023 goto err_unregister_pmops;
8024 }
8025
Jeff Johnson295189b2012-06-20 16:38:30 -07008026 // register net device notifier for device change notification
8027 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8028
8029 if(ret < 0)
8030 {
8031 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8032 goto err_free_power_on_lock;
8033 }
8034
8035 //Initialize the nlink service
8036 if(nl_srv_init() != 0)
8037 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308038 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008039 goto err_reg_netdev;
8040 }
8041
Leo Chang4ce1cc52013-10-21 18:27:15 -07008042#ifdef WLAN_KD_READY_NOTIFIER
8043 pHddCtx->kd_nl_init = 1;
8044#endif /* WLAN_KD_READY_NOTIFIER */
8045
Jeff Johnson295189b2012-06-20 16:38:30 -07008046 //Initialize the BTC service
8047 if(btc_activate_service(pHddCtx) != 0)
8048 {
8049 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8050 goto err_nl_srv;
8051 }
8052
8053#ifdef PTT_SOCK_SVC_ENABLE
8054 //Initialize the PTT service
8055 if(ptt_sock_activate_svc(pHddCtx) != 0)
8056 {
8057 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8058 goto err_nl_srv;
8059 }
8060#endif
8061
Jeff Johnson295189b2012-06-20 16:38:30 -07008062 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008063 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008064 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008065 /* Action frame registered in one adapter which will
8066 * applicable to all interfaces
8067 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008068 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008069 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008070
8071 mutex_init(&pHddCtx->sap_lock);
8072
8073 pHddCtx->isLoadUnloadInProgress = FALSE;
8074
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008075#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008076#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8077 /* Initialize the wake lcok */
8078 wake_lock_init(&pHddCtx->rx_wake_lock,
8079 WAKE_LOCK_SUSPEND,
8080 "qcom_rx_wakelock");
8081#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008082 /* Initialize the wake lcok */
8083 wake_lock_init(&pHddCtx->sap_wake_lock,
8084 WAKE_LOCK_SUSPEND,
8085 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008086#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008087
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008088 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8089 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008090
8091 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8092 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05308093
Jeff Johnsone7245742012-09-05 17:12:55 -07008094 // Initialize the restart logic
8095 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308096
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008097 //Register the traffic monitor timer now
8098 if ( pHddCtx->cfg_ini->dynSplitscan)
8099 {
8100 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8101 VOS_TIMER_TYPE_SW,
8102 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8103 (void *)pHddCtx);
8104 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008105 goto success;
8106
8107err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008108#ifdef WLAN_KD_READY_NOTIFIER
8109 nl_srv_exit(pHddCtx->ptt_pid);
8110#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008111 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008112#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008113err_reg_netdev:
8114 unregister_netdevice_notifier(&hdd_netdev_notifier);
8115
8116err_free_power_on_lock:
8117 free_riva_power_on_lock("wlan");
8118
8119err_unregister_pmops:
8120 hddDevTmUnregisterNotifyCallback(pHddCtx);
8121 hddDeregisterPmOps(pHddCtx);
8122
Yue Ma0d4891e2013-08-06 17:01:45 -07008123 hdd_debugfs_exit(pHddCtx);
8124
Jeff Johnson295189b2012-06-20 16:38:30 -07008125#ifdef WLAN_BTAMP_FEATURE
8126err_bap_stop:
8127 WLANBAP_Stop(pVosContext);
8128#endif
8129
8130#ifdef WLAN_BTAMP_FEATURE
8131err_bap_close:
8132 WLANBAP_Close(pVosContext);
8133#endif
8134
Jeff Johnson295189b2012-06-20 16:38:30 -07008135err_close_adapter:
8136 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008137
8138#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308139 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008140#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008141
8142err_vosstop:
8143 vos_stop(pVosContext);
8144
Amar Singhala49cbc52013-10-08 18:37:44 -07008145err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008146 status = vos_sched_close( pVosContext );
8147 if (!VOS_IS_STATUS_SUCCESS(status)) {
8148 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8149 "%s: Failed to close VOSS Scheduler", __func__);
8150 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8151 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008152 vos_close(pVosContext );
8153
8154err_wiphy_unregister:
8155
8156#ifdef CONFIG_ENABLE_LINUX_REG
8157 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07008158
Amar Singhal0a402232013-10-11 20:57:16 -07008159err_vos_nv_close:
8160
8161 vos_nv_close();
8162
Jeff Johnson295189b2012-06-20 16:38:30 -07008163err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008164#endif
8165
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008166 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008167
8168err_wdclose:
8169 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8170 vos_watchdog_close(pVosContext);
8171
Jeff Johnson295189b2012-06-20 16:38:30 -07008172err_config:
8173 kfree(pHddCtx->cfg_ini);
8174 pHddCtx->cfg_ini= NULL;
8175
8176err_free_hdd_context:
8177 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008178 wiphy_free(wiphy) ;
8179 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008180 VOS_BUG(1);
8181
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008182 if (hdd_is_ssr_required())
8183 {
8184 /* WDI timeout had happened during load, so SSR is needed here */
8185 subsystem_restart("wcnss");
8186 msleep(5000);
8187 }
8188 hdd_set_ssr_required (VOS_FALSE);
8189
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008190 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008191
8192success:
8193 EXIT();
8194 return 0;
8195}
8196
8197/**---------------------------------------------------------------------------
8198
Jeff Johnson32d95a32012-09-10 13:15:23 -07008199 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008200
Jeff Johnson32d95a32012-09-10 13:15:23 -07008201 This is the driver entry point - called in different timeline depending
8202 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008203
8204 \param - None
8205
8206 \return - 0 for success, non zero for failure
8207
8208 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008209static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008210{
8211 VOS_STATUS status;
8212 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008213 struct device *dev = NULL;
8214 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008215#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8216 int max_retries = 0;
8217#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008218
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308219#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8220 vos_wconn_trace_init();
8221#endif
8222
Jeff Johnson295189b2012-06-20 16:38:30 -07008223 ENTER();
8224
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008225#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008226 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008227#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008228
8229 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8230 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8231
8232 //Power Up Libra WLAN card first if not already powered up
8233 status = vos_chipPowerUp(NULL,NULL,NULL);
8234 if (!VOS_IS_STATUS_SUCCESS(status))
8235 {
8236 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8237 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308238#ifdef WLAN_OPEN_SOURCE
8239 wake_lock_destroy(&wlan_wake_lock);
8240#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008241 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008242 }
8243
Jeff Johnson295189b2012-06-20 16:38:30 -07008244#ifdef ANI_BUS_TYPE_PCI
8245
8246 dev = wcnss_wlan_get_device();
8247
8248#endif // ANI_BUS_TYPE_PCI
8249
8250#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008251
8252#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8253 /* wait until WCNSS driver downloads NV */
8254 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8255 msleep(1000);
8256 }
8257 if (max_retries >= 5) {
8258 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308259#ifdef WLAN_OPEN_SOURCE
8260 wake_lock_destroy(&wlan_wake_lock);
8261#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008262 return -ENODEV;
8263 }
8264#endif
8265
Jeff Johnson295189b2012-06-20 16:38:30 -07008266 dev = wcnss_wlan_get_device();
8267#endif // ANI_BUS_TYPE_PLATFORM
8268
8269
8270 do {
8271 if (NULL == dev) {
8272 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8273 ret_status = -1;
8274 break;
8275 }
8276
8277#ifdef MEMORY_DEBUG
8278 vos_mem_init();
8279#endif
8280
8281#ifdef TIMER_MANAGER
8282 vos_timer_manager_init();
8283#endif
8284
8285 /* Preopen VOSS so that it is ready to start at least SAL */
8286 status = vos_preOpen(&pVosContext);
8287
8288 if (!VOS_IS_STATUS_SUCCESS(status))
8289 {
8290 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8291 ret_status = -1;
8292 break;
8293 }
8294
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008295#ifndef MODULE
8296 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8297 */
8298 hdd_set_conparam((v_UINT_t)con_mode);
8299#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008300
8301 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008302 if (hdd_wlan_startup(dev))
8303 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008304 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008305 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008306 vos_preClose( &pVosContext );
8307 ret_status = -1;
8308 break;
8309 }
8310
8311 /* Cancel the vote for XO Core ON
8312 * This is done here for safety purposes in case we re-initialize without turning
8313 * it OFF in any error scenario.
8314 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008315 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008316 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008317 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008318 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8319 {
8320 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
8321 " Power consumed will be high\n");
8322 }
8323 } while (0);
8324
8325 if (0 != ret_status)
8326 {
8327 //Assert Deep sleep signal now to put Libra HW in lowest power state
8328 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8329 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8330
8331 //Vote off any PMIC voltage supplies
8332 vos_chipPowerDown(NULL, NULL, NULL);
8333#ifdef TIMER_MANAGER
8334 vos_timer_exit();
8335#endif
8336#ifdef MEMORY_DEBUG
8337 vos_mem_exit();
8338#endif
8339
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008340#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008341 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008342#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008343 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8344 }
8345 else
8346 {
8347 //Send WLAN UP indication to Nlink Service
8348 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8349
8350 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008351 }
8352
8353 EXIT();
8354
8355 return ret_status;
8356}
8357
Jeff Johnson32d95a32012-09-10 13:15:23 -07008358/**---------------------------------------------------------------------------
8359
8360 \brief hdd_module_init() - Init Function
8361
8362 This is the driver entry point (invoked when module is loaded using insmod)
8363
8364 \param - None
8365
8366 \return - 0 for success, non zero for failure
8367
8368 --------------------------------------------------------------------------*/
8369#ifdef MODULE
8370static int __init hdd_module_init ( void)
8371{
8372 return hdd_driver_init();
8373}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008374#else /* #ifdef MODULE */
8375static int __init hdd_module_init ( void)
8376{
8377 /* Driver initialization is delayed to fwpath_changed_handler */
8378 return 0;
8379}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008380#endif /* #ifdef MODULE */
8381
Jeff Johnson295189b2012-06-20 16:38:30 -07008382
8383/**---------------------------------------------------------------------------
8384
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008385 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008386
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008387 This is the driver exit point (invoked when module is unloaded using rmmod
8388 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008389
8390 \param - None
8391
8392 \return - None
8393
8394 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008395static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008396{
8397 hdd_context_t *pHddCtx = NULL;
8398 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008399 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008400
8401 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8402
8403 //Get the global vos context
8404 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8405
8406 if(!pVosContext)
8407 {
8408 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8409 goto done;
8410 }
8411
8412 //Get the HDD context.
8413 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8414
8415 if(!pHddCtx)
8416 {
8417 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8418 }
8419 else
8420 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008421 while(isWDresetInProgress()) {
8422 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8423 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008424 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008425
8426 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8427 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8428 "%s:SSR never completed, fatal error", __func__);
8429 VOS_BUG(0);
8430 }
8431 }
8432
Jeff Johnson295189b2012-06-20 16:38:30 -07008433
8434 pHddCtx->isLoadUnloadInProgress = TRUE;
8435 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8436
8437 //Do all the cleanup before deregistering the driver
8438 hdd_wlan_exit(pHddCtx);
8439 }
8440
Jeff Johnson295189b2012-06-20 16:38:30 -07008441 vos_preClose( &pVosContext );
8442
8443#ifdef TIMER_MANAGER
8444 vos_timer_exit();
8445#endif
8446#ifdef MEMORY_DEBUG
8447 vos_mem_exit();
8448#endif
8449
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308450#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8451 vos_wconn_trace_exit();
8452#endif
8453
Jeff Johnson295189b2012-06-20 16:38:30 -07008454done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008455#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008456 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008457#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008458 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8459}
8460
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008461/**---------------------------------------------------------------------------
8462
8463 \brief hdd_module_exit() - Exit function
8464
8465 This is the driver exit point (invoked when module is unloaded using rmmod)
8466
8467 \param - None
8468
8469 \return - None
8470
8471 --------------------------------------------------------------------------*/
8472static void __exit hdd_module_exit(void)
8473{
8474 hdd_driver_exit();
8475}
8476
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008477#ifdef MODULE
8478static int fwpath_changed_handler(const char *kmessage,
8479 struct kernel_param *kp)
8480{
Jeff Johnson76052702013-04-16 13:55:05 -07008481 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008482}
8483
8484static int con_mode_handler(const char *kmessage,
8485 struct kernel_param *kp)
8486{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008487 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008488}
8489#else /* #ifdef MODULE */
8490/**---------------------------------------------------------------------------
8491
Jeff Johnson76052702013-04-16 13:55:05 -07008492 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008493
Jeff Johnson76052702013-04-16 13:55:05 -07008494 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008495 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008496 - invoked when module parameter fwpath is modified from userspace to signal
8497 initializing the WLAN driver or when con_mode is modified from userspace
8498 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008499
8500 \return - 0 for success, non zero for failure
8501
8502 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008503static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008504{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008505 int ret_status;
8506
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008507 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008508 ret_status = hdd_driver_init();
8509 wlan_hdd_inited = ret_status ? 0 : 1;
8510 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008511 }
8512
8513 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008514
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008515 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008516
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008517 ret_status = hdd_driver_init();
8518 wlan_hdd_inited = ret_status ? 0 : 1;
8519 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008520}
8521
Jeff Johnson295189b2012-06-20 16:38:30 -07008522/**---------------------------------------------------------------------------
8523
Jeff Johnson76052702013-04-16 13:55:05 -07008524 \brief fwpath_changed_handler() - Handler Function
8525
8526 Handle changes to the fwpath parameter
8527
8528 \return - 0 for success, non zero for failure
8529
8530 --------------------------------------------------------------------------*/
8531static int fwpath_changed_handler(const char *kmessage,
8532 struct kernel_param *kp)
8533{
8534 int ret;
8535
8536 ret = param_set_copystring(kmessage, kp);
8537 if (0 == ret)
8538 ret = kickstart_driver();
8539 return ret;
8540}
8541
8542/**---------------------------------------------------------------------------
8543
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008544 \brief con_mode_handler() -
8545
8546 Handler function for module param con_mode when it is changed by userspace
8547 Dynamically linked - do nothing
8548 Statically linked - exit and init driver, as in rmmod and insmod
8549
Jeff Johnson76052702013-04-16 13:55:05 -07008550 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008551
Jeff Johnson76052702013-04-16 13:55:05 -07008552 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008553
8554 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008555static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008556{
Jeff Johnson76052702013-04-16 13:55:05 -07008557 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008558
Jeff Johnson76052702013-04-16 13:55:05 -07008559 ret = param_set_int(kmessage, kp);
8560 if (0 == ret)
8561 ret = kickstart_driver();
8562 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008563}
8564#endif /* #ifdef MODULE */
8565
8566/**---------------------------------------------------------------------------
8567
Jeff Johnson295189b2012-06-20 16:38:30 -07008568 \brief hdd_get_conparam() -
8569
8570 This is the driver exit point (invoked when module is unloaded using rmmod)
8571
8572 \param - None
8573
8574 \return - tVOS_CON_MODE
8575
8576 --------------------------------------------------------------------------*/
8577tVOS_CON_MODE hdd_get_conparam ( void )
8578{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008579#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008580 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008581#else
8582 return (tVOS_CON_MODE)curr_con_mode;
8583#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008584}
8585void hdd_set_conparam ( v_UINT_t newParam )
8586{
8587 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008588#ifndef MODULE
8589 curr_con_mode = con_mode;
8590#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008591}
8592/**---------------------------------------------------------------------------
8593
8594 \brief hdd_softap_sta_deauth() - function
8595
8596 This to take counter measure to handle deauth req from HDD
8597
8598 \param - pAdapter - Pointer to the HDD
8599
8600 \param - enable - boolean value
8601
8602 \return - None
8603
8604 --------------------------------------------------------------------------*/
8605
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008606VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008607{
Jeff Johnson295189b2012-06-20 16:38:30 -07008608 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008609 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008610
8611 ENTER();
8612
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008613 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8614 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008615
8616 //Ignore request to deauth bcmc station
8617 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008618 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008619
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008620 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008621
8622 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008623 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008624}
8625
8626/**---------------------------------------------------------------------------
8627
8628 \brief hdd_softap_sta_disassoc() - function
8629
8630 This to take counter measure to handle deauth req from HDD
8631
8632 \param - pAdapter - Pointer to the HDD
8633
8634 \param - enable - boolean value
8635
8636 \return - None
8637
8638 --------------------------------------------------------------------------*/
8639
8640void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8641{
8642 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8643
8644 ENTER();
8645
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308646 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008647
8648 //Ignore request to disassoc bcmc station
8649 if( pDestMacAddress[0] & 0x1 )
8650 return;
8651
8652 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8653}
8654
8655void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8656{
8657 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8658
8659 ENTER();
8660
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308661 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008662
8663 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8664}
8665
Jeff Johnson295189b2012-06-20 16:38:30 -07008666/**---------------------------------------------------------------------------
8667 *
8668 * \brief hdd_get__concurrency_mode() -
8669 *
8670 *
8671 * \param - None
8672 *
8673 * \return - CONCURRENCY MODE
8674 *
8675 * --------------------------------------------------------------------------*/
8676tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8677{
8678 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8679 hdd_context_t *pHddCtx;
8680
8681 if (NULL != pVosContext)
8682 {
8683 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8684 if (NULL != pHddCtx)
8685 {
8686 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8687 }
8688 }
8689
8690 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008691 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008692 return VOS_STA;
8693}
8694
8695/* Decide whether to allow/not the apps power collapse.
8696 * Allow apps power collapse if we are in connected state.
8697 * if not, allow only if we are in IMPS */
8698v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8699{
8700 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008701 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008702 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008703 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8704 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8705 hdd_adapter_t *pAdapter = NULL;
8706 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008707 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008708
Jeff Johnson295189b2012-06-20 16:38:30 -07008709 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8710 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008711
Yathish9f22e662012-12-10 14:21:35 -08008712 concurrent_state = hdd_get_concurrency_mode();
8713
8714#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8715 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8716 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8717 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8718 return TRUE;
8719#endif
8720
Jeff Johnson295189b2012-06-20 16:38:30 -07008721 /*loop through all adapters. TBD fix for Concurrency */
8722 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8723 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8724 {
8725 pAdapter = pAdapterNode->pAdapter;
8726 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8727 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8728 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008729 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008730 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008731 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008732 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8733 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008734 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008735 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008736 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8737 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008738 return FALSE;
8739 }
8740 }
8741 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8742 pAdapterNode = pNext;
8743 }
8744 return TRUE;
8745}
8746
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008747/* Decides whether to send suspend notification to Riva
8748 * if any adapter is in BMPS; then it is required */
8749v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8750{
8751 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8752 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8753
8754 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8755 {
8756 return TRUE;
8757 }
8758 return FALSE;
8759}
8760
Jeff Johnson295189b2012-06-20 16:38:30 -07008761void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8762{
8763 switch(mode)
8764 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008765 case VOS_STA_MODE:
8766 case VOS_P2P_CLIENT_MODE:
8767 case VOS_P2P_GO_MODE:
8768 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008769 pHddCtx->concurrency_mode |= (1 << mode);
8770 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008771 break;
8772 default:
8773 break;
8774
8775 }
8776 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8777 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8778}
8779
8780
8781void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8782{
8783 switch(mode)
8784 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008785 case VOS_STA_MODE:
8786 case VOS_P2P_CLIENT_MODE:
8787 case VOS_P2P_GO_MODE:
8788 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008789 pHddCtx->no_of_sessions[mode]--;
8790 if (!(pHddCtx->no_of_sessions[mode]))
8791 pHddCtx->concurrency_mode &= (~(1 << mode));
8792 break;
8793 default:
8794 break;
8795 }
8796 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8797 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8798}
8799
Jeff Johnsone7245742012-09-05 17:12:55 -07008800/**---------------------------------------------------------------------------
8801 *
8802 * \brief wlan_hdd_restart_init
8803 *
8804 * This function initalizes restart timer/flag. An internal function.
8805 *
8806 * \param - pHddCtx
8807 *
8808 * \return - None
8809 *
8810 * --------------------------------------------------------------------------*/
8811
8812static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8813{
8814 /* Initialize */
8815 pHddCtx->hdd_restart_retries = 0;
8816 atomic_set(&pHddCtx->isRestartInProgress, 0);
8817 vos_timer_init(&pHddCtx->hdd_restart_timer,
8818 VOS_TIMER_TYPE_SW,
8819 wlan_hdd_restart_timer_cb,
8820 pHddCtx);
8821}
8822/**---------------------------------------------------------------------------
8823 *
8824 * \brief wlan_hdd_restart_deinit
8825 *
8826 * This function cleans up the resources used. An internal function.
8827 *
8828 * \param - pHddCtx
8829 *
8830 * \return - None
8831 *
8832 * --------------------------------------------------------------------------*/
8833
8834static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8835{
8836
8837 VOS_STATUS vos_status;
8838 /* Block any further calls */
8839 atomic_set(&pHddCtx->isRestartInProgress, 1);
8840 /* Cleanup */
8841 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8842 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008843 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008844 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8845 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008846 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008847
8848}
8849
8850/**---------------------------------------------------------------------------
8851 *
8852 * \brief wlan_hdd_framework_restart
8853 *
8854 * This function uses a cfg80211 API to start a framework initiated WLAN
8855 * driver module unload/load.
8856 *
8857 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8858 *
8859 *
8860 * \param - pHddCtx
8861 *
8862 * \return - VOS_STATUS_SUCCESS: Success
8863 * VOS_STATUS_E_EMPTY: Adapter is Empty
8864 * VOS_STATUS_E_NOMEM: No memory
8865
8866 * --------------------------------------------------------------------------*/
8867
8868static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8869{
8870 VOS_STATUS status = VOS_STATUS_SUCCESS;
8871 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008872 int len = (sizeof (struct ieee80211_mgmt));
8873 struct ieee80211_mgmt *mgmt = NULL;
8874
8875 /* Prepare the DEAUTH managment frame with reason code */
8876 mgmt = kzalloc(len, GFP_KERNEL);
8877 if(mgmt == NULL)
8878 {
8879 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8880 "%s: memory allocation failed (%d bytes)", __func__, len);
8881 return VOS_STATUS_E_NOMEM;
8882 }
8883 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008884
8885 /* Iterate over all adapters/devices */
8886 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8887 do
8888 {
8889 if( (status == VOS_STATUS_SUCCESS) &&
8890 pAdapterNode &&
8891 pAdapterNode->pAdapter)
8892 {
8893 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8894 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8895 pAdapterNode->pAdapter->dev->name,
8896 pAdapterNode->pAdapter->device_mode,
8897 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008898 /*
8899 * CFG80211 event to restart the driver
8900 *
8901 * 'cfg80211_send_unprot_deauth' sends a
8902 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8903 * of SME(Linux Kernel) state machine.
8904 *
8905 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8906 * the driver.
8907 *
8908 */
8909
8910 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008911 }
8912 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8913 pAdapterNode = pNext;
8914 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8915
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008916
8917 /* Free the allocated management frame */
8918 kfree(mgmt);
8919
Jeff Johnsone7245742012-09-05 17:12:55 -07008920 /* Retry until we unload or reach max count */
8921 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
8922 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
8923
8924 return status;
8925
8926}
8927/**---------------------------------------------------------------------------
8928 *
8929 * \brief wlan_hdd_restart_timer_cb
8930 *
8931 * Restart timer callback. An internal function.
8932 *
8933 * \param - User data:
8934 *
8935 * \return - None
8936 *
8937 * --------------------------------------------------------------------------*/
8938
8939void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
8940{
8941 hdd_context_t *pHddCtx = usrDataForCallback;
8942 wlan_hdd_framework_restart(pHddCtx);
8943 return;
8944
8945}
8946
8947
8948/**---------------------------------------------------------------------------
8949 *
8950 * \brief wlan_hdd_restart_driver
8951 *
8952 * This function sends an event to supplicant to restart the WLAN driver.
8953 *
8954 * This function is called from vos_wlanRestart.
8955 *
8956 * \param - pHddCtx
8957 *
8958 * \return - VOS_STATUS_SUCCESS: Success
8959 * VOS_STATUS_E_EMPTY: Adapter is Empty
8960 * VOS_STATUS_E_ALREADY: Request already in progress
8961
8962 * --------------------------------------------------------------------------*/
8963VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
8964{
8965 VOS_STATUS status = VOS_STATUS_SUCCESS;
8966
8967 /* A tight check to make sure reentrancy */
8968 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
8969 {
8970 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8971 "%s: WLAN restart is already in progress", __func__);
8972
8973 return VOS_STATUS_E_ALREADY;
8974 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07008975 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08008976#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07008977 wcnss_reset_intr();
8978#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008979
Jeff Johnsone7245742012-09-05 17:12:55 -07008980 return status;
8981}
8982
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07008983/*
8984 * API to find if there is any STA or P2P-Client is connected
8985 */
8986VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
8987{
8988 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
8989}
Jeff Johnsone7245742012-09-05 17:12:55 -07008990
Jeff Johnson295189b2012-06-20 16:38:30 -07008991//Register the module init/exit functions
8992module_init(hdd_module_init);
8993module_exit(hdd_module_exit);
8994
8995MODULE_LICENSE("Dual BSD/GPL");
8996MODULE_AUTHOR("Qualcomm Atheros, Inc.");
8997MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
8998
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008999module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9000 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009001
Jeff Johnson76052702013-04-16 13:55:05 -07009002module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009003 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);