blob: ba0e4150e68521b7c3e72f16f51ecab1973bf2fd [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Rajeev Kumar8b373292014-01-08 20:36:55 -08002 * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +0530106#include <linux/inetdevice.h>
107#include <net/addrconf.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include "wlan_hdd_cfg80211.h"
109#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700111int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700112#include "sapApi.h"
113#include <linux/semaphore.h>
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -0700114#include <linux/ctype.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include <mach/subsystem_restart.h>
116#include <wlan_hdd_hostapd.h>
117#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700118#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700119#include "wlan_hdd_dev_pwr.h"
120#ifdef WLAN_BTAMP_FEATURE
121#include "bap_hdd_misc.h"
122#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700123#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700124#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800125#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530126#ifdef FEATURE_WLAN_TDLS
127#include "wlan_hdd_tdls.h"
128#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700129#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700130
131#ifdef MODULE
132#define WLAN_MODULE_NAME module_name(THIS_MODULE)
133#else
134#define WLAN_MODULE_NAME "wlan"
135#endif
136
137#ifdef TIMER_MANAGER
138#define TIMER_MANAGER_STR " +TIMER_MANAGER"
139#else
140#define TIMER_MANAGER_STR ""
141#endif
142
143#ifdef MEMORY_DEBUG
144#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
145#else
146#define MEMORY_DEBUG_STR ""
147#endif
148
149/* the Android framework expects this param even though we don't use it */
150#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700151static char fwpath_buffer[BUF_LEN];
152static struct kparam_string fwpath = {
153 .string = fwpath_buffer,
154 .maxlen = BUF_LEN,
155};
Arif Hussain66559122013-11-21 10:11:40 -0800156
157static char *country_code;
158static int enable_11d = -1;
159static int enable_dfs_chan_scan = -1;
160
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700161#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700162static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700163#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700164
Jeff Johnsone7245742012-09-05 17:12:55 -0700165/*
Jeff Johnson72a40512013-12-19 10:14:15 -0800166 * spinlock for synchronizing asynchronous request/response
167 * (full description of use in wlan_hdd_main.h)
168 */
169DEFINE_SPINLOCK(hdd_context_lock);
170
171/*
Jeff Johnsone7245742012-09-05 17:12:55 -0700172 * The rate at which the driver sends RESTART event to supplicant
173 * once the function 'vos_wlanRestart()' is called
174 *
175 */
176#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
177#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700178
179/*
180 * Size of Driver command strings from upper layer
181 */
182#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
183#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
184
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700185#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
186#define TID_MIN_VALUE 0
187#define TID_MAX_VALUE 15
188static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
189 tAniTrafStrmMetrics* pTsmMetrics);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -0800190static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
191 tCsrCcxBeaconReq *pCcxBcnReq);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700192#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
193
Srinivas Girigowda4081bb12014-01-06 17:12:58 -0800194#define WLAN_PRIV_DATA_MAX_LEN 4096
195
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700196/*
197 * Driver miracast parameters 0-Disabled
198 * 1-Source, 2-Sink
199 */
200#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
201#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
202
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800203#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700204static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700205#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700206/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700207static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700208
209//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700210static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
211static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
212static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
213void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800214void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700215
Jeff Johnson295189b2012-06-20 16:38:30 -0700216v_U16_t hdd_select_queue(struct net_device *dev,
217 struct sk_buff *skb);
218
219#ifdef WLAN_FEATURE_PACKET_FILTERING
220static void hdd_set_multicast_list(struct net_device *dev);
221#endif
222
223void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
224
225extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Amar Singhal0a402232013-10-11 20:57:16 -0700226
Srinivas Girigowdade697412013-02-14 16:31:48 -0800227#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
228void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
229static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700230static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
231 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
232 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700233static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
234 tANI_U8 *pTargetApBssid,
235 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800236#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700237#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
238VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
239#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
240
Mihir Shetee1093ba2014-01-21 20:13:32 +0530241static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx);
242
Jeff Johnson295189b2012-06-20 16:38:30 -0700243static int hdd_netdev_notifier_call(struct notifier_block * nb,
244 unsigned long state,
245 void *ndev)
246{
247 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700248 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700249 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700250#ifdef WLAN_BTAMP_FEATURE
251 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700252#endif
253
254 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700255 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700256 (strncmp(dev->name, "p2p", 3)))
257 return NOTIFY_DONE;
258
Jeff Johnson295189b2012-06-20 16:38:30 -0700259 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700260 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700261
Jeff Johnson27cee452013-03-27 11:10:24 -0700262 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700263 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800264 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700265 VOS_ASSERT(0);
266 return NOTIFY_DONE;
267 }
268
Jeff Johnson27cee452013-03-27 11:10:24 -0700269 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
270 if (NULL == pHddCtx)
271 {
272 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
273 VOS_ASSERT(0);
274 return NOTIFY_DONE;
275 }
Sameer Thalappil14067972014-01-23 14:54:54 -0800276 if (pHddCtx->isLogpInProgress)
277 return NOTIFY_DONE;
278
Jeff Johnson27cee452013-03-27 11:10:24 -0700279
280 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
281 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700282
283 switch (state) {
284 case NETDEV_REGISTER:
285 break;
286
287 case NETDEV_UNREGISTER:
288 break;
289
290 case NETDEV_UP:
291 break;
292
293 case NETDEV_DOWN:
294 break;
295
296 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700297 if(TRUE == pAdapter->isLinkUpSvcNeeded)
298 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700299 break;
300
301 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700302 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700303 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530304 long result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800305 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +0530306 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700307 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800308 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700309 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530310 if (result <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700311 {
312 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530313 "%s: Timeout occurred while waiting for abortscan %ld",
314 __func__, result);
Jeff Johnson295189b2012-06-20 16:38:30 -0700315 }
316 }
317 else
318 {
319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700320 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700321 }
322#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700323 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700324 status = WLANBAP_StopAmp();
325 if(VOS_STATUS_SUCCESS != status )
326 {
327 pHddCtx->isAmpAllowed = VOS_TRUE;
328 hddLog(VOS_TRACE_LEVEL_FATAL,
329 "%s: Failed to stop AMP", __func__);
330 }
331 else
332 {
333 //a state m/c implementation in PAL is TBD to avoid this delay
334 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700335 if ( pHddCtx->isAmpAllowed )
336 {
337 WLANBAP_DeregisterFromHCI();
338 pHddCtx->isAmpAllowed = VOS_FALSE;
339 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700340 }
341#endif //WLAN_BTAMP_FEATURE
342 break;
343
344 default:
345 break;
346 }
347
348 return NOTIFY_DONE;
349}
350
351struct notifier_block hdd_netdev_notifier = {
352 .notifier_call = hdd_netdev_notifier_call,
353};
354
355/*---------------------------------------------------------------------------
356 * Function definitions
357 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700358void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
359void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700360//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700361static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700362#ifndef MODULE
363/* current con_mode - used only for statically linked driver
364 * con_mode is changed by userspace to indicate a mode change which will
365 * result in calling the module exit and init functions. The module
366 * exit function will clean up based on the value of con_mode prior to it
367 * being changed by userspace. So curr_con_mode records the current con_mode
368 * for exit when con_mode becomes the next mode for init
369 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700370static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700371#endif
372
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800373/**---------------------------------------------------------------------------
374
375 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
376
377 Called immediately after the cfg.ini is read in order to configure
378 the desired trace levels.
379
380 \param - moduleId - module whose trace level is being configured
381 \param - bitmask - bitmask of log levels to be enabled
382
383 \return - void
384
385 --------------------------------------------------------------------------*/
386static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
387{
388 wpt_tracelevel level;
389
390 /* if the bitmask is the default value, then a bitmask was not
391 specified in cfg.ini, so leave the logging level alone (it
392 will remain at the "compiled in" default value) */
393 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
394 {
395 return;
396 }
397
398 /* a mask was specified. start by disabling all logging */
399 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
400
401 /* now cycle through the bitmask until all "set" bits are serviced */
402 level = VOS_TRACE_LEVEL_FATAL;
403 while (0 != bitmask)
404 {
405 if (bitmask & 1)
406 {
407 vos_trace_setValue(moduleId, level, 1);
408 }
409 level++;
410 bitmask >>= 1;
411 }
412}
413
414
Jeff Johnson295189b2012-06-20 16:38:30 -0700415/**---------------------------------------------------------------------------
416
417 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
418
419 Called immediately after the cfg.ini is read in order to configure
420 the desired trace levels in the WDI.
421
422 \param - moduleId - module whose trace level is being configured
423 \param - bitmask - bitmask of log levels to be enabled
424
425 \return - void
426
427 --------------------------------------------------------------------------*/
428static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
429{
430 wpt_tracelevel level;
431
432 /* if the bitmask is the default value, then a bitmask was not
433 specified in cfg.ini, so leave the logging level alone (it
434 will remain at the "compiled in" default value) */
435 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
436 {
437 return;
438 }
439
440 /* a mask was specified. start by disabling all logging */
441 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
442
443 /* now cycle through the bitmask until all "set" bits are serviced */
444 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
445 while (0 != bitmask)
446 {
447 if (bitmask & 1)
448 {
449 wpalTraceSetLevel(moduleId, level, 1);
450 }
451 level++;
452 bitmask >>= 1;
453 }
454}
Jeff Johnson295189b2012-06-20 16:38:30 -0700455
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530456/*
457 * FUNCTION: wlan_hdd_validate_context
458 * This function is used to check the HDD context
459 */
460int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
461{
462 ENTER();
463
464 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
465 {
466 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
467 "%s: HDD context is Null", __func__);
468 return -ENODEV;
469 }
470
471 if (pHddCtx->isLogpInProgress)
472 {
473 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
474 "%s: LOGP in Progress. Ignore!!!", __func__);
475 return -EAGAIN;
476 }
477
478 if (pHddCtx->isLoadUnloadInProgress)
479 {
480 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
481 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
482 return -EAGAIN;
483 }
484 return 0;
485}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700486#ifdef CONFIG_ENABLE_LINUX_REG
487void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
488{
489 hdd_adapter_t *pAdapter = NULL;
490 hdd_station_ctx_t *pHddStaCtx = NULL;
491 eCsrPhyMode phyMode;
492 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530493
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700494 if (NULL == pHddCtx)
495 {
496 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
497 "HDD Context is null !!");
498 return ;
499 }
500
501 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
502 if (NULL == pAdapter)
503 {
504 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
505 "pAdapter is null !!");
506 return ;
507 }
508
509 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
510 if (NULL == pHddStaCtx)
511 {
512 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
513 "pHddStaCtx is null !!");
514 return ;
515 }
516
517 cfg_param = pHddCtx->cfg_ini;
518 if (NULL == cfg_param)
519 {
520 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
521 "cfg_params not available !!");
522 return ;
523 }
524
525 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
526
527 if (!pHddCtx->isVHT80Allowed)
528 {
529 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
530 (eCSR_DOT11_MODE_11ac == phyMode) ||
531 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
532 {
533 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
534 "Setting phymode to 11n!!");
535 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
536 }
537 }
538 else
539 {
540 /*New country Supports 11ac as well resetting value back from .ini*/
541 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
542 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
543 return ;
544 }
545
546 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
547 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
548 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
549 {
550 VOS_STATUS vosStatus;
551
552 // need to issue a disconnect to CSR.
553 INIT_COMPLETION(pAdapter->disconnect_comp_var);
554 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
555 pAdapter->sessionId,
556 eCSR_DISCONNECT_REASON_UNSPECIFIED );
557
558 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530559 {
560 long ret;
561
562 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700563 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530564 if (0 >= ret)
565 hddLog(LOGE, FL("failure waiting for disconnect_comp_var %ld"),
566 ret);
567 }
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700568
569 }
570}
571#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530572void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
573{
574 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
575 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
576 hdd_config_t *cfg_param;
577 eCsrPhyMode phyMode;
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530578 long ret;
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530579
580 if (NULL == pHddCtx)
581 {
582 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
583 "HDD Context is null !!");
584 return ;
585 }
586
587 cfg_param = pHddCtx->cfg_ini;
588
589 if (NULL == cfg_param)
590 {
591 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
592 "cfg_params not available !!");
593 return ;
594 }
595
596 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
597
598 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
599 {
600 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
601 (eCSR_DOT11_MODE_11ac == phyMode) ||
602 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
603 {
604 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
605 "Setting phymode to 11n!!");
606 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
607 }
608 }
609 else
610 {
611 /*New country Supports 11ac as well resetting value back from .ini*/
612 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
613 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
614 return ;
615 }
616
617 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
618 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
619 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
620 {
621 VOS_STATUS vosStatus;
622
623 // need to issue a disconnect to CSR.
624 INIT_COMPLETION(pAdapter->disconnect_comp_var);
625 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
626 pAdapter->sessionId,
627 eCSR_DISCONNECT_REASON_UNSPECIFIED );
628
629 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530630 {
631 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530632 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530633 if (ret <= 0)
634 {
635 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
636 "wait on disconnect_comp_var is failed %ld", ret);
637 }
638 }
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530639
640 }
641}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700642#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530643
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700644void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
645{
646 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
647 hdd_config_t *cfg_param;
648
649 if (NULL == pHddCtx)
650 {
651 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
652 "HDD Context is null !!");
653 return ;
654 }
655
656 cfg_param = pHddCtx->cfg_ini;
657
658 if (NULL == cfg_param)
659 {
660 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
661 "cfg_params not available !!");
662 return ;
663 }
664
665 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
666 {
667 /*New country doesn't support DFS */
668 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
669 }
670 else
671 {
672 /*New country Supports DFS as well resetting value back from .ini*/
673 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
674 }
675
676}
677
Rajeev79dbe4c2013-10-05 11:03:42 +0530678#ifdef FEATURE_WLAN_BATCH_SCAN
679
680/**---------------------------------------------------------------------------
681
682 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
683 input string
684
685 This function extracts assigned integer from string in below format:
686 "STRING=10" : extracts integer 10 from this string
687
688 \param - pInPtr Pointer to input string
689 \param - base Base for string to int conversion(10 for decimal 16 for hex)
690 \param - pOutPtr Pointer to variable in which extracted integer needs to be
691 assigned
692 \param - pLastArg to tell whether it is last arguement in input string or
693 not
694
695 \return - NULL for failure cases
696 pointer to next arguement in input string for success cases
697 --------------------------------------------------------------------------*/
698static tANI_U8 *
699hdd_extract_assigned_int_from_str
700(
701 tANI_U8 *pInPtr,
702 tANI_U8 base,
703 tANI_U32 *pOutPtr,
704 tANI_U8 *pLastArg
705)
706{
707 int tempInt;
708 int v = 0;
709 char buf[32];
710 int val = 0;
711 *pLastArg = FALSE;
712
713 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
714 if (NULL == pInPtr)
715 {
716 return NULL;
717 }
718
719 pInPtr++;
720
721 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
722
723 val = sscanf(pInPtr, "%32s ", buf);
724 if (val < 0 && val > strlen(pInPtr))
725 {
726 return NULL;
727 }
728 pInPtr += val;
729 v = kstrtos32(buf, base, &tempInt);
730 if (v < 0)
731 {
732 return NULL;
733 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -0800734 if (tempInt < 0)
735 {
736 tempInt = 0;
737 }
Rajeev79dbe4c2013-10-05 11:03:42 +0530738 *pOutPtr = tempInt;
739
740 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
741 if (NULL == pInPtr)
742 {
743 *pLastArg = TRUE;
744 return NULL;
745 }
746 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
747
748 return pInPtr;
749}
750
751/**---------------------------------------------------------------------------
752
753 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
754 input string
755
756 This function extracts assigned character from string in below format:
757 "STRING=A" : extracts char 'A' from this string
758
759 \param - pInPtr Pointer to input string
760 \param - pOutPtr Pointer to variable in which extracted char needs to be
761 assigned
762 \param - pLastArg to tell whether it is last arguement in input string or
763 not
764
765 \return - NULL for failure cases
766 pointer to next arguement in input string for success cases
767 --------------------------------------------------------------------------*/
768static tANI_U8 *
769hdd_extract_assigned_char_from_str
770(
771 tANI_U8 *pInPtr,
772 tANI_U8 *pOutPtr,
773 tANI_U8 *pLastArg
774)
775{
776 *pLastArg = FALSE;
777
778 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
779 if (NULL == pInPtr)
780 {
781 return NULL;
782 }
783
784 pInPtr++;
785
786 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
787
788 *pOutPtr = *pInPtr;
789
790 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
791 if (NULL == pInPtr)
792 {
793 *pLastArg = TRUE;
794 return NULL;
795 }
796 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
797
798 return pInPtr;
799}
800
801
802/**---------------------------------------------------------------------------
803
804 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
805
806 This function parses set batch scan command in below format:
807 WLS_BATCHING_SET <space> followed by below arguements
808 "SCANFREQ=XX" : Optional defaults to 30 sec
809 "MSCAN=XX" : Required number of scans to attempt to batch
810 "BESTN=XX" : Best Network (RSSI) defaults to 16
811 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
812 A. implies only 5 GHz , B. implies only 2.4GHz
813 "RTT=X" : optional defaults to 0
814 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
815 error
816
817 For example input commands:
818 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
819 translated into set batch scan with following parameters:
820 a) Frequence 60 seconds
821 b) Batch 10 scans together
822 c) Best RSSI to be 20
823 d) 5GHz band only
824 e) RTT is equal to 0
825
826 \param - pValue Pointer to input channel list
827 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
828
829 \return - 0 for success non-zero for failure
830
831 --------------------------------------------------------------------------*/
832static int
833hdd_parse_set_batchscan_command
834(
835 tANI_U8 *pValue,
836 tSirSetBatchScanReq *pHddSetBatchScanReq
837)
838{
839 tANI_U8 *inPtr = pValue;
840 tANI_U8 val = 0;
841 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800842 tANI_U32 nScanFreq;
843 tANI_U32 nMscan;
844 tANI_U32 nBestN;
845 tANI_U8 ucRfBand;
846 tANI_U32 nRtt;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800847 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530848
849 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800850 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
851 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
852 nRtt = 0;
853 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530854
855 /*go to space after WLS_BATCHING_SET command*/
856 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
857 /*no argument after the command*/
858 if (NULL == inPtr)
859 {
860 return -EINVAL;
861 }
862
863 /*no space after the command*/
864 else if (SPACE_ASCII_VALUE != *inPtr)
865 {
866 return -EINVAL;
867 }
868
869 /*removing empty spaces*/
870 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
871
872 /*no argument followed by spaces*/
873 if ('\0' == *inPtr)
874 {
875 return -EINVAL;
876 }
877
878 /*check and parse SCANFREQ*/
879 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
880 {
881 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800882 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800883
Rajeev Kumarc933d982013-11-18 20:04:20 -0800884 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800885 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800886 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800887 }
888
Rajeev79dbe4c2013-10-05 11:03:42 +0530889 if ( (NULL == inPtr) || (TRUE == lastArg))
890 {
891 return -EINVAL;
892 }
893 }
894
895 /*check and parse MSCAN*/
896 if ((strncmp(inPtr, "MSCAN", 5) == 0))
897 {
898 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800899 &nMscan, &lastArg);
900
901 if (0 == nMscan)
902 {
903 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
904 "invalid MSCAN=%d", nMscan);
905 return -EINVAL;
906 }
907
Rajeev79dbe4c2013-10-05 11:03:42 +0530908 if (TRUE == lastArg)
909 {
910 goto done;
911 }
912 else if (NULL == inPtr)
913 {
914 return -EINVAL;
915 }
916 }
917 else
918 {
919 return -EINVAL;
920 }
921
922 /*check and parse BESTN*/
923 if ((strncmp(inPtr, "BESTN", 5) == 0))
924 {
925 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800926 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800927
Rajeev Kumarc933d982013-11-18 20:04:20 -0800928 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800929 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800930 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800931 }
932
Rajeev79dbe4c2013-10-05 11:03:42 +0530933 if (TRUE == lastArg)
934 {
935 goto done;
936 }
937 else if (NULL == inPtr)
938 {
939 return -EINVAL;
940 }
941 }
942
943 /*check and parse CHANNEL*/
944 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
945 {
946 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800947
Rajeev79dbe4c2013-10-05 11:03:42 +0530948 if (('A' == val) || ('a' == val))
949 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800950 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530951 }
952 else if (('B' == val) || ('b' == val))
953 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800954 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530955 }
956 else
957 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800958 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
959 }
960
961 if (TRUE == lastArg)
962 {
963 goto done;
964 }
965 else if (NULL == inPtr)
966 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530967 return -EINVAL;
968 }
969 }
970
971 /*check and parse RTT*/
972 if ((strncmp(inPtr, "RTT", 3) == 0))
973 {
974 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800975 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530976 if (TRUE == lastArg)
977 {
978 goto done;
979 }
980 if (NULL == inPtr)
981 {
982 return -EINVAL;
983 }
984 }
985
986
987done:
988
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800989 pHddSetBatchScanReq->scanFrequency = nScanFreq;
990 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
991 pHddSetBatchScanReq->bestNetwork = nBestN;
992 pHddSetBatchScanReq->rfBand = ucRfBand;
993 pHddSetBatchScanReq->rtt = nRtt;
994
Rajeev79dbe4c2013-10-05 11:03:42 +0530995 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
996 "Received WLS_BATCHING_SET with SCANFREQ=%d "
997 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
998 pHddSetBatchScanReq->scanFrequency,
999 pHddSetBatchScanReq->numberOfScansToBatch,
1000 pHddSetBatchScanReq->bestNetwork,
1001 pHddSetBatchScanReq->rfBand,
1002 pHddSetBatchScanReq->rtt);
1003
1004 return 0;
1005}/*End of hdd_parse_set_batchscan_command*/
1006
1007/**---------------------------------------------------------------------------
1008
1009 \brief hdd_set_batch_scan_req_callback () - This function is called after
1010 receiving set batch scan response from FW and it saves set batch scan
1011 response data FW to HDD context and sets the completion event on
1012 which hdd_ioctl is waiting
1013
1014 \param - callbackContext Pointer to HDD adapter
1015 \param - pRsp Pointer to set batch scan response data received from FW
1016
1017 \return - nothing
1018
1019 --------------------------------------------------------------------------*/
1020static void hdd_set_batch_scan_req_callback
1021(
1022 void *callbackContext,
1023 tSirSetBatchScanRsp *pRsp
1024)
1025{
1026 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1027 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1028
1029 /*sanity check*/
1030 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1031 {
1032 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1033 "%s: Invalid pAdapter magic", __func__);
1034 VOS_ASSERT(0);
1035 return;
1036 }
1037 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1038
1039 /*save set batch scan response*/
1040 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1041
1042 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1043 "Received set batch scan rsp from FW with nScansToBatch=%d",
1044 pHddSetBatchScanRsp->nScansToBatch);
1045
1046 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1047 complete(&pAdapter->hdd_set_batch_scan_req_var);
1048
1049 return;
1050}/*End of hdd_set_batch_scan_req_callback*/
1051
1052
1053/**---------------------------------------------------------------------------
1054
1055 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1056 info in hdd batch scan response queue
1057
1058 \param - pAdapter Pointer to hdd adapter
1059 \param - pAPMetaInfo Pointer to access point meta info
1060 \param - scanId scan ID of batch scan response
1061 \param - isLastAp tells whether AP is last AP in batch scan response or not
1062
1063 \return - nothing
1064
1065 --------------------------------------------------------------------------*/
1066static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1067 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1068{
1069 tHddBatchScanRsp *pHead;
1070 tHddBatchScanRsp *pNode;
1071 tHddBatchScanRsp *pPrev;
1072 tHddBatchScanRsp *pTemp;
1073 tANI_U8 ssidLen;
1074
1075 /*head of hdd batch scan response queue*/
1076 pHead = pAdapter->pBatchScanRsp;
1077
1078 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1079 if (NULL == pNode)
1080 {
1081 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1082 "%s: Could not allocate memory", __func__);
1083 VOS_ASSERT(0);
1084 return;
1085 }
1086
1087 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1088 sizeof(pNode->ApInfo.bssid));
1089 ssidLen = strlen(pApMetaInfo->ssid);
1090 if (SIR_MAX_SSID_SIZE < ssidLen)
1091 {
1092 /*invalid scan result*/
1093 vos_mem_free(pNode);
1094 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1095 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1096 return;
1097 }
1098 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1099 /*null terminate ssid*/
1100 pNode->ApInfo.ssid[ssidLen] = '\0';
1101 pNode->ApInfo.ch = pApMetaInfo->ch;
1102 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1103 pNode->ApInfo.age = pApMetaInfo->timestamp;
1104 pNode->ApInfo.batchId = scanId;
1105 pNode->ApInfo.isLastAp = isLastAp;
1106
1107 pNode->pNext = NULL;
1108 if (NULL == pHead)
1109 {
1110 pAdapter->pBatchScanRsp = pNode;
1111 }
1112 else
1113 {
1114 pTemp = pHead;
1115 while (NULL != pTemp)
1116 {
1117 pPrev = pTemp;
1118 pTemp = pTemp->pNext;
1119 }
1120 pPrev->pNext = pNode;
1121 }
1122
1123 return;
1124}/*End of hdd_populate_batch_scan_rsp_queue*/
1125
1126/**---------------------------------------------------------------------------
1127
1128 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1129 receiving batch scan response indication from FW. It saves get batch scan
1130 response data in HDD batch scan response queue. This callback sets the
1131 completion event on which hdd_ioctl is waiting only after getting complete
1132 batch scan response data from FW
1133
1134 \param - callbackContext Pointer to HDD adapter
1135 \param - pRsp Pointer to get batch scan response data received from FW
1136
1137 \return - nothing
1138
1139 --------------------------------------------------------------------------*/
1140static void hdd_batch_scan_result_ind_callback
1141(
1142 void *callbackContext,
1143 void *pRsp
1144)
1145{
1146 v_BOOL_t isLastAp;
1147 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001148 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301149 tANI_U32 numberScanList;
1150 tANI_U32 nextScanListOffset;
1151 tANI_U32 nextApMetaInfoOffset;
1152 hdd_adapter_t* pAdapter;
1153 tpSirBatchScanList pScanList;
1154 tpSirBatchScanNetworkInfo pApMetaInfo;
1155 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1156 tSirSetBatchScanReq *pReq;
1157
1158 pAdapter = (hdd_adapter_t *)callbackContext;
1159 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001160 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301161 {
1162 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1163 "%s: Invalid pAdapter magic", __func__);
1164 VOS_ASSERT(0);
1165 return;
1166 }
1167
1168 /*initialize locals*/
1169 pReq = &pAdapter->hddSetBatchScanReq;
1170 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1171 isLastAp = FALSE;
1172 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001173 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301174 numberScanList = 0;
1175 nextScanListOffset = 0;
1176 nextApMetaInfoOffset = 0;
1177 pScanList = NULL;
1178 pApMetaInfo = NULL;
1179
1180 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1181 {
1182 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1183 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1184 isLastAp = TRUE;
1185 goto done;
1186 }
1187
1188 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1189 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1190 "Batch scan rsp: numberScalList %d", numberScanList);
1191
1192 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1193 {
1194 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1195 "%s: numberScanList %d", __func__, numberScanList);
1196 isLastAp = TRUE;
1197 goto done;
1198 }
1199
1200 while (numberScanList)
1201 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001202 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301203 nextScanListOffset);
1204 if (NULL == pScanList)
1205 {
1206 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1207 "%s: pScanList is %p", __func__, pScanList);
1208 isLastAp = TRUE;
1209 goto done;
1210 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001211 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301212 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001213 "Batch scan rsp: numApMetaInfo %d scanId %d",
1214 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301215
1216 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1217 {
1218 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1219 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1220 isLastAp = TRUE;
1221 goto done;
1222 }
1223
Rajeev Kumarce651e42013-10-21 18:57:15 -07001224 /*Initialize next AP meta info offset for next scan list*/
1225 nextApMetaInfoOffset = 0;
1226
Rajeev79dbe4c2013-10-05 11:03:42 +05301227 while (numApMetaInfo)
1228 {
1229 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1230 nextApMetaInfoOffset);
1231 if (NULL == pApMetaInfo)
1232 {
1233 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1234 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1235 isLastAp = TRUE;
1236 goto done;
1237 }
1238 /*calculate AP age*/
1239 pApMetaInfo->timestamp =
1240 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1241
1242 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001243 "%s: bssId "MAC_ADDRESS_STR
1244 " ch %d rssi %d timestamp %d", __func__,
1245 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1246 pApMetaInfo->ch, pApMetaInfo->rssi,
1247 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301248
1249 /*mark last AP in batch scan response*/
1250 if ((TRUE == pBatchScanRsp->isLastResult) &&
1251 (1 == numberScanList) && (1 == numApMetaInfo))
1252 {
1253 isLastAp = TRUE;
1254 }
1255
1256 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1257 /*store batch scan repsonse in hdd queue*/
1258 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1259 pScanList->scanId, isLastAp);
1260 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1261
1262 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1263 numApMetaInfo--;
1264 }
1265
Rajeev Kumarce651e42013-10-21 18:57:15 -07001266 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1267 + (sizeof(tSirBatchScanNetworkInfo)
1268 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301269 numberScanList--;
1270 }
1271
1272done:
1273
1274 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1275 requested from hdd_ioctl*/
1276 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1277 (TRUE == isLastAp))
1278 {
1279 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1280 complete(&pAdapter->hdd_get_batch_scan_req_var);
1281 }
1282
1283 return;
1284}/*End of hdd_batch_scan_result_ind_callback*/
1285
1286/**---------------------------------------------------------------------------
1287
1288 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1289 response as per batch scan FR request format by putting proper markers
1290
1291 \param - pDest pointer to destination buffer
1292 \param - cur_len current length
1293 \param - tot_len total remaining size which can be written to user space
1294 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1295 \param - pAdapter Pointer to HDD adapter
1296
1297 \return - ret no of characters written
1298
1299 --------------------------------------------------------------------------*/
1300static tANI_U32
1301hdd_format_batch_scan_rsp
1302(
1303 tANI_U8 *pDest,
1304 tANI_U32 cur_len,
1305 tANI_U32 tot_len,
1306 tHddBatchScanRsp *pApMetaInfo,
1307 hdd_adapter_t* pAdapter
1308)
1309{
1310 tANI_U32 ret = 0;
1311 tANI_U32 rem_len = 0;
1312 tANI_U8 temp_len = 0;
1313 tANI_U8 temp_total_len = 0;
1314 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1315 tANI_U8 *pTemp = temp;
1316
1317 /*Batch scan reponse needs to be returned to user space in
1318 following format:
1319 "scancount=X\n" where X is the number of scans in current batch
1320 batch
1321 "trunc\n" optional present if current scan truncated
1322 "bssid=XX:XX:XX:XX:XX:XX\n"
1323 "ssid=XXXX\n"
1324 "freq=X\n" frequency in Mhz
1325 "level=XX\n"
1326 "age=X\n" ms
1327 "dist=X\n" cm (-1 if not available)
1328 "errror=X\n" (-1if not available)
1329 "====\n" (end of ap marker)
1330 "####\n" (end of scan marker)
1331 "----\n" (end of results)*/
1332 /*send scan result in above format to user space based on
1333 available length*/
1334 /*The GET response may have more data than the driver can return in its
1335 buffer. In that case the buffer should be filled to the nearest complete
1336 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1337 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1338 The final buffer should end with "----\n"*/
1339
1340 /*sanity*/
1341 if (cur_len > tot_len)
1342 {
1343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1344 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1345 return 0;
1346 }
1347 else
1348 {
1349 rem_len = (tot_len - cur_len);
1350 }
1351
1352 /*end scan marker*/
1353 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1354 {
1355 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1356 pTemp += temp_len;
1357 temp_total_len += temp_len;
1358 }
1359
1360 /*bssid*/
1361 temp_len = snprintf(pTemp, sizeof(temp),
1362 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1363 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1364 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1365 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1366 pTemp += temp_len;
1367 temp_total_len += temp_len;
1368
1369 /*ssid*/
1370 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1371 pApMetaInfo->ApInfo.ssid);
1372 pTemp += temp_len;
1373 temp_total_len += temp_len;
1374
1375 /*freq*/
1376 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001377 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301378 pTemp += temp_len;
1379 temp_total_len += temp_len;
1380
1381 /*level*/
1382 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1383 pApMetaInfo->ApInfo.rssi);
1384 pTemp += temp_len;
1385 temp_total_len += temp_len;
1386
1387 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001388 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301389 pApMetaInfo->ApInfo.age);
1390 pTemp += temp_len;
1391 temp_total_len += temp_len;
1392
1393 /*dist*/
1394 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1395 pTemp += temp_len;
1396 temp_total_len += temp_len;
1397
1398 /*error*/
1399 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1400 pTemp += temp_len;
1401 temp_total_len += temp_len;
1402
1403 /*end AP marker*/
1404 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1405 pTemp += temp_len;
1406 temp_total_len += temp_len;
1407
1408 /*last AP in batch scan response*/
1409 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1410 {
1411 /*end scan marker*/
1412 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1413 pTemp += temp_len;
1414 temp_total_len += temp_len;
1415
1416 /*end batch scan result marker*/
1417 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1418 pTemp += temp_len;
1419 temp_total_len += temp_len;
1420 }
1421
1422 if (temp_total_len < rem_len)
1423 {
1424 ret = temp_total_len + 1;
1425 strlcpy(pDest, temp, ret);
1426 pAdapter->isTruncated = FALSE;
1427 }
1428 else
1429 {
1430 pAdapter->isTruncated = TRUE;
1431 if (rem_len >= strlen("%%%%"))
1432 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001433 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301434 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001435 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301436 {
1437 ret = 0;
1438 }
1439 }
1440
1441 return ret;
1442
1443}/*End of hdd_format_batch_scan_rsp*/
1444
1445/**---------------------------------------------------------------------------
1446
1447 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1448 buffer starting with head of hdd batch scan response queue
1449
1450 \param - pAdapter Pointer to HDD adapter
1451 \param - pDest Pointer to user data buffer
1452 \param - cur_len current offset in user buffer
1453 \param - rem_len remaining no of bytes in user buffer
1454
1455 \return - number of bytes written in user buffer
1456
1457 --------------------------------------------------------------------------*/
1458
1459tANI_U32 hdd_populate_user_batch_scan_rsp
1460(
1461 hdd_adapter_t* pAdapter,
1462 tANI_U8 *pDest,
1463 tANI_U32 cur_len,
1464 tANI_U32 rem_len
1465)
1466{
1467 tHddBatchScanRsp *pHead;
1468 tHddBatchScanRsp *pPrev;
1469 tANI_U32 len;
1470
Kiet Lam34947452014-01-21 23:23:40 -08001471 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301472 pAdapter->isTruncated = FALSE;
1473
1474 /*head of hdd batch scan response queue*/
1475 pHead = pAdapter->pBatchScanRsp;
1476 while (pHead)
1477 {
1478 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1479 pAdapter);
1480 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001481 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301482 cur_len += len;
1483 if(TRUE == pAdapter->isTruncated)
1484 {
1485 /*result is truncated return rest of scan rsp in next req*/
1486 cur_len = rem_len;
1487 break;
1488 }
1489 pPrev = pHead;
1490 pHead = pHead->pNext;
1491 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08001492 if (TRUE == pPrev->ApInfo.isLastAp)
1493 {
1494 pAdapter->prev_batch_id = 0;
1495 }
1496 else
1497 {
1498 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1499 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301500 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08001501 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05301502 }
1503
1504 return cur_len;
1505}/*End of hdd_populate_user_batch_scan_rsp*/
1506
1507/**---------------------------------------------------------------------------
1508
1509 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1510 scan response data from HDD queue to user space
1511 It does following in detail:
1512 a) if HDD has enough data in its queue then it 1st copies data to user
1513 space and then send get batch scan indication message to FW. In this
1514 case it does not wait on any event and batch scan response data will
1515 be populated in HDD response queue in MC thread context after receiving
1516 indication from FW
1517 b) else send get batch scan indication message to FW and wait on an event
1518 which will be set once HDD receives complete batch scan response from
1519 FW and then this function returns batch scan response to user space
1520
1521 \param - pAdapter Pointer to HDD adapter
1522 \param - pPrivData Pointer to priv_data
1523
1524 \return - 0 for success -EFAULT for failure
1525
1526 --------------------------------------------------------------------------*/
1527
1528int hdd_return_batch_scan_rsp_to_user
1529(
1530 hdd_adapter_t* pAdapter,
1531 hdd_priv_data_t *pPrivData,
1532 tANI_U8 *command
1533)
1534{
1535 tANI_U8 *pDest;
1536 tANI_U32 count = 0;
1537 tANI_U32 len = 0;
1538 tANI_U32 cur_len = 0;
1539 tANI_U32 rem_len = 0;
1540 eHalStatus halStatus;
1541 unsigned long rc;
1542 tSirTriggerBatchScanResultInd *pReq;
1543
1544 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1545 pReq->param = 0;/*batch scan client*/
1546 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1547 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1548
1549 cur_len = pPrivData->used_len;
1550 if (pPrivData->total_len > pPrivData->used_len)
1551 {
1552 rem_len = pPrivData->total_len - pPrivData->used_len;
1553 }
1554 else
1555 {
1556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1557 "%s: Invalid user data buffer total_len %d used_len %d",
1558 __func__, pPrivData->total_len, pPrivData->used_len);
1559 return -EFAULT;
1560 }
1561
1562 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1563 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1564 cur_len, rem_len);
1565 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1566
1567 /*enough scan result available in cache to return to user space or
1568 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001569 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301570 {
1571 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1572 halStatus = sme_TriggerBatchScanResultInd(
1573 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1574 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1575 pAdapter);
1576 if ( eHAL_STATUS_SUCCESS == halStatus )
1577 {
1578 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1579 {
1580 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1581 rc = wait_for_completion_timeout(
1582 &pAdapter->hdd_get_batch_scan_req_var,
1583 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1584 if (0 == rc)
1585 {
1586 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1587 "%s: Timeout waiting to fetch batch scan rsp from fw",
1588 __func__);
1589 return -EFAULT;
1590 }
1591 }
1592
1593 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001594 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301595 pDest += len;
1596 cur_len += len;
1597
1598 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1599 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1600 cur_len, rem_len);
1601 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1602
1603 count = 0;
1604 len = (len - pPrivData->used_len);
1605 pDest = (command + pPrivData->used_len);
1606 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001607 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301608 while(count < len)
1609 {
1610 printk("%c", *(pDest + count));
1611 count++;
1612 }
1613 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1614 "%s: copy %d data to user buffer", __func__, len);
1615 if (copy_to_user(pPrivData->buf, pDest, len))
1616 {
1617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1618 "%s: failed to copy data to user buffer", __func__);
1619 return -EFAULT;
1620 }
1621 }
1622 else
1623 {
1624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1625 "sme_GetBatchScanScan returned failure halStatus %d",
1626 halStatus);
1627 return -EINVAL;
1628 }
1629 }
1630 else
1631 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301632 count = 0;
1633 len = (len - pPrivData->used_len);
1634 pDest = (command + pPrivData->used_len);
1635 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001636 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301637 while(count < len)
1638 {
1639 printk("%c", *(pDest + count));
1640 count++;
1641 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001642 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1643 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301644 if (copy_to_user(pPrivData->buf, pDest, len))
1645 {
1646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1647 "%s: failed to copy data to user buffer", __func__);
1648 return -EFAULT;
1649 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301650 }
1651
1652 return 0;
1653} /*End of hdd_return_batch_scan_rsp_to_user*/
1654
Rajeev Kumar8b373292014-01-08 20:36:55 -08001655
1656/**---------------------------------------------------------------------------
1657
1658 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
1659 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
1660 WLS_BATCHING VERSION
1661 WLS_BATCHING SET
1662 WLS_BATCHING GET
1663 WLS_BATCHING STOP
1664
1665 \param - pAdapter Pointer to HDD adapter
1666 \param - pPrivdata Pointer to priv_data
1667 \param - command Pointer to command
1668
1669 \return - 0 for success -EFAULT for failure
1670
1671 --------------------------------------------------------------------------*/
1672
1673int hdd_handle_batch_scan_ioctl
1674(
1675 hdd_adapter_t *pAdapter,
1676 hdd_priv_data_t *pPrivdata,
1677 tANI_U8 *command
1678)
1679{
1680 int ret = 0;
1681
1682 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
1683 {
1684 char extra[32];
1685 tANI_U8 len = 0;
1686 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
1687
1688 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1689 {
1690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1691 "%s: Batch scan feature is not supported by FW", __func__);
1692 ret = -EINVAL;
1693 goto exit;
1694 }
1695
1696 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
1697 version);
1698 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1699 {
1700 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1701 "%s: failed to copy data to user buffer", __func__);
1702 ret = -EFAULT;
1703 goto exit;
1704 }
1705 ret = HDD_BATCH_SCAN_VERSION;
1706 }
1707 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
1708 {
1709 int status;
1710 tANI_U8 *value = (command + 16);
1711 eHalStatus halStatus;
1712 unsigned long rc;
1713 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
1714 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
1715
1716 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1717 {
1718 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1719 "%s: Batch scan feature is not supported by FW", __func__);
1720 ret = -EINVAL;
1721 goto exit;
1722 }
1723
1724 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
1725 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
1726 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
1727 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
1728 {
1729 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1730 "Received WLS_BATCHING SET command in invalid mode %d "
1731 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
1732 pAdapter->device_mode);
1733 ret = -EINVAL;
1734 goto exit;
1735 }
1736
1737 status = hdd_parse_set_batchscan_command(value, pReq);
1738 if (status)
1739 {
1740 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1741 "Invalid WLS_BATCHING SET command");
1742 ret = -EINVAL;
1743 goto exit;
1744 }
1745
1746
1747 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
1748 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1749 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
1750 pAdapter);
1751
1752 if ( eHAL_STATUS_SUCCESS == halStatus )
1753 {
1754 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1755 "sme_SetBatchScanReq returned success halStatus %d",
1756 halStatus);
1757 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
1758 {
1759 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
1760 rc = wait_for_completion_timeout(
1761 &pAdapter->hdd_set_batch_scan_req_var,
1762 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
1763 if (0 == rc)
1764 {
1765 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1766 "%s: Timeout waiting for set batch scan to complete",
1767 __func__);
1768 ret = -EINVAL;
1769 goto exit;
1770 }
1771 }
1772 if ( !pRsp->nScansToBatch )
1773 {
1774 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1775 "%s: Received set batch scan failure response from FW",
1776 __func__);
1777 ret = -EINVAL;
1778 goto exit;
1779 }
1780 /*As per the Batch Scan Framework API we should return the MIN of
1781 either MSCAN or the max # of scans firmware can cache*/
1782 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
1783
1784 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
1785
1786 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1787 "%s: request MSCAN %d response MSCAN %d ret %d",
1788 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
1789 }
1790 else
1791 {
1792 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1793 "sme_SetBatchScanReq returned failure halStatus %d",
1794 halStatus);
1795 ret = -EINVAL;
1796 goto exit;
1797 }
1798 }
1799 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
1800 {
1801 eHalStatus halStatus;
1802 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
1803 pInd->param = 0;
1804
1805 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1806 {
1807 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1808 "%s: Batch scan feature is not supported by FW", __func__);
1809 ret = -EINVAL;
1810 goto exit;
1811 }
1812
1813 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1814 {
1815 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1816 "Batch scan is not yet enabled batch scan state %d",
1817 pAdapter->batchScanState);
1818 ret = -EINVAL;
1819 goto exit;
1820 }
1821
1822 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
1823
1824 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
1825 pAdapter->sessionId);
1826 if ( eHAL_STATUS_SUCCESS == halStatus )
1827 {
1828 ret = 0;
1829 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1830 "sme_StopBatchScanInd returned success halStatus %d",
1831 halStatus);
1832 }
1833 else
1834 {
1835 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1836 "sme_StopBatchScanInd returned failure halStatus %d",
1837 halStatus);
1838 ret = -EINVAL;
1839 goto exit;
1840 }
1841 }
1842 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
1843 {
1844 tANI_U32 remain_len;
1845
1846 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1847 {
1848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1849 "%s: Batch scan feature is not supported by FW", __func__);
1850 ret = -EINVAL;
1851 goto exit;
1852 }
1853
1854 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1855 {
1856 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1857 "Batch scan is not yet enabled could not return results"
1858 "Batch Scan state %d",
1859 pAdapter->batchScanState);
1860 ret = -EINVAL;
1861 goto exit;
1862 }
1863
1864 pPrivdata->used_len = 16;
1865 remain_len = pPrivdata->total_len - pPrivdata->used_len;
1866 if (remain_len < pPrivdata->total_len)
1867 {
1868 /*Clear previous batch scan response data if any*/
1869 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
1870 }
1871 else
1872 {
1873 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1874 "Invalid total length from user space can't fetch batch"
1875 " scan response total_len %d used_len %d remain len %d",
1876 pPrivdata->total_len, pPrivdata->used_len, remain_len);
1877 ret = -EINVAL;
1878 goto exit;
1879 }
1880 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
1881 }
1882
1883exit:
1884
1885 return ret;
1886}
1887
1888
Rajeev79dbe4c2013-10-05 11:03:42 +05301889#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1890
Jeff Johnson295189b2012-06-20 16:38:30 -07001891int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1892{
1893 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1894 hdd_priv_data_t priv_data;
1895 tANI_U8 *command = NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301896 long ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001897
1898 if (NULL == pAdapter)
1899 {
1900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301901 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001902 ret = -ENODEV;
1903 goto exit;
1904 }
1905
Jeff Johnsone7245742012-09-05 17:12:55 -07001906 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001907 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1909 "%s: invalid data", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001910 ret = -EINVAL;
1911 goto exit;
1912 }
1913
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001914 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1915 {
1916 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1917 "%s:LOGP in Progress. Ignore!!!", __func__);
1918 ret = -EBUSY;
1919 goto exit;
1920 }
1921
Jeff Johnson295189b2012-06-20 16:38:30 -07001922 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1923 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301924 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1925 FL("failed to get data from user buffer"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001926 ret = -EFAULT;
1927 goto exit;
1928 }
1929
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08001930 if (priv_data.total_len <= 0 ||
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301931 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001932 {
1933 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1934 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1935 priv_data.total_len);
1936 ret = -EINVAL;
1937 goto exit;
1938 }
1939
1940 /* Allocate +1 for '\0' */
1941 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001942 if (!command)
1943 {
1944 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301945 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001946 ret = -ENOMEM;
1947 goto exit;
1948 }
1949
1950 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1951 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301952 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1953 FL("failed to get data from user buffer"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001954 ret = -EFAULT;
1955 goto exit;
1956 }
1957
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001958 /* Making sure the command is NUL-terminated */
1959 command[priv_data.total_len] = '\0';
1960
Jeff Johnson295189b2012-06-20 16:38:30 -07001961 if ((SIOCDEVPRIVATE + 1) == cmd)
1962 {
1963 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1964
1965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001966 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001967
1968 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1969 {
1970 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1971 sizeof(tSirMacAddr)))
1972 {
1973 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001974 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001975 ret = -EFAULT;
1976 }
1977 }
Amar Singhal0974e402013-02-12 14:27:46 -08001978 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001979 {
Amar Singhal0974e402013-02-12 14:27:46 -08001980 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001981
Jeff Johnson295189b2012-06-20 16:38:30 -07001982 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001983
1984 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001985 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001986 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001987 "%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 -07001988 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001989 ret = hdd_setBand_helper(dev, ptr);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301990 if(ret != 0)
1991 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1992 "%s: failed to set band ret=%ld",__func__, ret);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001993 }
Kiet Lamf040f472013-11-20 21:15:23 +05301994 else if(strncmp(command, "SETWMMPS", 8) == 0)
1995 {
1996 tANI_U8 *ptr = command;
1997 ret = hdd_wmmps_helper(pAdapter, ptr);
1998 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001999 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
2000 {
2001 char *country_code;
2002
2003 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002004
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002005 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002006 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002007#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05302008 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002009#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002010 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2011 (void *)(tSmeChangeCountryCallback)
2012 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05302013 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002014 if (eHAL_STATUS_SUCCESS == ret)
2015 {
2016 ret = wait_for_completion_interruptible_timeout(
2017 &pAdapter->change_country_code,
2018 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
2019 if (0 >= ret)
2020 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302021 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %ld",
2022 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002023 }
2024 }
2025 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002026 {
2027 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302028 "%s: SME Change Country code fail ret=%ld", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002029 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002030 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002031
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002032 }
2033 /*
2034 command should be a string having format
2035 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2036 */
Amar Singhal0974e402013-02-12 14:27:46 -08002037 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002038 {
Amar Singhal0974e402013-02-12 14:27:46 -08002039 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002040
2041 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002042 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002043
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002044 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002045 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002046 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2047 {
2048 int suspend = 0;
2049 tANI_U8 *ptr = (tANI_U8*)command + 15;
2050
2051 suspend = *ptr - '0';
2052 hdd_set_wlan_suspend_mode(suspend);
2053 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002054#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2055 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2056 {
2057 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002058 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002059 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2060 eHalStatus status = eHAL_STATUS_SUCCESS;
2061
2062 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2063 value = value + 15;
2064
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002065 /* Convert the value from ascii to integer */
2066 ret = kstrtos8(value, 10, &rssi);
2067 if (ret < 0)
2068 {
2069 /* If the input value is greater than max value of datatype, then also
2070 kstrtou8 fails */
2071 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2072 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002073 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002074 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2075 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2076 ret = -EINVAL;
2077 goto exit;
2078 }
2079
Srinivas Girigowdade697412013-02-14 16:31:48 -08002080 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002081
Srinivas Girigowdade697412013-02-14 16:31:48 -08002082 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2083 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2084 {
2085 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2086 "Neighbor lookup threshold value %d is out of range"
2087 " (Min: %d Max: %d)", lookUpThreshold,
2088 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2089 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2090 ret = -EINVAL;
2091 goto exit;
2092 }
2093
2094 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2095 "%s: Received Command to Set Roam trigger"
2096 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2097
2098 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2099 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2100 if (eHAL_STATUS_SUCCESS != status)
2101 {
2102 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2103 "%s: Failed to set roam trigger, try again", __func__);
2104 ret = -EPERM;
2105 goto exit;
2106 }
2107
2108 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
2109 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2110 }
2111 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2112 {
2113 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2114 int rssi = (-1) * lookUpThreshold;
2115 char extra[32];
2116 tANI_U8 len = 0;
2117
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002118 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002119 if (copy_to_user(priv_data.buf, &extra, len + 1))
2120 {
2121 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2122 "%s: failed to copy data to user buffer", __func__);
2123 ret = -EFAULT;
2124 goto exit;
2125 }
2126 }
2127 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2128 {
2129 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002130 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002131 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002132
Srinivas Girigowdade697412013-02-14 16:31:48 -08002133 /* input refresh period is in terms of seconds */
2134 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2135 value = value + 18;
2136 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002137 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002138 if (ret < 0)
2139 {
2140 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002141 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002142 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002143 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002144 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002145 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2146 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002147 ret = -EINVAL;
2148 goto exit;
2149 }
2150
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002151 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2152 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002153 {
2154 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002155 "Roam scan period value %d is out of range"
2156 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002157 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2158 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002159 ret = -EINVAL;
2160 goto exit;
2161 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002162 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002163
2164 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2165 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002166 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002167
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002168 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2169 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002170 }
2171 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2172 {
2173 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2174 char extra[32];
2175 tANI_U8 len = 0;
2176
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002177 len = scnprintf(extra, sizeof(extra), "%s %d",
2178 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002179 /* Returned value is in units of seconds */
2180 if (copy_to_user(priv_data.buf, &extra, len + 1))
2181 {
2182 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2183 "%s: failed to copy data to user buffer", __func__);
2184 ret = -EFAULT;
2185 goto exit;
2186 }
2187 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002188 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2189 {
2190 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002191 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002192 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002193
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002194 /* input refresh period is in terms of seconds */
2195 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2196 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002197
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002198 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002199 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002200 if (ret < 0)
2201 {
2202 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002203 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002204 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002205 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002206 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002207 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2208 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2209 ret = -EINVAL;
2210 goto exit;
2211 }
2212
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002213 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2214 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2215 {
2216 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2217 "Neighbor scan results refresh period value %d is out of range"
2218 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2219 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2220 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2221 ret = -EINVAL;
2222 goto exit;
2223 }
2224 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2225
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002226 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2227 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002228 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002229
2230 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2231 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2232 }
2233 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2234 {
2235 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2236 char extra[32];
2237 tANI_U8 len = 0;
2238
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002239 len = scnprintf(extra, sizeof(extra), "%s %d",
2240 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002241 /* Returned value is in units of seconds */
2242 if (copy_to_user(priv_data.buf, &extra, len + 1))
2243 {
2244 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2245 "%s: failed to copy data to user buffer", __func__);
2246 ret = -EFAULT;
2247 goto exit;
2248 }
2249 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002250#ifdef FEATURE_WLAN_LFR
2251 /* SETROAMMODE */
2252 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2253 {
2254 tANI_U8 *value = command;
2255 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2256
2257 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2258 value = value + SIZE_OF_SETROAMMODE + 1;
2259
2260 /* Convert the value from ascii to integer */
2261 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2262 if (ret < 0)
2263 {
2264 /* If the input value is greater than max value of datatype, then also
2265 kstrtou8 fails */
2266 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2267 "%s: kstrtou8 failed range [%d - %d]", __func__,
2268 CFG_LFR_FEATURE_ENABLED_MIN,
2269 CFG_LFR_FEATURE_ENABLED_MAX);
2270 ret = -EINVAL;
2271 goto exit;
2272 }
2273 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2274 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2275 {
2276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2277 "Roam Mode value %d is out of range"
2278 " (Min: %d Max: %d)", roamMode,
2279 CFG_LFR_FEATURE_ENABLED_MIN,
2280 CFG_LFR_FEATURE_ENABLED_MAX);
2281 ret = -EINVAL;
2282 goto exit;
2283 }
2284
2285 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2286 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2287 /*
2288 * Note that
2289 * SETROAMMODE 0 is to enable LFR while
2290 * SETROAMMODE 1 is to disable LFR, but
2291 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2292 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2293 */
2294 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2295 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2296 else
2297 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2298
2299 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2300 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2301 }
2302 /* GETROAMMODE */
2303 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2304 {
2305 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2306 char extra[32];
2307 tANI_U8 len = 0;
2308
2309 /*
2310 * roamMode value shall be inverted because the sementics is different.
2311 */
2312 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2313 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2314 else
2315 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2316
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002317 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002318 if (copy_to_user(priv_data.buf, &extra, len + 1))
2319 {
2320 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2321 "%s: failed to copy data to user buffer", __func__);
2322 ret = -EFAULT;
2323 goto exit;
2324 }
2325 }
2326#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002327#endif
2328#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2329 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2330 {
2331 tANI_U8 *value = command;
2332 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2333
2334 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2335 value = value + 13;
2336 /* Convert the value from ascii to integer */
2337 ret = kstrtou8(value, 10, &roamRssiDiff);
2338 if (ret < 0)
2339 {
2340 /* If the input value is greater than max value of datatype, then also
2341 kstrtou8 fails */
2342 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2343 "%s: kstrtou8 failed range [%d - %d]", __func__,
2344 CFG_ROAM_RSSI_DIFF_MIN,
2345 CFG_ROAM_RSSI_DIFF_MAX);
2346 ret = -EINVAL;
2347 goto exit;
2348 }
2349
2350 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2351 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2352 {
2353 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2354 "Roam rssi diff value %d is out of range"
2355 " (Min: %d Max: %d)", roamRssiDiff,
2356 CFG_ROAM_RSSI_DIFF_MIN,
2357 CFG_ROAM_RSSI_DIFF_MAX);
2358 ret = -EINVAL;
2359 goto exit;
2360 }
2361
2362 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2363 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2364
2365 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2366 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2367 }
2368 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2369 {
2370 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2371 char extra[32];
2372 tANI_U8 len = 0;
2373
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002374 len = scnprintf(extra, sizeof(extra), "%s %d",
2375 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002376 if (copy_to_user(priv_data.buf, &extra, len + 1))
2377 {
2378 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2379 "%s: failed to copy data to user buffer", __func__);
2380 ret = -EFAULT;
2381 goto exit;
2382 }
2383 }
2384#endif
2385#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2386 else if (strncmp(command, "GETBAND", 7) == 0)
2387 {
2388 int band = -1;
2389 char extra[32];
2390 tANI_U8 len = 0;
2391 hdd_getBand_helper(pHddCtx, &band);
2392
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002393 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002394 if (copy_to_user(priv_data.buf, &extra, len + 1))
2395 {
2396 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2397 "%s: failed to copy data to user buffer", __func__);
2398 ret = -EFAULT;
2399 goto exit;
2400 }
2401 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002402 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2403 {
2404 tANI_U8 *value = command;
2405 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2406 tANI_U8 numChannels = 0;
2407 eHalStatus status = eHAL_STATUS_SUCCESS;
2408
2409 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2410 if (eHAL_STATUS_SUCCESS != status)
2411 {
2412 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2413 "%s: Failed to parse channel list information", __func__);
2414 ret = -EINVAL;
2415 goto exit;
2416 }
2417
2418 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2419 {
2420 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2421 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2422 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2423 ret = -EINVAL;
2424 goto exit;
2425 }
2426 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2427 numChannels);
2428 if (eHAL_STATUS_SUCCESS != status)
2429 {
2430 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2431 "%s: Failed to update channel list information", __func__);
2432 ret = -EINVAL;
2433 goto exit;
2434 }
2435 }
2436 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2437 {
2438 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2439 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002440 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002441 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002442 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002443
2444 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2445 ChannelList, &numChannels ))
2446 {
2447 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2448 "%s: failed to get roam scan channel list", __func__);
2449 ret = -EFAULT;
2450 goto exit;
2451 }
2452 /* output channel list is of the format
2453 [Number of roam scan channels][Channel1][Channel2]... */
2454 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002455 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002456 for (j = 0; (j < numChannels); j++)
2457 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002458 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2459 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002460 }
2461
2462 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 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002470 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2471 {
2472 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2473 char extra[32];
2474 tANI_U8 len = 0;
2475
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002476 /* Check if the features OKC/CCX/11R are supported simultaneously,
2477 then this operation is not permitted (return FAILURE) */
2478 if (ccxMode &&
2479 hdd_is_okc_mode_enabled(pHddCtx) &&
2480 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2481 {
2482 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2483 "%s: OKC/CCX/11R are supported simultaneously"
2484 " hence this operation is not permitted!", __func__);
2485 ret = -EPERM;
2486 goto exit;
2487 }
2488
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002489 len = scnprintf(extra, sizeof(extra), "%s %d",
2490 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002491 if (copy_to_user(priv_data.buf, &extra, len + 1))
2492 {
2493 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2494 "%s: failed to copy data to user buffer", __func__);
2495 ret = -EFAULT;
2496 goto exit;
2497 }
2498 }
2499 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2500 {
2501 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2502 char extra[32];
2503 tANI_U8 len = 0;
2504
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002505 /* Check if the features OKC/CCX/11R are supported simultaneously,
2506 then this operation is not permitted (return FAILURE) */
2507 if (okcMode &&
2508 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2509 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2510 {
2511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2512 "%s: OKC/CCX/11R are supported simultaneously"
2513 " hence this operation is not permitted!", __func__);
2514 ret = -EPERM;
2515 goto exit;
2516 }
2517
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002518 len = scnprintf(extra, sizeof(extra), "%s %d",
2519 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002520 if (copy_to_user(priv_data.buf, &extra, len + 1))
2521 {
2522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2523 "%s: failed to copy data to user buffer", __func__);
2524 ret = -EFAULT;
2525 goto exit;
2526 }
2527 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002528 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002529 {
2530 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2531 char extra[32];
2532 tANI_U8 len = 0;
2533
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002534 len = scnprintf(extra, sizeof(extra), "%s %d",
2535 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002536 if (copy_to_user(priv_data.buf, &extra, len + 1))
2537 {
2538 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2539 "%s: failed to copy data to user buffer", __func__);
2540 ret = -EFAULT;
2541 goto exit;
2542 }
2543 }
2544 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2545 {
2546 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2547 char extra[32];
2548 tANI_U8 len = 0;
2549
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002550 len = scnprintf(extra, sizeof(extra), "%s %d",
2551 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002552 if (copy_to_user(priv_data.buf, &extra, len + 1))
2553 {
2554 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2555 "%s: failed to copy data to user buffer", __func__);
2556 ret = -EFAULT;
2557 goto exit;
2558 }
2559 }
2560 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2561 {
2562 tANI_U8 *value = command;
2563 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2564
2565 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2566 value = value + 26;
2567 /* Convert the value from ascii to integer */
2568 ret = kstrtou8(value, 10, &minTime);
2569 if (ret < 0)
2570 {
2571 /* If the input value is greater than max value of datatype, then also
2572 kstrtou8 fails */
2573 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2574 "%s: kstrtou8 failed range [%d - %d]", __func__,
2575 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2576 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2577 ret = -EINVAL;
2578 goto exit;
2579 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002580 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2581 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2582 {
2583 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2584 "scan min channel time value %d is out of range"
2585 " (Min: %d Max: %d)", minTime,
2586 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2587 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2588 ret = -EINVAL;
2589 goto exit;
2590 }
2591
2592 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2593 "%s: Received Command to change channel min time = %d", __func__, minTime);
2594
2595 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2596 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2597 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002598 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2599 {
2600 tANI_U8 *value = command;
2601 tANI_U8 channel = 0;
2602 tANI_U8 dwellTime = 0;
2603 tANI_U8 bufLen = 0;
2604 tANI_U8 *buf = NULL;
2605 tSirMacAddr targetApBssid;
2606 eHalStatus status = eHAL_STATUS_SUCCESS;
2607 struct ieee80211_channel chan;
2608 tANI_U8 finalLen = 0;
2609 tANI_U8 *finalBuf = NULL;
2610 tANI_U8 temp = 0;
2611 u64 cookie;
2612 hdd_station_ctx_t *pHddStaCtx = NULL;
2613 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2614
2615 /* if not associated, no need to send action frame */
2616 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2617 {
2618 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2619 ret = -EINVAL;
2620 goto exit;
2621 }
2622
2623 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2624 &dwellTime, &buf, &bufLen);
2625 if (eHAL_STATUS_SUCCESS != status)
2626 {
2627 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2628 "%s: Failed to parse send action frame data", __func__);
2629 ret = -EINVAL;
2630 goto exit;
2631 }
2632
2633 /* if the target bssid is different from currently associated AP,
2634 then no need to send action frame */
2635 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2636 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2637 {
2638 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2639 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002640 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002641 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002642 goto exit;
2643 }
2644
2645 /* if the channel number is different from operating channel then
2646 no need to send action frame */
2647 if (channel != pHddStaCtx->conn_info.operationChannel)
2648 {
2649 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2650 "%s: channel(%d) is different from operating channel(%d)",
2651 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2652 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002653 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002654 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002655 goto exit;
2656 }
2657 chan.center_freq = sme_ChnToFreq(channel);
2658
2659 finalLen = bufLen + 24;
2660 finalBuf = vos_mem_malloc(finalLen);
2661 if (NULL == finalBuf)
2662 {
2663 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2664 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002665 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002666 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002667 goto exit;
2668 }
2669 vos_mem_zero(finalBuf, finalLen);
2670
2671 /* Fill subtype */
2672 temp = SIR_MAC_MGMT_ACTION << 4;
2673 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2674
2675 /* Fill type */
2676 temp = SIR_MAC_MGMT_FRAME;
2677 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2678
2679 /* Fill destination address (bssid of the AP) */
2680 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2681
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002682 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002683 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2684
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002685 /* Fill BSSID (AP mac address) */
2686 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002687
2688 /* Fill received buffer from 24th address */
2689 vos_mem_copy(finalBuf + 24, buf, bufLen);
2690
Jeff Johnson11c33152013-04-16 17:52:40 -07002691 /* done with the parsed buffer */
2692 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002693 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002694
Yue Maf49ba872013-08-19 12:04:25 -07002695 wlan_hdd_action( NULL,
2696#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2697 &(pAdapter->wdev),
2698#else
2699 dev,
2700#endif
2701 &chan, 0,
2702#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2703 NL80211_CHAN_HT20, 1,
2704#endif
2705 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002706 1, &cookie );
2707 vos_mem_free(finalBuf);
2708 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002709 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2710 {
2711 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2712 char extra[32];
2713 tANI_U8 len = 0;
2714
2715 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002716 len = scnprintf(extra, sizeof(extra), "%s %d",
2717 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002718 if (copy_to_user(priv_data.buf, &extra, len + 1))
2719 {
2720 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2721 "%s: failed to copy data to user buffer", __func__);
2722 ret = -EFAULT;
2723 goto exit;
2724 }
2725 }
2726 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2727 {
2728 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002729 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002730
2731 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2732 value = value + 19;
2733 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002734 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002735 if (ret < 0)
2736 {
2737 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002738 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002739 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002740 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002741 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2742 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2743 ret = -EINVAL;
2744 goto exit;
2745 }
2746
2747 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2748 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2749 {
2750 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2751 "lfr mode value %d is out of range"
2752 " (Min: %d Max: %d)", maxTime,
2753 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2754 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2755 ret = -EINVAL;
2756 goto exit;
2757 }
2758
2759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2760 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2761
2762 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
2763 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2764 }
2765 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2766 {
2767 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2768 char extra[32];
2769 tANI_U8 len = 0;
2770
2771 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002772 len = scnprintf(extra, sizeof(extra), "%s %d",
2773 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002774 if (copy_to_user(priv_data.buf, &extra, len + 1))
2775 {
2776 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2777 "%s: failed to copy data to user buffer", __func__);
2778 ret = -EFAULT;
2779 goto exit;
2780 }
2781 }
2782 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2783 {
2784 tANI_U8 *value = command;
2785 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2786
2787 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2788 value = value + 16;
2789 /* Convert the value from ascii to integer */
2790 ret = kstrtou16(value, 10, &val);
2791 if (ret < 0)
2792 {
2793 /* If the input value is greater than max value of datatype, then also
2794 kstrtou16 fails */
2795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2796 "%s: kstrtou16 failed range [%d - %d]", __func__,
2797 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2798 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2799 ret = -EINVAL;
2800 goto exit;
2801 }
2802
2803 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2804 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2805 {
2806 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2807 "scan home time value %d is out of range"
2808 " (Min: %d Max: %d)", val,
2809 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2810 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2811 ret = -EINVAL;
2812 goto exit;
2813 }
2814
2815 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2816 "%s: Received Command to change scan home time = %d", __func__, val);
2817
2818 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2819 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2820 }
2821 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2822 {
2823 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2824 char extra[32];
2825 tANI_U8 len = 0;
2826
2827 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002828 len = scnprintf(extra, sizeof(extra), "%s %d",
2829 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002830 if (copy_to_user(priv_data.buf, &extra, len + 1))
2831 {
2832 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2833 "%s: failed to copy data to user buffer", __func__);
2834 ret = -EFAULT;
2835 goto exit;
2836 }
2837 }
2838 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2839 {
2840 tANI_U8 *value = command;
2841 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2842
2843 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2844 value = value + 17;
2845 /* Convert the value from ascii to integer */
2846 ret = kstrtou8(value, 10, &val);
2847 if (ret < 0)
2848 {
2849 /* If the input value is greater than max value of datatype, then also
2850 kstrtou8 fails */
2851 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2852 "%s: kstrtou8 failed range [%d - %d]", __func__,
2853 CFG_ROAM_INTRA_BAND_MIN,
2854 CFG_ROAM_INTRA_BAND_MAX);
2855 ret = -EINVAL;
2856 goto exit;
2857 }
2858
2859 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2860 (val > CFG_ROAM_INTRA_BAND_MAX))
2861 {
2862 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2863 "intra band mode value %d is out of range"
2864 " (Min: %d Max: %d)", val,
2865 CFG_ROAM_INTRA_BAND_MIN,
2866 CFG_ROAM_INTRA_BAND_MAX);
2867 ret = -EINVAL;
2868 goto exit;
2869 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2871 "%s: Received Command to change intra band = %d", __func__, val);
2872
2873 pHddCtx->cfg_ini->nRoamIntraBand = val;
2874 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2875 }
2876 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2877 {
2878 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2879 char extra[32];
2880 tANI_U8 len = 0;
2881
2882 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002883 len = scnprintf(extra, sizeof(extra), "%s %d",
2884 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002885 if (copy_to_user(priv_data.buf, &extra, len + 1))
2886 {
2887 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2888 "%s: failed to copy data to user buffer", __func__);
2889 ret = -EFAULT;
2890 goto exit;
2891 }
2892 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002893 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2894 {
2895 tANI_U8 *value = command;
2896 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2897
2898 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2899 value = value + 15;
2900 /* Convert the value from ascii to integer */
2901 ret = kstrtou8(value, 10, &nProbes);
2902 if (ret < 0)
2903 {
2904 /* If the input value is greater than max value of datatype, then also
2905 kstrtou8 fails */
2906 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2907 "%s: kstrtou8 failed range [%d - %d]", __func__,
2908 CFG_ROAM_SCAN_N_PROBES_MIN,
2909 CFG_ROAM_SCAN_N_PROBES_MAX);
2910 ret = -EINVAL;
2911 goto exit;
2912 }
2913
2914 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2915 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2916 {
2917 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2918 "NProbes value %d is out of range"
2919 " (Min: %d Max: %d)", nProbes,
2920 CFG_ROAM_SCAN_N_PROBES_MIN,
2921 CFG_ROAM_SCAN_N_PROBES_MAX);
2922 ret = -EINVAL;
2923 goto exit;
2924 }
2925
2926 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2927 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2928
2929 pHddCtx->cfg_ini->nProbes = nProbes;
2930 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2931 }
2932 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2933 {
2934 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2935 char extra[32];
2936 tANI_U8 len = 0;
2937
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002938 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002939 if (copy_to_user(priv_data.buf, &extra, len + 1))
2940 {
2941 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2942 "%s: failed to copy data to user buffer", __func__);
2943 ret = -EFAULT;
2944 goto exit;
2945 }
2946 }
2947 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2948 {
2949 tANI_U8 *value = command;
2950 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
2951
2952 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2953 /* input value is in units of msec */
2954 value = value + 20;
2955 /* Convert the value from ascii to integer */
2956 ret = kstrtou16(value, 10, &homeAwayTime);
2957 if (ret < 0)
2958 {
2959 /* If the input value is greater than max value of datatype, then also
2960 kstrtou8 fails */
2961 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2962 "%s: kstrtou8 failed range [%d - %d]", __func__,
2963 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2964 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2965 ret = -EINVAL;
2966 goto exit;
2967 }
2968
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002969 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2970 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2971 {
2972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2973 "homeAwayTime value %d is out of range"
2974 " (Min: %d Max: %d)", homeAwayTime,
2975 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2976 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2977 ret = -EINVAL;
2978 goto exit;
2979 }
2980
2981 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2982 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002983 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2984 {
2985 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2986 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2987 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002988 }
2989 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2990 {
2991 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2992 char extra[32];
2993 tANI_U8 len = 0;
2994
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002995 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002996 if (copy_to_user(priv_data.buf, &extra, len + 1))
2997 {
2998 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2999 "%s: failed to copy data to user buffer", __func__);
3000 ret = -EFAULT;
3001 goto exit;
3002 }
3003 }
3004 else if (strncmp(command, "REASSOC", 7) == 0)
3005 {
3006 tANI_U8 *value = command;
3007 tANI_U8 channel = 0;
3008 tSirMacAddr targetApBssid;
3009 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003010#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3011 tCsrHandoffRequest handoffInfo;
3012#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003013 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003014 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3015
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003016 /* if not associated, no need to proceed with reassoc */
3017 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3018 {
3019 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3020 ret = -EINVAL;
3021 goto exit;
3022 }
3023
3024 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
3025 if (eHAL_STATUS_SUCCESS != status)
3026 {
3027 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3028 "%s: Failed to parse reassoc command data", __func__);
3029 ret = -EINVAL;
3030 goto exit;
3031 }
3032
3033 /* if the target bssid is same as currently associated AP,
3034 then no need to proceed with reassoc */
3035 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3036 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3037 {
3038 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3039 ret = -EINVAL;
3040 goto exit;
3041 }
3042
3043 /* Check channel number is a valid channel number */
3044 if(VOS_STATUS_SUCCESS !=
3045 wlan_hdd_validate_operation_channel(pAdapter, channel))
3046 {
3047 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003048 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003049 return -EINVAL;
3050 }
3051
3052 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003053#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3054 handoffInfo.channel = channel;
3055 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3056 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3057#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003058 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003059 else if (strncmp(command, "SETWESMODE", 10) == 0)
3060 {
3061 tANI_U8 *value = command;
3062 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3063
3064 /* Move pointer to ahead of SETWESMODE<delimiter> */
3065 value = value + 11;
3066 /* Convert the value from ascii to integer */
3067 ret = kstrtou8(value, 10, &wesMode);
3068 if (ret < 0)
3069 {
3070 /* If the input value is greater than max value of datatype, then also
3071 kstrtou8 fails */
3072 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3073 "%s: kstrtou8 failed range [%d - %d]", __func__,
3074 CFG_ENABLE_WES_MODE_NAME_MIN,
3075 CFG_ENABLE_WES_MODE_NAME_MAX);
3076 ret = -EINVAL;
3077 goto exit;
3078 }
3079
3080 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3081 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3082 {
3083 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3084 "WES Mode value %d is out of range"
3085 " (Min: %d Max: %d)", wesMode,
3086 CFG_ENABLE_WES_MODE_NAME_MIN,
3087 CFG_ENABLE_WES_MODE_NAME_MAX);
3088 ret = -EINVAL;
3089 goto exit;
3090 }
3091 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3092 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3093
3094 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3095 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3096 }
3097 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3098 {
3099 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3100 char extra[32];
3101 tANI_U8 len = 0;
3102
Arif Hussain826d9412013-11-12 16:44:54 -08003103 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003104 if (copy_to_user(priv_data.buf, &extra, len + 1))
3105 {
3106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3107 "%s: failed to copy data to user buffer", __func__);
3108 ret = -EFAULT;
3109 goto exit;
3110 }
3111 }
3112#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003113#ifdef FEATURE_WLAN_LFR
3114 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3115 {
3116 tANI_U8 *value = command;
3117 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3118
3119 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3120 value = value + 12;
3121 /* Convert the value from ascii to integer */
3122 ret = kstrtou8(value, 10, &lfrMode);
3123 if (ret < 0)
3124 {
3125 /* If the input value is greater than max value of datatype, then also
3126 kstrtou8 fails */
3127 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3128 "%s: kstrtou8 failed range [%d - %d]", __func__,
3129 CFG_LFR_FEATURE_ENABLED_MIN,
3130 CFG_LFR_FEATURE_ENABLED_MAX);
3131 ret = -EINVAL;
3132 goto exit;
3133 }
3134
3135 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3136 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3137 {
3138 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3139 "lfr mode value %d is out of range"
3140 " (Min: %d Max: %d)", lfrMode,
3141 CFG_LFR_FEATURE_ENABLED_MIN,
3142 CFG_LFR_FEATURE_ENABLED_MAX);
3143 ret = -EINVAL;
3144 goto exit;
3145 }
3146
3147 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3148 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3149
3150 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3151 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3152 }
3153#endif
3154#ifdef WLAN_FEATURE_VOWIFI_11R
3155 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3156 {
3157 tANI_U8 *value = command;
3158 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3159
3160 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3161 value = value + 18;
3162 /* Convert the value from ascii to integer */
3163 ret = kstrtou8(value, 10, &ft);
3164 if (ret < 0)
3165 {
3166 /* If the input value is greater than max value of datatype, then also
3167 kstrtou8 fails */
3168 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3169 "%s: kstrtou8 failed range [%d - %d]", __func__,
3170 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3171 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3172 ret = -EINVAL;
3173 goto exit;
3174 }
3175
3176 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3177 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3178 {
3179 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3180 "ft mode value %d is out of range"
3181 " (Min: %d Max: %d)", ft,
3182 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3183 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3184 ret = -EINVAL;
3185 goto exit;
3186 }
3187
3188 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3189 "%s: Received Command to change ft mode = %d", __func__, ft);
3190
3191 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3192 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3193 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303194
3195 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3196 {
3197 tANI_U8 *value = command;
3198 tSirMacAddr targetApBssid;
3199 tANI_U8 trigger = 0;
3200 eHalStatus status = eHAL_STATUS_SUCCESS;
3201 hdd_station_ctx_t *pHddStaCtx = NULL;
3202 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3203
3204 /* if not associated, no need to proceed with reassoc */
3205 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3206 {
3207 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3208 ret = -EINVAL;
3209 goto exit;
3210 }
3211
3212 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
3213 if (eHAL_STATUS_SUCCESS != status)
3214 {
3215 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3216 "%s: Failed to parse reassoc command data", __func__);
3217 ret = -EINVAL;
3218 goto exit;
3219 }
3220
3221 /* if the target bssid is same as currently associated AP,
3222 then no need to proceed with reassoc */
3223 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3224 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3225 {
3226 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3227 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3228 __func__);
3229 ret = -EINVAL;
3230 goto exit;
3231 }
3232
3233 /* Proceed with scan/roam */
3234 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3235 &targetApBssid[0],
3236 (tSmeFastRoamTrigger)(trigger));
3237 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003238#endif
3239#ifdef FEATURE_WLAN_CCX
3240 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3241 {
3242 tANI_U8 *value = command;
3243 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
3244
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003245 /* Check if the features OKC/CCX/11R are supported simultaneously,
3246 then this operation is not permitted (return FAILURE) */
3247 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3248 hdd_is_okc_mode_enabled(pHddCtx) &&
3249 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3250 {
3251 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3252 "%s: OKC/CCX/11R are supported simultaneously"
3253 " hence this operation is not permitted!", __func__);
3254 ret = -EPERM;
3255 goto exit;
3256 }
3257
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003258 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3259 value = value + 11;
3260 /* Convert the value from ascii to integer */
3261 ret = kstrtou8(value, 10, &ccxMode);
3262 if (ret < 0)
3263 {
3264 /* If the input value is greater than max value of datatype, then also
3265 kstrtou8 fails */
3266 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3267 "%s: kstrtou8 failed range [%d - %d]", __func__,
3268 CFG_CCX_FEATURE_ENABLED_MIN,
3269 CFG_CCX_FEATURE_ENABLED_MAX);
3270 ret = -EINVAL;
3271 goto exit;
3272 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003273 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
3274 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
3275 {
3276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3277 "Ccx mode value %d is out of range"
3278 " (Min: %d Max: %d)", ccxMode,
3279 CFG_CCX_FEATURE_ENABLED_MIN,
3280 CFG_CCX_FEATURE_ENABLED_MAX);
3281 ret = -EINVAL;
3282 goto exit;
3283 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003284 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3285 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
3286
3287 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
3288 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
3289 }
3290#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003291 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3292 {
3293 tANI_U8 *value = command;
3294 tANI_BOOLEAN roamScanControl = 0;
3295
3296 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3297 value = value + 19;
3298 /* Convert the value from ascii to integer */
3299 ret = kstrtou8(value, 10, &roamScanControl);
3300 if (ret < 0)
3301 {
3302 /* If the input value is greater than max value of datatype, then also
3303 kstrtou8 fails */
3304 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3305 "%s: kstrtou8 failed ", __func__);
3306 ret = -EINVAL;
3307 goto exit;
3308 }
3309
3310 if (0 != roamScanControl)
3311 {
3312 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3313 "roam scan control invalid value = %d",
3314 roamScanControl);
3315 ret = -EINVAL;
3316 goto exit;
3317 }
3318 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3319 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3320
3321 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3322 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003323#ifdef FEATURE_WLAN_OKC
3324 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3325 {
3326 tANI_U8 *value = command;
3327 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3328
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003329 /* Check if the features OKC/CCX/11R are supported simultaneously,
3330 then this operation is not permitted (return FAILURE) */
3331 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3332 hdd_is_okc_mode_enabled(pHddCtx) &&
3333 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3334 {
3335 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3336 "%s: OKC/CCX/11R are supported simultaneously"
3337 " hence this operation is not permitted!", __func__);
3338 ret = -EPERM;
3339 goto exit;
3340 }
3341
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003342 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3343 value = value + 11;
3344 /* Convert the value from ascii to integer */
3345 ret = kstrtou8(value, 10, &okcMode);
3346 if (ret < 0)
3347 {
3348 /* If the input value is greater than max value of datatype, then also
3349 kstrtou8 fails */
3350 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3351 "%s: kstrtou8 failed range [%d - %d]", __func__,
3352 CFG_OKC_FEATURE_ENABLED_MIN,
3353 CFG_OKC_FEATURE_ENABLED_MAX);
3354 ret = -EINVAL;
3355 goto exit;
3356 }
3357
3358 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3359 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3360 {
3361 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3362 "Okc mode value %d is out of range"
3363 " (Min: %d Max: %d)", okcMode,
3364 CFG_OKC_FEATURE_ENABLED_MIN,
3365 CFG_OKC_FEATURE_ENABLED_MAX);
3366 ret = -EINVAL;
3367 goto exit;
3368 }
3369
3370 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3371 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3372
3373 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3374 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003375#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003376 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3377 {
3378 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3379 char extra[32];
3380 tANI_U8 len = 0;
3381
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003382 len = scnprintf(extra, sizeof(extra), "%s %d",
3383 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003384 if (copy_to_user(priv_data.buf, &extra, len + 1))
3385 {
3386 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3387 "%s: failed to copy data to user buffer", __func__);
3388 ret = -EFAULT;
3389 goto exit;
3390 }
3391 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303392#ifdef WLAN_FEATURE_PACKET_FILTERING
3393 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3394 {
3395 tANI_U8 filterType = 0;
3396 tANI_U8 *value = command;
3397
3398 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3399 value = value + 22;
3400
3401 /* Convert the value from ascii to integer */
3402 ret = kstrtou8(value, 10, &filterType);
3403 if (ret < 0)
3404 {
3405 /* If the input value is greater than max value of datatype,
3406 * then also kstrtou8 fails
3407 */
3408 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3409 "%s: kstrtou8 failed range ", __func__);
3410 ret = -EINVAL;
3411 goto exit;
3412 }
3413
3414 if (filterType != 0 && filterType != 1)
3415 {
3416 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3417 "%s: Accepted Values are 0 and 1 ", __func__);
3418 ret = -EINVAL;
3419 goto exit;
3420 }
3421 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3422 pAdapter->sessionId);
3423 }
3424#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303425 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3426 {
3427 char *dhcpPhase;
c_hpothu9b781ba2013-12-30 20:57:45 +05303428 dhcpPhase = command + 11;
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303429 if ('1' == *dhcpPhase)
3430 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303431 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3432 FL("BTCOEXMODE %d"), *dhcpPhase);
3433
3434 pHddCtx->btCoexModeSet = TRUE;
3435
3436 /* Firmware failing to process DHCP START/STOP indications.
3437 * So, for now commentig below code, once issue is resolved,
3438 * follwing will be uncommented.
3439 */
3440 #if 0
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303441 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3442 pAdapter->macAddressCurrent.bytes);
c_hpothu9b781ba2013-12-30 20:57:45 +05303443 #endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303444 }
3445 else if ('2' == *dhcpPhase)
3446 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303447 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3448 FL("BTCOEXMODE %d"), *dhcpPhase);
3449
3450 pHddCtx->btCoexModeSet = FALSE;
3451
3452 /* Firmware failing to process DHCP START/STOP indications.
3453 * So, for now commentig below code, once issue is resolved,
3454 * follwing will be uncommented.
3455 */
3456 #if 0
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303457 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3458 pAdapter->macAddressCurrent.bytes);
c_hpothu9b781ba2013-12-30 20:57:45 +05303459 #endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303460 }
3461 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003462 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3463 {
3464 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3465 }
3466 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3467 {
3468 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3469 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303470 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3471 {
3472 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3473 char extra[32];
3474 tANI_U8 len = 0;
3475
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003476 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303477 (int)pCfg->nActiveMaxChnTime);
3478 if (copy_to_user(priv_data.buf, &extra, len + 1))
3479 {
3480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3481 "%s: failed to copy data to user buffer", __func__);
3482 ret = -EFAULT;
3483 goto exit;
3484 }
3485 ret = len;
3486 }
3487 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3488 {
3489 tANI_U8 *value = command;
3490 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3491 int val = 0, temp;
3492
3493 value = value + 13;
3494 temp = kstrtou32(value, 10, &val);
3495 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3496 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3497 {
3498 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3499 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3500 ret = -EFAULT;
3501 goto exit;
3502 }
3503 pCfg->nActiveMaxChnTime = val;
3504 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003505 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3506 {
3507 tANI_U8 filterType = 0;
3508 tANI_U8 *value;
3509 value = command + 9;
3510
3511 /* Convert the value from ascii to integer */
3512 ret = kstrtou8(value, 10, &filterType);
3513 if (ret < 0)
3514 {
3515 /* If the input value is greater than max value of datatype,
3516 * then also kstrtou8 fails
3517 */
3518 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3519 "%s: kstrtou8 failed range ", __func__);
3520 ret = -EINVAL;
3521 goto exit;
3522 }
3523 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3524 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3525 {
3526 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3527 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3528 " 2-Sink ", __func__);
3529 ret = -EINVAL;
3530 goto exit;
3531 }
3532 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3533 pHddCtx->drvr_miracast = filterType;
3534 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3535 }
Leo Chang614d2072013-08-22 14:59:44 -07003536 else if (strncmp(command, "SETMCRATE", 9) == 0)
3537 {
Leo Chang614d2072013-08-22 14:59:44 -07003538 tANI_U8 *value = command;
3539 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003540 tSirRateUpdateInd *rateUpdate;
3541 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003542
3543 /* Only valid for SAP mode */
3544 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3545 {
3546 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3547 "%s: SAP mode is not running", __func__);
3548 ret = -EFAULT;
3549 goto exit;
3550 }
3551
3552 /* Move pointer to ahead of SETMCRATE<delimiter> */
3553 /* input value is in units of hundred kbps */
3554 value = value + 10;
3555 /* Convert the value from ascii to integer, decimal base */
3556 ret = kstrtouint(value, 10, &targetRate);
3557
Leo Chang1f98cbd2013-10-17 15:03:52 -07003558 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3559 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003560 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003561 hddLog(VOS_TRACE_LEVEL_ERROR,
3562 "%s: SETMCRATE indication alloc fail", __func__);
3563 ret = -EFAULT;
3564 goto exit;
3565 }
3566 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3567
3568 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3569 "MC Target rate %d", targetRate);
3570 /* Ignore unicast */
3571 rateUpdate->ucastDataRate = -1;
3572 rateUpdate->mcastDataRate24GHz = targetRate;
3573 rateUpdate->mcastDataRate5GHz = targetRate;
3574 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3575 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3576 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3577 if (eHAL_STATUS_SUCCESS != status)
3578 {
3579 hddLog(VOS_TRACE_LEVEL_ERROR,
3580 "%s: SET_MC_RATE failed", __func__);
3581 vos_mem_free(rateUpdate);
3582 ret = -EFAULT;
3583 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003584 }
3585 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303586#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003587 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303588 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003589 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303590 }
3591#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003592#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3593 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3594 {
3595 tANI_U8 *value = command;
3596 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3597 tANI_U8 numChannels = 0;
3598 eHalStatus status = eHAL_STATUS_SUCCESS;
3599
3600 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3601 if (eHAL_STATUS_SUCCESS != status)
3602 {
3603 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3604 "%s: Failed to parse channel list information", __func__);
3605 ret = -EINVAL;
3606 goto exit;
3607 }
3608
3609 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3610 {
3611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3612 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3613 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3614 ret = -EINVAL;
3615 goto exit;
3616 }
3617 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3618 ChannelList,
3619 numChannels);
3620 if (eHAL_STATUS_SUCCESS != status)
3621 {
3622 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3623 "%s: Failed to update channel list information", __func__);
3624 ret = -EINVAL;
3625 goto exit;
3626 }
3627 }
3628 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3629 {
3630 tANI_U8 *value = command;
3631 char extra[128] = {0};
3632 int len = 0;
3633 tANI_U8 tid = 0;
3634 hdd_station_ctx_t *pHddStaCtx = NULL;
3635 tAniTrafStrmMetrics tsmMetrics;
3636 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3637
3638 /* if not associated, return error */
3639 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3640 {
3641 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3642 ret = -EINVAL;
3643 goto exit;
3644 }
3645
3646 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3647 value = value + 12;
3648 /* Convert the value from ascii to integer */
3649 ret = kstrtou8(value, 10, &tid);
3650 if (ret < 0)
3651 {
3652 /* If the input value is greater than max value of datatype, then also
3653 kstrtou8 fails */
3654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3655 "%s: kstrtou8 failed range [%d - %d]", __func__,
3656 TID_MIN_VALUE,
3657 TID_MAX_VALUE);
3658 ret = -EINVAL;
3659 goto exit;
3660 }
3661
3662 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3663 {
3664 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3665 "tid value %d is out of range"
3666 " (Min: %d Max: %d)", tid,
3667 TID_MIN_VALUE,
3668 TID_MAX_VALUE);
3669 ret = -EINVAL;
3670 goto exit;
3671 }
3672
3673 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3674 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3675
3676 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3677 {
3678 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3679 "%s: failed to get tsm stats", __func__);
3680 ret = -EFAULT;
3681 goto exit;
3682 }
3683
3684 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3685 "UplinkPktQueueDly(%d)\n"
3686 "UplinkPktQueueDlyHist[0](%d)\n"
3687 "UplinkPktQueueDlyHist[1](%d)\n"
3688 "UplinkPktQueueDlyHist[2](%d)\n"
3689 "UplinkPktQueueDlyHist[3](%d)\n"
3690 "UplinkPktTxDly(%lu)\n"
3691 "UplinkPktLoss(%d)\n"
3692 "UplinkPktCount(%d)\n"
3693 "RoamingCount(%d)\n"
3694 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3695 tsmMetrics.UplinkPktQueueDlyHist[0],
3696 tsmMetrics.UplinkPktQueueDlyHist[1],
3697 tsmMetrics.UplinkPktQueueDlyHist[2],
3698 tsmMetrics.UplinkPktQueueDlyHist[3],
3699 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3700 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3701
3702 /* Output TSM stats is of the format
3703 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3704 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003705 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003706 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3707 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3708 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3709 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3710 tsmMetrics.RoamingDly);
3711
3712 if (copy_to_user(priv_data.buf, &extra, len + 1))
3713 {
3714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3715 "%s: failed to copy data to user buffer", __func__);
3716 ret = -EFAULT;
3717 goto exit;
3718 }
3719 }
3720 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3721 {
3722 tANI_U8 *value = command;
3723 tANI_U8 *cckmIe = NULL;
3724 tANI_U8 cckmIeLen = 0;
3725 eHalStatus status = eHAL_STATUS_SUCCESS;
3726
3727 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3728 if (eHAL_STATUS_SUCCESS != status)
3729 {
3730 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3731 "%s: Failed to parse cckm ie data", __func__);
3732 ret = -EINVAL;
3733 goto exit;
3734 }
3735
3736 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3737 {
3738 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3739 "%s: CCKM Ie input length is more than max[%d]", __func__,
3740 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003741 vos_mem_free(cckmIe);
3742 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003743 ret = -EINVAL;
3744 goto exit;
3745 }
3746 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003747 vos_mem_free(cckmIe);
3748 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003749 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003750 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3751 {
3752 tANI_U8 *value = command;
3753 tCsrCcxBeaconReq ccxBcnReq;
3754 eHalStatus status = eHAL_STATUS_SUCCESS;
3755 status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
3756 if (eHAL_STATUS_SUCCESS != status)
3757 {
3758 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3759 "%s: Failed to parse ccx beacon req", __func__);
3760 ret = -EINVAL;
3761 goto exit;
3762 }
3763
3764 sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
3765 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003766#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003767 else {
3768 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3769 __func__, command);
3770 }
3771
Jeff Johnson295189b2012-06-20 16:38:30 -07003772 }
3773exit:
3774 if (command)
3775 {
3776 kfree(command);
3777 }
3778 return ret;
3779}
3780
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003781
3782
3783#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003784/**---------------------------------------------------------------------------
3785
3786 \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
3787
3788 This function parses the ccx beacon request passed in the format
3789 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3790 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3791 <space>Scan Mode N<space>Meas Duration N
3792 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3793 then take N.
3794 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3795 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3796 This function does not take care of removing duplicate channels from the list
3797
3798 \param - pValue Pointer to data
3799 \param - pCcxBcnReq output pointer to store parsed ie information
3800
3801 \return - 0 for success non-zero for failure
3802
3803 --------------------------------------------------------------------------*/
3804static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
3805 tCsrCcxBeaconReq *pCcxBcnReq)
3806{
3807 tANI_U8 *inPtr = pValue;
3808 int tempInt = 0;
3809 int j = 0, i = 0, v = 0;
3810 char buf[32];
3811
3812 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3813 /*no argument after the command*/
3814 if (NULL == inPtr)
3815 {
3816 return -EINVAL;
3817 }
3818 /*no space after the command*/
3819 else if (SPACE_ASCII_VALUE != *inPtr)
3820 {
3821 return -EINVAL;
3822 }
3823
3824 /*removing empty spaces*/
3825 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3826
3827 /*no argument followed by spaces*/
3828 if ('\0' == *inPtr) return -EINVAL;
3829
3830 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08003831 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003832 if (1 != v) return -EINVAL;
3833
3834 v = kstrtos32(buf, 10, &tempInt);
3835 if ( v < 0) return -EINVAL;
3836
3837 pCcxBcnReq->numBcnReqIe = tempInt;
3838
3839 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3840 "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
3841
3842 for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
3843 {
3844 for (i = 0; i < 4; i++)
3845 {
3846 /*inPtr pointing to the beginning of first space after number of ie fields*/
3847 inPtr = strpbrk( inPtr, " " );
3848 /*no ie data after the number of ie fields argument*/
3849 if (NULL == inPtr) return -EINVAL;
3850
3851 /*removing empty space*/
3852 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3853
3854 /*no ie data after the number of ie fields argument and spaces*/
3855 if ( '\0' == *inPtr ) return -EINVAL;
3856
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08003857 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003858 if (1 != v) return -EINVAL;
3859
3860 v = kstrtos32(buf, 10, &tempInt);
3861 if (v < 0) return -EINVAL;
3862
3863 switch (i)
3864 {
3865 case 0: /* Measurement token */
3866 if (tempInt <= 0)
3867 {
3868 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3869 "Invalid Measurement Token(%d)", tempInt);
3870 return -EINVAL;
3871 }
3872 pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
3873 break;
3874
3875 case 1: /* Channel number */
3876 if ((tempInt <= 0) ||
3877 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3878 {
3879 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3880 "Invalid Channel Number(%d)", tempInt);
3881 return -EINVAL;
3882 }
3883 pCcxBcnReq->bcnReq[j].channel = tempInt;
3884 break;
3885
3886 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003887 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003888 {
3889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3890 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
3891 return -EINVAL;
3892 }
3893 pCcxBcnReq->bcnReq[j].scanMode= tempInt;
3894 break;
3895
3896 case 3: /* Measurement duration */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003897 if (((tempInt <= 0) && (pCcxBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
3898 ((tempInt < 0) && (pCcxBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003899 {
3900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3901 "Invalid Measurement Duration(%d)", tempInt);
3902 return -EINVAL;
3903 }
3904 pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
3905 break;
3906 }
3907 }
3908 }
3909
3910 for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
3911 {
3912 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3913 "Index(%d) Measurement Token(%lu)Channel(%lu) Scan Mode(%lu) Measurement Duration(%lu)\n",
3914 j,
3915 pCcxBcnReq->bcnReq[j].measurementToken,
3916 pCcxBcnReq->bcnReq[j].channel,
3917 pCcxBcnReq->bcnReq[j].scanMode,
3918 pCcxBcnReq->bcnReq[j].measurementDuration);
3919 }
3920
3921 return VOS_STATUS_SUCCESS;
3922}
3923
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003924static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3925{
3926 struct statsContext *pStatsContext = NULL;
3927 hdd_adapter_t *pAdapter = NULL;
3928
3929 if (NULL == pContext)
3930 {
3931 hddLog(VOS_TRACE_LEVEL_ERROR,
3932 "%s: Bad param, pContext [%p]",
3933 __func__, pContext);
3934 return;
3935 }
3936
Jeff Johnson72a40512013-12-19 10:14:15 -08003937 /* there is a race condition that exists between this callback
3938 function and the caller since the caller could time out either
3939 before or while this code is executing. we use a spinlock to
3940 serialize these actions */
3941 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003942
3943 pStatsContext = pContext;
3944 pAdapter = pStatsContext->pAdapter;
3945 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3946 {
3947 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08003948 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003949 hddLog(VOS_TRACE_LEVEL_WARN,
3950 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3951 __func__, pAdapter, pStatsContext->magic);
3952 return;
3953 }
3954
Jeff Johnson72a40512013-12-19 10:14:15 -08003955 /* context is valid so caller is still waiting */
3956
3957 /* paranoia: invalidate the magic */
3958 pStatsContext->magic = 0;
3959
3960 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003961 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3962 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3963 tsmMetrics.UplinkPktQueueDlyHist,
3964 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3965 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3966 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3967 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3968 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3969 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3970 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3971
Jeff Johnson72a40512013-12-19 10:14:15 -08003972 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003973 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08003974
3975 /* serialization is complete */
3976 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003977}
3978
3979
3980
3981static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3982 tAniTrafStrmMetrics* pTsmMetrics)
3983{
3984 hdd_station_ctx_t *pHddStaCtx = NULL;
3985 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08003986 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003987 long lrc;
3988 struct statsContext context;
3989 hdd_context_t *pHddCtx = NULL;
3990
3991 if (NULL == pAdapter)
3992 {
3993 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3994 return VOS_STATUS_E_FAULT;
3995 }
3996
3997 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3998 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3999
4000 /* we are connected prepare our callback context */
4001 init_completion(&context.completion);
4002 context.pAdapter = pAdapter;
4003 context.magic = STATS_CONTEXT_MAGIC;
4004
4005 /* query tsm stats */
4006 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
4007 pHddStaCtx->conn_info.staId[ 0 ],
4008 pHddStaCtx->conn_info.bssId,
4009 &context, pHddCtx->pvosContext, tid);
4010
4011 if (eHAL_STATUS_SUCCESS != hstatus)
4012 {
Jeff Johnson72a40512013-12-19 10:14:15 -08004013 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
4014 __func__);
4015 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004016 }
4017 else
4018 {
4019 /* request was sent -- wait for the response */
4020 lrc = wait_for_completion_interruptible_timeout(&context.completion,
4021 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004022 if (lrc <= 0)
4023 {
4024 hddLog(VOS_TRACE_LEVEL_ERROR,
4025 "%s: SME %s while retrieving statistics",
4026 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004027 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004028 }
4029 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004030
Jeff Johnson72a40512013-12-19 10:14:15 -08004031 /* either we never sent a request, we sent a request and received a
4032 response or we sent a request and timed out. if we never sent a
4033 request or if we sent a request and got a response, we want to
4034 clear the magic out of paranoia. if we timed out there is a
4035 race condition such that the callback function could be
4036 executing at the same time we are. of primary concern is if the
4037 callback function had already verified the "magic" but had not
4038 yet set the completion variable when a timeout occurred. we
4039 serialize these activities by invalidating the magic while
4040 holding a shared spinlock which will cause us to block if the
4041 callback is currently executing */
4042 spin_lock(&hdd_context_lock);
4043 context.magic = 0;
4044 spin_unlock(&hdd_context_lock);
4045
4046 if (VOS_STATUS_SUCCESS == vstatus)
4047 {
4048 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4049 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4050 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4051 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4052 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4053 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4054 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4055 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4056 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4057 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4058 }
4059 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004060}
4061#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4062
Srinivas Girigowdade697412013-02-14 16:31:48 -08004063#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
4064void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4065{
4066 eCsrBand band = -1;
4067 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4068 switch (band)
4069 {
4070 case eCSR_BAND_ALL:
4071 *pBand = WLAN_HDD_UI_BAND_AUTO;
4072 break;
4073
4074 case eCSR_BAND_24:
4075 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4076 break;
4077
4078 case eCSR_BAND_5G:
4079 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4080 break;
4081
4082 default:
4083 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4084 *pBand = -1;
4085 break;
4086 }
4087}
4088
4089/**---------------------------------------------------------------------------
4090
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004091 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4092
4093 This function parses the send action frame data passed in the format
4094 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4095
Srinivas Girigowda56076852013-08-20 14:00:50 -07004096 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004097 \param - pTargetApBssid Pointer to target Ap bssid
4098 \param - pChannel Pointer to the Target AP channel
4099 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4100 \param - pBuf Pointer to data
4101 \param - pBufLen Pointer to data length
4102
4103 \return - 0 for success non-zero for failure
4104
4105 --------------------------------------------------------------------------*/
4106VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4107 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4108{
4109 tANI_U8 *inPtr = pValue;
4110 tANI_U8 *dataEnd;
4111 int tempInt;
4112 int j = 0;
4113 int i = 0;
4114 int v = 0;
4115 tANI_U8 tempBuf[32];
4116 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004117 /* 12 hexa decimal digits, 5 ':' and '\0' */
4118 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004119
4120 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4121 /*no argument after the command*/
4122 if (NULL == inPtr)
4123 {
4124 return -EINVAL;
4125 }
4126
4127 /*no space after the command*/
4128 else if (SPACE_ASCII_VALUE != *inPtr)
4129 {
4130 return -EINVAL;
4131 }
4132
4133 /*removing empty spaces*/
4134 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4135
4136 /*no argument followed by spaces*/
4137 if ('\0' == *inPtr)
4138 {
4139 return -EINVAL;
4140 }
4141
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004142 v = sscanf(inPtr, "%17s", macAddress);
4143 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004144 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004145 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4146 "Invalid MAC address or All hex inputs are not read (%d)", v);
4147 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004148 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004149
4150 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4151 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4152 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4153 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4154 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4155 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004156
4157 /* point to the next argument */
4158 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4159 /*no argument after the command*/
4160 if (NULL == inPtr) return -EINVAL;
4161
4162 /*removing empty spaces*/
4163 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4164
4165 /*no argument followed by spaces*/
4166 if ('\0' == *inPtr)
4167 {
4168 return -EINVAL;
4169 }
4170
4171 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004172 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004173 if (1 != v) return -EINVAL;
4174
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004175 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304176 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
4177 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004178
4179 *pChannel = tempInt;
4180
4181 /* point to the next argument */
4182 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4183 /*no argument after the command*/
4184 if (NULL == inPtr) return -EINVAL;
4185 /*removing empty spaces*/
4186 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4187
4188 /*no argument followed by spaces*/
4189 if ('\0' == *inPtr)
4190 {
4191 return -EINVAL;
4192 }
4193
4194 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004195 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004196 if (1 != v) return -EINVAL;
4197
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004198 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004199 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004200
4201 *pDwellTime = tempInt;
4202
4203 /* point to the next argument */
4204 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4205 /*no argument after the command*/
4206 if (NULL == inPtr) return -EINVAL;
4207 /*removing empty spaces*/
4208 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4209
4210 /*no argument followed by spaces*/
4211 if ('\0' == *inPtr)
4212 {
4213 return -EINVAL;
4214 }
4215
4216 /* find the length of data */
4217 dataEnd = inPtr;
4218 while(('\0' != *dataEnd) )
4219 {
4220 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004221 }
Kiet Lambe150c22013-11-21 16:30:32 +05304222 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004223 if ( *pBufLen <= 0) return -EINVAL;
4224
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004225 /* Allocate the number of bytes based on the number of input characters
4226 whether it is even or odd.
4227 if the number of input characters are even, then we need N/2 byte.
4228 if the number of input characters are odd, then we need do (N+1)/2 to
4229 compensate rounding off.
4230 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4231 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4232 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004233 if (NULL == *pBuf)
4234 {
4235 hddLog(VOS_TRACE_LEVEL_FATAL,
4236 "%s: vos_mem_alloc failed ", __func__);
4237 return -EINVAL;
4238 }
4239
4240 /* the buffer received from the upper layer is character buffer,
4241 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4242 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4243 and f0 in 3rd location */
4244 for (i = 0, j = 0; j < *pBufLen; j += 2)
4245 {
Kiet Lambe150c22013-11-21 16:30:32 +05304246 if( j+1 == *pBufLen)
4247 {
4248 tempByte = hdd_parse_hex(inPtr[j]);
4249 }
4250 else
4251 {
4252 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4253 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004254 (*pBuf)[i++] = tempByte;
4255 }
4256 *pBufLen = i;
4257 return VOS_STATUS_SUCCESS;
4258}
4259
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004260/**---------------------------------------------------------------------------
4261
Srinivas Girigowdade697412013-02-14 16:31:48 -08004262 \brief hdd_parse_channellist() - HDD Parse channel list
4263
4264 This function parses the channel list passed in the format
4265 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004266 if the Number of channels (N) does not match with the actual number of channels passed
4267 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4268 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4269 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4270 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004271
4272 \param - pValue Pointer to input channel list
4273 \param - ChannelList Pointer to local output array to record channel list
4274 \param - pNumChannels Pointer to number of roam scan channels
4275
4276 \return - 0 for success non-zero for failure
4277
4278 --------------------------------------------------------------------------*/
4279VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4280{
4281 tANI_U8 *inPtr = pValue;
4282 int tempInt;
4283 int j = 0;
4284 int v = 0;
4285 char buf[32];
4286
4287 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4288 /*no argument after the command*/
4289 if (NULL == inPtr)
4290 {
4291 return -EINVAL;
4292 }
4293
4294 /*no space after the command*/
4295 else if (SPACE_ASCII_VALUE != *inPtr)
4296 {
4297 return -EINVAL;
4298 }
4299
4300 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004301 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004302
4303 /*no argument followed by spaces*/
4304 if ('\0' == *inPtr)
4305 {
4306 return -EINVAL;
4307 }
4308
4309 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004310 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004311 if (1 != v) return -EINVAL;
4312
Srinivas Girigowdade697412013-02-14 16:31:48 -08004313 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004314 if ((v < 0) ||
4315 (tempInt <= 0) ||
4316 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4317 {
4318 return -EINVAL;
4319 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004320
4321 *pNumChannels = tempInt;
4322
4323 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4324 "Number of channels are: %d", *pNumChannels);
4325
4326 for (j = 0; j < (*pNumChannels); j++)
4327 {
4328 /*inPtr pointing to the beginning of first space after number of channels*/
4329 inPtr = strpbrk( inPtr, " " );
4330 /*no channel list after the number of channels argument*/
4331 if (NULL == inPtr)
4332 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004333 if (0 != j)
4334 {
4335 *pNumChannels = j;
4336 return VOS_STATUS_SUCCESS;
4337 }
4338 else
4339 {
4340 return -EINVAL;
4341 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004342 }
4343
4344 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004345 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004346
4347 /*no channel list after the number of channels argument and spaces*/
4348 if ( '\0' == *inPtr )
4349 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004350 if (0 != j)
4351 {
4352 *pNumChannels = j;
4353 return VOS_STATUS_SUCCESS;
4354 }
4355 else
4356 {
4357 return -EINVAL;
4358 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004359 }
4360
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004361 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004362 if (1 != v) return -EINVAL;
4363
Srinivas Girigowdade697412013-02-14 16:31:48 -08004364 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004365 if ((v < 0) ||
4366 (tempInt <= 0) ||
4367 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4368 {
4369 return -EINVAL;
4370 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004371 pChannelList[j] = tempInt;
4372
4373 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4374 "Channel %d added to preferred channel list",
4375 pChannelList[j] );
4376 }
4377
Srinivas Girigowdade697412013-02-14 16:31:48 -08004378 return VOS_STATUS_SUCCESS;
4379}
4380
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004381
4382/**---------------------------------------------------------------------------
4383
4384 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4385
4386 This function parses the reasoc command data passed in the format
4387 REASSOC<space><bssid><space><channel>
4388
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004389 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004390 \param - pTargetApBssid Pointer to target Ap bssid
4391 \param - pChannel Pointer to the Target AP channel
4392
4393 \return - 0 for success non-zero for failure
4394
4395 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004396VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4397 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004398{
4399 tANI_U8 *inPtr = pValue;
4400 int tempInt;
4401 int v = 0;
4402 tANI_U8 tempBuf[32];
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004403 /* 12 hexa decimal digits, 5 ':' and '\0' */
4404 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004405
4406 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4407 /*no argument after the command*/
4408 if (NULL == inPtr)
4409 {
4410 return -EINVAL;
4411 }
4412
4413 /*no space after the command*/
4414 else if (SPACE_ASCII_VALUE != *inPtr)
4415 {
4416 return -EINVAL;
4417 }
4418
4419 /*removing empty spaces*/
4420 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4421
4422 /*no argument followed by spaces*/
4423 if ('\0' == *inPtr)
4424 {
4425 return -EINVAL;
4426 }
4427
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004428 v = sscanf(inPtr, "%17s", macAddress);
4429 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004430 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004431 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4432 "Invalid MAC address or All hex inputs are not read (%d)", v);
4433 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004434 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004435
4436 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4437 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4438 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4439 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4440 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4441 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004442
4443 /* point to the next argument */
4444 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4445 /*no argument after the command*/
4446 if (NULL == inPtr) return -EINVAL;
4447
4448 /*removing empty spaces*/
4449 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4450
4451 /*no argument followed by spaces*/
4452 if ('\0' == *inPtr)
4453 {
4454 return -EINVAL;
4455 }
4456
4457 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004458 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004459 if (1 != v) return -EINVAL;
4460
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004461 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004462 if ((v < 0) ||
4463 (tempInt <= 0) ||
4464 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4465 {
4466 return -EINVAL;
4467 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004468
4469 *pChannel = tempInt;
4470 return VOS_STATUS_SUCCESS;
4471}
4472
4473#endif
4474
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004475#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4476/**---------------------------------------------------------------------------
4477
4478 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4479
4480 This function parses the SETCCKM IE command
4481 SETCCKMIE<space><ie data>
4482
4483 \param - pValue Pointer to input data
4484 \param - pCckmIe Pointer to output cckm Ie
4485 \param - pCckmIeLen Pointer to output cckm ie length
4486
4487 \return - 0 for success non-zero for failure
4488
4489 --------------------------------------------------------------------------*/
4490VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4491 tANI_U8 *pCckmIeLen)
4492{
4493 tANI_U8 *inPtr = pValue;
4494 tANI_U8 *dataEnd;
4495 int j = 0;
4496 int i = 0;
4497 tANI_U8 tempByte = 0;
4498
4499 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4500 /*no argument after the command*/
4501 if (NULL == inPtr)
4502 {
4503 return -EINVAL;
4504 }
4505
4506 /*no space after the command*/
4507 else if (SPACE_ASCII_VALUE != *inPtr)
4508 {
4509 return -EINVAL;
4510 }
4511
4512 /*removing empty spaces*/
4513 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4514
4515 /*no argument followed by spaces*/
4516 if ('\0' == *inPtr)
4517 {
4518 return -EINVAL;
4519 }
4520
4521 /* find the length of data */
4522 dataEnd = inPtr;
4523 while(('\0' != *dataEnd) )
4524 {
4525 dataEnd++;
4526 ++(*pCckmIeLen);
4527 }
4528 if ( *pCckmIeLen <= 0) return -EINVAL;
4529
4530 /* Allocate the number of bytes based on the number of input characters
4531 whether it is even or odd.
4532 if the number of input characters are even, then we need N/2 byte.
4533 if the number of input characters are odd, then we need do (N+1)/2 to
4534 compensate rounding off.
4535 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4536 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4537 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4538 if (NULL == *pCckmIe)
4539 {
4540 hddLog(VOS_TRACE_LEVEL_FATAL,
4541 "%s: vos_mem_alloc failed ", __func__);
4542 return -EINVAL;
4543 }
4544 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4545 /* the buffer received from the upper layer is character buffer,
4546 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4547 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4548 and f0 in 3rd location */
4549 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4550 {
4551 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4552 (*pCckmIe)[i++] = tempByte;
4553 }
4554 *pCckmIeLen = i;
4555
4556 return VOS_STATUS_SUCCESS;
4557}
4558#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4559
Jeff Johnson295189b2012-06-20 16:38:30 -07004560/**---------------------------------------------------------------------------
4561
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004562 \brief hdd_is_valid_mac_address() - Validate MAC address
4563
4564 This function validates whether the given MAC address is valid or not
4565 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4566 where X is the hexa decimal digit character and separated by ':'
4567 This algorithm works even if MAC address is not separated by ':'
4568
4569 This code checks given input string mac contains exactly 12 hexadecimal digits.
4570 and a separator colon : appears in the input string only after
4571 an even number of hex digits.
4572
4573 \param - pMacAddr pointer to the input MAC address
4574 \return - 1 for valid and 0 for invalid
4575
4576 --------------------------------------------------------------------------*/
4577
4578v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4579{
4580 int xdigit = 0;
4581 int separator = 0;
4582 while (*pMacAddr)
4583 {
4584 if (isxdigit(*pMacAddr))
4585 {
4586 xdigit++;
4587 }
4588 else if (':' == *pMacAddr)
4589 {
4590 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4591 break;
4592
4593 ++separator;
4594 }
4595 else
4596 {
4597 separator = -1;
4598 /* Invalid MAC found */
4599 return 0;
4600 }
4601 ++pMacAddr;
4602 }
4603 return (xdigit == 12 && (separator == 5 || separator == 0));
4604}
4605
4606/**---------------------------------------------------------------------------
4607
Jeff Johnson295189b2012-06-20 16:38:30 -07004608 \brief hdd_open() - HDD Open function
4609
4610 This is called in response to ifconfig up
4611
4612 \param - dev Pointer to net_device structure
4613
4614 \return - 0 for success non-zero for failure
4615
4616 --------------------------------------------------------------------------*/
4617int hdd_open (struct net_device *dev)
4618{
4619 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4620 hdd_context_t *pHddCtx;
4621 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4622 VOS_STATUS status;
4623 v_BOOL_t in_standby = TRUE;
4624
4625 if (NULL == pAdapter)
4626 {
4627 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05304628 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004629 return -ENODEV;
4630 }
4631
4632 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4633 if (NULL == pHddCtx)
4634 {
4635 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004636 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004637 return -ENODEV;
4638 }
4639
4640 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4641 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4642 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004643 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4644 {
4645 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304646 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004647 in_standby = FALSE;
4648 break;
4649 }
4650 else
4651 {
4652 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4653 pAdapterNode = pNext;
4654 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004655 }
4656
4657 if (TRUE == in_standby)
4658 {
4659 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4660 {
4661 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4662 "wlan out of power save", __func__);
4663 return -EINVAL;
4664 }
4665 }
4666
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004667 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004668 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4669 {
4670 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004671 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004672 /* Enable TX queues only when we are connected */
4673 netif_tx_start_all_queues(dev);
4674 }
4675
4676 return 0;
4677}
4678
4679int hdd_mon_open (struct net_device *dev)
4680{
4681 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4682
4683 if(pAdapter == NULL) {
4684 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004685 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004686 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004687 }
4688
4689 netif_start_queue(dev);
4690
4691 return 0;
4692}
4693/**---------------------------------------------------------------------------
4694
4695 \brief hdd_stop() - HDD stop function
4696
4697 This is called in response to ifconfig down
4698
4699 \param - dev Pointer to net_device structure
4700
4701 \return - 0 for success non-zero for failure
4702
4703 --------------------------------------------------------------------------*/
4704
4705int hdd_stop (struct net_device *dev)
4706{
4707 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4708 hdd_context_t *pHddCtx;
4709 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4710 VOS_STATUS status;
4711 v_BOOL_t enter_standby = TRUE;
4712
4713 ENTER();
4714
4715 if (NULL == pAdapter)
4716 {
4717 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05304718 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004719 return -ENODEV;
4720 }
4721
4722 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4723 if (NULL == pHddCtx)
4724 {
4725 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004726 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004727 return -ENODEV;
4728 }
4729
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004730 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004731 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4732 netif_tx_disable(pAdapter->dev);
4733 netif_carrier_off(pAdapter->dev);
4734
4735
4736 /* SoftAP ifaces should never go in power save mode
4737 making sure same here. */
4738 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4739 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004740 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004741 )
4742 {
4743 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304744 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4745 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004746 EXIT();
4747 return 0;
4748 }
4749
4750 /* Find if any iface is up then
4751 if any iface is up then can't put device to sleep/ power save mode. */
4752 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4753 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4754 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004755 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4756 {
4757 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304758 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004759 enter_standby = FALSE;
4760 break;
4761 }
4762 else
4763 {
4764 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4765 pAdapterNode = pNext;
4766 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004767 }
4768
4769 if (TRUE == enter_standby)
4770 {
4771 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4772 "entering standby", __func__);
4773 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4774 {
4775 /*log and return success*/
4776 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4777 "wlan in power save", __func__);
4778 }
4779 }
4780
4781 EXIT();
4782 return 0;
4783}
4784
4785/**---------------------------------------------------------------------------
4786
4787 \brief hdd_uninit() - HDD uninit function
4788
4789 This is called during the netdev unregister to uninitialize all data
4790associated with the device
4791
4792 \param - dev Pointer to net_device structure
4793
4794 \return - void
4795
4796 --------------------------------------------------------------------------*/
4797static void hdd_uninit (struct net_device *dev)
4798{
4799 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4800
4801 ENTER();
4802
4803 do
4804 {
4805 if (NULL == pAdapter)
4806 {
4807 hddLog(VOS_TRACE_LEVEL_FATAL,
4808 "%s: NULL pAdapter", __func__);
4809 break;
4810 }
4811
4812 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4813 {
4814 hddLog(VOS_TRACE_LEVEL_FATAL,
4815 "%s: Invalid magic", __func__);
4816 break;
4817 }
4818
4819 if (NULL == pAdapter->pHddCtx)
4820 {
4821 hddLog(VOS_TRACE_LEVEL_FATAL,
4822 "%s: NULL pHddCtx", __func__);
4823 break;
4824 }
4825
4826 if (dev != pAdapter->dev)
4827 {
4828 hddLog(VOS_TRACE_LEVEL_FATAL,
4829 "%s: Invalid device reference", __func__);
4830 /* we haven't validated all cases so let this go for now */
4831 }
4832
4833 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4834
4835 /* after uninit our adapter structure will no longer be valid */
4836 pAdapter->dev = NULL;
4837 pAdapter->magic = 0;
4838 } while (0);
4839
4840 EXIT();
4841}
4842
4843/**---------------------------------------------------------------------------
4844
4845 \brief hdd_release_firmware() -
4846
4847 This function calls the release firmware API to free the firmware buffer.
4848
4849 \param - pFileName Pointer to the File Name.
4850 pCtx - Pointer to the adapter .
4851
4852
4853 \return - 0 for success, non zero for failure
4854
4855 --------------------------------------------------------------------------*/
4856
4857VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4858{
4859 VOS_STATUS status = VOS_STATUS_SUCCESS;
4860 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4861 ENTER();
4862
4863
4864 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4865
4866 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4867
4868 if(pHddCtx->fw) {
4869 release_firmware(pHddCtx->fw);
4870 pHddCtx->fw = NULL;
4871 }
4872 else
4873 status = VOS_STATUS_E_FAILURE;
4874 }
4875 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4876 if(pHddCtx->nv) {
4877 release_firmware(pHddCtx->nv);
4878 pHddCtx->nv = NULL;
4879 }
4880 else
4881 status = VOS_STATUS_E_FAILURE;
4882
4883 }
4884
4885 EXIT();
4886 return status;
4887}
4888
4889/**---------------------------------------------------------------------------
4890
4891 \brief hdd_request_firmware() -
4892
4893 This function reads the firmware file using the request firmware
4894 API and returns the the firmware data and the firmware file size.
4895
4896 \param - pfileName - Pointer to the file name.
4897 - pCtx - Pointer to the adapter .
4898 - ppfw_data - Pointer to the pointer of the firmware data.
4899 - pSize - Pointer to the file size.
4900
4901 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4902
4903 --------------------------------------------------------------------------*/
4904
4905
4906VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4907{
4908 int status;
4909 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4910 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4911 ENTER();
4912
4913 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4914
4915 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4916
4917 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4918 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4919 __func__, pfileName);
4920 retval = VOS_STATUS_E_FAILURE;
4921 }
4922
4923 else {
4924 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4925 *pSize = pHddCtx->fw->size;
4926 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4927 __func__, *pSize);
4928 }
4929 }
4930 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4931
4932 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4933
4934 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4935 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4936 __func__, pfileName);
4937 retval = VOS_STATUS_E_FAILURE;
4938 }
4939
4940 else {
4941 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4942 *pSize = pHddCtx->nv->size;
4943 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4944 __func__, *pSize);
4945 }
4946 }
4947
4948 EXIT();
4949 return retval;
4950}
4951/**---------------------------------------------------------------------------
4952 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4953
4954 This is the function invoked by SME to inform the result of a full power
4955 request issued by HDD
4956
4957 \param - callbackcontext - Pointer to cookie
4958 status - result of request
4959
4960 \return - None
4961
4962--------------------------------------------------------------------------*/
4963void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4964{
4965 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4966
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004967 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004968 if(&pHddCtx->full_pwr_comp_var)
4969 {
4970 complete(&pHddCtx->full_pwr_comp_var);
4971 }
4972}
4973
4974/**---------------------------------------------------------------------------
4975
4976 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4977
4978 This is the function invoked by SME to inform the result of BMPS
4979 request issued by HDD
4980
4981 \param - callbackcontext - Pointer to cookie
4982 status - result of request
4983
4984 \return - None
4985
4986--------------------------------------------------------------------------*/
4987void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4988{
4989
4990 struct completion *completion_var = (struct completion*) callbackContext;
4991
Arif Hussain6d2a3322013-11-17 19:50:10 -08004992 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004993 if(completion_var != NULL)
4994 {
4995 complete(completion_var);
4996 }
4997}
4998
4999/**---------------------------------------------------------------------------
5000
5001 \brief hdd_get_cfg_file_size() -
5002
5003 This function reads the configuration file using the request firmware
5004 API and returns the configuration file size.
5005
5006 \param - pCtx - Pointer to the adapter .
5007 - pFileName - Pointer to the file name.
5008 - pBufSize - Pointer to the buffer size.
5009
5010 \return - 0 for success, non zero for failure
5011
5012 --------------------------------------------------------------------------*/
5013
5014VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
5015{
5016 int status;
5017 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5018
5019 ENTER();
5020
5021 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5022
5023 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5024 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5025 status = VOS_STATUS_E_FAILURE;
5026 }
5027 else {
5028 *pBufSize = pHddCtx->fw->size;
5029 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5030 release_firmware(pHddCtx->fw);
5031 pHddCtx->fw = NULL;
5032 }
5033
5034 EXIT();
5035 return VOS_STATUS_SUCCESS;
5036}
5037
5038/**---------------------------------------------------------------------------
5039
5040 \brief hdd_read_cfg_file() -
5041
5042 This function reads the configuration file using the request firmware
5043 API and returns the cfg data and the buffer size of the configuration file.
5044
5045 \param - pCtx - Pointer to the adapter .
5046 - pFileName - Pointer to the file name.
5047 - pBuffer - Pointer to the data buffer.
5048 - pBufSize - Pointer to the buffer size.
5049
5050 \return - 0 for success, non zero for failure
5051
5052 --------------------------------------------------------------------------*/
5053
5054VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5055 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5056{
5057 int status;
5058 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5059
5060 ENTER();
5061
5062 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5063
5064 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5065 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5066 return VOS_STATUS_E_FAILURE;
5067 }
5068 else {
5069 if(*pBufSize != pHddCtx->fw->size) {
5070 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5071 "file size", __func__);
5072 release_firmware(pHddCtx->fw);
5073 pHddCtx->fw = NULL;
5074 return VOS_STATUS_E_FAILURE;
5075 }
5076 else {
5077 if(pBuffer) {
5078 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5079 }
5080 release_firmware(pHddCtx->fw);
5081 pHddCtx->fw = NULL;
5082 }
5083 }
5084
5085 EXIT();
5086
5087 return VOS_STATUS_SUCCESS;
5088}
5089
5090/**---------------------------------------------------------------------------
5091
Jeff Johnson295189b2012-06-20 16:38:30 -07005092 \brief hdd_set_mac_address() -
5093
5094 This function sets the user specified mac address using
5095 the command ifconfig wlanX hw ether <mac adress>.
5096
5097 \param - dev - Pointer to the net device.
5098 - addr - Pointer to the sockaddr.
5099 \return - 0 for success, non zero for failure
5100
5101 --------------------------------------------------------------------------*/
5102
5103static int hdd_set_mac_address(struct net_device *dev, void *addr)
5104{
5105 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5106 struct sockaddr *psta_mac_addr = addr;
5107 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5108
5109 ENTER();
5110
5111 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5112
5113#ifdef HDD_SESSIONIZE
5114 // set the MAC address though the STA ID CFG.
5115 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5116 (v_U8_t *)&pAdapter->macAddressCurrent,
5117 sizeof( pAdapter->macAddressCurrent ),
5118 hdd_set_mac_addr_cb, VOS_FALSE );
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305119
5120 if(eHAL_STATUS_SUCCESS != halStatus)
5121 {
5122 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5123 "%s: failed to set MAC address in CFG", __func__);
5124 }
5125
Jeff Johnson295189b2012-06-20 16:38:30 -07005126#endif
5127
5128 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5129
5130 EXIT();
5131 return halStatus;
5132}
5133
5134tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5135{
5136 int i;
5137 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5138 {
5139 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
5140 break;
5141 }
5142
5143 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5144 return NULL;
5145
5146 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5147 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5148}
5149
5150void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5151{
5152 int i;
5153 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5154 {
5155 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5156 {
5157 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5158 break;
5159 }
5160 }
5161 return;
5162}
5163
5164#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5165 static struct net_device_ops wlan_drv_ops = {
5166 .ndo_open = hdd_open,
5167 .ndo_stop = hdd_stop,
5168 .ndo_uninit = hdd_uninit,
5169 .ndo_start_xmit = hdd_hard_start_xmit,
5170 .ndo_tx_timeout = hdd_tx_timeout,
5171 .ndo_get_stats = hdd_stats,
5172 .ndo_do_ioctl = hdd_ioctl,
5173 .ndo_set_mac_address = hdd_set_mac_address,
5174 .ndo_select_queue = hdd_select_queue,
5175#ifdef WLAN_FEATURE_PACKET_FILTERING
5176#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5177 .ndo_set_rx_mode = hdd_set_multicast_list,
5178#else
5179 .ndo_set_multicast_list = hdd_set_multicast_list,
5180#endif //LINUX_VERSION_CODE
5181#endif
5182 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005183 static struct net_device_ops wlan_mon_drv_ops = {
5184 .ndo_open = hdd_mon_open,
5185 .ndo_stop = hdd_stop,
5186 .ndo_uninit = hdd_uninit,
5187 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5188 .ndo_tx_timeout = hdd_tx_timeout,
5189 .ndo_get_stats = hdd_stats,
5190 .ndo_do_ioctl = hdd_ioctl,
5191 .ndo_set_mac_address = hdd_set_mac_address,
5192 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005193
5194#endif
5195
5196void hdd_set_station_ops( struct net_device *pWlanDev )
5197{
5198#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005199 pWlanDev->netdev_ops = &wlan_drv_ops;
5200#else
5201 pWlanDev->open = hdd_open;
5202 pWlanDev->stop = hdd_stop;
5203 pWlanDev->uninit = hdd_uninit;
5204 pWlanDev->hard_start_xmit = NULL;
5205 pWlanDev->tx_timeout = hdd_tx_timeout;
5206 pWlanDev->get_stats = hdd_stats;
5207 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005208 pWlanDev->set_mac_address = hdd_set_mac_address;
5209#endif
5210}
5211
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005212static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005213{
5214 struct net_device *pWlanDev = NULL;
5215 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005216 /*
5217 * cfg80211 initialization and registration....
5218 */
5219 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5220
Jeff Johnson295189b2012-06-20 16:38:30 -07005221 if(pWlanDev != NULL)
5222 {
5223
5224 //Save the pointer to the net_device in the HDD adapter
5225 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5226
Jeff Johnson295189b2012-06-20 16:38:30 -07005227 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5228
5229 pAdapter->dev = pWlanDev;
5230 pAdapter->pHddCtx = pHddCtx;
5231 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5232
5233 init_completion(&pAdapter->session_open_comp_var);
5234 init_completion(&pAdapter->session_close_comp_var);
5235 init_completion(&pAdapter->disconnect_comp_var);
5236 init_completion(&pAdapter->linkup_event_var);
5237 init_completion(&pAdapter->cancel_rem_on_chan_var);
5238 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005239#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5240 init_completion(&pAdapter->offchannel_tx_event);
5241#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005242 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005243#ifdef FEATURE_WLAN_TDLS
5244 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005245 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005246 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305247 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005248#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005249 init_completion(&pHddCtx->mc_sus_event_var);
5250 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305251 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005252 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005253 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005254
Rajeev79dbe4c2013-10-05 11:03:42 +05305255#ifdef FEATURE_WLAN_BATCH_SCAN
5256 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5257 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5258 pAdapter->pBatchScanRsp = NULL;
5259 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005260 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev79dbe4c2013-10-05 11:03:42 +05305261 mutex_init(&pAdapter->hdd_batch_scan_lock);
5262#endif
5263
Jeff Johnson295189b2012-06-20 16:38:30 -07005264 pAdapter->isLinkUpSvcNeeded = FALSE;
5265 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5266 //Init the net_device structure
5267 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5268
5269 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5270 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5271 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5272 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5273
5274 hdd_set_station_ops( pAdapter->dev );
5275
5276 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005277 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5278 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5279 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005280 /* set pWlanDev's parent to underlying device */
5281 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5282 }
5283
5284 return pAdapter;
5285}
5286
5287VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5288{
5289 struct net_device *pWlanDev = pAdapter->dev;
5290 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5291 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5292 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5293
5294 if( rtnl_lock_held )
5295 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005296 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005297 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5298 {
5299 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5300 return VOS_STATUS_E_FAILURE;
5301 }
5302 }
5303 if (register_netdevice(pWlanDev))
5304 {
5305 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5306 return VOS_STATUS_E_FAILURE;
5307 }
5308 }
5309 else
5310 {
5311 if(register_netdev(pWlanDev))
5312 {
5313 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5314 return VOS_STATUS_E_FAILURE;
5315 }
5316 }
5317 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5318
5319 return VOS_STATUS_SUCCESS;
5320}
5321
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005322static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005323{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005324 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005325
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005326 if (NULL == pAdapter)
5327 {
5328 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5329 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005330 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005331
5332 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5333 {
5334 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5335 return eHAL_STATUS_NOT_INITIALIZED;
5336 }
5337
5338 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5339
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005340#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005341 /* need to make sure all of our scheduled work has completed.
5342 * This callback is called from MC thread context, so it is safe to
5343 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005344 *
5345 * Even though this is called from MC thread context, if there is a faulty
5346 * work item in the system, that can hang this call forever. So flushing
5347 * this global work queue is not safe; and now we make sure that
5348 * individual work queues are stopped correctly. But the cancel work queue
5349 * is a GPL only API, so the proprietary version of the driver would still
5350 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005351 */
5352 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005353#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005354
5355 /* We can be blocked while waiting for scheduled work to be
5356 * flushed, and the adapter structure can potentially be freed, in
5357 * which case the magic will have been reset. So make sure the
5358 * magic is still good, and hence the adapter structure is still
5359 * valid, before signaling completion */
5360 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5361 {
5362 complete(&pAdapter->session_close_comp_var);
5363 }
5364
Jeff Johnson295189b2012-06-20 16:38:30 -07005365 return eHAL_STATUS_SUCCESS;
5366}
5367
5368VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5369{
5370 struct net_device *pWlanDev = pAdapter->dev;
5371 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5372 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5373 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5374 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305375 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005376
5377 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005378 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005379 //Open a SME session for future operation
5380 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005381 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005382 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5383 {
5384 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005385 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005386 halStatus, halStatus );
5387 status = VOS_STATUS_E_FAILURE;
5388 goto error_sme_open;
5389 }
5390
5391 //Block on a completion variable. Can't wait forever though.
5392 rc = wait_for_completion_interruptible_timeout(
5393 &pAdapter->session_open_comp_var,
5394 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305395 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005396 {
5397 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305398 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07005399 status = VOS_STATUS_E_FAILURE;
5400 goto error_sme_open;
5401 }
5402
5403 // Register wireless extensions
5404 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5405 {
5406 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005407 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005408 halStatus, halStatus );
5409 status = VOS_STATUS_E_FAILURE;
5410 goto error_register_wext;
5411 }
5412 //Safe to register the hard_start_xmit function again
5413#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5414 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5415#else
5416 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5417#endif
5418
5419 //Set the Connection State to Not Connected
5420 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5421
5422 //Set the default operation channel
5423 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5424
5425 /* Make the default Auth Type as OPEN*/
5426 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5427
5428 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5429 {
5430 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005431 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005432 status, status );
5433 goto error_init_txrx;
5434 }
5435
5436 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5437
5438 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5439 {
5440 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005441 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005442 status, status );
5443 goto error_wmm_init;
5444 }
5445
5446 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5447
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005448#ifdef FEATURE_WLAN_TDLS
5449 if(0 != wlan_hdd_tdls_init(pAdapter))
5450 {
5451 status = VOS_STATUS_E_FAILURE;
5452 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5453 goto error_tdls_init;
5454 }
5455 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5456#endif
5457
Jeff Johnson295189b2012-06-20 16:38:30 -07005458 return VOS_STATUS_SUCCESS;
5459
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005460#ifdef FEATURE_WLAN_TDLS
5461error_tdls_init:
5462 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5463 hdd_wmm_adapter_close(pAdapter);
5464#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005465error_wmm_init:
5466 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5467 hdd_deinit_tx_rx(pAdapter);
5468error_init_txrx:
5469 hdd_UnregisterWext(pWlanDev);
5470error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005471 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005472 {
5473 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005474 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005475 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005476 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005477 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305478 unsigned long rc;
5479
Jeff Johnson295189b2012-06-20 16:38:30 -07005480 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305481 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005482 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005483 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305484 if (rc <= 0)
5485 hddLog(VOS_TRACE_LEVEL_ERROR,
5486 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005487 }
5488}
5489error_sme_open:
5490 return status;
5491}
5492
Jeff Johnson295189b2012-06-20 16:38:30 -07005493void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5494{
5495 hdd_cfg80211_state_t *cfgState;
5496
5497 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5498
5499 if( NULL != cfgState->buf )
5500 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305501 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07005502 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5503 rc = wait_for_completion_interruptible_timeout(
5504 &pAdapter->tx_action_cnf_event,
5505 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305506 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005507 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005508 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305509 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
5510 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005511 }
5512 }
5513 return;
5514}
Jeff Johnson295189b2012-06-20 16:38:30 -07005515
5516void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5517{
5518 ENTER();
5519 switch ( pAdapter->device_mode )
5520 {
5521 case WLAN_HDD_INFRA_STATION:
5522 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005523 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005524 {
5525 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5526 {
5527 hdd_deinit_tx_rx( pAdapter );
5528 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5529 }
5530
5531 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5532 {
5533 hdd_wmm_adapter_close( pAdapter );
5534 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5535 }
5536
Jeff Johnson295189b2012-06-20 16:38:30 -07005537 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005538#ifdef FEATURE_WLAN_TDLS
5539 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5540 {
5541 wlan_hdd_tdls_exit(pAdapter);
5542 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5543 }
5544#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005545
5546 break;
5547 }
5548
5549 case WLAN_HDD_SOFTAP:
5550 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005551 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305552
5553 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5554 {
5555 hdd_wmm_adapter_close( pAdapter );
5556 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5557 }
5558
Jeff Johnson295189b2012-06-20 16:38:30 -07005559 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005560
5561 hdd_unregister_hostapd(pAdapter);
5562 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005563 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005564 break;
5565 }
5566
5567 case WLAN_HDD_MONITOR:
5568 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005569 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005570 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5571 {
5572 hdd_deinit_tx_rx( pAdapter );
5573 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5574 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005575 if(NULL != pAdapterforTx)
5576 {
5577 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5578 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005579 break;
5580 }
5581
5582
5583 default:
5584 break;
5585 }
5586
5587 EXIT();
5588}
5589
5590void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5591{
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305592 struct net_device *pWlanDev;
5593
5594 ENTER();
5595 if (NULL == pAdapter)
5596 {
5597 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5598 "%s: HDD adapter is Null", __func__);
5599 return;
5600 }
5601
5602 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005603
Rajeev79dbe4c2013-10-05 11:03:42 +05305604#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305605 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
5606 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08005607 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305608 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
5609 )
5610 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005611 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05305612 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005613 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
5614 {
5615 hdd_deinit_batch_scan(pAdapter);
5616 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305617 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08005618 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305619#endif
5620
Jeff Johnson295189b2012-06-20 16:38:30 -07005621 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5622 if( rtnl_held )
5623 {
5624 unregister_netdevice(pWlanDev);
5625 }
5626 else
5627 {
5628 unregister_netdev(pWlanDev);
5629 }
5630 // note that the pAdapter is no longer valid at this point
5631 // since the memory has been reclaimed
5632 }
5633
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305634 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005635}
5636
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005637void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5638{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305639 VOS_STATUS status;
5640 hdd_adapter_t *pAdapter = NULL;
5641 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005642
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305643 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005644
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305645 /*loop through all adapters.*/
5646 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005647 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305648 pAdapter = pAdapterNode->pAdapter;
5649 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5650 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005651
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305652 { // we skip this registration for modes other than STA and P2P client modes.
5653 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5654 pAdapterNode = pNext;
5655 continue;
5656 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005657
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305658 //Apply Dynamic DTIM For P2P
5659 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5660 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5661 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5662 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5663 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5664 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5665 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5666 (eConnectionState_Associated ==
5667 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5668 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5669 {
5670 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005671
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305672 powerRequest.uIgnoreDTIM = 1;
5673 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5674
5675 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5676 {
5677 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5678 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5679 }
5680 else
5681 {
5682 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5683 }
5684
5685 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5686 * specified during Enter/Exit BMPS when LCD off*/
5687 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5688 NULL, eANI_BOOLEAN_FALSE);
5689 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5690 NULL, eANI_BOOLEAN_FALSE);
5691
5692 /* switch to the DTIM specified in cfg.ini */
5693 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5694 "Switch to DTIM %d", powerRequest.uListenInterval);
5695 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5696 break;
5697
5698 }
5699
5700 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5701 pAdapterNode = pNext;
5702 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005703}
5704
5705void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5706{
5707 /*Switch back to DTIM 1*/
5708 tSirSetPowerParamsReq powerRequest = { 0 };
5709
5710 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5711 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005712 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005713
5714 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5715 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5716 NULL, eANI_BOOLEAN_FALSE);
5717 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5718 NULL, eANI_BOOLEAN_FALSE);
5719
5720 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5721 "Switch to DTIM%d",powerRequest.uListenInterval);
5722 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5723
5724}
5725
Jeff Johnson295189b2012-06-20 16:38:30 -07005726VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5727{
5728 VOS_STATUS status = VOS_STATUS_SUCCESS;
5729
5730 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5731 {
5732 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5733 }
5734
5735 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5736 {
5737 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5738 }
5739
5740 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5741 {
5742 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5743 }
5744
5745 return status;
5746}
5747
5748VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5749{
5750 hdd_adapter_t *pAdapter = NULL;
5751 eHalStatus halStatus;
5752 VOS_STATUS status = VOS_STATUS_E_INVAL;
5753 v_BOOL_t disableBmps = FALSE;
5754 v_BOOL_t disableImps = FALSE;
5755
5756 switch(session_type)
5757 {
5758 case WLAN_HDD_INFRA_STATION:
5759 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005760 case WLAN_HDD_P2P_CLIENT:
5761 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005762 //Exit BMPS -> Is Sta/P2P Client is already connected
5763 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5764 if((NULL != pAdapter)&&
5765 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5766 {
5767 disableBmps = TRUE;
5768 }
5769
5770 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5771 if((NULL != pAdapter)&&
5772 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5773 {
5774 disableBmps = TRUE;
5775 }
5776
5777 //Exit both Bmps and Imps incase of Go/SAP Mode
5778 if((WLAN_HDD_SOFTAP == session_type) ||
5779 (WLAN_HDD_P2P_GO == session_type))
5780 {
5781 disableBmps = TRUE;
5782 disableImps = TRUE;
5783 }
5784
5785 if(TRUE == disableImps)
5786 {
5787 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5788 {
5789 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5790 }
5791 }
5792
5793 if(TRUE == disableBmps)
5794 {
5795 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5796 {
5797 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5798
5799 if(eHAL_STATUS_SUCCESS != halStatus)
5800 {
5801 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005802 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005803 VOS_ASSERT(0);
5804 return status;
5805 }
5806 }
5807
5808 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5809 {
5810 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5811
5812 if(eHAL_STATUS_SUCCESS != halStatus)
5813 {
5814 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005815 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005816 VOS_ASSERT(0);
5817 return status;
5818 }
5819 }
5820 }
5821
5822 if((TRUE == disableBmps) ||
5823 (TRUE == disableImps))
5824 {
5825 /* Now, get the chip into Full Power now */
5826 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5827 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5828 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5829
5830 if(halStatus != eHAL_STATUS_SUCCESS)
5831 {
5832 if(halStatus == eHAL_STATUS_PMC_PENDING)
5833 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305834 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005835 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305836 ret = wait_for_completion_interruptible_timeout(
5837 &pHddCtx->full_pwr_comp_var,
5838 msecs_to_jiffies(1000));
5839 if (ret <= 0)
5840 {
5841 hddLog(VOS_TRACE_LEVEL_ERROR,
5842 "%s: wait on full_pwr_comp_var failed %ld",
5843 __func__, ret);
5844 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005845 }
5846 else
5847 {
5848 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005849 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005850 VOS_ASSERT(0);
5851 return status;
5852 }
5853 }
5854
5855 status = VOS_STATUS_SUCCESS;
5856 }
5857
5858 break;
5859 }
5860 return status;
5861}
5862
5863hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005864 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005865 tANI_U8 rtnl_held )
5866{
5867 hdd_adapter_t *pAdapter = NULL;
5868 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5869 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5870 VOS_STATUS exitbmpsStatus;
5871
Arif Hussain6d2a3322013-11-17 19:50:10 -08005872 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005873
5874 //Disable BMPS incase of Concurrency
5875 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5876
5877 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5878 {
5879 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305880 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005881 VOS_ASSERT(0);
5882 return NULL;
5883 }
5884
5885 switch(session_type)
5886 {
5887 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005888 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005889 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005890 {
5891 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5892
5893 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305894 {
5895 hddLog(VOS_TRACE_LEVEL_FATAL,
5896 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005897 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305898 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005899
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305900#ifdef FEATURE_WLAN_TDLS
5901 /* A Mutex Lock is introduced while changing/initializing the mode to
5902 * protect the concurrent access for the Adapters by TDLS module.
5903 */
5904 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5905 {
5906 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5907 "%s: unable to lock list", __func__);
5908 return NULL;
5909 }
5910#endif
5911
Jeff Johnsone7245742012-09-05 17:12:55 -07005912 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5913 NL80211_IFTYPE_P2P_CLIENT:
5914 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005915
Jeff Johnson295189b2012-06-20 16:38:30 -07005916 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305917#ifdef FEATURE_WLAN_TDLS
5918 mutex_unlock(&pHddCtx->tdls_lock);
5919#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05305920
5921 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005922 if( VOS_STATUS_SUCCESS != status )
5923 goto err_free_netdev;
5924
5925 status = hdd_register_interface( pAdapter, rtnl_held );
5926 if( VOS_STATUS_SUCCESS != status )
5927 {
5928 hdd_deinit_adapter(pHddCtx, pAdapter);
5929 goto err_free_netdev;
5930 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305931
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05305932 // Workqueue which gets scheduled in IPv4 notification callback.
5933 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
5934
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305935#ifdef WLAN_NS_OFFLOAD
5936 // Workqueue which gets scheduled in IPv6 notification callback.
5937 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
5938#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005939 //Stop the Interface TX queue.
5940 netif_tx_disable(pAdapter->dev);
5941 //netif_tx_disable(pWlanDev);
5942 netif_carrier_off(pAdapter->dev);
5943
5944 break;
5945 }
5946
Jeff Johnson295189b2012-06-20 16:38:30 -07005947 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005948 case WLAN_HDD_SOFTAP:
5949 {
5950 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5951 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305952 {
5953 hddLog(VOS_TRACE_LEVEL_FATAL,
5954 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005955 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305956 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005957
Jeff Johnson295189b2012-06-20 16:38:30 -07005958 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5959 NL80211_IFTYPE_AP:
5960 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005961 pAdapter->device_mode = session_type;
5962
5963 status = hdd_init_ap_mode(pAdapter);
5964 if( VOS_STATUS_SUCCESS != status )
5965 goto err_free_netdev;
5966
5967 status = hdd_register_hostapd( pAdapter, rtnl_held );
5968 if( VOS_STATUS_SUCCESS != status )
5969 {
5970 hdd_deinit_adapter(pHddCtx, pAdapter);
5971 goto err_free_netdev;
5972 }
5973
5974 netif_tx_disable(pAdapter->dev);
5975 netif_carrier_off(pAdapter->dev);
5976
5977 hdd_set_conparam( 1 );
5978 break;
5979 }
5980 case WLAN_HDD_MONITOR:
5981 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005982 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5983 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305984 {
5985 hddLog(VOS_TRACE_LEVEL_FATAL,
5986 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005987 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305988 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005989
5990 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5991 pAdapter->device_mode = session_type;
5992 status = hdd_register_interface( pAdapter, rtnl_held );
5993#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5994 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5995#else
5996 pAdapter->dev->open = hdd_mon_open;
5997 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5998#endif
5999 hdd_init_tx_rx( pAdapter );
6000 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6001 //Set adapter to be used for data tx. It will use either GO or softap.
6002 pAdapter->sessionCtx.monitor.pAdapterForTx =
6003 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07006004 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
6005 {
6006 pAdapter->sessionCtx.monitor.pAdapterForTx =
6007 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
6008 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006009 /* This workqueue will be used to transmit management packet over
6010 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006011 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
6012 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
6013 return NULL;
6014 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07006015
Jeff Johnson295189b2012-06-20 16:38:30 -07006016 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
6017 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006018 }
6019 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006020 case WLAN_HDD_FTM:
6021 {
6022 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6023
6024 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306025 {
6026 hddLog(VOS_TRACE_LEVEL_FATAL,
6027 FL("failed to allocate adapter for session %d"), session_type);
6028 return NULL;
6029 }
6030
Jeff Johnson295189b2012-06-20 16:38:30 -07006031 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6032 * message while loading driver in FTM mode. */
6033 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6034 pAdapter->device_mode = session_type;
6035 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306036
6037 hdd_init_tx_rx( pAdapter );
6038
6039 //Stop the Interface TX queue.
6040 netif_tx_disable(pAdapter->dev);
6041 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006042 }
6043 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006044 default:
6045 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306046 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6047 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006048 VOS_ASSERT(0);
6049 return NULL;
6050 }
6051 }
6052
Jeff Johnson295189b2012-06-20 16:38:30 -07006053 if( VOS_STATUS_SUCCESS == status )
6054 {
6055 //Add it to the hdd's session list.
6056 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6057 if( NULL == pHddAdapterNode )
6058 {
6059 status = VOS_STATUS_E_NOMEM;
6060 }
6061 else
6062 {
6063 pHddAdapterNode->pAdapter = pAdapter;
6064 status = hdd_add_adapter_back ( pHddCtx,
6065 pHddAdapterNode );
6066 }
6067 }
6068
6069 if( VOS_STATUS_SUCCESS != status )
6070 {
6071 if( NULL != pAdapter )
6072 {
6073 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6074 pAdapter = NULL;
6075 }
6076 if( NULL != pHddAdapterNode )
6077 {
6078 vos_mem_free( pHddAdapterNode );
6079 }
6080
6081 goto resume_bmps;
6082 }
6083
6084 if(VOS_STATUS_SUCCESS == status)
6085 {
6086 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6087
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006088 //Initialize the WoWL service
6089 if(!hdd_init_wowl(pAdapter))
6090 {
6091 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6092 goto err_free_netdev;
6093 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006094 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006095 return pAdapter;
6096
6097err_free_netdev:
6098 free_netdev(pAdapter->dev);
6099 wlan_hdd_release_intf_addr( pHddCtx,
6100 pAdapter->macAddressCurrent.bytes );
6101
6102resume_bmps:
6103 //If bmps disabled enable it
6104 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6105 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306106 if (pHddCtx->hdd_wlan_suspended)
6107 {
6108 hdd_set_pwrparams(pHddCtx);
6109 }
6110 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006111 }
6112 return NULL;
6113}
6114
6115VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6116 tANI_U8 rtnl_held )
6117{
6118 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6119 VOS_STATUS status;
6120
6121 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6122 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306123 {
6124 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6125 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006126 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306127 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006128
6129 while ( pCurrent->pAdapter != pAdapter )
6130 {
6131 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6132 if( VOS_STATUS_SUCCESS != status )
6133 break;
6134
6135 pCurrent = pNext;
6136 }
6137 pAdapterNode = pCurrent;
6138 if( VOS_STATUS_SUCCESS == status )
6139 {
6140 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6141 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306142
6143#ifdef FEATURE_WLAN_TDLS
6144
6145 /* A Mutex Lock is introduced while changing/initializing the mode to
6146 * protect the concurrent access for the Adapters by TDLS module.
6147 */
6148 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
6149 {
6150 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6151 "%s: unable to lock list", __func__);
6152 return VOS_STATUS_E_FAILURE;
6153 }
6154#endif
6155
Jeff Johnson295189b2012-06-20 16:38:30 -07006156 hdd_remove_adapter( pHddCtx, pAdapterNode );
6157 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006158 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006159
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306160#ifdef FEATURE_WLAN_TDLS
6161 mutex_unlock(&pHddCtx->tdls_lock);
6162#endif
6163
Jeff Johnson295189b2012-06-20 16:38:30 -07006164
6165 /* If there is a single session of STA/P2P client, re-enable BMPS */
6166 if ((!vos_concurrent_sessions_running()) &&
6167 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6168 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6169 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306170 if (pHddCtx->hdd_wlan_suspended)
6171 {
6172 hdd_set_pwrparams(pHddCtx);
6173 }
6174 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006175 }
6176
6177 return VOS_STATUS_SUCCESS;
6178 }
6179
6180 return VOS_STATUS_E_FAILURE;
6181}
6182
6183VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6184{
6185 hdd_adapter_list_node_t *pHddAdapterNode;
6186 VOS_STATUS status;
6187
6188 ENTER();
6189
6190 do
6191 {
6192 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6193 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6194 {
6195 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6196 vos_mem_free( pHddAdapterNode );
6197 }
6198 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6199
6200 EXIT();
6201
6202 return VOS_STATUS_SUCCESS;
6203}
6204
6205void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6206{
6207 v_U8_t addIE[1] = {0};
6208
6209 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6210 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6211 eANI_BOOLEAN_FALSE) )
6212 {
6213 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006214 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006215 }
6216
6217 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6218 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6219 eANI_BOOLEAN_FALSE) )
6220 {
6221 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006222 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006223 }
6224
6225 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6226 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6227 eANI_BOOLEAN_FALSE) )
6228 {
6229 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006230 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006231 }
6232}
6233
6234VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6235{
6236 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6237 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6238 union iwreq_data wrqu;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306239 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006240
6241 ENTER();
6242
6243 switch(pAdapter->device_mode)
6244 {
6245 case WLAN_HDD_INFRA_STATION:
6246 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006247 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006248 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6249 {
6250 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6251 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6252 pAdapter->sessionId,
6253 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6254 else
6255 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6256 pAdapter->sessionId,
6257 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6258 //success implies disconnect command got queued up successfully
6259 if(halStatus == eHAL_STATUS_SUCCESS)
6260 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306261 ret = wait_for_completion_interruptible_timeout(
6262 &pAdapter->disconnect_comp_var,
6263 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6264 if (ret <= 0)
6265 {
6266 hddLog(VOS_TRACE_LEVEL_ERROR,
6267 "%s: wait on disconnect_comp_var failed %ld",
6268 __func__, ret);
6269 }
6270 }
6271 else
6272 {
6273 hddLog(LOGE, "%s: failed to post disconnect event to SME",
6274 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006275 }
6276 memset(&wrqu, '\0', sizeof(wrqu));
6277 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6278 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6279 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6280 }
6281 else
6282 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306283 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006284 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306285#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306286#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306287 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6288#endif
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306289 if (pAdapter->ipv6_notifier_registered)
6290 {
6291 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
6292 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
6293 pAdapter->ipv6_notifier_registered = false;
6294 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306295#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306296 if (pAdapter->ipv4_notifier_registered)
6297 {
6298 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6299 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6300 pAdapter->ipv4_notifier_registered = false;
6301 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306302#ifdef WLAN_OPEN_SOURCE
6303 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6304#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006305 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6306 {
6307 INIT_COMPLETION(pAdapter->session_close_comp_var);
6308 if (eHAL_STATUS_SUCCESS ==
6309 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6310 hdd_smeCloseSessionCallback, pAdapter))
6311 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306312 unsigned long ret;
6313
Jeff Johnson295189b2012-06-20 16:38:30 -07006314 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306315 ret = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006316 &pAdapter->session_close_comp_var,
6317 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306318 if ( 0 >= ret)
6319 {
6320 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
6321 __func__, ret);
6322 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006323 }
6324 }
6325
6326 break;
6327
6328 case WLAN_HDD_SOFTAP:
6329 case WLAN_HDD_P2P_GO:
6330 //Any softap specific cleanup here...
6331 mutex_lock(&pHddCtx->sap_lock);
6332 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6333 {
6334 VOS_STATUS status;
6335 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6336
6337 //Stop Bss.
6338 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6339 if (VOS_IS_STATUS_SUCCESS(status))
6340 {
6341 hdd_hostapd_state_t *pHostapdState =
6342 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6343
6344 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6345
6346 if (!VOS_IS_STATUS_SUCCESS(status))
6347 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306348 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
6349 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006350 }
6351 }
6352 else
6353 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006354 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006355 }
6356 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6357
6358 if (eHAL_STATUS_FAILURE ==
6359 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6360 0, NULL, eANI_BOOLEAN_FALSE))
6361 {
6362 hddLog(LOGE,
6363 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006364 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006365 }
6366
6367 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6368 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6369 eANI_BOOLEAN_FALSE) )
6370 {
6371 hddLog(LOGE,
6372 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6373 }
6374
6375 // Reset WNI_CFG_PROBE_RSP Flags
6376 wlan_hdd_reset_prob_rspies(pAdapter);
6377 kfree(pAdapter->sessionCtx.ap.beacon);
6378 pAdapter->sessionCtx.ap.beacon = NULL;
6379 }
6380 mutex_unlock(&pHddCtx->sap_lock);
6381 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006382
Jeff Johnson295189b2012-06-20 16:38:30 -07006383 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006384#ifdef WLAN_OPEN_SOURCE
6385 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6386#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006387 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006388
Jeff Johnson295189b2012-06-20 16:38:30 -07006389 default:
6390 break;
6391 }
6392
6393 EXIT();
6394 return VOS_STATUS_SUCCESS;
6395}
6396
6397VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6398{
6399 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6400 VOS_STATUS status;
6401 hdd_adapter_t *pAdapter;
6402
6403 ENTER();
6404
6405 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6406
6407 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6408 {
6409 pAdapter = pAdapterNode->pAdapter;
6410 netif_tx_disable(pAdapter->dev);
6411 netif_carrier_off(pAdapter->dev);
6412
6413 hdd_stop_adapter( pHddCtx, pAdapter );
6414
6415 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6416 pAdapterNode = pNext;
6417 }
6418
6419 EXIT();
6420
6421 return VOS_STATUS_SUCCESS;
6422}
6423
Rajeev Kumarf999e582014-01-09 17:33:29 -08006424
6425#ifdef FEATURE_WLAN_BATCH_SCAN
6426/**---------------------------------------------------------------------------
6427
6428 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
6429 structures
6430
6431 \param - pAdapter Pointer to HDD adapter
6432
6433 \return - None
6434
6435 --------------------------------------------------------------------------*/
6436void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
6437{
6438 tHddBatchScanRsp *pNode;
6439 tHddBatchScanRsp *pPrev;
6440
6441 if (pAdapter)
6442 {
6443 pNode = pAdapter->pBatchScanRsp;
6444 while (pNode)
6445 {
6446 pPrev = pNode;
6447 pNode = pNode->pNext;
6448 vos_mem_free((v_VOID_t * )pPrev);
6449 }
6450 pAdapter->pBatchScanRsp = NULL;
6451 }
6452
6453 pAdapter->pBatchScanRsp = NULL;
6454 pAdapter->numScanList = 0;
6455 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
6456 pAdapter->prev_batch_id = 0;
6457
6458 return;
6459}
6460#endif
6461
6462
Jeff Johnson295189b2012-06-20 16:38:30 -07006463VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6464{
6465 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6466 VOS_STATUS status;
6467 hdd_adapter_t *pAdapter;
6468
6469 ENTER();
6470
6471 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6472
6473 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6474 {
6475 pAdapter = pAdapterNode->pAdapter;
6476 netif_tx_disable(pAdapter->dev);
6477 netif_carrier_off(pAdapter->dev);
6478
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006479 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6480
Jeff Johnson295189b2012-06-20 16:38:30 -07006481 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306482 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6483 {
6484 hdd_wmm_adapter_close( pAdapter );
6485 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6486 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006487
Rajeev Kumarf999e582014-01-09 17:33:29 -08006488#ifdef FEATURE_WLAN_BATCH_SCAN
6489 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6490 {
6491 hdd_deinit_batch_scan(pAdapter);
6492 }
6493#endif
6494
Jeff Johnson295189b2012-06-20 16:38:30 -07006495 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6496 pAdapterNode = pNext;
6497 }
6498
6499 EXIT();
6500
6501 return VOS_STATUS_SUCCESS;
6502}
6503
6504VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6505{
6506 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6507 VOS_STATUS status;
6508 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306509 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006510
6511 ENTER();
6512
6513 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6514
6515 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6516 {
6517 pAdapter = pAdapterNode->pAdapter;
6518
6519 switch(pAdapter->device_mode)
6520 {
6521 case WLAN_HDD_INFRA_STATION:
6522 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006523 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306524
6525 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6526
Jeff Johnson295189b2012-06-20 16:38:30 -07006527 hdd_init_station_mode(pAdapter);
6528 /* Open the gates for HDD to receive Wext commands */
6529 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006530 pHddCtx->scan_info.mScanPending = FALSE;
6531 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006532
6533 //Trigger the initial scan
6534 hdd_wlan_initial_scan(pAdapter);
6535
6536 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306537 if (eConnectionState_Associated == connState ||
6538 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006539 {
6540 union iwreq_data wrqu;
6541 memset(&wrqu, '\0', sizeof(wrqu));
6542 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6543 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6544 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006545 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006546
Jeff Johnson295189b2012-06-20 16:38:30 -07006547 /* indicate disconnected event to nl80211 */
6548 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6549 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006550 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306551 else if (eConnectionState_Connecting == connState)
6552 {
6553 /*
6554 * Indicate connect failure to supplicant if we were in the
6555 * process of connecting
6556 */
6557 cfg80211_connect_result(pAdapter->dev, NULL,
6558 NULL, 0, NULL, 0,
6559 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6560 GFP_KERNEL);
6561 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006562 break;
6563
6564 case WLAN_HDD_SOFTAP:
6565 /* softAP can handle SSR */
6566 break;
6567
6568 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006569 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006570 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006571 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006572 break;
6573
6574 case WLAN_HDD_MONITOR:
6575 /* monitor interface start */
6576 break;
6577 default:
6578 break;
6579 }
6580
6581 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6582 pAdapterNode = pNext;
6583 }
6584
6585 EXIT();
6586
6587 return VOS_STATUS_SUCCESS;
6588}
6589
6590VOS_STATUS hdd_reconnect_all_adapters( 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 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306596 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006597
6598 ENTER();
6599
6600 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6601
6602 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6603 {
6604 pAdapter = pAdapterNode->pAdapter;
6605
6606 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6607 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6608 {
6609 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6610 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6611
6612 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6613 init_completion(&pAdapter->disconnect_comp_var);
6614 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6615 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6616
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306617 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006618 &pAdapter->disconnect_comp_var,
6619 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306620 if (0 >= ret)
6621 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
6622 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07006623
6624 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6625 pHddCtx->isAmpAllowed = VOS_FALSE;
6626 sme_RoamConnect(pHddCtx->hHal,
6627 pAdapter->sessionId, &(pWextState->roamProfile),
6628 &roamId);
6629 }
6630
6631 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6632 pAdapterNode = pNext;
6633 }
6634
6635 EXIT();
6636
6637 return VOS_STATUS_SUCCESS;
6638}
6639
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006640void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6641{
6642 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6643 VOS_STATUS status;
6644 hdd_adapter_t *pAdapter;
6645 hdd_station_ctx_t *pHddStaCtx;
6646 hdd_ap_ctx_t *pHddApCtx;
6647 hdd_hostapd_state_t * pHostapdState;
6648 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6649 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6650 const char *p2pMode = "DEV";
6651 const char *ccMode = "Standalone";
6652 int n;
6653
6654 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6655 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6656 {
6657 pAdapter = pAdapterNode->pAdapter;
6658 switch (pAdapter->device_mode) {
6659 case WLAN_HDD_INFRA_STATION:
6660 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6661 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6662 staChannel = pHddStaCtx->conn_info.operationChannel;
6663 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6664 }
6665 break;
6666 case WLAN_HDD_P2P_CLIENT:
6667 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6668 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6669 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6670 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6671 p2pMode = "CLI";
6672 }
6673 break;
6674 case WLAN_HDD_P2P_GO:
6675 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6676 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6677 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6678 p2pChannel = pHddApCtx->operatingChannel;
6679 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6680 }
6681 p2pMode = "GO";
6682 break;
6683 case WLAN_HDD_SOFTAP:
6684 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6685 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6686 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6687 apChannel = pHddApCtx->operatingChannel;
6688 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6689 }
6690 break;
6691 default:
6692 break;
6693 }
6694 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6695 pAdapterNode = pNext;
6696 }
6697 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6698 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6699 }
6700 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6701 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6702 if (p2pChannel > 0) {
6703 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6704 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6705 }
6706 if (apChannel > 0) {
6707 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6708 apChannel, MAC_ADDR_ARRAY(apBssid));
6709 }
6710
6711 if (p2pChannel > 0 && apChannel > 0) {
6712 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6713 }
6714}
6715
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006716bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006717{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006718 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006719}
6720
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006721/* Once SSR is disabled then it cannot be set. */
6722void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006723{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006724 if (HDD_SSR_DISABLED == isSsrRequired)
6725 return;
6726
Jeff Johnson295189b2012-06-20 16:38:30 -07006727 isSsrRequired = value;
6728}
6729
6730VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6731 hdd_adapter_list_node_t** ppAdapterNode)
6732{
6733 VOS_STATUS status;
6734 spin_lock(&pHddCtx->hddAdapters.lock);
6735 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6736 (hdd_list_node_t**) ppAdapterNode );
6737 spin_unlock(&pHddCtx->hddAdapters.lock);
6738 return status;
6739}
6740
6741VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6742 hdd_adapter_list_node_t* pAdapterNode,
6743 hdd_adapter_list_node_t** pNextAdapterNode)
6744{
6745 VOS_STATUS status;
6746 spin_lock(&pHddCtx->hddAdapters.lock);
6747 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6748 (hdd_list_node_t*) pAdapterNode,
6749 (hdd_list_node_t**)pNextAdapterNode );
6750
6751 spin_unlock(&pHddCtx->hddAdapters.lock);
6752 return status;
6753}
6754
6755VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6756 hdd_adapter_list_node_t* pAdapterNode)
6757{
6758 VOS_STATUS status;
6759 spin_lock(&pHddCtx->hddAdapters.lock);
6760 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6761 &pAdapterNode->node );
6762 spin_unlock(&pHddCtx->hddAdapters.lock);
6763 return status;
6764}
6765
6766VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6767 hdd_adapter_list_node_t** ppAdapterNode)
6768{
6769 VOS_STATUS status;
6770 spin_lock(&pHddCtx->hddAdapters.lock);
6771 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6772 (hdd_list_node_t**) ppAdapterNode );
6773 spin_unlock(&pHddCtx->hddAdapters.lock);
6774 return status;
6775}
6776
6777VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6778 hdd_adapter_list_node_t* pAdapterNode)
6779{
6780 VOS_STATUS status;
6781 spin_lock(&pHddCtx->hddAdapters.lock);
6782 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6783 (hdd_list_node_t*) pAdapterNode );
6784 spin_unlock(&pHddCtx->hddAdapters.lock);
6785 return status;
6786}
6787
6788VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6789 hdd_adapter_list_node_t* pAdapterNode)
6790{
6791 VOS_STATUS status;
6792 spin_lock(&pHddCtx->hddAdapters.lock);
6793 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6794 (hdd_list_node_t*) pAdapterNode );
6795 spin_unlock(&pHddCtx->hddAdapters.lock);
6796 return status;
6797}
6798
6799hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6800 tSirMacAddr macAddr )
6801{
6802 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6803 hdd_adapter_t *pAdapter;
6804 VOS_STATUS status;
6805
6806 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6807
6808 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6809 {
6810 pAdapter = pAdapterNode->pAdapter;
6811
6812 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6813 macAddr, sizeof(tSirMacAddr) ) )
6814 {
6815 return pAdapter;
6816 }
6817 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6818 pAdapterNode = pNext;
6819 }
6820
6821 return NULL;
6822
6823}
6824
6825hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6826{
6827 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6828 hdd_adapter_t *pAdapter;
6829 VOS_STATUS status;
6830
6831 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6832
6833 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6834 {
6835 pAdapter = pAdapterNode->pAdapter;
6836
6837 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6838 IFNAMSIZ ) )
6839 {
6840 return pAdapter;
6841 }
6842 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6843 pAdapterNode = pNext;
6844 }
6845
6846 return NULL;
6847
6848}
6849
6850hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6851{
6852 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6853 hdd_adapter_t *pAdapter;
6854 VOS_STATUS status;
6855
6856 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6857
6858 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6859 {
6860 pAdapter = pAdapterNode->pAdapter;
6861
6862 if( pAdapter && (mode == pAdapter->device_mode) )
6863 {
6864 return pAdapter;
6865 }
6866 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6867 pAdapterNode = pNext;
6868 }
6869
6870 return NULL;
6871
6872}
6873
6874//Remove this function later
6875hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6876{
6877 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6878 hdd_adapter_t *pAdapter;
6879 VOS_STATUS status;
6880
6881 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6882
6883 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6884 {
6885 pAdapter = pAdapterNode->pAdapter;
6886
6887 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6888 {
6889 return pAdapter;
6890 }
6891
6892 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6893 pAdapterNode = pNext;
6894 }
6895
6896 return NULL;
6897
6898}
6899
Jeff Johnson295189b2012-06-20 16:38:30 -07006900/**---------------------------------------------------------------------------
6901
6902 \brief hdd_set_monitor_tx_adapter() -
6903
6904 This API initializes the adapter to be used while transmitting on monitor
6905 adapter.
6906
6907 \param - pHddCtx - Pointer to the HDD context.
6908 pAdapter - Adapter that will used for TX. This can be NULL.
6909 \return - None.
6910 --------------------------------------------------------------------------*/
6911void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6912{
6913 hdd_adapter_t *pMonAdapter;
6914
6915 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6916
6917 if( NULL != pMonAdapter )
6918 {
6919 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6920 }
6921}
Jeff Johnson295189b2012-06-20 16:38:30 -07006922/**---------------------------------------------------------------------------
6923
6924 \brief hdd_select_queue() -
6925
6926 This API returns the operating channel of the requested device mode
6927
6928 \param - pHddCtx - Pointer to the HDD context.
6929 - mode - Device mode for which operating channel is required
6930 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6931 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6932 \return - channel number. "0" id the requested device is not found OR it is not connected.
6933 --------------------------------------------------------------------------*/
6934v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6935{
6936 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6937 VOS_STATUS status;
6938 hdd_adapter_t *pAdapter;
6939 v_U8_t operatingChannel = 0;
6940
6941 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6942
6943 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6944 {
6945 pAdapter = pAdapterNode->pAdapter;
6946
6947 if( mode == pAdapter->device_mode )
6948 {
6949 switch(pAdapter->device_mode)
6950 {
6951 case WLAN_HDD_INFRA_STATION:
6952 case WLAN_HDD_P2P_CLIENT:
6953 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6954 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6955 break;
6956 case WLAN_HDD_SOFTAP:
6957 case WLAN_HDD_P2P_GO:
6958 /*softap connection info */
6959 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6960 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6961 break;
6962 default:
6963 break;
6964 }
6965
6966 break; //Found the device of interest. break the loop
6967 }
6968
6969 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6970 pAdapterNode = pNext;
6971 }
6972 return operatingChannel;
6973}
6974
6975#ifdef WLAN_FEATURE_PACKET_FILTERING
6976/**---------------------------------------------------------------------------
6977
6978 \brief hdd_set_multicast_list() -
6979
6980 This used to set the multicast address list.
6981
6982 \param - dev - Pointer to the WLAN device.
6983 - skb - Pointer to OS packet (sk_buff).
6984 \return - success/fail
6985
6986 --------------------------------------------------------------------------*/
6987static void hdd_set_multicast_list(struct net_device *dev)
6988{
6989 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006990 int mc_count;
6991 int i = 0;
6992 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306993
6994 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006995 {
6996 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306997 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006998 return;
6999 }
7000
7001 if (dev->flags & IFF_ALLMULTI)
7002 {
7003 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007004 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307005 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007006 }
7007 else
7008 {
7009 mc_count = netdev_mc_count(dev);
7010 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007011 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07007012 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
7013 {
7014 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007015 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307016 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007017 return;
7018 }
7019
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307020 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007021
7022 netdev_for_each_mc_addr(ha, dev) {
7023 if (i == mc_count)
7024 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307025 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7026 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007027 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007028 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307029 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007030 i++;
7031 }
7032 }
7033 return;
7034}
7035#endif
7036
7037/**---------------------------------------------------------------------------
7038
7039 \brief hdd_select_queue() -
7040
7041 This function is registered with the Linux OS for network
7042 core to decide which queue to use first.
7043
7044 \param - dev - Pointer to the WLAN device.
7045 - skb - Pointer to OS packet (sk_buff).
7046 \return - ac, Queue Index/access category corresponding to UP in IP header
7047
7048 --------------------------------------------------------------------------*/
7049v_U16_t hdd_select_queue(struct net_device *dev,
7050 struct sk_buff *skb)
7051{
7052 return hdd_wmm_select_queue(dev, skb);
7053}
7054
7055
7056/**---------------------------------------------------------------------------
7057
7058 \brief hdd_wlan_initial_scan() -
7059
7060 This function triggers the initial scan
7061
7062 \param - pAdapter - Pointer to the HDD adapter.
7063
7064 --------------------------------------------------------------------------*/
7065void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
7066{
7067 tCsrScanRequest scanReq;
7068 tCsrChannelInfo channelInfo;
7069 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07007070 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007071 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7072
7073 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
7074 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
7075 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
7076
7077 if(sme_Is11dSupported(pHddCtx->hHal))
7078 {
7079 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
7080 if ( HAL_STATUS_SUCCESS( halStatus ) )
7081 {
7082 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
7083 if( !scanReq.ChannelInfo.ChannelList )
7084 {
7085 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
7086 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007087 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007088 return;
7089 }
7090 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
7091 channelInfo.numOfChannels);
7092 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
7093 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007094 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007095 }
7096
7097 scanReq.scanType = eSIR_PASSIVE_SCAN;
7098 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
7099 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
7100 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7101 }
7102 else
7103 {
7104 scanReq.scanType = eSIR_ACTIVE_SCAN;
7105 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7106 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7107 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7108 }
7109
7110 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7111 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7112 {
7113 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7114 __func__, halStatus );
7115 }
7116
7117 if(sme_Is11dSupported(pHddCtx->hHal))
7118 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7119}
7120
Jeff Johnson295189b2012-06-20 16:38:30 -07007121/**---------------------------------------------------------------------------
7122
7123 \brief hdd_full_power_callback() - HDD full power callback function
7124
7125 This is the function invoked by SME to inform the result of a full power
7126 request issued by HDD
7127
7128 \param - callbackcontext - Pointer to cookie
7129 \param - status - result of request
7130
7131 \return - None
7132
7133 --------------------------------------------------------------------------*/
7134static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7135{
Jeff Johnson72a40512013-12-19 10:14:15 -08007136 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007137
7138 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307139 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007140
7141 if (NULL == callbackContext)
7142 {
7143 hddLog(VOS_TRACE_LEVEL_ERROR,
7144 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007145 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007146 return;
7147 }
7148
Jeff Johnson72a40512013-12-19 10:14:15 -08007149 /* there is a race condition that exists between this callback
7150 function and the caller since the caller could time out either
7151 before or while this code is executing. we use a spinlock to
7152 serialize these actions */
7153 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007154
7155 if (POWER_CONTEXT_MAGIC != pContext->magic)
7156 {
7157 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007158 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007159 hddLog(VOS_TRACE_LEVEL_WARN,
7160 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007161 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007162 return;
7163 }
7164
Jeff Johnson72a40512013-12-19 10:14:15 -08007165 /* context is valid so caller is still waiting */
7166
7167 /* paranoia: invalidate the magic */
7168 pContext->magic = 0;
7169
7170 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007171 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007172
7173 /* serialization is complete */
7174 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007175}
7176
7177/**---------------------------------------------------------------------------
7178
7179 \brief hdd_wlan_exit() - HDD WLAN exit function
7180
7181 This is the driver exit point (invoked during rmmod)
7182
7183 \param - pHddCtx - Pointer to the HDD Context
7184
7185 \return - None
7186
7187 --------------------------------------------------------------------------*/
7188void hdd_wlan_exit(hdd_context_t *pHddCtx)
7189{
7190 eHalStatus halStatus;
7191 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7192 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307193 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007194 hdd_adapter_t* pAdapter;
Jeff Johnson72a40512013-12-19 10:14:15 -08007195 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007196 long lrc;
7197
7198 ENTER();
7199
Jeff Johnson88ba7742013-02-27 14:36:02 -08007200 if (VOS_FTM_MODE != hdd_get_conparam())
7201 {
7202 // Unloading, restart logic is no more required.
7203 wlan_hdd_restart_deinit(pHddCtx);
7204 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007205
Jeff Johnson295189b2012-06-20 16:38:30 -07007206 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007207 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007208 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007209 {
7210 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
7211 WLAN_HDD_INFRA_STATION);
7212 if (pAdapter == NULL)
7213 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
7214
7215 if (pAdapter != NULL)
7216 {
7217 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
7218 hdd_UnregisterWext(pAdapter->dev);
7219 }
7220 }
7221 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007222
Jeff Johnson295189b2012-06-20 16:38:30 -07007223 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08007224 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307225 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08007226 wlan_hdd_ftm_close(pHddCtx);
7227 goto free_hdd_ctx;
7228 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007229 //Stop the Interface TX queue.
7230 //netif_tx_disable(pWlanDev);
7231 //netif_carrier_off(pWlanDev);
7232
Jeff Johnson295189b2012-06-20 16:38:30 -07007233 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7234 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307235 hddLog(VOS_TRACE_LEVEL_INFO,"%s: SAP MODE",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007236 pAdapter = hdd_get_adapter(pHddCtx,
7237 WLAN_HDD_SOFTAP);
7238 }
7239 else
7240 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007241 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007242 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307243 hddLog(VOS_TRACE_LEVEL_INFO,"%s: STA MODE",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007244 pAdapter = hdd_get_adapter(pHddCtx,
7245 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007246 if (pAdapter == NULL)
7247 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07007248 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007249 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307250
7251 if(NULL == pAdapter)
7252 {
7253 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: pAdapter is NULL",__func__);
7254 goto free_hdd_ctx;
7255 }
7256
Jeff Johnson295189b2012-06-20 16:38:30 -07007257 /* DeRegister with platform driver as client for Suspend/Resume */
7258 vosStatus = hddDeregisterPmOps(pHddCtx);
7259 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7260 {
7261 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7262 VOS_ASSERT(0);
7263 }
7264
7265 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7266 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7267 {
7268 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7269 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007270
7271 // Cancel any outstanding scan requests. We are about to close all
7272 // of our adapters, but an adapter structure is what SME passes back
7273 // to our callback function. Hence if there are any outstanding scan
7274 // requests then there is a race condition between when the adapter
7275 // is closed and when the callback is invoked. We try to resolve that
7276 // race condition here by canceling any outstanding scans before we
7277 // close the adapters.
7278 // Note that the scans may be cancelled in an asynchronous manner, so
7279 // ideally there needs to be some kind of synchronization. Rather than
7280 // introduce a new synchronization here, we will utilize the fact that
7281 // we are about to Request Full Power, and since that is synchronized,
7282 // the expectation is that by the time Request Full Power has completed,
7283 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007284 if (NULL != pAdapter)
7285 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
7286 else
7287 hddLog(VOS_TRACE_LEVEL_ERROR,
7288 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007289
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007290 //Stop the traffic monitor timer
7291 if ( VOS_TIMER_STATE_RUNNING ==
7292 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7293 {
7294 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7295 }
7296
7297 // Destroy the traffic monitor timer
7298 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7299 &pHddCtx->tx_rx_trafficTmr)))
7300 {
7301 hddLog(VOS_TRACE_LEVEL_ERROR,
7302 "%s: Cannot deallocate Traffic monitor timer", __func__);
7303 }
7304
Jeff Johnson295189b2012-06-20 16:38:30 -07007305 //Disable IMPS/BMPS as we do not want the device to enter any power
7306 //save mode during shutdown
7307 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7308 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7309 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7310
7311 //Ensure that device is in full power as we will touch H/W during vos_Stop
7312 init_completion(&powerContext.completion);
7313 powerContext.magic = POWER_CONTEXT_MAGIC;
7314
7315 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7316 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7317
7318 if (eHAL_STATUS_SUCCESS != halStatus)
7319 {
7320 if (eHAL_STATUS_PMC_PENDING == halStatus)
7321 {
7322 /* request was sent -- wait for the response */
7323 lrc = wait_for_completion_interruptible_timeout(
7324 &powerContext.completion,
7325 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007326 if (lrc <= 0)
7327 {
7328 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007329 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007330 }
7331 }
7332 else
7333 {
7334 hddLog(VOS_TRACE_LEVEL_ERROR,
7335 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007336 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007337 /* continue -- need to clean up as much as possible */
7338 }
7339 }
7340
Jeff Johnson72a40512013-12-19 10:14:15 -08007341 /* either we never sent a request, we sent a request and received a
7342 response or we sent a request and timed out. if we never sent a
7343 request or if we sent a request and got a response, we want to
7344 clear the magic out of paranoia. if we timed out there is a
7345 race condition such that the callback function could be
7346 executing at the same time we are. of primary concern is if the
7347 callback function had already verified the "magic" but had not
7348 yet set the completion variable when a timeout occurred. we
7349 serialize these activities by invalidating the magic while
7350 holding a shared spinlock which will cause us to block if the
7351 callback is currently executing */
7352 spin_lock(&hdd_context_lock);
7353 powerContext.magic = 0;
7354 spin_unlock(&hdd_context_lock);
7355
Yue Ma0d4891e2013-08-06 17:01:45 -07007356 hdd_debugfs_exit(pHddCtx);
7357
Jeff Johnson295189b2012-06-20 16:38:30 -07007358 // Unregister the Net Device Notifier
7359 unregister_netdevice_notifier(&hdd_netdev_notifier);
7360
Jeff Johnson295189b2012-06-20 16:38:30 -07007361 hdd_stop_all_adapters( pHddCtx );
7362
Jeff Johnson295189b2012-06-20 16:38:30 -07007363#ifdef WLAN_BTAMP_FEATURE
7364 vosStatus = WLANBAP_Stop(pVosContext);
7365 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7366 {
7367 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7368 "%s: Failed to stop BAP",__func__);
7369 }
7370#endif //WLAN_BTAMP_FEATURE
7371
7372 //Stop all the modules
7373 vosStatus = vos_stop( pVosContext );
7374 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7375 {
7376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7377 "%s: Failed to stop VOSS",__func__);
7378 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7379 }
7380
Jeff Johnson295189b2012-06-20 16:38:30 -07007381 //Assert Deep sleep signal now to put Libra HW in lowest power state
7382 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7383 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7384
7385 //Vote off any PMIC voltage supplies
7386 vos_chipPowerDown(NULL, NULL, NULL);
7387
7388 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7389
Leo Chang59cdc7e2013-07-10 10:08:21 -07007390
Jeff Johnson295189b2012-06-20 16:38:30 -07007391 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007392 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007393
7394 //Close the scheduler before calling vos_close to make sure no thread is
7395 // scheduled after the each module close is called i.e after all the data
7396 // structures are freed.
7397 vosStatus = vos_sched_close( pVosContext );
7398 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7399 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7400 "%s: Failed to close VOSS Scheduler",__func__);
7401 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7402 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007403#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007404#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7405 /* Destroy the wake lock */
7406 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7407#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007408 /* Destroy the wake lock */
7409 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007410#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007411
Mihir Shete7a24b5f2013-12-21 12:18:31 +05307412#ifdef CONFIG_ENABLE_LINUX_REG
7413 vosStatus = vos_nv_close();
7414 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7415 {
7416 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7417 "%s: Failed to close NV", __func__);
7418 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7419 }
7420#endif
7421
Jeff Johnson295189b2012-06-20 16:38:30 -07007422 //Close VOSS
7423 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7424 vos_close(pVosContext);
7425
Jeff Johnson295189b2012-06-20 16:38:30 -07007426 //Close Watchdog
7427 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7428 vos_watchdog_close(pVosContext);
7429
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307430 //Clean up HDD Nlink Service
7431 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007432#ifdef WLAN_KD_READY_NOTIFIER
7433 nl_srv_exit(pHddCtx->ptt_pid);
7434#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307435 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007436#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307437
Jeff Johnson295189b2012-06-20 16:38:30 -07007438 /* Cancel the vote for XO Core ON.
7439 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7440 * exited at this point
7441 */
7442 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007443 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007444 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7445 {
7446 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7447 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007448 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007449 }
7450
7451 hdd_close_all_adapters( pHddCtx );
7452
7453
7454 //Free up dynamically allocated members inside HDD Adapter
7455 kfree(pHddCtx->cfg_ini);
7456 pHddCtx->cfg_ini= NULL;
7457
7458 /* free the power on lock from platform driver */
7459 if (free_riva_power_on_lock("wlan"))
7460 {
7461 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7462 __func__);
7463 }
7464
Jeff Johnson88ba7742013-02-27 14:36:02 -08007465free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007466 /* FTM mode, WIPHY did not registered
7467 If un-register here, system crash will happen */
7468 if (VOS_FTM_MODE != hdd_get_conparam())
7469 {
7470 wiphy_unregister(wiphy) ;
7471 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007472 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007473 if (hdd_is_ssr_required())
7474 {
7475 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007476 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007477 msleep(5000);
7478 }
7479 hdd_set_ssr_required (VOS_FALSE);
7480}
7481
7482
7483/**---------------------------------------------------------------------------
7484
7485 \brief hdd_update_config_from_nv() - Function to update the contents of
7486 the running configuration with parameters taken from NV storage
7487
7488 \param - pHddCtx - Pointer to the HDD global context
7489
7490 \return - VOS_STATUS_SUCCESS if successful
7491
7492 --------------------------------------------------------------------------*/
7493static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7494{
Jeff Johnson295189b2012-06-20 16:38:30 -07007495 v_BOOL_t itemIsValid = VOS_FALSE;
7496 VOS_STATUS status;
7497 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7498 v_U8_t macLoop;
7499
7500 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7501 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7502 if(status != VOS_STATUS_SUCCESS)
7503 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007504 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007505 return VOS_STATUS_E_FAILURE;
7506 }
7507
7508 if (itemIsValid == VOS_TRUE)
7509 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007510 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007511 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7512 VOS_MAX_CONCURRENCY_PERSONA);
7513 if(status != VOS_STATUS_SUCCESS)
7514 {
7515 /* Get MAC from NV fail, not update CFG info
7516 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08007517 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007518 return VOS_STATUS_E_FAILURE;
7519 }
7520
7521 /* If first MAC is not valid, treat all others are not valid
7522 * Then all MACs will be got from ini file */
7523 if(vos_is_macaddr_zero(&macFromNV[0]))
7524 {
7525 /* MAC address in NV file is not configured yet */
7526 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7527 return VOS_STATUS_E_INVAL;
7528 }
7529
7530 /* Get MAC address from NV, update CFG info */
7531 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7532 {
7533 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7534 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307535 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07007536 /* This MAC is not valid, skip it
7537 * This MAC will be got from ini file */
7538 }
7539 else
7540 {
7541 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7542 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7543 VOS_MAC_ADDR_SIZE);
7544 }
7545 }
7546 }
7547 else
7548 {
7549 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7550 return VOS_STATUS_E_FAILURE;
7551 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007552
Jeff Johnson295189b2012-06-20 16:38:30 -07007553
7554 return VOS_STATUS_SUCCESS;
7555}
7556
7557/**---------------------------------------------------------------------------
7558
7559 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7560
7561 \param - pAdapter - Pointer to the HDD
7562
7563 \return - None
7564
7565 --------------------------------------------------------------------------*/
7566VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7567{
7568 eHalStatus halStatus;
7569 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307570 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007571
Jeff Johnson295189b2012-06-20 16:38:30 -07007572
7573 // Send ready indication to the HDD. This will kick off the MAC
7574 // into a 'running' state and should kick off an initial scan.
7575 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7576 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7577 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307578 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007579 "code %08d [x%08x]",__func__, halStatus, halStatus );
7580 return VOS_STATUS_E_FAILURE;
7581 }
7582
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307583 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007584 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7585 // And RIVA will crash
7586 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7587 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307588 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7589 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7590
7591
Jeff Johnson295189b2012-06-20 16:38:30 -07007592 return VOS_STATUS_SUCCESS;
7593}
7594
Jeff Johnson295189b2012-06-20 16:38:30 -07007595/* wake lock APIs for HDD */
7596void hdd_prevent_suspend(void)
7597{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007598#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007599 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007600#else
7601 wcnss_prevent_suspend();
7602#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007603}
7604
7605void hdd_allow_suspend(void)
7606{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007607#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007608 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007609#else
7610 wcnss_allow_suspend();
7611#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007612}
7613
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05307614void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007615{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007616#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007617 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007618#else
7619 /* Do nothing as there is no API in wcnss for timeout*/
7620#endif
7621}
7622
Jeff Johnson295189b2012-06-20 16:38:30 -07007623/**---------------------------------------------------------------------------
7624
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007625 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7626 information between Host and Riva
7627
7628 This function gets reported version of FW
7629 It also finds the version of Riva headers used to compile the host
7630 It compares the above two and prints a warning if they are different
7631 It gets the SW and HW version string
7632 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7633 indicating the features they support through a bitmap
7634
7635 \param - pHddCtx - Pointer to HDD context
7636
7637 \return - void
7638
7639 --------------------------------------------------------------------------*/
7640
7641void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7642{
7643
7644 tSirVersionType versionCompiled;
7645 tSirVersionType versionReported;
7646 tSirVersionString versionString;
7647 tANI_U8 fwFeatCapsMsgSupported = 0;
7648 VOS_STATUS vstatus;
7649
7650 /* retrieve and display WCNSS version information */
7651 do {
7652
7653 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7654 &versionCompiled);
7655 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7656 {
7657 hddLog(VOS_TRACE_LEVEL_FATAL,
7658 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007659 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007660 break;
7661 }
7662
7663 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7664 &versionReported);
7665 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7666 {
7667 hddLog(VOS_TRACE_LEVEL_FATAL,
7668 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007669 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007670 break;
7671 }
7672
7673 if ((versionCompiled.major != versionReported.major) ||
7674 (versionCompiled.minor != versionReported.minor) ||
7675 (versionCompiled.version != versionReported.version) ||
7676 (versionCompiled.revision != versionReported.revision))
7677 {
7678 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7679 "Host expected %u.%u.%u.%u\n",
7680 WLAN_MODULE_NAME,
7681 (int)versionReported.major,
7682 (int)versionReported.minor,
7683 (int)versionReported.version,
7684 (int)versionReported.revision,
7685 (int)versionCompiled.major,
7686 (int)versionCompiled.minor,
7687 (int)versionCompiled.version,
7688 (int)versionCompiled.revision);
7689 }
7690 else
7691 {
7692 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7693 WLAN_MODULE_NAME,
7694 (int)versionReported.major,
7695 (int)versionReported.minor,
7696 (int)versionReported.version,
7697 (int)versionReported.revision);
7698 }
7699
7700 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7701 versionString,
7702 sizeof(versionString));
7703 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7704 {
7705 hddLog(VOS_TRACE_LEVEL_FATAL,
7706 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007707 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007708 break;
7709 }
7710
7711 pr_info("%s: WCNSS software version %s\n",
7712 WLAN_MODULE_NAME, versionString);
7713
7714 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7715 versionString,
7716 sizeof(versionString));
7717 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7718 {
7719 hddLog(VOS_TRACE_LEVEL_FATAL,
7720 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007721 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007722 break;
7723 }
7724
7725 pr_info("%s: WCNSS hardware version %s\n",
7726 WLAN_MODULE_NAME, versionString);
7727
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007728 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7729 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007730 send the message only if it the riva is 1.1
7731 minor numbers for different riva branches:
7732 0 -> (1.0)Mainline Build
7733 1 -> (1.1)Mainline Build
7734 2->(1.04) Stability Build
7735 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007736 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007737 ((versionReported.minor>=1) && (versionReported.version>=1)))
7738 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7739 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007740
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007741 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007742 {
7743#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7744 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7745 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7746#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007747 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7748 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7749 {
7750 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7751 }
7752
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007753 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007754 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007755
7756 } while (0);
7757
7758}
7759
7760/**---------------------------------------------------------------------------
7761
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307762 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7763
7764 \param - pHddCtx - Pointer to the hdd context
7765
7766 \return - true if hardware supports 5GHz
7767
7768 --------------------------------------------------------------------------*/
7769static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7770{
7771 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7772 * then hardware support 5Ghz.
7773 */
7774 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7775 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05307776 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307777 return true;
7778 }
7779 else
7780 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05307781 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307782 __func__);
7783 return false;
7784 }
7785}
7786
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307787/**---------------------------------------------------------------------------
7788
7789 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
7790 generate function
7791
7792 This is generate the random mac address for WLAN interface
7793
7794 \param - pHddCtx - Pointer to HDD context
7795 idx - Start interface index to get auto
7796 generated mac addr.
7797 mac_addr - Mac address
7798
7799 \return - 0 for success, < 0 for failure
7800
7801 --------------------------------------------------------------------------*/
7802
7803static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
7804 int idx, v_MACADDR_t mac_addr)
7805{
7806 int i;
7807 unsigned int serialno;
7808 serialno = wcnss_get_serial_number();
7809
7810 if (0 != serialno)
7811 {
7812 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7813 bytes of the serial number that can be used to generate
7814 the other 3 bytes of the MAC address. Mask off all but
7815 the lower 3 bytes (this will also make sure we don't
7816 overflow in the next step) */
7817 serialno &= 0x00FFFFFF;
7818
7819 /* we need a unique address for each session */
7820 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7821
7822 /* autogen other Mac addresses */
7823 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7824 {
7825 /* start with the entire default address */
7826 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
7827 /* then replace the lower 3 bytes */
7828 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7829 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7830 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7831
7832 serialno++;
7833 hddLog(VOS_TRACE_LEVEL_ERROR,
7834 "%s: Derived Mac Addr: "
7835 MAC_ADDRESS_STR, __func__,
7836 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
7837 }
7838
7839 }
7840 else
7841 {
7842 hddLog(LOGE, FL("Failed to Get Serial NO"));
7843 return -1;
7844 }
7845 return 0;
7846}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307847
7848/**---------------------------------------------------------------------------
7849
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05307850 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
7851 completed to flush out the scan results
7852
7853 11d scan is done during driver load and is a passive scan on all
7854 channels supported by the device, 11d scans may find some APs on
7855 frequencies which are forbidden to be used in the regulatory domain
7856 the device is operating in. If these APs are notified to the supplicant
7857 it may try to connect to these APs, thus flush out all the scan results
7858 which are present in SME after 11d scan is done.
7859
7860 \return - eHalStatus
7861
7862 --------------------------------------------------------------------------*/
7863static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
7864 tANI_U32 scanId, eCsrScanStatus status)
7865{
7866 ENTER();
7867
7868 sme_ScanFlushResult(halHandle, 0);
7869
7870 EXIT();
7871
7872 return eHAL_STATUS_SUCCESS;
7873}
7874
7875/**---------------------------------------------------------------------------
7876
Jeff Johnson295189b2012-06-20 16:38:30 -07007877 \brief hdd_wlan_startup() - HDD init function
7878
7879 This is the driver startup code executed once a WLAN device has been detected
7880
7881 \param - dev - Pointer to the underlying device
7882
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007883 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007884
7885 --------------------------------------------------------------------------*/
7886
7887int hdd_wlan_startup(struct device *dev )
7888{
7889 VOS_STATUS status;
7890 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007891 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007892 hdd_context_t *pHddCtx = NULL;
7893 v_CONTEXT_t pVosContext= NULL;
7894#ifdef WLAN_BTAMP_FEATURE
7895 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7896 WLANBAP_ConfigType btAmpConfig;
7897 hdd_config_t *pConfig;
7898#endif
7899 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007900 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307901 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07007902
7903 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007904 /*
7905 * cfg80211: wiphy allocation
7906 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307907 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007908
7909 if(wiphy == NULL)
7910 {
7911 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007912 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007913 }
7914
7915 pHddCtx = wiphy_priv(wiphy);
7916
Jeff Johnson295189b2012-06-20 16:38:30 -07007917 //Initialize the adapter context to zeros.
7918 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7919
Jeff Johnson295189b2012-06-20 16:38:30 -07007920 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007921 hdd_prevent_suspend();
7922 pHddCtx->isLoadUnloadInProgress = TRUE;
7923
7924 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7925
7926 /*Get vos context here bcoz vos_open requires it*/
7927 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7928
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007929 if(pVosContext == NULL)
7930 {
7931 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7932 goto err_free_hdd_context;
7933 }
7934
Jeff Johnson295189b2012-06-20 16:38:30 -07007935 //Save the Global VOSS context in adapter context for future.
7936 pHddCtx->pvosContext = pVosContext;
7937
7938 //Save the adapter context in global context for future.
7939 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7940
Jeff Johnson295189b2012-06-20 16:38:30 -07007941 pHddCtx->parent_dev = dev;
7942
7943 init_completion(&pHddCtx->full_pwr_comp_var);
7944 init_completion(&pHddCtx->standby_comp_var);
7945 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007946 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007947 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307948 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007949
7950#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007951 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007952#else
7953 init_completion(&pHddCtx->driver_crda_req);
7954#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007955
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307956 spin_lock_init(&pHddCtx->schedScan_lock);
7957
Jeff Johnson295189b2012-06-20 16:38:30 -07007958 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7959
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307960#ifdef FEATURE_WLAN_TDLS
7961 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7962 * invoked by other instances also) to protect the concurrent
7963 * access for the Adapters by TDLS module.
7964 */
7965 mutex_init(&pHddCtx->tdls_lock);
7966#endif
7967
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307968 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007969 // Load all config first as TL config is needed during vos_open
7970 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7971 if(pHddCtx->cfg_ini == NULL)
7972 {
7973 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7974 goto err_free_hdd_context;
7975 }
7976
7977 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7978
7979 // Read and parse the qcom_cfg.ini file
7980 status = hdd_parse_config_ini( pHddCtx );
7981 if ( VOS_STATUS_SUCCESS != status )
7982 {
7983 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7984 __func__, WLAN_INI_FILE);
7985 goto err_config;
7986 }
Arif Hussaind5218912013-12-05 01:10:55 -08007987#ifdef MEMORY_DEBUG
7988 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
7989 vos_mem_init();
7990
7991 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
7992 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
7993#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007994
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307995 /* INI has been read, initialise the configuredMcastBcastFilter with
7996 * INI value as this will serve as the default value
7997 */
7998 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7999 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
8000 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308001
8002 if (false == hdd_is_5g_supported(pHddCtx))
8003 {
8004 //5Ghz is not supported.
8005 if (1 != pHddCtx->cfg_ini->nBandCapability)
8006 {
8007 hddLog(VOS_TRACE_LEVEL_INFO,
8008 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
8009 pHddCtx->cfg_ini->nBandCapability = 1;
8010 }
8011 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308012
8013 /* If SNR Monitoring is enabled, FW has to parse all beacons
8014 * for calcaluting and storing the average SNR, so set Nth beacon
8015 * filter to 1 to enable FW to parse all the beaocons
8016 */
8017 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
8018 {
8019 /* The log level is deliberately set to WARN as overriding
8020 * nthBeaconFilter to 1 will increase power cosumption and this
8021 * might just prove helpful to detect the power issue.
8022 */
8023 hddLog(VOS_TRACE_LEVEL_WARN,
8024 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
8025 pHddCtx->cfg_ini->nthBeaconFilter = 1;
8026 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008027 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308028 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07008029 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008030 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008031 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008032 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
8033 {
8034 hddLog(VOS_TRACE_LEVEL_FATAL,
8035 "%s: wlan_hdd_cfg80211_init return failure", __func__);
8036 goto err_config;
8037 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008038 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008039
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008040 // Update VOS trace levels based upon the cfg.ini
8041 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
8042 pHddCtx->cfg_ini->vosTraceEnableBAP);
8043 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
8044 pHddCtx->cfg_ini->vosTraceEnableTL);
8045 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
8046 pHddCtx->cfg_ini->vosTraceEnableWDI);
8047 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
8048 pHddCtx->cfg_ini->vosTraceEnableHDD);
8049 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
8050 pHddCtx->cfg_ini->vosTraceEnableSME);
8051 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
8052 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05308053 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
8054 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008055 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
8056 pHddCtx->cfg_ini->vosTraceEnableWDA);
8057 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
8058 pHddCtx->cfg_ini->vosTraceEnableSYS);
8059 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
8060 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008061 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
8062 pHddCtx->cfg_ini->vosTraceEnableSAP);
8063 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
8064 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008065
Jeff Johnson295189b2012-06-20 16:38:30 -07008066 // Update WDI trace levels based upon the cfg.ini
8067 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
8068 pHddCtx->cfg_ini->wdiTraceEnableDAL);
8069 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
8070 pHddCtx->cfg_ini->wdiTraceEnableCTL);
8071 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
8072 pHddCtx->cfg_ini->wdiTraceEnableDAT);
8073 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
8074 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008075
Jeff Johnson88ba7742013-02-27 14:36:02 -08008076 if (VOS_FTM_MODE == hdd_get_conparam())
8077 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008078 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
8079 {
8080 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
8081 goto err_free_hdd_context;
8082 }
8083 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
8084 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08008085 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008086
Jeff Johnson88ba7742013-02-27 14:36:02 -08008087 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07008088 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8089 {
8090 status = vos_watchdog_open(pVosContext,
8091 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
8092
8093 if(!VOS_IS_STATUS_SUCCESS( status ))
8094 {
8095 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308096 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008097 }
8098 }
8099
8100 pHddCtx->isLogpInProgress = FALSE;
8101 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8102
Jeff Johnson295189b2012-06-20 16:38:30 -07008103 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
8104 if(!VOS_IS_STATUS_SUCCESS(status))
8105 {
8106 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008107 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008108 }
8109
Amar Singhala49cbc52013-10-08 18:37:44 -07008110#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008111 /* initialize the NV module. This is required so that
8112 we can initialize the channel information in wiphy
8113 from the NV.bin data. The channel information in
8114 wiphy needs to be initialized before wiphy registration */
8115
8116 status = vos_nv_open();
8117 if (!VOS_IS_STATUS_SUCCESS(status))
8118 {
8119 /* NV module cannot be initialized */
8120 hddLog( VOS_TRACE_LEVEL_FATAL,
8121 "%s: vos_nv_open failed", __func__);
8122 goto err_clkvote;
8123 }
8124
8125 status = vos_init_wiphy_from_nv_bin();
8126 if (!VOS_IS_STATUS_SUCCESS(status))
8127 {
8128 /* NV module cannot be initialized */
8129 hddLog( VOS_TRACE_LEVEL_FATAL,
8130 "%s: vos_init_wiphy failed", __func__);
8131 goto err_vos_nv_close;
8132 }
8133
Amar Singhala49cbc52013-10-08 18:37:44 -07008134#endif
8135
Jeff Johnson295189b2012-06-20 16:38:30 -07008136 status = vos_open( &pVosContext, 0);
8137 if ( !VOS_IS_STATUS_SUCCESS( status ))
8138 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008139 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308140 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07008141 }
8142
Jeff Johnson295189b2012-06-20 16:38:30 -07008143 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8144
8145 if ( NULL == pHddCtx->hHal )
8146 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008147 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008148 goto err_vosclose;
8149 }
8150
Mihir Shetee1093ba2014-01-21 20:13:32 +05308151#ifdef CONFIG_ENABLE_LINUX_REG
8152 /* registration of wiphy dev with cfg80211 */
8153 if (0 > wlan_hdd_cfg80211_register(wiphy))
8154 {
8155 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8156 goto err_vosclose;
8157 }
8158
8159 status = wlan_hdd_init_channels(pHddCtx);
8160 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8161 {
8162 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
8163 __func__);
8164 goto err_wiphy_unregister;
8165 }
8166#endif
8167
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008168 status = vos_preStart( pHddCtx->pvosContext );
8169 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8170 {
8171 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308172 goto err_wiphy_unregister;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008173 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008174
Arif Hussaineaf68602013-12-30 23:10:44 -08008175 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8176 {
8177 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8178 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8179 __func__, enable_dfs_chan_scan);
8180 }
8181 if (0 == enable_11d || 1 == enable_11d)
8182 {
8183 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8184 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8185 __func__, enable_11d);
8186 }
8187
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008188 /* Note that the vos_preStart() sequence triggers the cfg download.
8189 The cfg download must occur before we update the SME config
8190 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008191 status = hdd_set_sme_config( pHddCtx );
8192
8193 if ( VOS_STATUS_SUCCESS != status )
8194 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008195 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308196 goto err_wiphy_unregister;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008197 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008198
8199 //Initialize the WMM module
8200 status = hdd_wmm_init(pHddCtx);
8201 if (!VOS_IS_STATUS_SUCCESS(status))
8202 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008203 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308204 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008205 }
8206
Jeff Johnson295189b2012-06-20 16:38:30 -07008207 /* In the integrated architecture we update the configuration from
8208 the INI file and from NV before vOSS has been started so that
8209 the final contents are available to send down to the cCPU */
8210
8211 // Apply the cfg.ini to cfg.dat
8212 if (FALSE == hdd_update_config_dat(pHddCtx))
8213 {
8214 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mihir Shetee1093ba2014-01-21 20:13:32 +05308215 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008216 }
8217
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308218 // Get mac addr from platform driver
8219 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8220
8221 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008222 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308223 /* Store the mac addr for first interface */
8224 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8225
8226 hddLog(VOS_TRACE_LEVEL_ERROR,
8227 "%s: WLAN Mac Addr: "
8228 MAC_ADDRESS_STR, __func__,
8229 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8230
8231 /* Here, passing Arg2 as 1 because we do not want to change the
8232 last 3 bytes (means non OUI bytes) of first interface mac
8233 addr.
8234 */
8235 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8236 {
8237 hddLog(VOS_TRACE_LEVEL_ERROR,
8238 "%s: Failed to generate wlan interface mac addr "
8239 "using MAC from ini file ", __func__);
8240 }
8241 }
8242 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8243 {
8244 // Apply the NV to cfg.dat
8245 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008246#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8247 /* There was not a valid set of MAC Addresses in NV. See if the
8248 default addresses were modified by the cfg.ini settings. If so,
8249 we'll use them, but if not, we'll autogenerate a set of MAC
8250 addresses based upon the device serial number */
8251
8252 static const v_MACADDR_t default_address =
8253 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008254
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308255 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8256 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008257 {
8258 /* cfg.ini has the default address, invoke autogen logic */
8259
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308260 /* Here, passing Arg2 as 0 because we want to change the
8261 last 3 bytes (means non OUI bytes) of all the interfaces
8262 mac addr.
8263 */
8264 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8265 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008266 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308267 hddLog(VOS_TRACE_LEVEL_ERROR,
8268 "%s: Failed to generate wlan interface mac addr "
8269 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8270 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008271 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008272 }
8273 else
8274#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8275 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008276 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008277 "%s: Invalid MAC address in NV, using MAC from ini file "
8278 MAC_ADDRESS_STR, __func__,
8279 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8280 }
8281 }
8282 {
8283 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308284
8285 /* Set the MAC Address Currently this is used by HAL to
8286 * add self sta. Remove this once self sta is added as
8287 * part of session open.
8288 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008289 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8290 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8291 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308292
Jeff Johnson295189b2012-06-20 16:38:30 -07008293 if (!HAL_STATUS_SUCCESS( halStatus ))
8294 {
8295 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8296 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mihir Shetee1093ba2014-01-21 20:13:32 +05308297 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008298 }
8299 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008300
8301 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8302 Note: Firmware image will be read and downloaded inside vos_start API */
8303 status = vos_start( pHddCtx->pvosContext );
8304 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8305 {
8306 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308307 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008308 }
8309
Leo Chang6cec3e22014-01-21 15:33:49 -08008310#ifdef FEATURE_WLAN_CH_AVOID
8311 /* Plug in avoid channel notification callback
8312 * This should happen before ADD_SELF_STA
8313 * FW will send first IND with ADD_SELF_STA REQ from host */
8314 sme_AddChAvoidCallback(pHddCtx->hHal,
8315 hdd_hostapd_ch_avoid_cb);
8316#endif /* FEATURE_WLAN_CH_AVOID */
8317
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008318 /* Exchange capability info between Host and FW and also get versioning info from FW */
8319 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008320
8321 status = hdd_post_voss_start_config( pHddCtx );
8322 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8323 {
8324 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
8325 __func__);
8326 goto err_vosstop;
8327 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008328
8329#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308330 wlan_hdd_cfg80211_update_reg_info( wiphy );
8331
8332 /* registration of wiphy dev with cfg80211 */
8333 if (0 > wlan_hdd_cfg80211_register(wiphy))
8334 {
8335 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8336 goto err_vosstop;
8337 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008338#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008339
Jeff Johnson295189b2012-06-20 16:38:30 -07008340 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8341 {
8342 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
8343 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8344 }
8345 else
8346 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008347 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
8348 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8349 if (pAdapter != NULL)
8350 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308351 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07008352 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308353 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
8354 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
8355 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07008356
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308357 /* Generate the P2P Device Address. This consists of the device's
8358 * primary MAC address with the locally administered bit set.
8359 */
8360 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07008361 }
8362 else
8363 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308364 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
8365 if (p2p_dev_addr != NULL)
8366 {
8367 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
8368 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
8369 }
8370 else
8371 {
8372 hddLog(VOS_TRACE_LEVEL_FATAL,
8373 "%s: Failed to allocate mac_address for p2p_device",
8374 __func__);
8375 goto err_close_adapter;
8376 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008377 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008378
8379 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
8380 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
8381 if ( NULL == pP2pAdapter )
8382 {
8383 hddLog(VOS_TRACE_LEVEL_FATAL,
8384 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008385 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008386 goto err_close_adapter;
8387 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008388 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008389 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008390
8391 if( pAdapter == NULL )
8392 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008393 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
8394 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008395 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008396
Arif Hussain66559122013-11-21 10:11:40 -08008397 if (country_code)
8398 {
8399 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08008400 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08008401 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8402#ifndef CONFIG_ENABLE_LINUX_REG
8403 hdd_checkandupdate_phymode(pAdapter, country_code);
8404#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08008405 ret = sme_ChangeCountryCode(pHddCtx->hHal,
8406 (void *)(tSmeChangeCountryCallback)
8407 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08008408 country_code,
8409 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308410 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008411 if (eHAL_STATUS_SUCCESS == ret)
8412 {
Arif Hussaincb607082013-12-20 11:57:42 -08008413 ret = wait_for_completion_interruptible_timeout(
8414 &pAdapter->change_country_code,
8415 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
8416
8417 if (0 >= ret)
8418 {
8419 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8420 "%s: SME while setting country code timed out", __func__);
8421 }
Arif Hussain66559122013-11-21 10:11:40 -08008422 }
8423 else
8424 {
Arif Hussaincb607082013-12-20 11:57:42 -08008425 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8426 "%s: SME Change Country code from module param fail ret=%d",
8427 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08008428 }
8429 }
8430
Jeff Johnson295189b2012-06-20 16:38:30 -07008431#ifdef WLAN_BTAMP_FEATURE
8432 vStatus = WLANBAP_Open(pVosContext);
8433 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8434 {
8435 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8436 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008437 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008438 }
8439
8440 vStatus = BSL_Init(pVosContext);
8441 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8442 {
8443 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8444 "%s: Failed to Init BSL",__func__);
8445 goto err_bap_close;
8446 }
8447 vStatus = WLANBAP_Start(pVosContext);
8448 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8449 {
8450 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8451 "%s: Failed to start TL",__func__);
8452 goto err_bap_close;
8453 }
8454
8455 pConfig = pHddCtx->cfg_ini;
8456 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8457 status = WLANBAP_SetConfig(&btAmpConfig);
8458
8459#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008460
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008461#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8462 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8463 {
8464 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8465 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8466 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8467 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8468 }
8469#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008470#ifdef FEATURE_WLAN_SCAN_PNO
8471 /*SME must send channel update configuration to RIVA*/
8472 sme_UpdateChannelConfig(pHddCtx->hHal);
8473#endif
8474
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308475 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
8476
Jeff Johnson295189b2012-06-20 16:38:30 -07008477 /* Register with platform driver as client for Suspend/Resume */
8478 status = hddRegisterPmOps(pHddCtx);
8479 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8480 {
8481 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8482#ifdef WLAN_BTAMP_FEATURE
8483 goto err_bap_stop;
8484#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008485 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008486#endif //WLAN_BTAMP_FEATURE
8487 }
8488
Yue Ma0d4891e2013-08-06 17:01:45 -07008489 /* Open debugfs interface */
8490 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8491 {
8492 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8493 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008494 }
8495
Jeff Johnson295189b2012-06-20 16:38:30 -07008496 /* Register TM level change handler function to the platform */
8497 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8498 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8499 {
8500 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8501 goto err_unregister_pmops;
8502 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008503
8504 /* register for riva power on lock to platform driver */
8505 if (req_riva_power_on_lock("wlan"))
8506 {
8507 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8508 __func__);
8509 goto err_unregister_pmops;
8510 }
8511
Jeff Johnson295189b2012-06-20 16:38:30 -07008512 // register net device notifier for device change notification
8513 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8514
8515 if(ret < 0)
8516 {
8517 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8518 goto err_free_power_on_lock;
8519 }
8520
8521 //Initialize the nlink service
8522 if(nl_srv_init() != 0)
8523 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308524 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008525 goto err_reg_netdev;
8526 }
8527
Leo Chang4ce1cc52013-10-21 18:27:15 -07008528#ifdef WLAN_KD_READY_NOTIFIER
8529 pHddCtx->kd_nl_init = 1;
8530#endif /* WLAN_KD_READY_NOTIFIER */
8531
Jeff Johnson295189b2012-06-20 16:38:30 -07008532 //Initialize the BTC service
8533 if(btc_activate_service(pHddCtx) != 0)
8534 {
8535 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8536 goto err_nl_srv;
8537 }
8538
8539#ifdef PTT_SOCK_SVC_ENABLE
8540 //Initialize the PTT service
8541 if(ptt_sock_activate_svc(pHddCtx) != 0)
8542 {
8543 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8544 goto err_nl_srv;
8545 }
8546#endif
8547
Jeff Johnson295189b2012-06-20 16:38:30 -07008548 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008549 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008550 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008551 /* Action frame registered in one adapter which will
8552 * applicable to all interfaces
8553 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008554 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008555 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008556
8557 mutex_init(&pHddCtx->sap_lock);
8558
8559 pHddCtx->isLoadUnloadInProgress = FALSE;
8560
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008561#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008562#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8563 /* Initialize the wake lcok */
8564 wake_lock_init(&pHddCtx->rx_wake_lock,
8565 WAKE_LOCK_SUSPEND,
8566 "qcom_rx_wakelock");
8567#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008568 /* Initialize the wake lcok */
8569 wake_lock_init(&pHddCtx->sap_wake_lock,
8570 WAKE_LOCK_SUSPEND,
8571 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008572#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008573
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008574 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8575 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008576
8577 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8578 hdd_allow_suspend();
Abhishek Singha306a442013-11-07 18:39:01 +05308579#ifndef CONFIG_ENABLE_LINUX_REG
8580 /*updating wiphy so that regulatory user hints can be processed*/
8581 if (wiphy)
8582 {
8583 regulatory_hint(wiphy, "00");
8584 }
8585#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008586 // Initialize the restart logic
8587 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308588
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008589 //Register the traffic monitor timer now
8590 if ( pHddCtx->cfg_ini->dynSplitscan)
8591 {
8592 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8593 VOS_TIMER_TYPE_SW,
8594 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8595 (void *)pHddCtx);
8596 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008597 goto success;
8598
8599err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008600#ifdef WLAN_KD_READY_NOTIFIER
8601 nl_srv_exit(pHddCtx->ptt_pid);
8602#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008603 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008604#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008605err_reg_netdev:
8606 unregister_netdevice_notifier(&hdd_netdev_notifier);
8607
8608err_free_power_on_lock:
8609 free_riva_power_on_lock("wlan");
8610
8611err_unregister_pmops:
8612 hddDevTmUnregisterNotifyCallback(pHddCtx);
8613 hddDeregisterPmOps(pHddCtx);
8614
Yue Ma0d4891e2013-08-06 17:01:45 -07008615 hdd_debugfs_exit(pHddCtx);
8616
Jeff Johnson295189b2012-06-20 16:38:30 -07008617#ifdef WLAN_BTAMP_FEATURE
8618err_bap_stop:
8619 WLANBAP_Stop(pVosContext);
8620#endif
8621
8622#ifdef WLAN_BTAMP_FEATURE
8623err_bap_close:
8624 WLANBAP_Close(pVosContext);
8625#endif
8626
Jeff Johnson295189b2012-06-20 16:38:30 -07008627err_close_adapter:
8628 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008629
8630#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308631 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008632#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008633
8634err_vosstop:
8635 vos_stop(pVosContext);
8636
Mihir Shetee1093ba2014-01-21 20:13:32 +05308637err_wiphy_unregister:
8638#ifdef CONFIG_ENABLE_LINUX_REG
8639 wiphy_unregister(wiphy);
8640#endif
8641
Amar Singhala49cbc52013-10-08 18:37:44 -07008642err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008643 status = vos_sched_close( pVosContext );
8644 if (!VOS_IS_STATUS_SUCCESS(status)) {
8645 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8646 "%s: Failed to close VOSS Scheduler", __func__);
8647 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8648 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008649 vos_close(pVosContext );
8650
Amar Singhala49cbc52013-10-08 18:37:44 -07008651#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008652err_vos_nv_close:
8653
8654 vos_nv_close();
8655
Jeff Johnson295189b2012-06-20 16:38:30 -07008656err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008657#endif
8658
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008659 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008660
8661err_wdclose:
8662 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8663 vos_watchdog_close(pVosContext);
8664
Jeff Johnson295189b2012-06-20 16:38:30 -07008665err_config:
8666 kfree(pHddCtx->cfg_ini);
8667 pHddCtx->cfg_ini= NULL;
8668
8669err_free_hdd_context:
8670 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008671 wiphy_free(wiphy) ;
8672 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008673 VOS_BUG(1);
8674
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008675 if (hdd_is_ssr_required())
8676 {
8677 /* WDI timeout had happened during load, so SSR is needed here */
8678 subsystem_restart("wcnss");
8679 msleep(5000);
8680 }
8681 hdd_set_ssr_required (VOS_FALSE);
8682
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008683 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008684
8685success:
8686 EXIT();
8687 return 0;
8688}
8689
8690/**---------------------------------------------------------------------------
8691
Jeff Johnson32d95a32012-09-10 13:15:23 -07008692 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008693
Jeff Johnson32d95a32012-09-10 13:15:23 -07008694 This is the driver entry point - called in different timeline depending
8695 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008696
8697 \param - None
8698
8699 \return - 0 for success, non zero for failure
8700
8701 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008702static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008703{
8704 VOS_STATUS status;
8705 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008706 struct device *dev = NULL;
8707 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008708#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8709 int max_retries = 0;
8710#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008711
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308712#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8713 vos_wconn_trace_init();
8714#endif
8715
Jeff Johnson295189b2012-06-20 16:38:30 -07008716 ENTER();
8717
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008718#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008719 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008720#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008721
8722 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8723 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8724
8725 //Power Up Libra WLAN card first if not already powered up
8726 status = vos_chipPowerUp(NULL,NULL,NULL);
8727 if (!VOS_IS_STATUS_SUCCESS(status))
8728 {
8729 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8730 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308731#ifdef WLAN_OPEN_SOURCE
8732 wake_lock_destroy(&wlan_wake_lock);
8733#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008734 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008735 }
8736
Jeff Johnson295189b2012-06-20 16:38:30 -07008737#ifdef ANI_BUS_TYPE_PCI
8738
8739 dev = wcnss_wlan_get_device();
8740
8741#endif // ANI_BUS_TYPE_PCI
8742
8743#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008744
8745#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8746 /* wait until WCNSS driver downloads NV */
8747 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8748 msleep(1000);
8749 }
8750 if (max_retries >= 5) {
8751 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308752#ifdef WLAN_OPEN_SOURCE
8753 wake_lock_destroy(&wlan_wake_lock);
8754#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008755 return -ENODEV;
8756 }
8757#endif
8758
Jeff Johnson295189b2012-06-20 16:38:30 -07008759 dev = wcnss_wlan_get_device();
8760#endif // ANI_BUS_TYPE_PLATFORM
8761
8762
8763 do {
8764 if (NULL == dev) {
8765 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8766 ret_status = -1;
8767 break;
8768 }
8769
Jeff Johnson295189b2012-06-20 16:38:30 -07008770#ifdef TIMER_MANAGER
8771 vos_timer_manager_init();
8772#endif
8773
8774 /* Preopen VOSS so that it is ready to start at least SAL */
8775 status = vos_preOpen(&pVosContext);
8776
8777 if (!VOS_IS_STATUS_SUCCESS(status))
8778 {
8779 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8780 ret_status = -1;
8781 break;
8782 }
8783
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008784#ifndef MODULE
8785 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8786 */
8787 hdd_set_conparam((v_UINT_t)con_mode);
8788#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008789
8790 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008791 if (hdd_wlan_startup(dev))
8792 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008793 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008794 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008795 vos_preClose( &pVosContext );
8796 ret_status = -1;
8797 break;
8798 }
8799
8800 /* Cancel the vote for XO Core ON
8801 * This is done here for safety purposes in case we re-initialize without turning
8802 * it OFF in any error scenario.
8803 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008804 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008805 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008806 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008807 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8808 {
8809 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08008810 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07008811 }
8812 } while (0);
8813
8814 if (0 != ret_status)
8815 {
8816 //Assert Deep sleep signal now to put Libra HW in lowest power state
8817 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8818 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8819
8820 //Vote off any PMIC voltage supplies
8821 vos_chipPowerDown(NULL, NULL, NULL);
8822#ifdef TIMER_MANAGER
8823 vos_timer_exit();
8824#endif
8825#ifdef MEMORY_DEBUG
8826 vos_mem_exit();
8827#endif
8828
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008829#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008830 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008831#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008832 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8833 }
8834 else
8835 {
8836 //Send WLAN UP indication to Nlink Service
8837 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8838
8839 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008840 }
8841
8842 EXIT();
8843
8844 return ret_status;
8845}
8846
Jeff Johnson32d95a32012-09-10 13:15:23 -07008847/**---------------------------------------------------------------------------
8848
8849 \brief hdd_module_init() - Init Function
8850
8851 This is the driver entry point (invoked when module is loaded using insmod)
8852
8853 \param - None
8854
8855 \return - 0 for success, non zero for failure
8856
8857 --------------------------------------------------------------------------*/
8858#ifdef MODULE
8859static int __init hdd_module_init ( void)
8860{
8861 return hdd_driver_init();
8862}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008863#else /* #ifdef MODULE */
8864static int __init hdd_module_init ( void)
8865{
8866 /* Driver initialization is delayed to fwpath_changed_handler */
8867 return 0;
8868}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008869#endif /* #ifdef MODULE */
8870
Jeff Johnson295189b2012-06-20 16:38:30 -07008871
8872/**---------------------------------------------------------------------------
8873
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008874 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008875
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008876 This is the driver exit point (invoked when module is unloaded using rmmod
8877 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008878
8879 \param - None
8880
8881 \return - None
8882
8883 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008884static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008885{
8886 hdd_context_t *pHddCtx = NULL;
8887 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008888 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008889
8890 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8891
8892 //Get the global vos context
8893 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8894
8895 if(!pVosContext)
8896 {
8897 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8898 goto done;
8899 }
8900
8901 //Get the HDD context.
8902 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8903
8904 if(!pHddCtx)
8905 {
8906 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8907 }
8908 else
8909 {
Sameer Thalappil14067972014-01-23 14:54:54 -08008910 while (pHddCtx->isLogpInProgress) {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008911 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8912 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008913 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008914
8915 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8916 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8917 "%s:SSR never completed, fatal error", __func__);
8918 VOS_BUG(0);
8919 }
8920 }
8921
Jeff Johnson295189b2012-06-20 16:38:30 -07008922
8923 pHddCtx->isLoadUnloadInProgress = TRUE;
8924 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8925
8926 //Do all the cleanup before deregistering the driver
8927 hdd_wlan_exit(pHddCtx);
8928 }
8929
Jeff Johnson295189b2012-06-20 16:38:30 -07008930 vos_preClose( &pVosContext );
8931
8932#ifdef TIMER_MANAGER
8933 vos_timer_exit();
8934#endif
8935#ifdef MEMORY_DEBUG
8936 vos_mem_exit();
8937#endif
8938
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308939#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8940 vos_wconn_trace_exit();
8941#endif
8942
Jeff Johnson295189b2012-06-20 16:38:30 -07008943done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008944#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008945 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008946#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008947 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8948}
8949
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008950/**---------------------------------------------------------------------------
8951
8952 \brief hdd_module_exit() - Exit function
8953
8954 This is the driver exit point (invoked when module is unloaded using rmmod)
8955
8956 \param - None
8957
8958 \return - None
8959
8960 --------------------------------------------------------------------------*/
8961static void __exit hdd_module_exit(void)
8962{
8963 hdd_driver_exit();
8964}
8965
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008966#ifdef MODULE
8967static int fwpath_changed_handler(const char *kmessage,
8968 struct kernel_param *kp)
8969{
Jeff Johnson76052702013-04-16 13:55:05 -07008970 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008971}
8972
8973static int con_mode_handler(const char *kmessage,
8974 struct kernel_param *kp)
8975{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008976 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008977}
8978#else /* #ifdef MODULE */
8979/**---------------------------------------------------------------------------
8980
Jeff Johnson76052702013-04-16 13:55:05 -07008981 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008982
Jeff Johnson76052702013-04-16 13:55:05 -07008983 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008984 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008985 - invoked when module parameter fwpath is modified from userspace to signal
8986 initializing the WLAN driver or when con_mode is modified from userspace
8987 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008988
8989 \return - 0 for success, non zero for failure
8990
8991 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008992static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008993{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008994 int ret_status;
8995
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008996 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008997 ret_status = hdd_driver_init();
8998 wlan_hdd_inited = ret_status ? 0 : 1;
8999 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009000 }
9001
9002 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07009003
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009004 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07009005
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009006 ret_status = hdd_driver_init();
9007 wlan_hdd_inited = ret_status ? 0 : 1;
9008 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009009}
9010
Jeff Johnson295189b2012-06-20 16:38:30 -07009011/**---------------------------------------------------------------------------
9012
Jeff Johnson76052702013-04-16 13:55:05 -07009013 \brief fwpath_changed_handler() - Handler Function
9014
9015 Handle changes to the fwpath parameter
9016
9017 \return - 0 for success, non zero for failure
9018
9019 --------------------------------------------------------------------------*/
9020static int fwpath_changed_handler(const char *kmessage,
9021 struct kernel_param *kp)
9022{
9023 int ret;
9024
9025 ret = param_set_copystring(kmessage, kp);
9026 if (0 == ret)
9027 ret = kickstart_driver();
9028 return ret;
9029}
9030
9031/**---------------------------------------------------------------------------
9032
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009033 \brief con_mode_handler() -
9034
9035 Handler function for module param con_mode when it is changed by userspace
9036 Dynamically linked - do nothing
9037 Statically linked - exit and init driver, as in rmmod and insmod
9038
Jeff Johnson76052702013-04-16 13:55:05 -07009039 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009040
Jeff Johnson76052702013-04-16 13:55:05 -07009041 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009042
9043 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009044static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009045{
Jeff Johnson76052702013-04-16 13:55:05 -07009046 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009047
Jeff Johnson76052702013-04-16 13:55:05 -07009048 ret = param_set_int(kmessage, kp);
9049 if (0 == ret)
9050 ret = kickstart_driver();
9051 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009052}
9053#endif /* #ifdef MODULE */
9054
9055/**---------------------------------------------------------------------------
9056
Jeff Johnson295189b2012-06-20 16:38:30 -07009057 \brief hdd_get_conparam() -
9058
9059 This is the driver exit point (invoked when module is unloaded using rmmod)
9060
9061 \param - None
9062
9063 \return - tVOS_CON_MODE
9064
9065 --------------------------------------------------------------------------*/
9066tVOS_CON_MODE hdd_get_conparam ( void )
9067{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009068#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07009069 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009070#else
9071 return (tVOS_CON_MODE)curr_con_mode;
9072#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009073}
9074void hdd_set_conparam ( v_UINT_t newParam )
9075{
9076 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009077#ifndef MODULE
9078 curr_con_mode = con_mode;
9079#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009080}
9081/**---------------------------------------------------------------------------
9082
9083 \brief hdd_softap_sta_deauth() - function
9084
9085 This to take counter measure to handle deauth req from HDD
9086
9087 \param - pAdapter - Pointer to the HDD
9088
9089 \param - enable - boolean value
9090
9091 \return - None
9092
9093 --------------------------------------------------------------------------*/
9094
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009095VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07009096{
Jeff Johnson295189b2012-06-20 16:38:30 -07009097 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009098 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07009099
9100 ENTER();
9101
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07009102 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
9103 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009104
9105 //Ignore request to deauth bcmc station
9106 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009107 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009108
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009109 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07009110
9111 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009112 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009113}
9114
9115/**---------------------------------------------------------------------------
9116
9117 \brief hdd_softap_sta_disassoc() - function
9118
9119 This to take counter measure to handle deauth req from HDD
9120
9121 \param - pAdapter - Pointer to the HDD
9122
9123 \param - enable - boolean value
9124
9125 \return - None
9126
9127 --------------------------------------------------------------------------*/
9128
9129void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
9130{
9131 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9132
9133 ENTER();
9134
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309135 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009136
9137 //Ignore request to disassoc bcmc station
9138 if( pDestMacAddress[0] & 0x1 )
9139 return;
9140
9141 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
9142}
9143
9144void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
9145{
9146 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9147
9148 ENTER();
9149
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309150 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009151
9152 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
9153}
9154
Jeff Johnson295189b2012-06-20 16:38:30 -07009155/**---------------------------------------------------------------------------
9156 *
9157 * \brief hdd_get__concurrency_mode() -
9158 *
9159 *
9160 * \param - None
9161 *
9162 * \return - CONCURRENCY MODE
9163 *
9164 * --------------------------------------------------------------------------*/
9165tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9166{
9167 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9168 hdd_context_t *pHddCtx;
9169
9170 if (NULL != pVosContext)
9171 {
9172 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9173 if (NULL != pHddCtx)
9174 {
9175 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9176 }
9177 }
9178
9179 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009180 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009181 return VOS_STA;
9182}
9183
9184/* Decide whether to allow/not the apps power collapse.
9185 * Allow apps power collapse if we are in connected state.
9186 * if not, allow only if we are in IMPS */
9187v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
9188{
9189 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08009190 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009191 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07009192 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9193 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9194 hdd_adapter_t *pAdapter = NULL;
9195 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08009196 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009197
Jeff Johnson295189b2012-06-20 16:38:30 -07009198 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9199 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009200
Yathish9f22e662012-12-10 14:21:35 -08009201 concurrent_state = hdd_get_concurrency_mode();
9202
9203#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
9204 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
9205 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
9206 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
9207 return TRUE;
9208#endif
9209
Jeff Johnson295189b2012-06-20 16:38:30 -07009210 /*loop through all adapters. TBD fix for Concurrency */
9211 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9212 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9213 {
9214 pAdapter = pAdapterNode->pAdapter;
9215 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
9216 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9217 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009218 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07009219 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08009220 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009221 (eANI_BOOLEAN_TRUE == scanRspPending) ||
9222 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07009223 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009224 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009225 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
9226 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07009227 return FALSE;
9228 }
9229 }
9230 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9231 pAdapterNode = pNext;
9232 }
9233 return TRUE;
9234}
9235
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08009236/* Decides whether to send suspend notification to Riva
9237 * if any adapter is in BMPS; then it is required */
9238v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
9239{
9240 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
9241 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9242
9243 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
9244 {
9245 return TRUE;
9246 }
9247 return FALSE;
9248}
9249
Jeff Johnson295189b2012-06-20 16:38:30 -07009250void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9251{
9252 switch(mode)
9253 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009254 case VOS_STA_MODE:
9255 case VOS_P2P_CLIENT_MODE:
9256 case VOS_P2P_GO_MODE:
9257 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07009258 pHddCtx->concurrency_mode |= (1 << mode);
9259 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07009260 break;
9261 default:
9262 break;
9263
9264 }
9265 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9266 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9267}
9268
9269
9270void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9271{
9272 switch(mode)
9273 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009274 case VOS_STA_MODE:
9275 case VOS_P2P_CLIENT_MODE:
9276 case VOS_P2P_GO_MODE:
9277 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07009278 pHddCtx->no_of_sessions[mode]--;
9279 if (!(pHddCtx->no_of_sessions[mode]))
9280 pHddCtx->concurrency_mode &= (~(1 << mode));
9281 break;
9282 default:
9283 break;
9284 }
9285 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9286 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9287}
9288
Jeff Johnsone7245742012-09-05 17:12:55 -07009289/**---------------------------------------------------------------------------
9290 *
9291 * \brief wlan_hdd_restart_init
9292 *
9293 * This function initalizes restart timer/flag. An internal function.
9294 *
9295 * \param - pHddCtx
9296 *
9297 * \return - None
9298 *
9299 * --------------------------------------------------------------------------*/
9300
9301static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
9302{
9303 /* Initialize */
9304 pHddCtx->hdd_restart_retries = 0;
9305 atomic_set(&pHddCtx->isRestartInProgress, 0);
9306 vos_timer_init(&pHddCtx->hdd_restart_timer,
9307 VOS_TIMER_TYPE_SW,
9308 wlan_hdd_restart_timer_cb,
9309 pHddCtx);
9310}
9311/**---------------------------------------------------------------------------
9312 *
9313 * \brief wlan_hdd_restart_deinit
9314 *
9315 * This function cleans up the resources used. An internal function.
9316 *
9317 * \param - pHddCtx
9318 *
9319 * \return - None
9320 *
9321 * --------------------------------------------------------------------------*/
9322
9323static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
9324{
9325
9326 VOS_STATUS vos_status;
9327 /* Block any further calls */
9328 atomic_set(&pHddCtx->isRestartInProgress, 1);
9329 /* Cleanup */
9330 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
9331 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309332 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009333 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
9334 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309335 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009336
9337}
9338
9339/**---------------------------------------------------------------------------
9340 *
9341 * \brief wlan_hdd_framework_restart
9342 *
9343 * This function uses a cfg80211 API to start a framework initiated WLAN
9344 * driver module unload/load.
9345 *
9346 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
9347 *
9348 *
9349 * \param - pHddCtx
9350 *
9351 * \return - VOS_STATUS_SUCCESS: Success
9352 * VOS_STATUS_E_EMPTY: Adapter is Empty
9353 * VOS_STATUS_E_NOMEM: No memory
9354
9355 * --------------------------------------------------------------------------*/
9356
9357static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
9358{
9359 VOS_STATUS status = VOS_STATUS_SUCCESS;
9360 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009361 int len = (sizeof (struct ieee80211_mgmt));
9362 struct ieee80211_mgmt *mgmt = NULL;
9363
9364 /* Prepare the DEAUTH managment frame with reason code */
9365 mgmt = kzalloc(len, GFP_KERNEL);
9366 if(mgmt == NULL)
9367 {
9368 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9369 "%s: memory allocation failed (%d bytes)", __func__, len);
9370 return VOS_STATUS_E_NOMEM;
9371 }
9372 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07009373
9374 /* Iterate over all adapters/devices */
9375 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9376 do
9377 {
9378 if( (status == VOS_STATUS_SUCCESS) &&
9379 pAdapterNode &&
9380 pAdapterNode->pAdapter)
9381 {
9382 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9383 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
9384 pAdapterNode->pAdapter->dev->name,
9385 pAdapterNode->pAdapter->device_mode,
9386 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009387 /*
9388 * CFG80211 event to restart the driver
9389 *
9390 * 'cfg80211_send_unprot_deauth' sends a
9391 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
9392 * of SME(Linux Kernel) state machine.
9393 *
9394 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
9395 * the driver.
9396 *
9397 */
9398
9399 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07009400 }
9401 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9402 pAdapterNode = pNext;
9403 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
9404
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009405
9406 /* Free the allocated management frame */
9407 kfree(mgmt);
9408
Jeff Johnsone7245742012-09-05 17:12:55 -07009409 /* Retry until we unload or reach max count */
9410 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
9411 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
9412
9413 return status;
9414
9415}
9416/**---------------------------------------------------------------------------
9417 *
9418 * \brief wlan_hdd_restart_timer_cb
9419 *
9420 * Restart timer callback. An internal function.
9421 *
9422 * \param - User data:
9423 *
9424 * \return - None
9425 *
9426 * --------------------------------------------------------------------------*/
9427
9428void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9429{
9430 hdd_context_t *pHddCtx = usrDataForCallback;
9431 wlan_hdd_framework_restart(pHddCtx);
9432 return;
9433
9434}
9435
9436
9437/**---------------------------------------------------------------------------
9438 *
9439 * \brief wlan_hdd_restart_driver
9440 *
9441 * This function sends an event to supplicant to restart the WLAN driver.
9442 *
9443 * This function is called from vos_wlanRestart.
9444 *
9445 * \param - pHddCtx
9446 *
9447 * \return - VOS_STATUS_SUCCESS: Success
9448 * VOS_STATUS_E_EMPTY: Adapter is Empty
9449 * VOS_STATUS_E_ALREADY: Request already in progress
9450
9451 * --------------------------------------------------------------------------*/
9452VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9453{
9454 VOS_STATUS status = VOS_STATUS_SUCCESS;
9455
9456 /* A tight check to make sure reentrancy */
9457 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9458 {
9459 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9460 "%s: WLAN restart is already in progress", __func__);
9461
9462 return VOS_STATUS_E_ALREADY;
9463 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009464 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009465#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009466 wcnss_reset_intr();
9467#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009468
Jeff Johnsone7245742012-09-05 17:12:55 -07009469 return status;
9470}
9471
Mihir Shetee1093ba2014-01-21 20:13:32 +05309472/**---------------------------------------------------------------------------
9473 *
9474 * \brief wlan_hdd_init_channels
9475 *
9476 * This function is used to initialize the channel list in CSR
9477 *
9478 * This function is called from hdd_wlan_startup
9479 *
9480 * \param - pHddCtx: HDD context
9481 *
9482 * \return - VOS_STATUS_SUCCESS: Success
9483 * VOS_STATUS_E_FAULT: Failure reported by SME
9484
9485 * --------------------------------------------------------------------------*/
9486static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
9487{
9488 eHalStatus status;
9489
9490 status = sme_InitChannels(pHddCtx->hHal);
9491 if (HAL_STATUS_SUCCESS(status))
9492 {
9493 return VOS_STATUS_SUCCESS;
9494 }
9495 else
9496 {
9497 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
9498 __func__, status);
9499 return VOS_STATUS_E_FAULT;
9500 }
9501}
9502
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009503/*
9504 * API to find if there is any STA or P2P-Client is connected
9505 */
9506VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9507{
9508 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9509}
Jeff Johnsone7245742012-09-05 17:12:55 -07009510
Jeff Johnson295189b2012-06-20 16:38:30 -07009511//Register the module init/exit functions
9512module_init(hdd_module_init);
9513module_exit(hdd_module_exit);
9514
9515MODULE_LICENSE("Dual BSD/GPL");
9516MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9517MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9518
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009519module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9520 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009521
Jeff Johnson76052702013-04-16 13:55:05 -07009522module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009523 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -08009524
9525module_param(enable_dfs_chan_scan, int,
9526 S_IRUSR | S_IRGRP | S_IROTH);
9527
9528module_param(enable_11d, int,
9529 S_IRUSR | S_IRGRP | S_IROTH);
9530
9531module_param(country_code, charp,
9532 S_IRUSR | S_IRGRP | S_IROTH);