blob: a7864d1ad2eb29712c00f772fc090960d291a671 [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);
Srinivas, Dasari138af4f2014-02-07 11:13:45 +0530306 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId,
307 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -0700308 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800309 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700310 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530311 if (result <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700312 {
313 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530314 "%s: Timeout occurred while waiting for abortscan %ld",
315 __func__, result);
Jeff Johnson295189b2012-06-20 16:38:30 -0700316 }
317 }
318 else
319 {
320 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700321 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700322 }
323#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700324 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700325 status = WLANBAP_StopAmp();
326 if(VOS_STATUS_SUCCESS != status )
327 {
328 pHddCtx->isAmpAllowed = VOS_TRUE;
329 hddLog(VOS_TRACE_LEVEL_FATAL,
330 "%s: Failed to stop AMP", __func__);
331 }
332 else
333 {
334 //a state m/c implementation in PAL is TBD to avoid this delay
335 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700336 if ( pHddCtx->isAmpAllowed )
337 {
338 WLANBAP_DeregisterFromHCI();
339 pHddCtx->isAmpAllowed = VOS_FALSE;
340 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700341 }
342#endif //WLAN_BTAMP_FEATURE
343 break;
344
345 default:
346 break;
347 }
348
349 return NOTIFY_DONE;
350}
351
352struct notifier_block hdd_netdev_notifier = {
353 .notifier_call = hdd_netdev_notifier_call,
354};
355
356/*---------------------------------------------------------------------------
357 * Function definitions
358 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700359void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
360void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700361//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700362static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700363#ifndef MODULE
364/* current con_mode - used only for statically linked driver
365 * con_mode is changed by userspace to indicate a mode change which will
366 * result in calling the module exit and init functions. The module
367 * exit function will clean up based on the value of con_mode prior to it
368 * being changed by userspace. So curr_con_mode records the current con_mode
369 * for exit when con_mode becomes the next mode for init
370 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700371static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700372#endif
373
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800374/**---------------------------------------------------------------------------
375
376 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
377
378 Called immediately after the cfg.ini is read in order to configure
379 the desired trace levels.
380
381 \param - moduleId - module whose trace level is being configured
382 \param - bitmask - bitmask of log levels to be enabled
383
384 \return - void
385
386 --------------------------------------------------------------------------*/
387static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
388{
389 wpt_tracelevel level;
390
391 /* if the bitmask is the default value, then a bitmask was not
392 specified in cfg.ini, so leave the logging level alone (it
393 will remain at the "compiled in" default value) */
394 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
395 {
396 return;
397 }
398
399 /* a mask was specified. start by disabling all logging */
400 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
401
402 /* now cycle through the bitmask until all "set" bits are serviced */
403 level = VOS_TRACE_LEVEL_FATAL;
404 while (0 != bitmask)
405 {
406 if (bitmask & 1)
407 {
408 vos_trace_setValue(moduleId, level, 1);
409 }
410 level++;
411 bitmask >>= 1;
412 }
413}
414
415
Jeff Johnson295189b2012-06-20 16:38:30 -0700416/**---------------------------------------------------------------------------
417
418 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
419
420 Called immediately after the cfg.ini is read in order to configure
421 the desired trace levels in the WDI.
422
423 \param - moduleId - module whose trace level is being configured
424 \param - bitmask - bitmask of log levels to be enabled
425
426 \return - void
427
428 --------------------------------------------------------------------------*/
429static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
430{
431 wpt_tracelevel level;
432
433 /* if the bitmask is the default value, then a bitmask was not
434 specified in cfg.ini, so leave the logging level alone (it
435 will remain at the "compiled in" default value) */
436 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
437 {
438 return;
439 }
440
441 /* a mask was specified. start by disabling all logging */
442 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
443
444 /* now cycle through the bitmask until all "set" bits are serviced */
445 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
446 while (0 != bitmask)
447 {
448 if (bitmask & 1)
449 {
450 wpalTraceSetLevel(moduleId, level, 1);
451 }
452 level++;
453 bitmask >>= 1;
454 }
455}
Jeff Johnson295189b2012-06-20 16:38:30 -0700456
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530457/*
458 * FUNCTION: wlan_hdd_validate_context
459 * This function is used to check the HDD context
460 */
461int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
462{
463 ENTER();
464
465 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
466 {
467 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
468 "%s: HDD context is Null", __func__);
469 return -ENODEV;
470 }
471
472 if (pHddCtx->isLogpInProgress)
473 {
474 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
475 "%s: LOGP in Progress. Ignore!!!", __func__);
476 return -EAGAIN;
477 }
478
479 if (pHddCtx->isLoadUnloadInProgress)
480 {
481 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
482 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
483 return -EAGAIN;
484 }
485 return 0;
486}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700487#ifdef CONFIG_ENABLE_LINUX_REG
488void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
489{
490 hdd_adapter_t *pAdapter = NULL;
491 hdd_station_ctx_t *pHddStaCtx = NULL;
492 eCsrPhyMode phyMode;
493 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530494
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700495 if (NULL == pHddCtx)
496 {
497 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
498 "HDD Context is null !!");
499 return ;
500 }
501
502 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
503 if (NULL == pAdapter)
504 {
505 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
506 "pAdapter is null !!");
507 return ;
508 }
509
510 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
511 if (NULL == pHddStaCtx)
512 {
513 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
514 "pHddStaCtx is null !!");
515 return ;
516 }
517
518 cfg_param = pHddCtx->cfg_ini;
519 if (NULL == cfg_param)
520 {
521 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
522 "cfg_params not available !!");
523 return ;
524 }
525
526 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
527
528 if (!pHddCtx->isVHT80Allowed)
529 {
530 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
531 (eCSR_DOT11_MODE_11ac == phyMode) ||
532 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
533 {
534 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
535 "Setting phymode to 11n!!");
536 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
537 }
538 }
539 else
540 {
541 /*New country Supports 11ac as well resetting value back from .ini*/
542 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
543 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
544 return ;
545 }
546
547 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
548 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
549 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
550 {
551 VOS_STATUS vosStatus;
552
553 // need to issue a disconnect to CSR.
554 INIT_COMPLETION(pAdapter->disconnect_comp_var);
555 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
556 pAdapter->sessionId,
557 eCSR_DISCONNECT_REASON_UNSPECIFIED );
558
559 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530560 {
561 long ret;
562
563 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700564 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530565 if (0 >= ret)
566 hddLog(LOGE, FL("failure waiting for disconnect_comp_var %ld"),
567 ret);
568 }
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700569
570 }
571}
572#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530573void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
574{
575 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
576 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
577 hdd_config_t *cfg_param;
578 eCsrPhyMode phyMode;
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530579 long ret;
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530580
581 if (NULL == pHddCtx)
582 {
583 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
584 "HDD Context is null !!");
585 return ;
586 }
587
588 cfg_param = pHddCtx->cfg_ini;
589
590 if (NULL == cfg_param)
591 {
592 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
593 "cfg_params not available !!");
594 return ;
595 }
596
597 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
598
599 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
600 {
601 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
602 (eCSR_DOT11_MODE_11ac == phyMode) ||
603 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
604 {
605 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
606 "Setting phymode to 11n!!");
607 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
608 }
609 }
610 else
611 {
612 /*New country Supports 11ac as well resetting value back from .ini*/
613 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
614 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
615 return ;
616 }
617
618 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
619 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
620 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
621 {
622 VOS_STATUS vosStatus;
623
624 // need to issue a disconnect to CSR.
625 INIT_COMPLETION(pAdapter->disconnect_comp_var);
626 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
627 pAdapter->sessionId,
628 eCSR_DISCONNECT_REASON_UNSPECIFIED );
629
630 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530631 {
632 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530633 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530634 if (ret <= 0)
635 {
636 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
637 "wait on disconnect_comp_var is failed %ld", ret);
638 }
639 }
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530640
641 }
642}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700643#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530644
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700645void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
646{
647 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
648 hdd_config_t *cfg_param;
649
650 if (NULL == pHddCtx)
651 {
652 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
653 "HDD Context is null !!");
654 return ;
655 }
656
657 cfg_param = pHddCtx->cfg_ini;
658
659 if (NULL == cfg_param)
660 {
661 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
662 "cfg_params not available !!");
663 return ;
664 }
665
666 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
667 {
668 /*New country doesn't support DFS */
669 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
670 }
671 else
672 {
673 /*New country Supports DFS as well resetting value back from .ini*/
674 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
675 }
676
677}
678
Rajeev79dbe4c2013-10-05 11:03:42 +0530679#ifdef FEATURE_WLAN_BATCH_SCAN
680
681/**---------------------------------------------------------------------------
682
683 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
684 input string
685
686 This function extracts assigned integer from string in below format:
687 "STRING=10" : extracts integer 10 from this string
688
689 \param - pInPtr Pointer to input string
690 \param - base Base for string to int conversion(10 for decimal 16 for hex)
691 \param - pOutPtr Pointer to variable in which extracted integer needs to be
692 assigned
693 \param - pLastArg to tell whether it is last arguement in input string or
694 not
695
696 \return - NULL for failure cases
697 pointer to next arguement in input string for success cases
698 --------------------------------------------------------------------------*/
699static tANI_U8 *
700hdd_extract_assigned_int_from_str
701(
702 tANI_U8 *pInPtr,
703 tANI_U8 base,
704 tANI_U32 *pOutPtr,
705 tANI_U8 *pLastArg
706)
707{
708 int tempInt;
709 int v = 0;
710 char buf[32];
711 int val = 0;
712 *pLastArg = FALSE;
713
714 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
715 if (NULL == pInPtr)
716 {
717 return NULL;
718 }
719
720 pInPtr++;
721
722 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
723
724 val = sscanf(pInPtr, "%32s ", buf);
725 if (val < 0 && val > strlen(pInPtr))
726 {
727 return NULL;
728 }
729 pInPtr += val;
730 v = kstrtos32(buf, base, &tempInt);
731 if (v < 0)
732 {
733 return NULL;
734 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -0800735 if (tempInt < 0)
736 {
737 tempInt = 0;
738 }
Rajeev79dbe4c2013-10-05 11:03:42 +0530739 *pOutPtr = tempInt;
740
741 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
742 if (NULL == pInPtr)
743 {
744 *pLastArg = TRUE;
745 return NULL;
746 }
747 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
748
749 return pInPtr;
750}
751
752/**---------------------------------------------------------------------------
753
754 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
755 input string
756
757 This function extracts assigned character from string in below format:
758 "STRING=A" : extracts char 'A' from this string
759
760 \param - pInPtr Pointer to input string
761 \param - pOutPtr Pointer to variable in which extracted char needs to be
762 assigned
763 \param - pLastArg to tell whether it is last arguement in input string or
764 not
765
766 \return - NULL for failure cases
767 pointer to next arguement in input string for success cases
768 --------------------------------------------------------------------------*/
769static tANI_U8 *
770hdd_extract_assigned_char_from_str
771(
772 tANI_U8 *pInPtr,
773 tANI_U8 *pOutPtr,
774 tANI_U8 *pLastArg
775)
776{
777 *pLastArg = FALSE;
778
779 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
780 if (NULL == pInPtr)
781 {
782 return NULL;
783 }
784
785 pInPtr++;
786
787 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
788
789 *pOutPtr = *pInPtr;
790
791 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
792 if (NULL == pInPtr)
793 {
794 *pLastArg = TRUE;
795 return NULL;
796 }
797 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
798
799 return pInPtr;
800}
801
802
803/**---------------------------------------------------------------------------
804
805 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
806
807 This function parses set batch scan command in below format:
808 WLS_BATCHING_SET <space> followed by below arguements
809 "SCANFREQ=XX" : Optional defaults to 30 sec
810 "MSCAN=XX" : Required number of scans to attempt to batch
811 "BESTN=XX" : Best Network (RSSI) defaults to 16
812 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
813 A. implies only 5 GHz , B. implies only 2.4GHz
814 "RTT=X" : optional defaults to 0
815 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
816 error
817
818 For example input commands:
819 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
820 translated into set batch scan with following parameters:
821 a) Frequence 60 seconds
822 b) Batch 10 scans together
823 c) Best RSSI to be 20
824 d) 5GHz band only
825 e) RTT is equal to 0
826
827 \param - pValue Pointer to input channel list
828 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
829
830 \return - 0 for success non-zero for failure
831
832 --------------------------------------------------------------------------*/
833static int
834hdd_parse_set_batchscan_command
835(
836 tANI_U8 *pValue,
837 tSirSetBatchScanReq *pHddSetBatchScanReq
838)
839{
840 tANI_U8 *inPtr = pValue;
841 tANI_U8 val = 0;
842 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800843 tANI_U32 nScanFreq;
844 tANI_U32 nMscan;
845 tANI_U32 nBestN;
846 tANI_U8 ucRfBand;
847 tANI_U32 nRtt;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800848 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530849
850 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800851 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
852 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
853 nRtt = 0;
854 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530855
856 /*go to space after WLS_BATCHING_SET command*/
857 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
858 /*no argument after the command*/
859 if (NULL == inPtr)
860 {
861 return -EINVAL;
862 }
863
864 /*no space after the command*/
865 else if (SPACE_ASCII_VALUE != *inPtr)
866 {
867 return -EINVAL;
868 }
869
870 /*removing empty spaces*/
871 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
872
873 /*no argument followed by spaces*/
874 if ('\0' == *inPtr)
875 {
876 return -EINVAL;
877 }
878
879 /*check and parse SCANFREQ*/
880 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
881 {
882 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800883 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800884
Rajeev Kumarc933d982013-11-18 20:04:20 -0800885 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800886 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800887 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800888 }
889
Rajeev79dbe4c2013-10-05 11:03:42 +0530890 if ( (NULL == inPtr) || (TRUE == lastArg))
891 {
892 return -EINVAL;
893 }
894 }
895
896 /*check and parse MSCAN*/
897 if ((strncmp(inPtr, "MSCAN", 5) == 0))
898 {
899 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800900 &nMscan, &lastArg);
901
902 if (0 == nMscan)
903 {
904 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
905 "invalid MSCAN=%d", nMscan);
906 return -EINVAL;
907 }
908
Rajeev79dbe4c2013-10-05 11:03:42 +0530909 if (TRUE == lastArg)
910 {
911 goto done;
912 }
913 else if (NULL == inPtr)
914 {
915 return -EINVAL;
916 }
917 }
918 else
919 {
920 return -EINVAL;
921 }
922
923 /*check and parse BESTN*/
924 if ((strncmp(inPtr, "BESTN", 5) == 0))
925 {
926 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800927 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800928
Rajeev Kumarc933d982013-11-18 20:04:20 -0800929 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800930 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800931 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800932 }
933
Rajeev79dbe4c2013-10-05 11:03:42 +0530934 if (TRUE == lastArg)
935 {
936 goto done;
937 }
938 else if (NULL == inPtr)
939 {
940 return -EINVAL;
941 }
942 }
943
944 /*check and parse CHANNEL*/
945 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
946 {
947 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800948
Rajeev79dbe4c2013-10-05 11:03:42 +0530949 if (('A' == val) || ('a' == val))
950 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800951 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530952 }
953 else if (('B' == val) || ('b' == val))
954 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800955 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530956 }
957 else
958 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800959 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
960 }
961
962 if (TRUE == lastArg)
963 {
964 goto done;
965 }
966 else if (NULL == inPtr)
967 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530968 return -EINVAL;
969 }
970 }
971
972 /*check and parse RTT*/
973 if ((strncmp(inPtr, "RTT", 3) == 0))
974 {
975 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800976 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530977 if (TRUE == lastArg)
978 {
979 goto done;
980 }
981 if (NULL == inPtr)
982 {
983 return -EINVAL;
984 }
985 }
986
987
988done:
989
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800990 pHddSetBatchScanReq->scanFrequency = nScanFreq;
991 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
992 pHddSetBatchScanReq->bestNetwork = nBestN;
993 pHddSetBatchScanReq->rfBand = ucRfBand;
994 pHddSetBatchScanReq->rtt = nRtt;
995
Rajeev79dbe4c2013-10-05 11:03:42 +0530996 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
997 "Received WLS_BATCHING_SET with SCANFREQ=%d "
998 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
999 pHddSetBatchScanReq->scanFrequency,
1000 pHddSetBatchScanReq->numberOfScansToBatch,
1001 pHddSetBatchScanReq->bestNetwork,
1002 pHddSetBatchScanReq->rfBand,
1003 pHddSetBatchScanReq->rtt);
1004
1005 return 0;
1006}/*End of hdd_parse_set_batchscan_command*/
1007
1008/**---------------------------------------------------------------------------
1009
1010 \brief hdd_set_batch_scan_req_callback () - This function is called after
1011 receiving set batch scan response from FW and it saves set batch scan
1012 response data FW to HDD context and sets the completion event on
1013 which hdd_ioctl is waiting
1014
1015 \param - callbackContext Pointer to HDD adapter
1016 \param - pRsp Pointer to set batch scan response data received from FW
1017
1018 \return - nothing
1019
1020 --------------------------------------------------------------------------*/
1021static void hdd_set_batch_scan_req_callback
1022(
1023 void *callbackContext,
1024 tSirSetBatchScanRsp *pRsp
1025)
1026{
1027 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1028 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1029
1030 /*sanity check*/
1031 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1032 {
1033 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1034 "%s: Invalid pAdapter magic", __func__);
1035 VOS_ASSERT(0);
1036 return;
1037 }
1038 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1039
1040 /*save set batch scan response*/
1041 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1042
1043 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1044 "Received set batch scan rsp from FW with nScansToBatch=%d",
1045 pHddSetBatchScanRsp->nScansToBatch);
1046
1047 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1048 complete(&pAdapter->hdd_set_batch_scan_req_var);
1049
1050 return;
1051}/*End of hdd_set_batch_scan_req_callback*/
1052
1053
1054/**---------------------------------------------------------------------------
1055
1056 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1057 info in hdd batch scan response queue
1058
1059 \param - pAdapter Pointer to hdd adapter
1060 \param - pAPMetaInfo Pointer to access point meta info
1061 \param - scanId scan ID of batch scan response
1062 \param - isLastAp tells whether AP is last AP in batch scan response or not
1063
1064 \return - nothing
1065
1066 --------------------------------------------------------------------------*/
1067static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1068 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1069{
1070 tHddBatchScanRsp *pHead;
1071 tHddBatchScanRsp *pNode;
1072 tHddBatchScanRsp *pPrev;
1073 tHddBatchScanRsp *pTemp;
1074 tANI_U8 ssidLen;
1075
1076 /*head of hdd batch scan response queue*/
1077 pHead = pAdapter->pBatchScanRsp;
1078
1079 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1080 if (NULL == pNode)
1081 {
1082 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1083 "%s: Could not allocate memory", __func__);
1084 VOS_ASSERT(0);
1085 return;
1086 }
1087
1088 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1089 sizeof(pNode->ApInfo.bssid));
1090 ssidLen = strlen(pApMetaInfo->ssid);
1091 if (SIR_MAX_SSID_SIZE < ssidLen)
1092 {
1093 /*invalid scan result*/
1094 vos_mem_free(pNode);
1095 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1096 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1097 return;
1098 }
1099 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1100 /*null terminate ssid*/
1101 pNode->ApInfo.ssid[ssidLen] = '\0';
1102 pNode->ApInfo.ch = pApMetaInfo->ch;
1103 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1104 pNode->ApInfo.age = pApMetaInfo->timestamp;
1105 pNode->ApInfo.batchId = scanId;
1106 pNode->ApInfo.isLastAp = isLastAp;
1107
1108 pNode->pNext = NULL;
1109 if (NULL == pHead)
1110 {
1111 pAdapter->pBatchScanRsp = pNode;
1112 }
1113 else
1114 {
1115 pTemp = pHead;
1116 while (NULL != pTemp)
1117 {
1118 pPrev = pTemp;
1119 pTemp = pTemp->pNext;
1120 }
1121 pPrev->pNext = pNode;
1122 }
1123
1124 return;
1125}/*End of hdd_populate_batch_scan_rsp_queue*/
1126
1127/**---------------------------------------------------------------------------
1128
1129 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1130 receiving batch scan response indication from FW. It saves get batch scan
1131 response data in HDD batch scan response queue. This callback sets the
1132 completion event on which hdd_ioctl is waiting only after getting complete
1133 batch scan response data from FW
1134
1135 \param - callbackContext Pointer to HDD adapter
1136 \param - pRsp Pointer to get batch scan response data received from FW
1137
1138 \return - nothing
1139
1140 --------------------------------------------------------------------------*/
1141static void hdd_batch_scan_result_ind_callback
1142(
1143 void *callbackContext,
1144 void *pRsp
1145)
1146{
1147 v_BOOL_t isLastAp;
1148 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001149 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301150 tANI_U32 numberScanList;
1151 tANI_U32 nextScanListOffset;
1152 tANI_U32 nextApMetaInfoOffset;
1153 hdd_adapter_t* pAdapter;
1154 tpSirBatchScanList pScanList;
1155 tpSirBatchScanNetworkInfo pApMetaInfo;
1156 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1157 tSirSetBatchScanReq *pReq;
1158
1159 pAdapter = (hdd_adapter_t *)callbackContext;
1160 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001161 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301162 {
1163 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1164 "%s: Invalid pAdapter magic", __func__);
1165 VOS_ASSERT(0);
1166 return;
1167 }
1168
1169 /*initialize locals*/
1170 pReq = &pAdapter->hddSetBatchScanReq;
1171 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1172 isLastAp = FALSE;
1173 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001174 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301175 numberScanList = 0;
1176 nextScanListOffset = 0;
1177 nextApMetaInfoOffset = 0;
1178 pScanList = NULL;
1179 pApMetaInfo = NULL;
1180
1181 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1182 {
1183 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1184 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1185 isLastAp = TRUE;
1186 goto done;
1187 }
1188
1189 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1190 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1191 "Batch scan rsp: numberScalList %d", numberScanList);
1192
1193 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1194 {
1195 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1196 "%s: numberScanList %d", __func__, numberScanList);
1197 isLastAp = TRUE;
1198 goto done;
1199 }
1200
1201 while (numberScanList)
1202 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001203 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301204 nextScanListOffset);
1205 if (NULL == pScanList)
1206 {
1207 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1208 "%s: pScanList is %p", __func__, pScanList);
1209 isLastAp = TRUE;
1210 goto done;
1211 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001212 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301213 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001214 "Batch scan rsp: numApMetaInfo %d scanId %d",
1215 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301216
1217 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1218 {
1219 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1220 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1221 isLastAp = TRUE;
1222 goto done;
1223 }
1224
Rajeev Kumarce651e42013-10-21 18:57:15 -07001225 /*Initialize next AP meta info offset for next scan list*/
1226 nextApMetaInfoOffset = 0;
1227
Rajeev79dbe4c2013-10-05 11:03:42 +05301228 while (numApMetaInfo)
1229 {
1230 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1231 nextApMetaInfoOffset);
1232 if (NULL == pApMetaInfo)
1233 {
1234 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1235 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1236 isLastAp = TRUE;
1237 goto done;
1238 }
1239 /*calculate AP age*/
1240 pApMetaInfo->timestamp =
1241 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1242
1243 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001244 "%s: bssId "MAC_ADDRESS_STR
1245 " ch %d rssi %d timestamp %d", __func__,
1246 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1247 pApMetaInfo->ch, pApMetaInfo->rssi,
1248 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301249
1250 /*mark last AP in batch scan response*/
1251 if ((TRUE == pBatchScanRsp->isLastResult) &&
1252 (1 == numberScanList) && (1 == numApMetaInfo))
1253 {
1254 isLastAp = TRUE;
1255 }
1256
1257 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1258 /*store batch scan repsonse in hdd queue*/
1259 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1260 pScanList->scanId, isLastAp);
1261 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1262
1263 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1264 numApMetaInfo--;
1265 }
1266
Rajeev Kumarce651e42013-10-21 18:57:15 -07001267 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1268 + (sizeof(tSirBatchScanNetworkInfo)
1269 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301270 numberScanList--;
1271 }
1272
1273done:
1274
1275 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1276 requested from hdd_ioctl*/
1277 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1278 (TRUE == isLastAp))
1279 {
1280 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1281 complete(&pAdapter->hdd_get_batch_scan_req_var);
1282 }
1283
1284 return;
1285}/*End of hdd_batch_scan_result_ind_callback*/
1286
1287/**---------------------------------------------------------------------------
1288
1289 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1290 response as per batch scan FR request format by putting proper markers
1291
1292 \param - pDest pointer to destination buffer
1293 \param - cur_len current length
1294 \param - tot_len total remaining size which can be written to user space
1295 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1296 \param - pAdapter Pointer to HDD adapter
1297
1298 \return - ret no of characters written
1299
1300 --------------------------------------------------------------------------*/
1301static tANI_U32
1302hdd_format_batch_scan_rsp
1303(
1304 tANI_U8 *pDest,
1305 tANI_U32 cur_len,
1306 tANI_U32 tot_len,
1307 tHddBatchScanRsp *pApMetaInfo,
1308 hdd_adapter_t* pAdapter
1309)
1310{
1311 tANI_U32 ret = 0;
1312 tANI_U32 rem_len = 0;
1313 tANI_U8 temp_len = 0;
1314 tANI_U8 temp_total_len = 0;
1315 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1316 tANI_U8 *pTemp = temp;
1317
1318 /*Batch scan reponse needs to be returned to user space in
1319 following format:
1320 "scancount=X\n" where X is the number of scans in current batch
1321 batch
1322 "trunc\n" optional present if current scan truncated
1323 "bssid=XX:XX:XX:XX:XX:XX\n"
1324 "ssid=XXXX\n"
1325 "freq=X\n" frequency in Mhz
1326 "level=XX\n"
1327 "age=X\n" ms
1328 "dist=X\n" cm (-1 if not available)
1329 "errror=X\n" (-1if not available)
1330 "====\n" (end of ap marker)
1331 "####\n" (end of scan marker)
1332 "----\n" (end of results)*/
1333 /*send scan result in above format to user space based on
1334 available length*/
1335 /*The GET response may have more data than the driver can return in its
1336 buffer. In that case the buffer should be filled to the nearest complete
1337 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1338 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1339 The final buffer should end with "----\n"*/
1340
1341 /*sanity*/
1342 if (cur_len > tot_len)
1343 {
1344 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1345 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1346 return 0;
1347 }
1348 else
1349 {
1350 rem_len = (tot_len - cur_len);
1351 }
1352
1353 /*end scan marker*/
1354 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1355 {
1356 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1357 pTemp += temp_len;
1358 temp_total_len += temp_len;
1359 }
1360
1361 /*bssid*/
1362 temp_len = snprintf(pTemp, sizeof(temp),
1363 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1364 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1365 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1366 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1367 pTemp += temp_len;
1368 temp_total_len += temp_len;
1369
1370 /*ssid*/
1371 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1372 pApMetaInfo->ApInfo.ssid);
1373 pTemp += temp_len;
1374 temp_total_len += temp_len;
1375
1376 /*freq*/
1377 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001378 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301379 pTemp += temp_len;
1380 temp_total_len += temp_len;
1381
1382 /*level*/
1383 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1384 pApMetaInfo->ApInfo.rssi);
1385 pTemp += temp_len;
1386 temp_total_len += temp_len;
1387
1388 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001389 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301390 pApMetaInfo->ApInfo.age);
1391 pTemp += temp_len;
1392 temp_total_len += temp_len;
1393
1394 /*dist*/
1395 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1396 pTemp += temp_len;
1397 temp_total_len += temp_len;
1398
1399 /*error*/
1400 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1401 pTemp += temp_len;
1402 temp_total_len += temp_len;
1403
1404 /*end AP marker*/
1405 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1406 pTemp += temp_len;
1407 temp_total_len += temp_len;
1408
1409 /*last AP in batch scan response*/
1410 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1411 {
1412 /*end scan marker*/
1413 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1414 pTemp += temp_len;
1415 temp_total_len += temp_len;
1416
1417 /*end batch scan result marker*/
1418 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1419 pTemp += temp_len;
1420 temp_total_len += temp_len;
1421 }
1422
1423 if (temp_total_len < rem_len)
1424 {
1425 ret = temp_total_len + 1;
1426 strlcpy(pDest, temp, ret);
1427 pAdapter->isTruncated = FALSE;
1428 }
1429 else
1430 {
1431 pAdapter->isTruncated = TRUE;
1432 if (rem_len >= strlen("%%%%"))
1433 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001434 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301435 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001436 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301437 {
1438 ret = 0;
1439 }
1440 }
1441
1442 return ret;
1443
1444}/*End of hdd_format_batch_scan_rsp*/
1445
1446/**---------------------------------------------------------------------------
1447
1448 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1449 buffer starting with head of hdd batch scan response queue
1450
1451 \param - pAdapter Pointer to HDD adapter
1452 \param - pDest Pointer to user data buffer
1453 \param - cur_len current offset in user buffer
1454 \param - rem_len remaining no of bytes in user buffer
1455
1456 \return - number of bytes written in user buffer
1457
1458 --------------------------------------------------------------------------*/
1459
1460tANI_U32 hdd_populate_user_batch_scan_rsp
1461(
1462 hdd_adapter_t* pAdapter,
1463 tANI_U8 *pDest,
1464 tANI_U32 cur_len,
1465 tANI_U32 rem_len
1466)
1467{
1468 tHddBatchScanRsp *pHead;
1469 tHddBatchScanRsp *pPrev;
1470 tANI_U32 len;
1471
Kiet Lam34947452014-01-21 23:23:40 -08001472 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301473 pAdapter->isTruncated = FALSE;
1474
1475 /*head of hdd batch scan response queue*/
1476 pHead = pAdapter->pBatchScanRsp;
1477 while (pHead)
1478 {
1479 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1480 pAdapter);
1481 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001482 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301483 cur_len += len;
1484 if(TRUE == pAdapter->isTruncated)
1485 {
1486 /*result is truncated return rest of scan rsp in next req*/
1487 cur_len = rem_len;
1488 break;
1489 }
1490 pPrev = pHead;
1491 pHead = pHead->pNext;
1492 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08001493 if (TRUE == pPrev->ApInfo.isLastAp)
1494 {
1495 pAdapter->prev_batch_id = 0;
1496 }
1497 else
1498 {
1499 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1500 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301501 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08001502 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05301503 }
1504
1505 return cur_len;
1506}/*End of hdd_populate_user_batch_scan_rsp*/
1507
1508/**---------------------------------------------------------------------------
1509
1510 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1511 scan response data from HDD queue to user space
1512 It does following in detail:
1513 a) if HDD has enough data in its queue then it 1st copies data to user
1514 space and then send get batch scan indication message to FW. In this
1515 case it does not wait on any event and batch scan response data will
1516 be populated in HDD response queue in MC thread context after receiving
1517 indication from FW
1518 b) else send get batch scan indication message to FW and wait on an event
1519 which will be set once HDD receives complete batch scan response from
1520 FW and then this function returns batch scan response to user space
1521
1522 \param - pAdapter Pointer to HDD adapter
1523 \param - pPrivData Pointer to priv_data
1524
1525 \return - 0 for success -EFAULT for failure
1526
1527 --------------------------------------------------------------------------*/
1528
1529int hdd_return_batch_scan_rsp_to_user
1530(
1531 hdd_adapter_t* pAdapter,
1532 hdd_priv_data_t *pPrivData,
1533 tANI_U8 *command
1534)
1535{
1536 tANI_U8 *pDest;
1537 tANI_U32 count = 0;
1538 tANI_U32 len = 0;
1539 tANI_U32 cur_len = 0;
1540 tANI_U32 rem_len = 0;
1541 eHalStatus halStatus;
1542 unsigned long rc;
1543 tSirTriggerBatchScanResultInd *pReq;
1544
1545 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1546 pReq->param = 0;/*batch scan client*/
1547 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1548 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1549
1550 cur_len = pPrivData->used_len;
1551 if (pPrivData->total_len > pPrivData->used_len)
1552 {
1553 rem_len = pPrivData->total_len - pPrivData->used_len;
1554 }
1555 else
1556 {
1557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1558 "%s: Invalid user data buffer total_len %d used_len %d",
1559 __func__, pPrivData->total_len, pPrivData->used_len);
1560 return -EFAULT;
1561 }
1562
1563 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1564 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1565 cur_len, rem_len);
1566 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1567
1568 /*enough scan result available in cache to return to user space or
1569 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001570 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301571 {
1572 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1573 halStatus = sme_TriggerBatchScanResultInd(
1574 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1575 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1576 pAdapter);
1577 if ( eHAL_STATUS_SUCCESS == halStatus )
1578 {
1579 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1580 {
1581 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1582 rc = wait_for_completion_timeout(
1583 &pAdapter->hdd_get_batch_scan_req_var,
1584 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1585 if (0 == rc)
1586 {
1587 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1588 "%s: Timeout waiting to fetch batch scan rsp from fw",
1589 __func__);
1590 return -EFAULT;
1591 }
1592 }
1593
1594 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001595 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301596 pDest += len;
1597 cur_len += len;
1598
1599 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1600 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1601 cur_len, rem_len);
1602 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1603
1604 count = 0;
1605 len = (len - pPrivData->used_len);
1606 pDest = (command + pPrivData->used_len);
1607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001608 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301609 while(count < len)
1610 {
1611 printk("%c", *(pDest + count));
1612 count++;
1613 }
1614 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1615 "%s: copy %d data to user buffer", __func__, len);
1616 if (copy_to_user(pPrivData->buf, pDest, len))
1617 {
1618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1619 "%s: failed to copy data to user buffer", __func__);
1620 return -EFAULT;
1621 }
1622 }
1623 else
1624 {
1625 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1626 "sme_GetBatchScanScan returned failure halStatus %d",
1627 halStatus);
1628 return -EINVAL;
1629 }
1630 }
1631 else
1632 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301633 count = 0;
1634 len = (len - pPrivData->used_len);
1635 pDest = (command + pPrivData->used_len);
1636 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001637 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301638 while(count < len)
1639 {
1640 printk("%c", *(pDest + count));
1641 count++;
1642 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001643 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1644 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301645 if (copy_to_user(pPrivData->buf, pDest, len))
1646 {
1647 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1648 "%s: failed to copy data to user buffer", __func__);
1649 return -EFAULT;
1650 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301651 }
1652
1653 return 0;
1654} /*End of hdd_return_batch_scan_rsp_to_user*/
1655
Rajeev Kumar8b373292014-01-08 20:36:55 -08001656
1657/**---------------------------------------------------------------------------
1658
1659 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
1660 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
1661 WLS_BATCHING VERSION
1662 WLS_BATCHING SET
1663 WLS_BATCHING GET
1664 WLS_BATCHING STOP
1665
1666 \param - pAdapter Pointer to HDD adapter
1667 \param - pPrivdata Pointer to priv_data
1668 \param - command Pointer to command
1669
1670 \return - 0 for success -EFAULT for failure
1671
1672 --------------------------------------------------------------------------*/
1673
1674int hdd_handle_batch_scan_ioctl
1675(
1676 hdd_adapter_t *pAdapter,
1677 hdd_priv_data_t *pPrivdata,
1678 tANI_U8 *command
1679)
1680{
1681 int ret = 0;
1682
1683 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
1684 {
1685 char extra[32];
1686 tANI_U8 len = 0;
1687 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
1688
1689 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1690 {
1691 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1692 "%s: Batch scan feature is not supported by FW", __func__);
1693 ret = -EINVAL;
1694 goto exit;
1695 }
1696
1697 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
1698 version);
1699 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1700 {
1701 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1702 "%s: failed to copy data to user buffer", __func__);
1703 ret = -EFAULT;
1704 goto exit;
1705 }
1706 ret = HDD_BATCH_SCAN_VERSION;
1707 }
1708 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
1709 {
1710 int status;
1711 tANI_U8 *value = (command + 16);
1712 eHalStatus halStatus;
1713 unsigned long rc;
1714 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
1715 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
1716
1717 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1718 {
1719 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1720 "%s: Batch scan feature is not supported by FW", __func__);
1721 ret = -EINVAL;
1722 goto exit;
1723 }
1724
1725 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
1726 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
1727 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
1728 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
1729 {
1730 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1731 "Received WLS_BATCHING SET command in invalid mode %d "
1732 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
1733 pAdapter->device_mode);
1734 ret = -EINVAL;
1735 goto exit;
1736 }
1737
1738 status = hdd_parse_set_batchscan_command(value, pReq);
1739 if (status)
1740 {
1741 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1742 "Invalid WLS_BATCHING SET command");
1743 ret = -EINVAL;
1744 goto exit;
1745 }
1746
1747
1748 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
1749 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1750 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
1751 pAdapter);
1752
1753 if ( eHAL_STATUS_SUCCESS == halStatus )
1754 {
1755 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1756 "sme_SetBatchScanReq returned success halStatus %d",
1757 halStatus);
1758 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
1759 {
1760 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
1761 rc = wait_for_completion_timeout(
1762 &pAdapter->hdd_set_batch_scan_req_var,
1763 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
1764 if (0 == rc)
1765 {
1766 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1767 "%s: Timeout waiting for set batch scan to complete",
1768 __func__);
1769 ret = -EINVAL;
1770 goto exit;
1771 }
1772 }
1773 if ( !pRsp->nScansToBatch )
1774 {
1775 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1776 "%s: Received set batch scan failure response from FW",
1777 __func__);
1778 ret = -EINVAL;
1779 goto exit;
1780 }
1781 /*As per the Batch Scan Framework API we should return the MIN of
1782 either MSCAN or the max # of scans firmware can cache*/
1783 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
1784
1785 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
1786
1787 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1788 "%s: request MSCAN %d response MSCAN %d ret %d",
1789 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
1790 }
1791 else
1792 {
1793 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1794 "sme_SetBatchScanReq returned failure halStatus %d",
1795 halStatus);
1796 ret = -EINVAL;
1797 goto exit;
1798 }
1799 }
1800 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
1801 {
1802 eHalStatus halStatus;
1803 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
1804 pInd->param = 0;
1805
1806 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1807 {
1808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1809 "%s: Batch scan feature is not supported by FW", __func__);
1810 ret = -EINVAL;
1811 goto exit;
1812 }
1813
1814 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1815 {
1816 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1817 "Batch scan is not yet enabled batch scan state %d",
1818 pAdapter->batchScanState);
1819 ret = -EINVAL;
1820 goto exit;
1821 }
1822
1823 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
1824
1825 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
1826 pAdapter->sessionId);
1827 if ( eHAL_STATUS_SUCCESS == halStatus )
1828 {
1829 ret = 0;
1830 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1831 "sme_StopBatchScanInd returned success halStatus %d",
1832 halStatus);
1833 }
1834 else
1835 {
1836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1837 "sme_StopBatchScanInd returned failure halStatus %d",
1838 halStatus);
1839 ret = -EINVAL;
1840 goto exit;
1841 }
1842 }
1843 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
1844 {
1845 tANI_U32 remain_len;
1846
1847 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1848 {
1849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1850 "%s: Batch scan feature is not supported by FW", __func__);
1851 ret = -EINVAL;
1852 goto exit;
1853 }
1854
1855 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1856 {
1857 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1858 "Batch scan is not yet enabled could not return results"
1859 "Batch Scan state %d",
1860 pAdapter->batchScanState);
1861 ret = -EINVAL;
1862 goto exit;
1863 }
1864
1865 pPrivdata->used_len = 16;
1866 remain_len = pPrivdata->total_len - pPrivdata->used_len;
1867 if (remain_len < pPrivdata->total_len)
1868 {
1869 /*Clear previous batch scan response data if any*/
1870 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
1871 }
1872 else
1873 {
1874 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1875 "Invalid total length from user space can't fetch batch"
1876 " scan response total_len %d used_len %d remain len %d",
1877 pPrivdata->total_len, pPrivdata->used_len, remain_len);
1878 ret = -EINVAL;
1879 goto exit;
1880 }
1881 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
1882 }
1883
1884exit:
1885
1886 return ret;
1887}
1888
1889
Rajeev79dbe4c2013-10-05 11:03:42 +05301890#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1891
Jeff Johnson295189b2012-06-20 16:38:30 -07001892int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1893{
1894 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1895 hdd_priv_data_t priv_data;
1896 tANI_U8 *command = NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301897 long ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001898
1899 if (NULL == pAdapter)
1900 {
1901 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301902 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001903 ret = -ENODEV;
1904 goto exit;
1905 }
1906
Jeff Johnsone7245742012-09-05 17:12:55 -07001907 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001908 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301909 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1910 "%s: invalid data", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001911 ret = -EINVAL;
1912 goto exit;
1913 }
1914
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001915 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1916 {
1917 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1918 "%s:LOGP in Progress. Ignore!!!", __func__);
1919 ret = -EBUSY;
1920 goto exit;
1921 }
1922
Jeff Johnson295189b2012-06-20 16:38:30 -07001923 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1924 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301925 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1926 FL("failed to get data from user buffer"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001927 ret = -EFAULT;
1928 goto exit;
1929 }
1930
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08001931 if (priv_data.total_len <= 0 ||
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301932 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001933 {
1934 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1935 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1936 priv_data.total_len);
1937 ret = -EINVAL;
1938 goto exit;
1939 }
1940
1941 /* Allocate +1 for '\0' */
1942 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001943 if (!command)
1944 {
1945 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301946 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001947 ret = -ENOMEM;
1948 goto exit;
1949 }
1950
1951 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1952 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301953 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1954 FL("failed to get data from user buffer"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001955 ret = -EFAULT;
1956 goto exit;
1957 }
1958
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001959 /* Making sure the command is NUL-terminated */
1960 command[priv_data.total_len] = '\0';
1961
Jeff Johnson295189b2012-06-20 16:38:30 -07001962 if ((SIOCDEVPRIVATE + 1) == cmd)
1963 {
1964 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1965
1966 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001967 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001968
1969 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1970 {
1971 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1972 sizeof(tSirMacAddr)))
1973 {
1974 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001975 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001976 ret = -EFAULT;
1977 }
1978 }
Amar Singhal0974e402013-02-12 14:27:46 -08001979 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001980 {
Amar Singhal0974e402013-02-12 14:27:46 -08001981 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001982
Jeff Johnson295189b2012-06-20 16:38:30 -07001983 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001984
1985 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001986 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001987 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001988 "%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 -07001989 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001990 ret = hdd_setBand_helper(dev, ptr);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301991 if(ret != 0)
1992 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1993 "%s: failed to set band ret=%ld",__func__, ret);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001994 }
Kiet Lamf040f472013-11-20 21:15:23 +05301995 else if(strncmp(command, "SETWMMPS", 8) == 0)
1996 {
1997 tANI_U8 *ptr = command;
1998 ret = hdd_wmmps_helper(pAdapter, ptr);
1999 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07002000 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
2001 {
2002 char *country_code;
2003
2004 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002005
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002006 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002007 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002008#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05302009 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002010#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002011 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2012 (void *)(tSmeChangeCountryCallback)
2013 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05302014 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002015 if (eHAL_STATUS_SUCCESS == ret)
2016 {
2017 ret = wait_for_completion_interruptible_timeout(
2018 &pAdapter->change_country_code,
2019 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
2020 if (0 >= ret)
2021 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302022 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %ld",
2023 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002024 }
2025 }
2026 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002027 {
2028 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302029 "%s: SME Change Country code fail ret=%ld", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002030 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002031 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002032
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002033 }
2034 /*
2035 command should be a string having format
2036 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2037 */
Amar Singhal0974e402013-02-12 14:27:46 -08002038 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002039 {
Amar Singhal0974e402013-02-12 14:27:46 -08002040 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002041
2042 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002043 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002044
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002045 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002046 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002047 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2048 {
2049 int suspend = 0;
2050 tANI_U8 *ptr = (tANI_U8*)command + 15;
2051
2052 suspend = *ptr - '0';
2053 hdd_set_wlan_suspend_mode(suspend);
2054 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002055#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2056 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2057 {
2058 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002059 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002060 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2061 eHalStatus status = eHAL_STATUS_SUCCESS;
2062
2063 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2064 value = value + 15;
2065
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002066 /* Convert the value from ascii to integer */
2067 ret = kstrtos8(value, 10, &rssi);
2068 if (ret < 0)
2069 {
2070 /* If the input value is greater than max value of datatype, then also
2071 kstrtou8 fails */
2072 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2073 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002074 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002075 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2076 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2077 ret = -EINVAL;
2078 goto exit;
2079 }
2080
Srinivas Girigowdade697412013-02-14 16:31:48 -08002081 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002082
Srinivas Girigowdade697412013-02-14 16:31:48 -08002083 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2084 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2085 {
2086 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2087 "Neighbor lookup threshold value %d is out of range"
2088 " (Min: %d Max: %d)", lookUpThreshold,
2089 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2090 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2091 ret = -EINVAL;
2092 goto exit;
2093 }
2094
2095 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2096 "%s: Received Command to Set Roam trigger"
2097 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2098
2099 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2100 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2101 if (eHAL_STATUS_SUCCESS != status)
2102 {
2103 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2104 "%s: Failed to set roam trigger, try again", __func__);
2105 ret = -EPERM;
2106 goto exit;
2107 }
2108
2109 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
2110 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2111 }
2112 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2113 {
2114 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2115 int rssi = (-1) * lookUpThreshold;
2116 char extra[32];
2117 tANI_U8 len = 0;
2118
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002119 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002120 if (copy_to_user(priv_data.buf, &extra, len + 1))
2121 {
2122 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2123 "%s: failed to copy data to user buffer", __func__);
2124 ret = -EFAULT;
2125 goto exit;
2126 }
2127 }
2128 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2129 {
2130 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002131 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002132 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002133
Srinivas Girigowdade697412013-02-14 16:31:48 -08002134 /* input refresh period is in terms of seconds */
2135 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2136 value = value + 18;
2137 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002138 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002139 if (ret < 0)
2140 {
2141 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002142 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002143 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002144 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002145 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002146 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2147 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002148 ret = -EINVAL;
2149 goto exit;
2150 }
2151
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002152 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2153 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002154 {
2155 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002156 "Roam scan period value %d is out of range"
2157 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002158 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2159 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002160 ret = -EINVAL;
2161 goto exit;
2162 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002163 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002164
2165 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2166 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002167 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002168
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002169 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2170 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002171 }
2172 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2173 {
2174 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2175 char extra[32];
2176 tANI_U8 len = 0;
2177
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002178 len = scnprintf(extra, sizeof(extra), "%s %d",
2179 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002180 /* Returned value is in units of seconds */
2181 if (copy_to_user(priv_data.buf, &extra, len + 1))
2182 {
2183 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2184 "%s: failed to copy data to user buffer", __func__);
2185 ret = -EFAULT;
2186 goto exit;
2187 }
2188 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002189 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2190 {
2191 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002192 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002193 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002194
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002195 /* input refresh period is in terms of seconds */
2196 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2197 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002198
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002199 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002200 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002201 if (ret < 0)
2202 {
2203 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002204 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002205 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002206 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002207 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002208 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2209 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2210 ret = -EINVAL;
2211 goto exit;
2212 }
2213
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002214 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2215 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2216 {
2217 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2218 "Neighbor scan results refresh period value %d is out of range"
2219 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2220 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2221 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2222 ret = -EINVAL;
2223 goto exit;
2224 }
2225 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2226
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2228 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002229 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002230
2231 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2232 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2233 }
2234 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2235 {
2236 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2237 char extra[32];
2238 tANI_U8 len = 0;
2239
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002240 len = scnprintf(extra, sizeof(extra), "%s %d",
2241 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002242 /* Returned value is in units of seconds */
2243 if (copy_to_user(priv_data.buf, &extra, len + 1))
2244 {
2245 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2246 "%s: failed to copy data to user buffer", __func__);
2247 ret = -EFAULT;
2248 goto exit;
2249 }
2250 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002251#ifdef FEATURE_WLAN_LFR
2252 /* SETROAMMODE */
2253 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2254 {
2255 tANI_U8 *value = command;
2256 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2257
2258 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2259 value = value + SIZE_OF_SETROAMMODE + 1;
2260
2261 /* Convert the value from ascii to integer */
2262 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2263 if (ret < 0)
2264 {
2265 /* If the input value is greater than max value of datatype, then also
2266 kstrtou8 fails */
2267 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2268 "%s: kstrtou8 failed range [%d - %d]", __func__,
2269 CFG_LFR_FEATURE_ENABLED_MIN,
2270 CFG_LFR_FEATURE_ENABLED_MAX);
2271 ret = -EINVAL;
2272 goto exit;
2273 }
2274 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2275 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2276 {
2277 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2278 "Roam Mode value %d is out of range"
2279 " (Min: %d Max: %d)", roamMode,
2280 CFG_LFR_FEATURE_ENABLED_MIN,
2281 CFG_LFR_FEATURE_ENABLED_MAX);
2282 ret = -EINVAL;
2283 goto exit;
2284 }
2285
2286 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2287 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2288 /*
2289 * Note that
2290 * SETROAMMODE 0 is to enable LFR while
2291 * SETROAMMODE 1 is to disable LFR, but
2292 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2293 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2294 */
2295 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2296 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2297 else
2298 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2299
2300 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2301 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2302 }
2303 /* GETROAMMODE */
2304 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2305 {
2306 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2307 char extra[32];
2308 tANI_U8 len = 0;
2309
2310 /*
2311 * roamMode value shall be inverted because the sementics is different.
2312 */
2313 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2314 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2315 else
2316 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2317
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002318 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002319 if (copy_to_user(priv_data.buf, &extra, len + 1))
2320 {
2321 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2322 "%s: failed to copy data to user buffer", __func__);
2323 ret = -EFAULT;
2324 goto exit;
2325 }
2326 }
2327#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002328#endif
2329#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2330 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2331 {
2332 tANI_U8 *value = command;
2333 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2334
2335 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2336 value = value + 13;
2337 /* Convert the value from ascii to integer */
2338 ret = kstrtou8(value, 10, &roamRssiDiff);
2339 if (ret < 0)
2340 {
2341 /* If the input value is greater than max value of datatype, then also
2342 kstrtou8 fails */
2343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2344 "%s: kstrtou8 failed range [%d - %d]", __func__,
2345 CFG_ROAM_RSSI_DIFF_MIN,
2346 CFG_ROAM_RSSI_DIFF_MAX);
2347 ret = -EINVAL;
2348 goto exit;
2349 }
2350
2351 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2352 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2353 {
2354 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2355 "Roam rssi diff value %d is out of range"
2356 " (Min: %d Max: %d)", roamRssiDiff,
2357 CFG_ROAM_RSSI_DIFF_MIN,
2358 CFG_ROAM_RSSI_DIFF_MAX);
2359 ret = -EINVAL;
2360 goto exit;
2361 }
2362
2363 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2364 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2365
2366 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2367 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2368 }
2369 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2370 {
2371 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2372 char extra[32];
2373 tANI_U8 len = 0;
2374
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002375 len = scnprintf(extra, sizeof(extra), "%s %d",
2376 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002377 if (copy_to_user(priv_data.buf, &extra, len + 1))
2378 {
2379 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2380 "%s: failed to copy data to user buffer", __func__);
2381 ret = -EFAULT;
2382 goto exit;
2383 }
2384 }
2385#endif
2386#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2387 else if (strncmp(command, "GETBAND", 7) == 0)
2388 {
2389 int band = -1;
2390 char extra[32];
2391 tANI_U8 len = 0;
2392 hdd_getBand_helper(pHddCtx, &band);
2393
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002394 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002395 if (copy_to_user(priv_data.buf, &extra, len + 1))
2396 {
2397 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2398 "%s: failed to copy data to user buffer", __func__);
2399 ret = -EFAULT;
2400 goto exit;
2401 }
2402 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002403 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2404 {
2405 tANI_U8 *value = command;
2406 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2407 tANI_U8 numChannels = 0;
2408 eHalStatus status = eHAL_STATUS_SUCCESS;
2409
2410 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2411 if (eHAL_STATUS_SUCCESS != status)
2412 {
2413 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2414 "%s: Failed to parse channel list information", __func__);
2415 ret = -EINVAL;
2416 goto exit;
2417 }
2418
2419 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2420 {
2421 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2422 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2423 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2424 ret = -EINVAL;
2425 goto exit;
2426 }
2427 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2428 numChannels);
2429 if (eHAL_STATUS_SUCCESS != status)
2430 {
2431 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2432 "%s: Failed to update channel list information", __func__);
2433 ret = -EINVAL;
2434 goto exit;
2435 }
2436 }
2437 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2438 {
2439 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2440 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002441 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002442 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002443 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002444
2445 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2446 ChannelList, &numChannels ))
2447 {
2448 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2449 "%s: failed to get roam scan channel list", __func__);
2450 ret = -EFAULT;
2451 goto exit;
2452 }
2453 /* output channel list is of the format
2454 [Number of roam scan channels][Channel1][Channel2]... */
2455 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002456 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002457 for (j = 0; (j < numChannels); j++)
2458 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002459 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2460 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002461 }
2462
2463 if (copy_to_user(priv_data.buf, &extra, len + 1))
2464 {
2465 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2466 "%s: failed to copy data to user buffer", __func__);
2467 ret = -EFAULT;
2468 goto exit;
2469 }
2470 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002471 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2472 {
2473 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2474 char extra[32];
2475 tANI_U8 len = 0;
2476
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002477 /* Check if the features OKC/CCX/11R are supported simultaneously,
2478 then this operation is not permitted (return FAILURE) */
2479 if (ccxMode &&
2480 hdd_is_okc_mode_enabled(pHddCtx) &&
2481 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2482 {
2483 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2484 "%s: OKC/CCX/11R are supported simultaneously"
2485 " hence this operation is not permitted!", __func__);
2486 ret = -EPERM;
2487 goto exit;
2488 }
2489
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002490 len = scnprintf(extra, sizeof(extra), "%s %d",
2491 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002492 if (copy_to_user(priv_data.buf, &extra, len + 1))
2493 {
2494 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2495 "%s: failed to copy data to user buffer", __func__);
2496 ret = -EFAULT;
2497 goto exit;
2498 }
2499 }
2500 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2501 {
2502 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2503 char extra[32];
2504 tANI_U8 len = 0;
2505
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002506 /* Check if the features OKC/CCX/11R are supported simultaneously,
2507 then this operation is not permitted (return FAILURE) */
2508 if (okcMode &&
2509 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2510 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2511 {
2512 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2513 "%s: OKC/CCX/11R are supported simultaneously"
2514 " hence this operation is not permitted!", __func__);
2515 ret = -EPERM;
2516 goto exit;
2517 }
2518
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002519 len = scnprintf(extra, sizeof(extra), "%s %d",
2520 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002521 if (copy_to_user(priv_data.buf, &extra, len + 1))
2522 {
2523 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2524 "%s: failed to copy data to user buffer", __func__);
2525 ret = -EFAULT;
2526 goto exit;
2527 }
2528 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002529 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002530 {
2531 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2532 char extra[32];
2533 tANI_U8 len = 0;
2534
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002535 len = scnprintf(extra, sizeof(extra), "%s %d",
2536 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002537 if (copy_to_user(priv_data.buf, &extra, len + 1))
2538 {
2539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2540 "%s: failed to copy data to user buffer", __func__);
2541 ret = -EFAULT;
2542 goto exit;
2543 }
2544 }
2545 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2546 {
2547 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2548 char extra[32];
2549 tANI_U8 len = 0;
2550
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002551 len = scnprintf(extra, sizeof(extra), "%s %d",
2552 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002553 if (copy_to_user(priv_data.buf, &extra, len + 1))
2554 {
2555 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2556 "%s: failed to copy data to user buffer", __func__);
2557 ret = -EFAULT;
2558 goto exit;
2559 }
2560 }
2561 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2562 {
2563 tANI_U8 *value = command;
2564 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2565
2566 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2567 value = value + 26;
2568 /* Convert the value from ascii to integer */
2569 ret = kstrtou8(value, 10, &minTime);
2570 if (ret < 0)
2571 {
2572 /* If the input value is greater than max value of datatype, then also
2573 kstrtou8 fails */
2574 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2575 "%s: kstrtou8 failed range [%d - %d]", __func__,
2576 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2577 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2578 ret = -EINVAL;
2579 goto exit;
2580 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002581 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2582 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2583 {
2584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2585 "scan min channel time value %d is out of range"
2586 " (Min: %d Max: %d)", minTime,
2587 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2588 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2589 ret = -EINVAL;
2590 goto exit;
2591 }
2592
2593 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2594 "%s: Received Command to change channel min time = %d", __func__, minTime);
2595
2596 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2597 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2598 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002599 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2600 {
2601 tANI_U8 *value = command;
2602 tANI_U8 channel = 0;
2603 tANI_U8 dwellTime = 0;
2604 tANI_U8 bufLen = 0;
2605 tANI_U8 *buf = NULL;
2606 tSirMacAddr targetApBssid;
2607 eHalStatus status = eHAL_STATUS_SUCCESS;
2608 struct ieee80211_channel chan;
2609 tANI_U8 finalLen = 0;
2610 tANI_U8 *finalBuf = NULL;
2611 tANI_U8 temp = 0;
2612 u64 cookie;
2613 hdd_station_ctx_t *pHddStaCtx = NULL;
2614 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2615
2616 /* if not associated, no need to send action frame */
2617 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2618 {
2619 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2620 ret = -EINVAL;
2621 goto exit;
2622 }
2623
2624 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2625 &dwellTime, &buf, &bufLen);
2626 if (eHAL_STATUS_SUCCESS != status)
2627 {
2628 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2629 "%s: Failed to parse send action frame data", __func__);
2630 ret = -EINVAL;
2631 goto exit;
2632 }
2633
2634 /* if the target bssid is different from currently associated AP,
2635 then no need to send action frame */
2636 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2637 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2638 {
2639 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2640 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002641 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002642 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002643 goto exit;
2644 }
2645
2646 /* if the channel number is different from operating channel then
2647 no need to send action frame */
2648 if (channel != pHddStaCtx->conn_info.operationChannel)
2649 {
2650 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2651 "%s: channel(%d) is different from operating channel(%d)",
2652 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2653 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002654 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002655 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002656 goto exit;
2657 }
2658 chan.center_freq = sme_ChnToFreq(channel);
2659
2660 finalLen = bufLen + 24;
2661 finalBuf = vos_mem_malloc(finalLen);
2662 if (NULL == finalBuf)
2663 {
2664 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2665 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002666 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002667 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002668 goto exit;
2669 }
2670 vos_mem_zero(finalBuf, finalLen);
2671
2672 /* Fill subtype */
2673 temp = SIR_MAC_MGMT_ACTION << 4;
2674 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2675
2676 /* Fill type */
2677 temp = SIR_MAC_MGMT_FRAME;
2678 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2679
2680 /* Fill destination address (bssid of the AP) */
2681 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2682
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002683 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002684 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2685
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002686 /* Fill BSSID (AP mac address) */
2687 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002688
2689 /* Fill received buffer from 24th address */
2690 vos_mem_copy(finalBuf + 24, buf, bufLen);
2691
Jeff Johnson11c33152013-04-16 17:52:40 -07002692 /* done with the parsed buffer */
2693 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002694 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002695
Yue Maf49ba872013-08-19 12:04:25 -07002696 wlan_hdd_action( NULL,
2697#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2698 &(pAdapter->wdev),
2699#else
2700 dev,
2701#endif
2702 &chan, 0,
2703#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2704 NL80211_CHAN_HT20, 1,
2705#endif
2706 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002707 1, &cookie );
2708 vos_mem_free(finalBuf);
2709 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002710 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2711 {
2712 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2713 char extra[32];
2714 tANI_U8 len = 0;
2715
2716 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002717 len = scnprintf(extra, sizeof(extra), "%s %d",
2718 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002719 if (copy_to_user(priv_data.buf, &extra, len + 1))
2720 {
2721 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2722 "%s: failed to copy data to user buffer", __func__);
2723 ret = -EFAULT;
2724 goto exit;
2725 }
2726 }
2727 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2728 {
2729 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002730 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002731
2732 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2733 value = value + 19;
2734 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002735 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002736 if (ret < 0)
2737 {
2738 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002739 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002740 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002741 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002742 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2743 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2744 ret = -EINVAL;
2745 goto exit;
2746 }
2747
2748 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2749 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2750 {
2751 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2752 "lfr mode value %d is out of range"
2753 " (Min: %d Max: %d)", maxTime,
2754 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2755 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2756 ret = -EINVAL;
2757 goto exit;
2758 }
2759
2760 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2761 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2762
2763 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
2764 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2765 }
2766 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2767 {
2768 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2769 char extra[32];
2770 tANI_U8 len = 0;
2771
2772 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002773 len = scnprintf(extra, sizeof(extra), "%s %d",
2774 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002775 if (copy_to_user(priv_data.buf, &extra, len + 1))
2776 {
2777 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2778 "%s: failed to copy data to user buffer", __func__);
2779 ret = -EFAULT;
2780 goto exit;
2781 }
2782 }
2783 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2784 {
2785 tANI_U8 *value = command;
2786 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2787
2788 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2789 value = value + 16;
2790 /* Convert the value from ascii to integer */
2791 ret = kstrtou16(value, 10, &val);
2792 if (ret < 0)
2793 {
2794 /* If the input value is greater than max value of datatype, then also
2795 kstrtou16 fails */
2796 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2797 "%s: kstrtou16 failed range [%d - %d]", __func__,
2798 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2799 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2800 ret = -EINVAL;
2801 goto exit;
2802 }
2803
2804 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2805 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2806 {
2807 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2808 "scan home time value %d is out of range"
2809 " (Min: %d Max: %d)", val,
2810 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2811 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2812 ret = -EINVAL;
2813 goto exit;
2814 }
2815
2816 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2817 "%s: Received Command to change scan home time = %d", __func__, val);
2818
2819 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2820 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2821 }
2822 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2823 {
2824 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2825 char extra[32];
2826 tANI_U8 len = 0;
2827
2828 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002829 len = scnprintf(extra, sizeof(extra), "%s %d",
2830 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002831 if (copy_to_user(priv_data.buf, &extra, len + 1))
2832 {
2833 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2834 "%s: failed to copy data to user buffer", __func__);
2835 ret = -EFAULT;
2836 goto exit;
2837 }
2838 }
2839 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2840 {
2841 tANI_U8 *value = command;
2842 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2843
2844 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2845 value = value + 17;
2846 /* Convert the value from ascii to integer */
2847 ret = kstrtou8(value, 10, &val);
2848 if (ret < 0)
2849 {
2850 /* If the input value is greater than max value of datatype, then also
2851 kstrtou8 fails */
2852 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2853 "%s: kstrtou8 failed range [%d - %d]", __func__,
2854 CFG_ROAM_INTRA_BAND_MIN,
2855 CFG_ROAM_INTRA_BAND_MAX);
2856 ret = -EINVAL;
2857 goto exit;
2858 }
2859
2860 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2861 (val > CFG_ROAM_INTRA_BAND_MAX))
2862 {
2863 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2864 "intra band mode value %d is out of range"
2865 " (Min: %d Max: %d)", val,
2866 CFG_ROAM_INTRA_BAND_MIN,
2867 CFG_ROAM_INTRA_BAND_MAX);
2868 ret = -EINVAL;
2869 goto exit;
2870 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002871 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2872 "%s: Received Command to change intra band = %d", __func__, val);
2873
2874 pHddCtx->cfg_ini->nRoamIntraBand = val;
2875 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2876 }
2877 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2878 {
2879 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2880 char extra[32];
2881 tANI_U8 len = 0;
2882
2883 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002884 len = scnprintf(extra, sizeof(extra), "%s %d",
2885 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002886 if (copy_to_user(priv_data.buf, &extra, len + 1))
2887 {
2888 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2889 "%s: failed to copy data to user buffer", __func__);
2890 ret = -EFAULT;
2891 goto exit;
2892 }
2893 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002894 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2895 {
2896 tANI_U8 *value = command;
2897 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2898
2899 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2900 value = value + 15;
2901 /* Convert the value from ascii to integer */
2902 ret = kstrtou8(value, 10, &nProbes);
2903 if (ret < 0)
2904 {
2905 /* If the input value is greater than max value of datatype, then also
2906 kstrtou8 fails */
2907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2908 "%s: kstrtou8 failed range [%d - %d]", __func__,
2909 CFG_ROAM_SCAN_N_PROBES_MIN,
2910 CFG_ROAM_SCAN_N_PROBES_MAX);
2911 ret = -EINVAL;
2912 goto exit;
2913 }
2914
2915 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2916 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2917 {
2918 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2919 "NProbes value %d is out of range"
2920 " (Min: %d Max: %d)", nProbes,
2921 CFG_ROAM_SCAN_N_PROBES_MIN,
2922 CFG_ROAM_SCAN_N_PROBES_MAX);
2923 ret = -EINVAL;
2924 goto exit;
2925 }
2926
2927 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2928 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2929
2930 pHddCtx->cfg_ini->nProbes = nProbes;
2931 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2932 }
2933 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2934 {
2935 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2936 char extra[32];
2937 tANI_U8 len = 0;
2938
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002939 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002940 if (copy_to_user(priv_data.buf, &extra, len + 1))
2941 {
2942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2943 "%s: failed to copy data to user buffer", __func__);
2944 ret = -EFAULT;
2945 goto exit;
2946 }
2947 }
2948 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2949 {
2950 tANI_U8 *value = command;
2951 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
2952
2953 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2954 /* input value is in units of msec */
2955 value = value + 20;
2956 /* Convert the value from ascii to integer */
2957 ret = kstrtou16(value, 10, &homeAwayTime);
2958 if (ret < 0)
2959 {
2960 /* If the input value is greater than max value of datatype, then also
2961 kstrtou8 fails */
2962 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2963 "%s: kstrtou8 failed range [%d - %d]", __func__,
2964 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2965 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2966 ret = -EINVAL;
2967 goto exit;
2968 }
2969
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002970 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2971 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2972 {
2973 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2974 "homeAwayTime value %d is out of range"
2975 " (Min: %d Max: %d)", homeAwayTime,
2976 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2977 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2978 ret = -EINVAL;
2979 goto exit;
2980 }
2981
2982 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2983 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002984 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2985 {
2986 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2987 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2988 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002989 }
2990 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2991 {
2992 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2993 char extra[32];
2994 tANI_U8 len = 0;
2995
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002996 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002997 if (copy_to_user(priv_data.buf, &extra, len + 1))
2998 {
2999 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3000 "%s: failed to copy data to user buffer", __func__);
3001 ret = -EFAULT;
3002 goto exit;
3003 }
3004 }
3005 else if (strncmp(command, "REASSOC", 7) == 0)
3006 {
3007 tANI_U8 *value = command;
3008 tANI_U8 channel = 0;
3009 tSirMacAddr targetApBssid;
3010 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003011#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3012 tCsrHandoffRequest handoffInfo;
3013#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003014 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003015 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3016
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003017 /* if not associated, no need to proceed with reassoc */
3018 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3019 {
3020 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3021 ret = -EINVAL;
3022 goto exit;
3023 }
3024
3025 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
3026 if (eHAL_STATUS_SUCCESS != status)
3027 {
3028 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3029 "%s: Failed to parse reassoc command data", __func__);
3030 ret = -EINVAL;
3031 goto exit;
3032 }
3033
3034 /* if the target bssid is same as currently associated AP,
3035 then no need to proceed with reassoc */
3036 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3037 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3038 {
3039 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3040 ret = -EINVAL;
3041 goto exit;
3042 }
3043
3044 /* Check channel number is a valid channel number */
3045 if(VOS_STATUS_SUCCESS !=
3046 wlan_hdd_validate_operation_channel(pAdapter, channel))
3047 {
3048 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003049 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003050 return -EINVAL;
3051 }
3052
3053 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003054#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3055 handoffInfo.channel = channel;
3056 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3057 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3058#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003059 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003060 else if (strncmp(command, "SETWESMODE", 10) == 0)
3061 {
3062 tANI_U8 *value = command;
3063 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3064
3065 /* Move pointer to ahead of SETWESMODE<delimiter> */
3066 value = value + 11;
3067 /* Convert the value from ascii to integer */
3068 ret = kstrtou8(value, 10, &wesMode);
3069 if (ret < 0)
3070 {
3071 /* If the input value is greater than max value of datatype, then also
3072 kstrtou8 fails */
3073 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3074 "%s: kstrtou8 failed range [%d - %d]", __func__,
3075 CFG_ENABLE_WES_MODE_NAME_MIN,
3076 CFG_ENABLE_WES_MODE_NAME_MAX);
3077 ret = -EINVAL;
3078 goto exit;
3079 }
3080
3081 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3082 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3083 {
3084 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3085 "WES Mode value %d is out of range"
3086 " (Min: %d Max: %d)", wesMode,
3087 CFG_ENABLE_WES_MODE_NAME_MIN,
3088 CFG_ENABLE_WES_MODE_NAME_MAX);
3089 ret = -EINVAL;
3090 goto exit;
3091 }
3092 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3093 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3094
3095 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3096 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3097 }
3098 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3099 {
3100 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3101 char extra[32];
3102 tANI_U8 len = 0;
3103
Arif Hussain826d9412013-11-12 16:44:54 -08003104 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003105 if (copy_to_user(priv_data.buf, &extra, len + 1))
3106 {
3107 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3108 "%s: failed to copy data to user buffer", __func__);
3109 ret = -EFAULT;
3110 goto exit;
3111 }
3112 }
3113#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003114#ifdef FEATURE_WLAN_LFR
3115 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3116 {
3117 tANI_U8 *value = command;
3118 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3119
3120 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3121 value = value + 12;
3122 /* Convert the value from ascii to integer */
3123 ret = kstrtou8(value, 10, &lfrMode);
3124 if (ret < 0)
3125 {
3126 /* If the input value is greater than max value of datatype, then also
3127 kstrtou8 fails */
3128 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3129 "%s: kstrtou8 failed range [%d - %d]", __func__,
3130 CFG_LFR_FEATURE_ENABLED_MIN,
3131 CFG_LFR_FEATURE_ENABLED_MAX);
3132 ret = -EINVAL;
3133 goto exit;
3134 }
3135
3136 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3137 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3138 {
3139 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3140 "lfr mode value %d is out of range"
3141 " (Min: %d Max: %d)", lfrMode,
3142 CFG_LFR_FEATURE_ENABLED_MIN,
3143 CFG_LFR_FEATURE_ENABLED_MAX);
3144 ret = -EINVAL;
3145 goto exit;
3146 }
3147
3148 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3149 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3150
3151 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3152 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3153 }
3154#endif
3155#ifdef WLAN_FEATURE_VOWIFI_11R
3156 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3157 {
3158 tANI_U8 *value = command;
3159 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3160
3161 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3162 value = value + 18;
3163 /* Convert the value from ascii to integer */
3164 ret = kstrtou8(value, 10, &ft);
3165 if (ret < 0)
3166 {
3167 /* If the input value is greater than max value of datatype, then also
3168 kstrtou8 fails */
3169 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3170 "%s: kstrtou8 failed range [%d - %d]", __func__,
3171 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3172 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3173 ret = -EINVAL;
3174 goto exit;
3175 }
3176
3177 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3178 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3179 {
3180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3181 "ft mode value %d is out of range"
3182 " (Min: %d Max: %d)", ft,
3183 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3184 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3185 ret = -EINVAL;
3186 goto exit;
3187 }
3188
3189 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3190 "%s: Received Command to change ft mode = %d", __func__, ft);
3191
3192 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3193 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3194 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303195
3196 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3197 {
3198 tANI_U8 *value = command;
3199 tSirMacAddr targetApBssid;
3200 tANI_U8 trigger = 0;
3201 eHalStatus status = eHAL_STATUS_SUCCESS;
3202 hdd_station_ctx_t *pHddStaCtx = NULL;
3203 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3204
3205 /* if not associated, no need to proceed with reassoc */
3206 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3207 {
3208 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3209 ret = -EINVAL;
3210 goto exit;
3211 }
3212
3213 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
3214 if (eHAL_STATUS_SUCCESS != status)
3215 {
3216 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3217 "%s: Failed to parse reassoc command data", __func__);
3218 ret = -EINVAL;
3219 goto exit;
3220 }
3221
3222 /* if the target bssid is same as currently associated AP,
3223 then no need to proceed with reassoc */
3224 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3225 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3226 {
3227 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3228 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3229 __func__);
3230 ret = -EINVAL;
3231 goto exit;
3232 }
3233
3234 /* Proceed with scan/roam */
3235 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3236 &targetApBssid[0],
3237 (tSmeFastRoamTrigger)(trigger));
3238 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003239#endif
3240#ifdef FEATURE_WLAN_CCX
3241 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3242 {
3243 tANI_U8 *value = command;
3244 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
3245
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003246 /* Check if the features OKC/CCX/11R are supported simultaneously,
3247 then this operation is not permitted (return FAILURE) */
3248 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3249 hdd_is_okc_mode_enabled(pHddCtx) &&
3250 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3251 {
3252 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3253 "%s: OKC/CCX/11R are supported simultaneously"
3254 " hence this operation is not permitted!", __func__);
3255 ret = -EPERM;
3256 goto exit;
3257 }
3258
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003259 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3260 value = value + 11;
3261 /* Convert the value from ascii to integer */
3262 ret = kstrtou8(value, 10, &ccxMode);
3263 if (ret < 0)
3264 {
3265 /* If the input value is greater than max value of datatype, then also
3266 kstrtou8 fails */
3267 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3268 "%s: kstrtou8 failed range [%d - %d]", __func__,
3269 CFG_CCX_FEATURE_ENABLED_MIN,
3270 CFG_CCX_FEATURE_ENABLED_MAX);
3271 ret = -EINVAL;
3272 goto exit;
3273 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003274 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
3275 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
3276 {
3277 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3278 "Ccx mode value %d is out of range"
3279 " (Min: %d Max: %d)", ccxMode,
3280 CFG_CCX_FEATURE_ENABLED_MIN,
3281 CFG_CCX_FEATURE_ENABLED_MAX);
3282 ret = -EINVAL;
3283 goto exit;
3284 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003285 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3286 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
3287
3288 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
3289 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
3290 }
3291#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003292 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3293 {
3294 tANI_U8 *value = command;
3295 tANI_BOOLEAN roamScanControl = 0;
3296
3297 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3298 value = value + 19;
3299 /* Convert the value from ascii to integer */
3300 ret = kstrtou8(value, 10, &roamScanControl);
3301 if (ret < 0)
3302 {
3303 /* If the input value is greater than max value of datatype, then also
3304 kstrtou8 fails */
3305 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3306 "%s: kstrtou8 failed ", __func__);
3307 ret = -EINVAL;
3308 goto exit;
3309 }
3310
3311 if (0 != roamScanControl)
3312 {
3313 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3314 "roam scan control invalid value = %d",
3315 roamScanControl);
3316 ret = -EINVAL;
3317 goto exit;
3318 }
3319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3320 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3321
3322 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3323 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003324#ifdef FEATURE_WLAN_OKC
3325 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3326 {
3327 tANI_U8 *value = command;
3328 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3329
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003330 /* Check if the features OKC/CCX/11R are supported simultaneously,
3331 then this operation is not permitted (return FAILURE) */
3332 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3333 hdd_is_okc_mode_enabled(pHddCtx) &&
3334 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3335 {
3336 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3337 "%s: OKC/CCX/11R are supported simultaneously"
3338 " hence this operation is not permitted!", __func__);
3339 ret = -EPERM;
3340 goto exit;
3341 }
3342
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003343 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3344 value = value + 11;
3345 /* Convert the value from ascii to integer */
3346 ret = kstrtou8(value, 10, &okcMode);
3347 if (ret < 0)
3348 {
3349 /* If the input value is greater than max value of datatype, then also
3350 kstrtou8 fails */
3351 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3352 "%s: kstrtou8 failed range [%d - %d]", __func__,
3353 CFG_OKC_FEATURE_ENABLED_MIN,
3354 CFG_OKC_FEATURE_ENABLED_MAX);
3355 ret = -EINVAL;
3356 goto exit;
3357 }
3358
3359 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3360 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3361 {
3362 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3363 "Okc mode value %d is out of range"
3364 " (Min: %d Max: %d)", okcMode,
3365 CFG_OKC_FEATURE_ENABLED_MIN,
3366 CFG_OKC_FEATURE_ENABLED_MAX);
3367 ret = -EINVAL;
3368 goto exit;
3369 }
3370
3371 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3372 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3373
3374 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3375 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003376#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003377 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3378 {
3379 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3380 char extra[32];
3381 tANI_U8 len = 0;
3382
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003383 len = scnprintf(extra, sizeof(extra), "%s %d",
3384 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003385 if (copy_to_user(priv_data.buf, &extra, len + 1))
3386 {
3387 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3388 "%s: failed to copy data to user buffer", __func__);
3389 ret = -EFAULT;
3390 goto exit;
3391 }
3392 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303393#ifdef WLAN_FEATURE_PACKET_FILTERING
3394 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3395 {
3396 tANI_U8 filterType = 0;
3397 tANI_U8 *value = command;
3398
3399 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3400 value = value + 22;
3401
3402 /* Convert the value from ascii to integer */
3403 ret = kstrtou8(value, 10, &filterType);
3404 if (ret < 0)
3405 {
3406 /* If the input value is greater than max value of datatype,
3407 * then also kstrtou8 fails
3408 */
3409 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3410 "%s: kstrtou8 failed range ", __func__);
3411 ret = -EINVAL;
3412 goto exit;
3413 }
3414
3415 if (filterType != 0 && filterType != 1)
3416 {
3417 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3418 "%s: Accepted Values are 0 and 1 ", __func__);
3419 ret = -EINVAL;
3420 goto exit;
3421 }
3422 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3423 pAdapter->sessionId);
3424 }
3425#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303426 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3427 {
3428 char *dhcpPhase;
c_hpothu9b781ba2013-12-30 20:57:45 +05303429 dhcpPhase = command + 11;
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303430 if ('1' == *dhcpPhase)
3431 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3433 FL("BTCOEXMODE %d"), *dhcpPhase);
3434
3435 pHddCtx->btCoexModeSet = TRUE;
3436
3437 /* Firmware failing to process DHCP START/STOP indications.
3438 * So, for now commentig below code, once issue is resolved,
3439 * follwing will be uncommented.
3440 */
3441 #if 0
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303442 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3443 pAdapter->macAddressCurrent.bytes);
c_hpothu9b781ba2013-12-30 20:57:45 +05303444 #endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303445 }
3446 else if ('2' == *dhcpPhase)
3447 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303448 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3449 FL("BTCOEXMODE %d"), *dhcpPhase);
3450
3451 pHddCtx->btCoexModeSet = FALSE;
3452
3453 /* Firmware failing to process DHCP START/STOP indications.
3454 * So, for now commentig below code, once issue is resolved,
3455 * follwing will be uncommented.
3456 */
3457 #if 0
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303458 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3459 pAdapter->macAddressCurrent.bytes);
c_hpothu9b781ba2013-12-30 20:57:45 +05303460 #endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303461 }
3462 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003463 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3464 {
3465 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3466 }
3467 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3468 {
3469 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3470 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303471 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3472 {
3473 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3474 char extra[32];
3475 tANI_U8 len = 0;
3476
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003477 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303478 (int)pCfg->nActiveMaxChnTime);
3479 if (copy_to_user(priv_data.buf, &extra, len + 1))
3480 {
3481 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3482 "%s: failed to copy data to user buffer", __func__);
3483 ret = -EFAULT;
3484 goto exit;
3485 }
3486 ret = len;
3487 }
3488 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3489 {
3490 tANI_U8 *value = command;
3491 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3492 int val = 0, temp;
3493
3494 value = value + 13;
3495 temp = kstrtou32(value, 10, &val);
3496 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3497 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3498 {
3499 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3500 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3501 ret = -EFAULT;
3502 goto exit;
3503 }
3504 pCfg->nActiveMaxChnTime = val;
3505 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003506 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3507 {
3508 tANI_U8 filterType = 0;
3509 tANI_U8 *value;
3510 value = command + 9;
3511
3512 /* Convert the value from ascii to integer */
3513 ret = kstrtou8(value, 10, &filterType);
3514 if (ret < 0)
3515 {
3516 /* If the input value is greater than max value of datatype,
3517 * then also kstrtou8 fails
3518 */
3519 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3520 "%s: kstrtou8 failed range ", __func__);
3521 ret = -EINVAL;
3522 goto exit;
3523 }
3524 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3525 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3526 {
3527 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3528 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3529 " 2-Sink ", __func__);
3530 ret = -EINVAL;
3531 goto exit;
3532 }
3533 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3534 pHddCtx->drvr_miracast = filterType;
3535 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3536 }
Leo Chang614d2072013-08-22 14:59:44 -07003537 else if (strncmp(command, "SETMCRATE", 9) == 0)
3538 {
Leo Chang614d2072013-08-22 14:59:44 -07003539 tANI_U8 *value = command;
3540 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003541 tSirRateUpdateInd *rateUpdate;
3542 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003543
3544 /* Only valid for SAP mode */
3545 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3546 {
3547 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3548 "%s: SAP mode is not running", __func__);
3549 ret = -EFAULT;
3550 goto exit;
3551 }
3552
3553 /* Move pointer to ahead of SETMCRATE<delimiter> */
3554 /* input value is in units of hundred kbps */
3555 value = value + 10;
3556 /* Convert the value from ascii to integer, decimal base */
3557 ret = kstrtouint(value, 10, &targetRate);
3558
Leo Chang1f98cbd2013-10-17 15:03:52 -07003559 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3560 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003561 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003562 hddLog(VOS_TRACE_LEVEL_ERROR,
3563 "%s: SETMCRATE indication alloc fail", __func__);
3564 ret = -EFAULT;
3565 goto exit;
3566 }
3567 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3568
3569 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3570 "MC Target rate %d", targetRate);
3571 /* Ignore unicast */
3572 rateUpdate->ucastDataRate = -1;
3573 rateUpdate->mcastDataRate24GHz = targetRate;
3574 rateUpdate->mcastDataRate5GHz = targetRate;
3575 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3576 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3577 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3578 if (eHAL_STATUS_SUCCESS != status)
3579 {
3580 hddLog(VOS_TRACE_LEVEL_ERROR,
3581 "%s: SET_MC_RATE failed", __func__);
3582 vos_mem_free(rateUpdate);
3583 ret = -EFAULT;
3584 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003585 }
3586 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303587#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003588 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303589 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003590 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303591 }
3592#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003593#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3594 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3595 {
3596 tANI_U8 *value = command;
3597 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3598 tANI_U8 numChannels = 0;
3599 eHalStatus status = eHAL_STATUS_SUCCESS;
3600
3601 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3602 if (eHAL_STATUS_SUCCESS != status)
3603 {
3604 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3605 "%s: Failed to parse channel list information", __func__);
3606 ret = -EINVAL;
3607 goto exit;
3608 }
3609
3610 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3611 {
3612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3613 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3614 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3615 ret = -EINVAL;
3616 goto exit;
3617 }
3618 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3619 ChannelList,
3620 numChannels);
3621 if (eHAL_STATUS_SUCCESS != status)
3622 {
3623 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3624 "%s: Failed to update channel list information", __func__);
3625 ret = -EINVAL;
3626 goto exit;
3627 }
3628 }
3629 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3630 {
3631 tANI_U8 *value = command;
3632 char extra[128] = {0};
3633 int len = 0;
3634 tANI_U8 tid = 0;
3635 hdd_station_ctx_t *pHddStaCtx = NULL;
3636 tAniTrafStrmMetrics tsmMetrics;
3637 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3638
3639 /* if not associated, return error */
3640 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3641 {
3642 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3643 ret = -EINVAL;
3644 goto exit;
3645 }
3646
3647 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3648 value = value + 12;
3649 /* Convert the value from ascii to integer */
3650 ret = kstrtou8(value, 10, &tid);
3651 if (ret < 0)
3652 {
3653 /* If the input value is greater than max value of datatype, then also
3654 kstrtou8 fails */
3655 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3656 "%s: kstrtou8 failed range [%d - %d]", __func__,
3657 TID_MIN_VALUE,
3658 TID_MAX_VALUE);
3659 ret = -EINVAL;
3660 goto exit;
3661 }
3662
3663 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3664 {
3665 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3666 "tid value %d is out of range"
3667 " (Min: %d Max: %d)", tid,
3668 TID_MIN_VALUE,
3669 TID_MAX_VALUE);
3670 ret = -EINVAL;
3671 goto exit;
3672 }
3673
3674 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3675 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3676
3677 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3678 {
3679 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3680 "%s: failed to get tsm stats", __func__);
3681 ret = -EFAULT;
3682 goto exit;
3683 }
3684
3685 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3686 "UplinkPktQueueDly(%d)\n"
3687 "UplinkPktQueueDlyHist[0](%d)\n"
3688 "UplinkPktQueueDlyHist[1](%d)\n"
3689 "UplinkPktQueueDlyHist[2](%d)\n"
3690 "UplinkPktQueueDlyHist[3](%d)\n"
3691 "UplinkPktTxDly(%lu)\n"
3692 "UplinkPktLoss(%d)\n"
3693 "UplinkPktCount(%d)\n"
3694 "RoamingCount(%d)\n"
3695 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3696 tsmMetrics.UplinkPktQueueDlyHist[0],
3697 tsmMetrics.UplinkPktQueueDlyHist[1],
3698 tsmMetrics.UplinkPktQueueDlyHist[2],
3699 tsmMetrics.UplinkPktQueueDlyHist[3],
3700 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3701 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3702
3703 /* Output TSM stats is of the format
3704 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3705 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003706 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003707 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3708 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3709 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3710 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3711 tsmMetrics.RoamingDly);
3712
3713 if (copy_to_user(priv_data.buf, &extra, len + 1))
3714 {
3715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3716 "%s: failed to copy data to user buffer", __func__);
3717 ret = -EFAULT;
3718 goto exit;
3719 }
3720 }
3721 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3722 {
3723 tANI_U8 *value = command;
3724 tANI_U8 *cckmIe = NULL;
3725 tANI_U8 cckmIeLen = 0;
3726 eHalStatus status = eHAL_STATUS_SUCCESS;
3727
3728 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3729 if (eHAL_STATUS_SUCCESS != status)
3730 {
3731 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3732 "%s: Failed to parse cckm ie data", __func__);
3733 ret = -EINVAL;
3734 goto exit;
3735 }
3736
3737 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3738 {
3739 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3740 "%s: CCKM Ie input length is more than max[%d]", __func__,
3741 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003742 vos_mem_free(cckmIe);
3743 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003744 ret = -EINVAL;
3745 goto exit;
3746 }
3747 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003748 vos_mem_free(cckmIe);
3749 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003750 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003751 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3752 {
3753 tANI_U8 *value = command;
3754 tCsrCcxBeaconReq ccxBcnReq;
3755 eHalStatus status = eHAL_STATUS_SUCCESS;
3756 status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
3757 if (eHAL_STATUS_SUCCESS != status)
3758 {
3759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3760 "%s: Failed to parse ccx beacon req", __func__);
3761 ret = -EINVAL;
3762 goto exit;
3763 }
3764
3765 sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
3766 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003767#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003768 else {
3769 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3770 __func__, command);
3771 }
3772
Jeff Johnson295189b2012-06-20 16:38:30 -07003773 }
3774exit:
3775 if (command)
3776 {
3777 kfree(command);
3778 }
3779 return ret;
3780}
3781
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003782
3783
3784#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003785/**---------------------------------------------------------------------------
3786
3787 \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
3788
3789 This function parses the ccx beacon request passed in the format
3790 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3791 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3792 <space>Scan Mode N<space>Meas Duration N
3793 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3794 then take N.
3795 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3796 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3797 This function does not take care of removing duplicate channels from the list
3798
3799 \param - pValue Pointer to data
3800 \param - pCcxBcnReq output pointer to store parsed ie information
3801
3802 \return - 0 for success non-zero for failure
3803
3804 --------------------------------------------------------------------------*/
3805static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
3806 tCsrCcxBeaconReq *pCcxBcnReq)
3807{
3808 tANI_U8 *inPtr = pValue;
3809 int tempInt = 0;
3810 int j = 0, i = 0, v = 0;
3811 char buf[32];
3812
3813 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3814 /*no argument after the command*/
3815 if (NULL == inPtr)
3816 {
3817 return -EINVAL;
3818 }
3819 /*no space after the command*/
3820 else if (SPACE_ASCII_VALUE != *inPtr)
3821 {
3822 return -EINVAL;
3823 }
3824
3825 /*removing empty spaces*/
3826 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3827
3828 /*no argument followed by spaces*/
3829 if ('\0' == *inPtr) return -EINVAL;
3830
3831 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08003832 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003833 if (1 != v) return -EINVAL;
3834
3835 v = kstrtos32(buf, 10, &tempInt);
3836 if ( v < 0) return -EINVAL;
3837
3838 pCcxBcnReq->numBcnReqIe = tempInt;
3839
3840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3841 "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
3842
3843 for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
3844 {
3845 for (i = 0; i < 4; i++)
3846 {
3847 /*inPtr pointing to the beginning of first space after number of ie fields*/
3848 inPtr = strpbrk( inPtr, " " );
3849 /*no ie data after the number of ie fields argument*/
3850 if (NULL == inPtr) return -EINVAL;
3851
3852 /*removing empty space*/
3853 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3854
3855 /*no ie data after the number of ie fields argument and spaces*/
3856 if ( '\0' == *inPtr ) return -EINVAL;
3857
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08003858 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003859 if (1 != v) return -EINVAL;
3860
3861 v = kstrtos32(buf, 10, &tempInt);
3862 if (v < 0) return -EINVAL;
3863
3864 switch (i)
3865 {
3866 case 0: /* Measurement token */
3867 if (tempInt <= 0)
3868 {
3869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3870 "Invalid Measurement Token(%d)", tempInt);
3871 return -EINVAL;
3872 }
3873 pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
3874 break;
3875
3876 case 1: /* Channel number */
3877 if ((tempInt <= 0) ||
3878 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3879 {
3880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3881 "Invalid Channel Number(%d)", tempInt);
3882 return -EINVAL;
3883 }
3884 pCcxBcnReq->bcnReq[j].channel = tempInt;
3885 break;
3886
3887 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003888 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003889 {
3890 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3891 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
3892 return -EINVAL;
3893 }
3894 pCcxBcnReq->bcnReq[j].scanMode= tempInt;
3895 break;
3896
3897 case 3: /* Measurement duration */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003898 if (((tempInt <= 0) && (pCcxBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
3899 ((tempInt < 0) && (pCcxBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003900 {
3901 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3902 "Invalid Measurement Duration(%d)", tempInt);
3903 return -EINVAL;
3904 }
3905 pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
3906 break;
3907 }
3908 }
3909 }
3910
3911 for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
3912 {
3913 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3914 "Index(%d) Measurement Token(%lu)Channel(%lu) Scan Mode(%lu) Measurement Duration(%lu)\n",
3915 j,
3916 pCcxBcnReq->bcnReq[j].measurementToken,
3917 pCcxBcnReq->bcnReq[j].channel,
3918 pCcxBcnReq->bcnReq[j].scanMode,
3919 pCcxBcnReq->bcnReq[j].measurementDuration);
3920 }
3921
3922 return VOS_STATUS_SUCCESS;
3923}
3924
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003925static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3926{
3927 struct statsContext *pStatsContext = NULL;
3928 hdd_adapter_t *pAdapter = NULL;
3929
3930 if (NULL == pContext)
3931 {
3932 hddLog(VOS_TRACE_LEVEL_ERROR,
3933 "%s: Bad param, pContext [%p]",
3934 __func__, pContext);
3935 return;
3936 }
3937
Jeff Johnson72a40512013-12-19 10:14:15 -08003938 /* there is a race condition that exists between this callback
3939 function and the caller since the caller could time out either
3940 before or while this code is executing. we use a spinlock to
3941 serialize these actions */
3942 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003943
3944 pStatsContext = pContext;
3945 pAdapter = pStatsContext->pAdapter;
3946 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3947 {
3948 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08003949 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003950 hddLog(VOS_TRACE_LEVEL_WARN,
3951 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3952 __func__, pAdapter, pStatsContext->magic);
3953 return;
3954 }
3955
Jeff Johnson72a40512013-12-19 10:14:15 -08003956 /* context is valid so caller is still waiting */
3957
3958 /* paranoia: invalidate the magic */
3959 pStatsContext->magic = 0;
3960
3961 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003962 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3963 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3964 tsmMetrics.UplinkPktQueueDlyHist,
3965 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3966 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3967 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3968 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3969 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3970 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3971 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3972
Jeff Johnson72a40512013-12-19 10:14:15 -08003973 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003974 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08003975
3976 /* serialization is complete */
3977 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003978}
3979
3980
3981
3982static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3983 tAniTrafStrmMetrics* pTsmMetrics)
3984{
3985 hdd_station_ctx_t *pHddStaCtx = NULL;
3986 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08003987 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003988 long lrc;
3989 struct statsContext context;
3990 hdd_context_t *pHddCtx = NULL;
3991
3992 if (NULL == pAdapter)
3993 {
3994 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3995 return VOS_STATUS_E_FAULT;
3996 }
3997
3998 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3999 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4000
4001 /* we are connected prepare our callback context */
4002 init_completion(&context.completion);
4003 context.pAdapter = pAdapter;
4004 context.magic = STATS_CONTEXT_MAGIC;
4005
4006 /* query tsm stats */
4007 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
4008 pHddStaCtx->conn_info.staId[ 0 ],
4009 pHddStaCtx->conn_info.bssId,
4010 &context, pHddCtx->pvosContext, tid);
4011
4012 if (eHAL_STATUS_SUCCESS != hstatus)
4013 {
Jeff Johnson72a40512013-12-19 10:14:15 -08004014 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
4015 __func__);
4016 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004017 }
4018 else
4019 {
4020 /* request was sent -- wait for the response */
4021 lrc = wait_for_completion_interruptible_timeout(&context.completion,
4022 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004023 if (lrc <= 0)
4024 {
4025 hddLog(VOS_TRACE_LEVEL_ERROR,
4026 "%s: SME %s while retrieving statistics",
4027 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004028 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004029 }
4030 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004031
Jeff Johnson72a40512013-12-19 10:14:15 -08004032 /* either we never sent a request, we sent a request and received a
4033 response or we sent a request and timed out. if we never sent a
4034 request or if we sent a request and got a response, we want to
4035 clear the magic out of paranoia. if we timed out there is a
4036 race condition such that the callback function could be
4037 executing at the same time we are. of primary concern is if the
4038 callback function had already verified the "magic" but had not
4039 yet set the completion variable when a timeout occurred. we
4040 serialize these activities by invalidating the magic while
4041 holding a shared spinlock which will cause us to block if the
4042 callback is currently executing */
4043 spin_lock(&hdd_context_lock);
4044 context.magic = 0;
4045 spin_unlock(&hdd_context_lock);
4046
4047 if (VOS_STATUS_SUCCESS == vstatus)
4048 {
4049 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4050 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4051 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4052 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4053 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4054 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4055 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4056 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4057 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4058 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4059 }
4060 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004061}
4062#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4063
Srinivas Girigowdade697412013-02-14 16:31:48 -08004064#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
4065void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4066{
4067 eCsrBand band = -1;
4068 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4069 switch (band)
4070 {
4071 case eCSR_BAND_ALL:
4072 *pBand = WLAN_HDD_UI_BAND_AUTO;
4073 break;
4074
4075 case eCSR_BAND_24:
4076 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4077 break;
4078
4079 case eCSR_BAND_5G:
4080 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4081 break;
4082
4083 default:
4084 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4085 *pBand = -1;
4086 break;
4087 }
4088}
4089
4090/**---------------------------------------------------------------------------
4091
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004092 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4093
4094 This function parses the send action frame data passed in the format
4095 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4096
Srinivas Girigowda56076852013-08-20 14:00:50 -07004097 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004098 \param - pTargetApBssid Pointer to target Ap bssid
4099 \param - pChannel Pointer to the Target AP channel
4100 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4101 \param - pBuf Pointer to data
4102 \param - pBufLen Pointer to data length
4103
4104 \return - 0 for success non-zero for failure
4105
4106 --------------------------------------------------------------------------*/
4107VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4108 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4109{
4110 tANI_U8 *inPtr = pValue;
4111 tANI_U8 *dataEnd;
4112 int tempInt;
4113 int j = 0;
4114 int i = 0;
4115 int v = 0;
4116 tANI_U8 tempBuf[32];
4117 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004118 /* 12 hexa decimal digits, 5 ':' and '\0' */
4119 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004120
4121 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4122 /*no argument after the command*/
4123 if (NULL == inPtr)
4124 {
4125 return -EINVAL;
4126 }
4127
4128 /*no space after the command*/
4129 else if (SPACE_ASCII_VALUE != *inPtr)
4130 {
4131 return -EINVAL;
4132 }
4133
4134 /*removing empty spaces*/
4135 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4136
4137 /*no argument followed by spaces*/
4138 if ('\0' == *inPtr)
4139 {
4140 return -EINVAL;
4141 }
4142
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004143 v = sscanf(inPtr, "%17s", macAddress);
4144 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004145 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004146 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4147 "Invalid MAC address or All hex inputs are not read (%d)", v);
4148 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004149 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004150
4151 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4152 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4153 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4154 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4155 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4156 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004157
4158 /* point to the next argument */
4159 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4160 /*no argument after the command*/
4161 if (NULL == inPtr) return -EINVAL;
4162
4163 /*removing empty spaces*/
4164 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4165
4166 /*no argument followed by spaces*/
4167 if ('\0' == *inPtr)
4168 {
4169 return -EINVAL;
4170 }
4171
4172 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004173 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004174 if (1 != v) return -EINVAL;
4175
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004176 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304177 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
4178 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004179
4180 *pChannel = tempInt;
4181
4182 /* point to the next argument */
4183 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4184 /*no argument after the command*/
4185 if (NULL == inPtr) return -EINVAL;
4186 /*removing empty spaces*/
4187 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4188
4189 /*no argument followed by spaces*/
4190 if ('\0' == *inPtr)
4191 {
4192 return -EINVAL;
4193 }
4194
4195 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004196 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004197 if (1 != v) return -EINVAL;
4198
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004199 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004200 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004201
4202 *pDwellTime = tempInt;
4203
4204 /* point to the next argument */
4205 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4206 /*no argument after the command*/
4207 if (NULL == inPtr) return -EINVAL;
4208 /*removing empty spaces*/
4209 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4210
4211 /*no argument followed by spaces*/
4212 if ('\0' == *inPtr)
4213 {
4214 return -EINVAL;
4215 }
4216
4217 /* find the length of data */
4218 dataEnd = inPtr;
4219 while(('\0' != *dataEnd) )
4220 {
4221 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004222 }
Kiet Lambe150c22013-11-21 16:30:32 +05304223 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004224 if ( *pBufLen <= 0) return -EINVAL;
4225
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004226 /* Allocate the number of bytes based on the number of input characters
4227 whether it is even or odd.
4228 if the number of input characters are even, then we need N/2 byte.
4229 if the number of input characters are odd, then we need do (N+1)/2 to
4230 compensate rounding off.
4231 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4232 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4233 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004234 if (NULL == *pBuf)
4235 {
4236 hddLog(VOS_TRACE_LEVEL_FATAL,
4237 "%s: vos_mem_alloc failed ", __func__);
4238 return -EINVAL;
4239 }
4240
4241 /* the buffer received from the upper layer is character buffer,
4242 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4243 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4244 and f0 in 3rd location */
4245 for (i = 0, j = 0; j < *pBufLen; j += 2)
4246 {
Kiet Lambe150c22013-11-21 16:30:32 +05304247 if( j+1 == *pBufLen)
4248 {
4249 tempByte = hdd_parse_hex(inPtr[j]);
4250 }
4251 else
4252 {
4253 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4254 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004255 (*pBuf)[i++] = tempByte;
4256 }
4257 *pBufLen = i;
4258 return VOS_STATUS_SUCCESS;
4259}
4260
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004261/**---------------------------------------------------------------------------
4262
Srinivas Girigowdade697412013-02-14 16:31:48 -08004263 \brief hdd_parse_channellist() - HDD Parse channel list
4264
4265 This function parses the channel list passed in the format
4266 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004267 if the Number of channels (N) does not match with the actual number of channels passed
4268 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4269 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4270 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4271 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004272
4273 \param - pValue Pointer to input channel list
4274 \param - ChannelList Pointer to local output array to record channel list
4275 \param - pNumChannels Pointer to number of roam scan channels
4276
4277 \return - 0 for success non-zero for failure
4278
4279 --------------------------------------------------------------------------*/
4280VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4281{
4282 tANI_U8 *inPtr = pValue;
4283 int tempInt;
4284 int j = 0;
4285 int v = 0;
4286 char buf[32];
4287
4288 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4289 /*no argument after the command*/
4290 if (NULL == inPtr)
4291 {
4292 return -EINVAL;
4293 }
4294
4295 /*no space after the command*/
4296 else if (SPACE_ASCII_VALUE != *inPtr)
4297 {
4298 return -EINVAL;
4299 }
4300
4301 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004302 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004303
4304 /*no argument followed by spaces*/
4305 if ('\0' == *inPtr)
4306 {
4307 return -EINVAL;
4308 }
4309
4310 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004311 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004312 if (1 != v) return -EINVAL;
4313
Srinivas Girigowdade697412013-02-14 16:31:48 -08004314 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004315 if ((v < 0) ||
4316 (tempInt <= 0) ||
4317 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4318 {
4319 return -EINVAL;
4320 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004321
4322 *pNumChannels = tempInt;
4323
4324 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4325 "Number of channels are: %d", *pNumChannels);
4326
4327 for (j = 0; j < (*pNumChannels); j++)
4328 {
4329 /*inPtr pointing to the beginning of first space after number of channels*/
4330 inPtr = strpbrk( inPtr, " " );
4331 /*no channel list after the number of channels argument*/
4332 if (NULL == inPtr)
4333 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004334 if (0 != j)
4335 {
4336 *pNumChannels = j;
4337 return VOS_STATUS_SUCCESS;
4338 }
4339 else
4340 {
4341 return -EINVAL;
4342 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004343 }
4344
4345 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004346 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004347
4348 /*no channel list after the number of channels argument and spaces*/
4349 if ( '\0' == *inPtr )
4350 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004351 if (0 != j)
4352 {
4353 *pNumChannels = j;
4354 return VOS_STATUS_SUCCESS;
4355 }
4356 else
4357 {
4358 return -EINVAL;
4359 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004360 }
4361
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004362 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004363 if (1 != v) return -EINVAL;
4364
Srinivas Girigowdade697412013-02-14 16:31:48 -08004365 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004366 if ((v < 0) ||
4367 (tempInt <= 0) ||
4368 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4369 {
4370 return -EINVAL;
4371 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004372 pChannelList[j] = tempInt;
4373
4374 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4375 "Channel %d added to preferred channel list",
4376 pChannelList[j] );
4377 }
4378
Srinivas Girigowdade697412013-02-14 16:31:48 -08004379 return VOS_STATUS_SUCCESS;
4380}
4381
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004382
4383/**---------------------------------------------------------------------------
4384
4385 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4386
4387 This function parses the reasoc command data passed in the format
4388 REASSOC<space><bssid><space><channel>
4389
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004390 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004391 \param - pTargetApBssid Pointer to target Ap bssid
4392 \param - pChannel Pointer to the Target AP channel
4393
4394 \return - 0 for success non-zero for failure
4395
4396 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004397VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4398 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004399{
4400 tANI_U8 *inPtr = pValue;
4401 int tempInt;
4402 int v = 0;
4403 tANI_U8 tempBuf[32];
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004404 /* 12 hexa decimal digits, 5 ':' and '\0' */
4405 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004406
4407 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4408 /*no argument after the command*/
4409 if (NULL == inPtr)
4410 {
4411 return -EINVAL;
4412 }
4413
4414 /*no space after the command*/
4415 else if (SPACE_ASCII_VALUE != *inPtr)
4416 {
4417 return -EINVAL;
4418 }
4419
4420 /*removing empty spaces*/
4421 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4422
4423 /*no argument followed by spaces*/
4424 if ('\0' == *inPtr)
4425 {
4426 return -EINVAL;
4427 }
4428
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004429 v = sscanf(inPtr, "%17s", macAddress);
4430 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004431 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4433 "Invalid MAC address or All hex inputs are not read (%d)", v);
4434 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004435 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004436
4437 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4438 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4439 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4440 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4441 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4442 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004443
4444 /* point to the next argument */
4445 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4446 /*no argument after the command*/
4447 if (NULL == inPtr) return -EINVAL;
4448
4449 /*removing empty spaces*/
4450 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4451
4452 /*no argument followed by spaces*/
4453 if ('\0' == *inPtr)
4454 {
4455 return -EINVAL;
4456 }
4457
4458 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004459 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004460 if (1 != v) return -EINVAL;
4461
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004462 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004463 if ((v < 0) ||
4464 (tempInt <= 0) ||
4465 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4466 {
4467 return -EINVAL;
4468 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004469
4470 *pChannel = tempInt;
4471 return VOS_STATUS_SUCCESS;
4472}
4473
4474#endif
4475
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004476#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4477/**---------------------------------------------------------------------------
4478
4479 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4480
4481 This function parses the SETCCKM IE command
4482 SETCCKMIE<space><ie data>
4483
4484 \param - pValue Pointer to input data
4485 \param - pCckmIe Pointer to output cckm Ie
4486 \param - pCckmIeLen Pointer to output cckm ie length
4487
4488 \return - 0 for success non-zero for failure
4489
4490 --------------------------------------------------------------------------*/
4491VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4492 tANI_U8 *pCckmIeLen)
4493{
4494 tANI_U8 *inPtr = pValue;
4495 tANI_U8 *dataEnd;
4496 int j = 0;
4497 int i = 0;
4498 tANI_U8 tempByte = 0;
4499
4500 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4501 /*no argument after the command*/
4502 if (NULL == inPtr)
4503 {
4504 return -EINVAL;
4505 }
4506
4507 /*no space after the command*/
4508 else if (SPACE_ASCII_VALUE != *inPtr)
4509 {
4510 return -EINVAL;
4511 }
4512
4513 /*removing empty spaces*/
4514 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4515
4516 /*no argument followed by spaces*/
4517 if ('\0' == *inPtr)
4518 {
4519 return -EINVAL;
4520 }
4521
4522 /* find the length of data */
4523 dataEnd = inPtr;
4524 while(('\0' != *dataEnd) )
4525 {
4526 dataEnd++;
4527 ++(*pCckmIeLen);
4528 }
4529 if ( *pCckmIeLen <= 0) return -EINVAL;
4530
4531 /* Allocate the number of bytes based on the number of input characters
4532 whether it is even or odd.
4533 if the number of input characters are even, then we need N/2 byte.
4534 if the number of input characters are odd, then we need do (N+1)/2 to
4535 compensate rounding off.
4536 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4537 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4538 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4539 if (NULL == *pCckmIe)
4540 {
4541 hddLog(VOS_TRACE_LEVEL_FATAL,
4542 "%s: vos_mem_alloc failed ", __func__);
4543 return -EINVAL;
4544 }
4545 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4546 /* the buffer received from the upper layer is character buffer,
4547 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4548 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4549 and f0 in 3rd location */
4550 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4551 {
4552 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4553 (*pCckmIe)[i++] = tempByte;
4554 }
4555 *pCckmIeLen = i;
4556
4557 return VOS_STATUS_SUCCESS;
4558}
4559#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4560
Jeff Johnson295189b2012-06-20 16:38:30 -07004561/**---------------------------------------------------------------------------
4562
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004563 \brief hdd_is_valid_mac_address() - Validate MAC address
4564
4565 This function validates whether the given MAC address is valid or not
4566 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4567 where X is the hexa decimal digit character and separated by ':'
4568 This algorithm works even if MAC address is not separated by ':'
4569
4570 This code checks given input string mac contains exactly 12 hexadecimal digits.
4571 and a separator colon : appears in the input string only after
4572 an even number of hex digits.
4573
4574 \param - pMacAddr pointer to the input MAC address
4575 \return - 1 for valid and 0 for invalid
4576
4577 --------------------------------------------------------------------------*/
4578
4579v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4580{
4581 int xdigit = 0;
4582 int separator = 0;
4583 while (*pMacAddr)
4584 {
4585 if (isxdigit(*pMacAddr))
4586 {
4587 xdigit++;
4588 }
4589 else if (':' == *pMacAddr)
4590 {
4591 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4592 break;
4593
4594 ++separator;
4595 }
4596 else
4597 {
4598 separator = -1;
4599 /* Invalid MAC found */
4600 return 0;
4601 }
4602 ++pMacAddr;
4603 }
4604 return (xdigit == 12 && (separator == 5 || separator == 0));
4605}
4606
4607/**---------------------------------------------------------------------------
4608
Jeff Johnson295189b2012-06-20 16:38:30 -07004609 \brief hdd_open() - HDD Open function
4610
4611 This is called in response to ifconfig up
4612
4613 \param - dev Pointer to net_device structure
4614
4615 \return - 0 for success non-zero for failure
4616
4617 --------------------------------------------------------------------------*/
4618int hdd_open (struct net_device *dev)
4619{
4620 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4621 hdd_context_t *pHddCtx;
4622 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4623 VOS_STATUS status;
4624 v_BOOL_t in_standby = TRUE;
4625
4626 if (NULL == pAdapter)
4627 {
4628 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05304629 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004630 return -ENODEV;
4631 }
4632
4633 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4634 if (NULL == pHddCtx)
4635 {
4636 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004637 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004638 return -ENODEV;
4639 }
4640
4641 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4642 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4643 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004644 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4645 {
4646 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304647 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004648 in_standby = FALSE;
4649 break;
4650 }
4651 else
4652 {
4653 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4654 pAdapterNode = pNext;
4655 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004656 }
4657
4658 if (TRUE == in_standby)
4659 {
4660 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4661 {
4662 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4663 "wlan out of power save", __func__);
4664 return -EINVAL;
4665 }
4666 }
4667
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004668 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004669 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4670 {
4671 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004672 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004673 /* Enable TX queues only when we are connected */
4674 netif_tx_start_all_queues(dev);
4675 }
4676
4677 return 0;
4678}
4679
4680int hdd_mon_open (struct net_device *dev)
4681{
4682 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4683
4684 if(pAdapter == NULL) {
4685 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004686 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004687 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004688 }
4689
4690 netif_start_queue(dev);
4691
4692 return 0;
4693}
4694/**---------------------------------------------------------------------------
4695
4696 \brief hdd_stop() - HDD stop function
4697
4698 This is called in response to ifconfig down
4699
4700 \param - dev Pointer to net_device structure
4701
4702 \return - 0 for success non-zero for failure
4703
4704 --------------------------------------------------------------------------*/
4705
4706int hdd_stop (struct net_device *dev)
4707{
4708 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4709 hdd_context_t *pHddCtx;
4710 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4711 VOS_STATUS status;
4712 v_BOOL_t enter_standby = TRUE;
4713
4714 ENTER();
4715
4716 if (NULL == pAdapter)
4717 {
4718 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05304719 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004720 return -ENODEV;
4721 }
4722
4723 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4724 if (NULL == pHddCtx)
4725 {
4726 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004727 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004728 return -ENODEV;
4729 }
4730
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004731 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004732 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4733 netif_tx_disable(pAdapter->dev);
4734 netif_carrier_off(pAdapter->dev);
4735
4736
4737 /* SoftAP ifaces should never go in power save mode
4738 making sure same here. */
4739 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4740 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004741 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004742 )
4743 {
4744 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4746 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004747 EXIT();
4748 return 0;
4749 }
4750
4751 /* Find if any iface is up then
4752 if any iface is up then can't put device to sleep/ power save mode. */
4753 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4754 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4755 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004756 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4757 {
4758 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304759 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004760 enter_standby = FALSE;
4761 break;
4762 }
4763 else
4764 {
4765 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4766 pAdapterNode = pNext;
4767 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004768 }
4769
4770 if (TRUE == enter_standby)
4771 {
4772 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4773 "entering standby", __func__);
4774 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4775 {
4776 /*log and return success*/
4777 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4778 "wlan in power save", __func__);
4779 }
4780 }
4781
4782 EXIT();
4783 return 0;
4784}
4785
4786/**---------------------------------------------------------------------------
4787
4788 \brief hdd_uninit() - HDD uninit function
4789
4790 This is called during the netdev unregister to uninitialize all data
4791associated with the device
4792
4793 \param - dev Pointer to net_device structure
4794
4795 \return - void
4796
4797 --------------------------------------------------------------------------*/
4798static void hdd_uninit (struct net_device *dev)
4799{
4800 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4801
4802 ENTER();
4803
4804 do
4805 {
4806 if (NULL == pAdapter)
4807 {
4808 hddLog(VOS_TRACE_LEVEL_FATAL,
4809 "%s: NULL pAdapter", __func__);
4810 break;
4811 }
4812
4813 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4814 {
4815 hddLog(VOS_TRACE_LEVEL_FATAL,
4816 "%s: Invalid magic", __func__);
4817 break;
4818 }
4819
4820 if (NULL == pAdapter->pHddCtx)
4821 {
4822 hddLog(VOS_TRACE_LEVEL_FATAL,
4823 "%s: NULL pHddCtx", __func__);
4824 break;
4825 }
4826
4827 if (dev != pAdapter->dev)
4828 {
4829 hddLog(VOS_TRACE_LEVEL_FATAL,
4830 "%s: Invalid device reference", __func__);
4831 /* we haven't validated all cases so let this go for now */
4832 }
4833
4834 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4835
4836 /* after uninit our adapter structure will no longer be valid */
4837 pAdapter->dev = NULL;
4838 pAdapter->magic = 0;
4839 } while (0);
4840
4841 EXIT();
4842}
4843
4844/**---------------------------------------------------------------------------
4845
4846 \brief hdd_release_firmware() -
4847
4848 This function calls the release firmware API to free the firmware buffer.
4849
4850 \param - pFileName Pointer to the File Name.
4851 pCtx - Pointer to the adapter .
4852
4853
4854 \return - 0 for success, non zero for failure
4855
4856 --------------------------------------------------------------------------*/
4857
4858VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4859{
4860 VOS_STATUS status = VOS_STATUS_SUCCESS;
4861 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4862 ENTER();
4863
4864
4865 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4866
4867 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4868
4869 if(pHddCtx->fw) {
4870 release_firmware(pHddCtx->fw);
4871 pHddCtx->fw = NULL;
4872 }
4873 else
4874 status = VOS_STATUS_E_FAILURE;
4875 }
4876 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4877 if(pHddCtx->nv) {
4878 release_firmware(pHddCtx->nv);
4879 pHddCtx->nv = NULL;
4880 }
4881 else
4882 status = VOS_STATUS_E_FAILURE;
4883
4884 }
4885
4886 EXIT();
4887 return status;
4888}
4889
4890/**---------------------------------------------------------------------------
4891
4892 \brief hdd_request_firmware() -
4893
4894 This function reads the firmware file using the request firmware
4895 API and returns the the firmware data and the firmware file size.
4896
4897 \param - pfileName - Pointer to the file name.
4898 - pCtx - Pointer to the adapter .
4899 - ppfw_data - Pointer to the pointer of the firmware data.
4900 - pSize - Pointer to the file size.
4901
4902 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4903
4904 --------------------------------------------------------------------------*/
4905
4906
4907VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4908{
4909 int status;
4910 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4911 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4912 ENTER();
4913
4914 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4915
4916 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4917
4918 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4919 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4920 __func__, pfileName);
4921 retval = VOS_STATUS_E_FAILURE;
4922 }
4923
4924 else {
4925 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4926 *pSize = pHddCtx->fw->size;
4927 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4928 __func__, *pSize);
4929 }
4930 }
4931 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4932
4933 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4934
4935 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4936 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4937 __func__, pfileName);
4938 retval = VOS_STATUS_E_FAILURE;
4939 }
4940
4941 else {
4942 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4943 *pSize = pHddCtx->nv->size;
4944 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4945 __func__, *pSize);
4946 }
4947 }
4948
4949 EXIT();
4950 return retval;
4951}
4952/**---------------------------------------------------------------------------
4953 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4954
4955 This is the function invoked by SME to inform the result of a full power
4956 request issued by HDD
4957
4958 \param - callbackcontext - Pointer to cookie
4959 status - result of request
4960
4961 \return - None
4962
4963--------------------------------------------------------------------------*/
4964void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4965{
4966 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4967
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004968 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004969 if(&pHddCtx->full_pwr_comp_var)
4970 {
4971 complete(&pHddCtx->full_pwr_comp_var);
4972 }
4973}
4974
4975/**---------------------------------------------------------------------------
4976
4977 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4978
4979 This is the function invoked by SME to inform the result of BMPS
4980 request issued by HDD
4981
4982 \param - callbackcontext - Pointer to cookie
4983 status - result of request
4984
4985 \return - None
4986
4987--------------------------------------------------------------------------*/
4988void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4989{
4990
4991 struct completion *completion_var = (struct completion*) callbackContext;
4992
Arif Hussain6d2a3322013-11-17 19:50:10 -08004993 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004994 if(completion_var != NULL)
4995 {
4996 complete(completion_var);
4997 }
4998}
4999
5000/**---------------------------------------------------------------------------
5001
5002 \brief hdd_get_cfg_file_size() -
5003
5004 This function reads the configuration file using the request firmware
5005 API and returns the configuration file size.
5006
5007 \param - pCtx - Pointer to the adapter .
5008 - pFileName - Pointer to the file name.
5009 - pBufSize - Pointer to the buffer size.
5010
5011 \return - 0 for success, non zero for failure
5012
5013 --------------------------------------------------------------------------*/
5014
5015VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
5016{
5017 int status;
5018 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5019
5020 ENTER();
5021
5022 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5023
5024 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5025 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5026 status = VOS_STATUS_E_FAILURE;
5027 }
5028 else {
5029 *pBufSize = pHddCtx->fw->size;
5030 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5031 release_firmware(pHddCtx->fw);
5032 pHddCtx->fw = NULL;
5033 }
5034
5035 EXIT();
5036 return VOS_STATUS_SUCCESS;
5037}
5038
5039/**---------------------------------------------------------------------------
5040
5041 \brief hdd_read_cfg_file() -
5042
5043 This function reads the configuration file using the request firmware
5044 API and returns the cfg data and the buffer size of the configuration file.
5045
5046 \param - pCtx - Pointer to the adapter .
5047 - pFileName - Pointer to the file name.
5048 - pBuffer - Pointer to the data buffer.
5049 - pBufSize - Pointer to the buffer size.
5050
5051 \return - 0 for success, non zero for failure
5052
5053 --------------------------------------------------------------------------*/
5054
5055VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5056 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5057{
5058 int status;
5059 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5060
5061 ENTER();
5062
5063 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5064
5065 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5066 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5067 return VOS_STATUS_E_FAILURE;
5068 }
5069 else {
5070 if(*pBufSize != pHddCtx->fw->size) {
5071 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5072 "file size", __func__);
5073 release_firmware(pHddCtx->fw);
5074 pHddCtx->fw = NULL;
5075 return VOS_STATUS_E_FAILURE;
5076 }
5077 else {
5078 if(pBuffer) {
5079 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5080 }
5081 release_firmware(pHddCtx->fw);
5082 pHddCtx->fw = NULL;
5083 }
5084 }
5085
5086 EXIT();
5087
5088 return VOS_STATUS_SUCCESS;
5089}
5090
5091/**---------------------------------------------------------------------------
5092
Jeff Johnson295189b2012-06-20 16:38:30 -07005093 \brief hdd_set_mac_address() -
5094
5095 This function sets the user specified mac address using
5096 the command ifconfig wlanX hw ether <mac adress>.
5097
5098 \param - dev - Pointer to the net device.
5099 - addr - Pointer to the sockaddr.
5100 \return - 0 for success, non zero for failure
5101
5102 --------------------------------------------------------------------------*/
5103
5104static int hdd_set_mac_address(struct net_device *dev, void *addr)
5105{
5106 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5107 struct sockaddr *psta_mac_addr = addr;
5108 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5109
5110 ENTER();
5111
5112 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5113
5114#ifdef HDD_SESSIONIZE
5115 // set the MAC address though the STA ID CFG.
5116 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5117 (v_U8_t *)&pAdapter->macAddressCurrent,
5118 sizeof( pAdapter->macAddressCurrent ),
5119 hdd_set_mac_addr_cb, VOS_FALSE );
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305120
5121 if(eHAL_STATUS_SUCCESS != halStatus)
5122 {
5123 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5124 "%s: failed to set MAC address in CFG", __func__);
5125 }
5126
Jeff Johnson295189b2012-06-20 16:38:30 -07005127#endif
5128
5129 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5130
5131 EXIT();
5132 return halStatus;
5133}
5134
5135tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5136{
5137 int i;
5138 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5139 {
5140 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
5141 break;
5142 }
5143
5144 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5145 return NULL;
5146
5147 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5148 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5149}
5150
5151void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5152{
5153 int i;
5154 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5155 {
5156 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5157 {
5158 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5159 break;
5160 }
5161 }
5162 return;
5163}
5164
5165#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5166 static struct net_device_ops wlan_drv_ops = {
5167 .ndo_open = hdd_open,
5168 .ndo_stop = hdd_stop,
5169 .ndo_uninit = hdd_uninit,
5170 .ndo_start_xmit = hdd_hard_start_xmit,
5171 .ndo_tx_timeout = hdd_tx_timeout,
5172 .ndo_get_stats = hdd_stats,
5173 .ndo_do_ioctl = hdd_ioctl,
5174 .ndo_set_mac_address = hdd_set_mac_address,
5175 .ndo_select_queue = hdd_select_queue,
5176#ifdef WLAN_FEATURE_PACKET_FILTERING
5177#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5178 .ndo_set_rx_mode = hdd_set_multicast_list,
5179#else
5180 .ndo_set_multicast_list = hdd_set_multicast_list,
5181#endif //LINUX_VERSION_CODE
5182#endif
5183 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005184 static struct net_device_ops wlan_mon_drv_ops = {
5185 .ndo_open = hdd_mon_open,
5186 .ndo_stop = hdd_stop,
5187 .ndo_uninit = hdd_uninit,
5188 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5189 .ndo_tx_timeout = hdd_tx_timeout,
5190 .ndo_get_stats = hdd_stats,
5191 .ndo_do_ioctl = hdd_ioctl,
5192 .ndo_set_mac_address = hdd_set_mac_address,
5193 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005194
5195#endif
5196
5197void hdd_set_station_ops( struct net_device *pWlanDev )
5198{
5199#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005200 pWlanDev->netdev_ops = &wlan_drv_ops;
5201#else
5202 pWlanDev->open = hdd_open;
5203 pWlanDev->stop = hdd_stop;
5204 pWlanDev->uninit = hdd_uninit;
5205 pWlanDev->hard_start_xmit = NULL;
5206 pWlanDev->tx_timeout = hdd_tx_timeout;
5207 pWlanDev->get_stats = hdd_stats;
5208 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005209 pWlanDev->set_mac_address = hdd_set_mac_address;
5210#endif
5211}
5212
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005213static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005214{
5215 struct net_device *pWlanDev = NULL;
5216 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005217 /*
5218 * cfg80211 initialization and registration....
5219 */
5220 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5221
Jeff Johnson295189b2012-06-20 16:38:30 -07005222 if(pWlanDev != NULL)
5223 {
5224
5225 //Save the pointer to the net_device in the HDD adapter
5226 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5227
Jeff Johnson295189b2012-06-20 16:38:30 -07005228 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5229
5230 pAdapter->dev = pWlanDev;
5231 pAdapter->pHddCtx = pHddCtx;
5232 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5233
5234 init_completion(&pAdapter->session_open_comp_var);
5235 init_completion(&pAdapter->session_close_comp_var);
5236 init_completion(&pAdapter->disconnect_comp_var);
5237 init_completion(&pAdapter->linkup_event_var);
5238 init_completion(&pAdapter->cancel_rem_on_chan_var);
5239 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005240#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5241 init_completion(&pAdapter->offchannel_tx_event);
5242#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005243 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005244#ifdef FEATURE_WLAN_TDLS
5245 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005246 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005247 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305248 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005249#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005250 init_completion(&pHddCtx->mc_sus_event_var);
5251 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305252 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005253 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005254 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005255
Rajeev79dbe4c2013-10-05 11:03:42 +05305256#ifdef FEATURE_WLAN_BATCH_SCAN
5257 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5258 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5259 pAdapter->pBatchScanRsp = NULL;
5260 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005261 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev79dbe4c2013-10-05 11:03:42 +05305262 mutex_init(&pAdapter->hdd_batch_scan_lock);
5263#endif
5264
Jeff Johnson295189b2012-06-20 16:38:30 -07005265 pAdapter->isLinkUpSvcNeeded = FALSE;
5266 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5267 //Init the net_device structure
5268 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5269
5270 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5271 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5272 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5273 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5274
5275 hdd_set_station_ops( pAdapter->dev );
5276
5277 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005278 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5279 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5280 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005281 /* set pWlanDev's parent to underlying device */
5282 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5283 }
5284
5285 return pAdapter;
5286}
5287
5288VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5289{
5290 struct net_device *pWlanDev = pAdapter->dev;
5291 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5292 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5293 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5294
5295 if( rtnl_lock_held )
5296 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005297 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005298 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5299 {
5300 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5301 return VOS_STATUS_E_FAILURE;
5302 }
5303 }
5304 if (register_netdevice(pWlanDev))
5305 {
5306 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5307 return VOS_STATUS_E_FAILURE;
5308 }
5309 }
5310 else
5311 {
5312 if(register_netdev(pWlanDev))
5313 {
5314 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5315 return VOS_STATUS_E_FAILURE;
5316 }
5317 }
5318 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5319
5320 return VOS_STATUS_SUCCESS;
5321}
5322
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005323static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005324{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005325 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005326
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005327 if (NULL == pAdapter)
5328 {
5329 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5330 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005331 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005332
5333 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5334 {
5335 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5336 return eHAL_STATUS_NOT_INITIALIZED;
5337 }
5338
5339 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5340
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005341#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005342 /* need to make sure all of our scheduled work has completed.
5343 * This callback is called from MC thread context, so it is safe to
5344 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005345 *
5346 * Even though this is called from MC thread context, if there is a faulty
5347 * work item in the system, that can hang this call forever. So flushing
5348 * this global work queue is not safe; and now we make sure that
5349 * individual work queues are stopped correctly. But the cancel work queue
5350 * is a GPL only API, so the proprietary version of the driver would still
5351 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005352 */
5353 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005354#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005355
5356 /* We can be blocked while waiting for scheduled work to be
5357 * flushed, and the adapter structure can potentially be freed, in
5358 * which case the magic will have been reset. So make sure the
5359 * magic is still good, and hence the adapter structure is still
5360 * valid, before signaling completion */
5361 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5362 {
5363 complete(&pAdapter->session_close_comp_var);
5364 }
5365
Jeff Johnson295189b2012-06-20 16:38:30 -07005366 return eHAL_STATUS_SUCCESS;
5367}
5368
5369VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5370{
5371 struct net_device *pWlanDev = pAdapter->dev;
5372 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5373 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5374 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5375 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305376 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005377
5378 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005379 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005380 //Open a SME session for future operation
5381 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005382 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005383 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5384 {
5385 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005386 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005387 halStatus, halStatus );
5388 status = VOS_STATUS_E_FAILURE;
5389 goto error_sme_open;
5390 }
5391
5392 //Block on a completion variable. Can't wait forever though.
5393 rc = wait_for_completion_interruptible_timeout(
5394 &pAdapter->session_open_comp_var,
5395 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305396 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005397 {
5398 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305399 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07005400 status = VOS_STATUS_E_FAILURE;
5401 goto error_sme_open;
5402 }
5403
5404 // Register wireless extensions
5405 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5406 {
5407 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005408 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005409 halStatus, halStatus );
5410 status = VOS_STATUS_E_FAILURE;
5411 goto error_register_wext;
5412 }
5413 //Safe to register the hard_start_xmit function again
5414#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5415 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5416#else
5417 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5418#endif
5419
5420 //Set the Connection State to Not Connected
5421 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5422
5423 //Set the default operation channel
5424 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5425
5426 /* Make the default Auth Type as OPEN*/
5427 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5428
5429 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5430 {
5431 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005432 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005433 status, status );
5434 goto error_init_txrx;
5435 }
5436
5437 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5438
5439 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5440 {
5441 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005442 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005443 status, status );
5444 goto error_wmm_init;
5445 }
5446
5447 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5448
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005449#ifdef FEATURE_WLAN_TDLS
5450 if(0 != wlan_hdd_tdls_init(pAdapter))
5451 {
5452 status = VOS_STATUS_E_FAILURE;
5453 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5454 goto error_tdls_init;
5455 }
5456 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5457#endif
5458
Jeff Johnson295189b2012-06-20 16:38:30 -07005459 return VOS_STATUS_SUCCESS;
5460
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005461#ifdef FEATURE_WLAN_TDLS
5462error_tdls_init:
5463 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5464 hdd_wmm_adapter_close(pAdapter);
5465#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005466error_wmm_init:
5467 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5468 hdd_deinit_tx_rx(pAdapter);
5469error_init_txrx:
5470 hdd_UnregisterWext(pWlanDev);
5471error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005472 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005473 {
5474 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005475 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005476 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005477 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005478 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305479 unsigned long rc;
5480
Jeff Johnson295189b2012-06-20 16:38:30 -07005481 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305482 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005483 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005484 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305485 if (rc <= 0)
5486 hddLog(VOS_TRACE_LEVEL_ERROR,
5487 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005488 }
5489}
5490error_sme_open:
5491 return status;
5492}
5493
Jeff Johnson295189b2012-06-20 16:38:30 -07005494void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5495{
5496 hdd_cfg80211_state_t *cfgState;
5497
5498 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5499
5500 if( NULL != cfgState->buf )
5501 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305502 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07005503 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5504 rc = wait_for_completion_interruptible_timeout(
5505 &pAdapter->tx_action_cnf_event,
5506 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305507 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005508 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005509 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305510 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
5511 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005512 }
5513 }
5514 return;
5515}
Jeff Johnson295189b2012-06-20 16:38:30 -07005516
5517void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5518{
5519 ENTER();
5520 switch ( pAdapter->device_mode )
5521 {
5522 case WLAN_HDD_INFRA_STATION:
5523 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005524 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005525 {
5526 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5527 {
5528 hdd_deinit_tx_rx( pAdapter );
5529 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5530 }
5531
5532 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5533 {
5534 hdd_wmm_adapter_close( pAdapter );
5535 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5536 }
5537
Jeff Johnson295189b2012-06-20 16:38:30 -07005538 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005539#ifdef FEATURE_WLAN_TDLS
5540 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5541 {
5542 wlan_hdd_tdls_exit(pAdapter);
5543 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5544 }
5545#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005546
5547 break;
5548 }
5549
5550 case WLAN_HDD_SOFTAP:
5551 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005552 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305553
5554 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5555 {
5556 hdd_wmm_adapter_close( pAdapter );
5557 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5558 }
5559
Jeff Johnson295189b2012-06-20 16:38:30 -07005560 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005561
5562 hdd_unregister_hostapd(pAdapter);
5563 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005564 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005565 break;
5566 }
5567
5568 case WLAN_HDD_MONITOR:
5569 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005570 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005571 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5572 {
5573 hdd_deinit_tx_rx( pAdapter );
5574 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5575 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005576 if(NULL != pAdapterforTx)
5577 {
5578 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5579 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005580 break;
5581 }
5582
5583
5584 default:
5585 break;
5586 }
5587
5588 EXIT();
5589}
5590
5591void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5592{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08005593 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305594
5595 ENTER();
5596 if (NULL == pAdapter)
5597 {
5598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5599 "%s: HDD adapter is Null", __func__);
5600 return;
5601 }
5602
5603 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005604
Rajeev79dbe4c2013-10-05 11:03:42 +05305605#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305606 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
5607 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08005608 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305609 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
5610 )
5611 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005612 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05305613 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005614 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
5615 {
5616 hdd_deinit_batch_scan(pAdapter);
5617 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305618 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08005619 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305620#endif
5621
Jeff Johnson295189b2012-06-20 16:38:30 -07005622 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5623 if( rtnl_held )
5624 {
5625 unregister_netdevice(pWlanDev);
5626 }
5627 else
5628 {
5629 unregister_netdev(pWlanDev);
5630 }
5631 // note that the pAdapter is no longer valid at this point
5632 // since the memory has been reclaimed
5633 }
5634
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305635 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005636}
5637
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005638void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5639{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305640 VOS_STATUS status;
5641 hdd_adapter_t *pAdapter = NULL;
5642 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005643
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305644 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005645
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305646 /*loop through all adapters.*/
5647 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005648 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305649 pAdapter = pAdapterNode->pAdapter;
5650 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5651 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005652
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305653 { // we skip this registration for modes other than STA and P2P client modes.
5654 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5655 pAdapterNode = pNext;
5656 continue;
5657 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005658
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305659 //Apply Dynamic DTIM For P2P
5660 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5661 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5662 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5663 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5664 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5665 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5666 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5667 (eConnectionState_Associated ==
5668 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5669 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5670 {
5671 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005672
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305673 powerRequest.uIgnoreDTIM = 1;
5674 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5675
5676 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5677 {
5678 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5679 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5680 }
5681 else
5682 {
5683 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5684 }
5685
5686 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5687 * specified during Enter/Exit BMPS when LCD off*/
5688 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5689 NULL, eANI_BOOLEAN_FALSE);
5690 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5691 NULL, eANI_BOOLEAN_FALSE);
5692
5693 /* switch to the DTIM specified in cfg.ini */
5694 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5695 "Switch to DTIM %d", powerRequest.uListenInterval);
5696 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5697 break;
5698
5699 }
5700
5701 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5702 pAdapterNode = pNext;
5703 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005704}
5705
5706void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5707{
5708 /*Switch back to DTIM 1*/
5709 tSirSetPowerParamsReq powerRequest = { 0 };
5710
5711 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5712 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005713 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005714
5715 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5716 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5717 NULL, eANI_BOOLEAN_FALSE);
5718 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5719 NULL, eANI_BOOLEAN_FALSE);
5720
5721 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5722 "Switch to DTIM%d",powerRequest.uListenInterval);
5723 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5724
5725}
5726
Jeff Johnson295189b2012-06-20 16:38:30 -07005727VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5728{
5729 VOS_STATUS status = VOS_STATUS_SUCCESS;
5730
5731 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5732 {
5733 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5734 }
5735
5736 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5737 {
5738 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5739 }
5740
5741 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5742 {
5743 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5744 }
5745
5746 return status;
5747}
5748
5749VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5750{
5751 hdd_adapter_t *pAdapter = NULL;
5752 eHalStatus halStatus;
5753 VOS_STATUS status = VOS_STATUS_E_INVAL;
5754 v_BOOL_t disableBmps = FALSE;
5755 v_BOOL_t disableImps = FALSE;
5756
5757 switch(session_type)
5758 {
5759 case WLAN_HDD_INFRA_STATION:
5760 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005761 case WLAN_HDD_P2P_CLIENT:
5762 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005763 //Exit BMPS -> Is Sta/P2P Client is already connected
5764 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5765 if((NULL != pAdapter)&&
5766 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5767 {
5768 disableBmps = TRUE;
5769 }
5770
5771 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5772 if((NULL != pAdapter)&&
5773 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5774 {
5775 disableBmps = TRUE;
5776 }
5777
5778 //Exit both Bmps and Imps incase of Go/SAP Mode
5779 if((WLAN_HDD_SOFTAP == session_type) ||
5780 (WLAN_HDD_P2P_GO == session_type))
5781 {
5782 disableBmps = TRUE;
5783 disableImps = TRUE;
5784 }
5785
5786 if(TRUE == disableImps)
5787 {
5788 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5789 {
5790 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5791 }
5792 }
5793
5794 if(TRUE == disableBmps)
5795 {
5796 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5797 {
5798 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5799
5800 if(eHAL_STATUS_SUCCESS != halStatus)
5801 {
5802 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005803 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005804 VOS_ASSERT(0);
5805 return status;
5806 }
5807 }
5808
5809 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5810 {
5811 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5812
5813 if(eHAL_STATUS_SUCCESS != halStatus)
5814 {
5815 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005816 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005817 VOS_ASSERT(0);
5818 return status;
5819 }
5820 }
5821 }
5822
5823 if((TRUE == disableBmps) ||
5824 (TRUE == disableImps))
5825 {
5826 /* Now, get the chip into Full Power now */
5827 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5828 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5829 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5830
5831 if(halStatus != eHAL_STATUS_SUCCESS)
5832 {
5833 if(halStatus == eHAL_STATUS_PMC_PENDING)
5834 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305835 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005836 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305837 ret = wait_for_completion_interruptible_timeout(
5838 &pHddCtx->full_pwr_comp_var,
5839 msecs_to_jiffies(1000));
5840 if (ret <= 0)
5841 {
5842 hddLog(VOS_TRACE_LEVEL_ERROR,
5843 "%s: wait on full_pwr_comp_var failed %ld",
5844 __func__, ret);
5845 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005846 }
5847 else
5848 {
5849 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005850 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005851 VOS_ASSERT(0);
5852 return status;
5853 }
5854 }
5855
5856 status = VOS_STATUS_SUCCESS;
5857 }
5858
5859 break;
5860 }
5861 return status;
5862}
5863
5864hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005865 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005866 tANI_U8 rtnl_held )
5867{
5868 hdd_adapter_t *pAdapter = NULL;
5869 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5870 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5871 VOS_STATUS exitbmpsStatus;
5872
Arif Hussain6d2a3322013-11-17 19:50:10 -08005873 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005874
5875 //Disable BMPS incase of Concurrency
5876 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5877
5878 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5879 {
5880 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305881 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005882 VOS_ASSERT(0);
5883 return NULL;
5884 }
5885
5886 switch(session_type)
5887 {
5888 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005889 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005890 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005891 {
5892 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5893
5894 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305895 {
5896 hddLog(VOS_TRACE_LEVEL_FATAL,
5897 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005898 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305899 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005900
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305901#ifdef FEATURE_WLAN_TDLS
5902 /* A Mutex Lock is introduced while changing/initializing the mode to
5903 * protect the concurrent access for the Adapters by TDLS module.
5904 */
5905 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5906 {
5907 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5908 "%s: unable to lock list", __func__);
5909 return NULL;
5910 }
5911#endif
5912
Jeff Johnsone7245742012-09-05 17:12:55 -07005913 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5914 NL80211_IFTYPE_P2P_CLIENT:
5915 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005916
Jeff Johnson295189b2012-06-20 16:38:30 -07005917 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305918#ifdef FEATURE_WLAN_TDLS
5919 mutex_unlock(&pHddCtx->tdls_lock);
5920#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05305921
5922 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005923 if( VOS_STATUS_SUCCESS != status )
5924 goto err_free_netdev;
5925
5926 status = hdd_register_interface( pAdapter, rtnl_held );
5927 if( VOS_STATUS_SUCCESS != status )
5928 {
5929 hdd_deinit_adapter(pHddCtx, pAdapter);
5930 goto err_free_netdev;
5931 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305932
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05305933 // Workqueue which gets scheduled in IPv4 notification callback.
5934 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
5935
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305936#ifdef WLAN_NS_OFFLOAD
5937 // Workqueue which gets scheduled in IPv6 notification callback.
5938 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
5939#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005940 //Stop the Interface TX queue.
5941 netif_tx_disable(pAdapter->dev);
5942 //netif_tx_disable(pWlanDev);
5943 netif_carrier_off(pAdapter->dev);
5944
5945 break;
5946 }
5947
Jeff Johnson295189b2012-06-20 16:38:30 -07005948 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005949 case WLAN_HDD_SOFTAP:
5950 {
5951 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5952 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305953 {
5954 hddLog(VOS_TRACE_LEVEL_FATAL,
5955 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005956 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305957 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005958
Jeff Johnson295189b2012-06-20 16:38:30 -07005959 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5960 NL80211_IFTYPE_AP:
5961 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005962 pAdapter->device_mode = session_type;
5963
5964 status = hdd_init_ap_mode(pAdapter);
5965 if( VOS_STATUS_SUCCESS != status )
5966 goto err_free_netdev;
5967
5968 status = hdd_register_hostapd( pAdapter, rtnl_held );
5969 if( VOS_STATUS_SUCCESS != status )
5970 {
5971 hdd_deinit_adapter(pHddCtx, pAdapter);
5972 goto err_free_netdev;
5973 }
5974
5975 netif_tx_disable(pAdapter->dev);
5976 netif_carrier_off(pAdapter->dev);
5977
5978 hdd_set_conparam( 1 );
5979 break;
5980 }
5981 case WLAN_HDD_MONITOR:
5982 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005983 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5984 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305985 {
5986 hddLog(VOS_TRACE_LEVEL_FATAL,
5987 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005988 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305989 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005990
5991 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5992 pAdapter->device_mode = session_type;
5993 status = hdd_register_interface( pAdapter, rtnl_held );
5994#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5995 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5996#else
5997 pAdapter->dev->open = hdd_mon_open;
5998 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5999#endif
6000 hdd_init_tx_rx( pAdapter );
6001 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6002 //Set adapter to be used for data tx. It will use either GO or softap.
6003 pAdapter->sessionCtx.monitor.pAdapterForTx =
6004 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07006005 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
6006 {
6007 pAdapter->sessionCtx.monitor.pAdapterForTx =
6008 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
6009 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006010 /* This workqueue will be used to transmit management packet over
6011 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006012 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
6013 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
6014 return NULL;
6015 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07006016
Jeff Johnson295189b2012-06-20 16:38:30 -07006017 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
6018 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006019 }
6020 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006021 case WLAN_HDD_FTM:
6022 {
6023 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6024
6025 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306026 {
6027 hddLog(VOS_TRACE_LEVEL_FATAL,
6028 FL("failed to allocate adapter for session %d"), session_type);
6029 return NULL;
6030 }
6031
Jeff Johnson295189b2012-06-20 16:38:30 -07006032 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6033 * message while loading driver in FTM mode. */
6034 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6035 pAdapter->device_mode = session_type;
6036 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306037
6038 hdd_init_tx_rx( pAdapter );
6039
6040 //Stop the Interface TX queue.
6041 netif_tx_disable(pAdapter->dev);
6042 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006043 }
6044 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006045 default:
6046 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306047 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6048 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006049 VOS_ASSERT(0);
6050 return NULL;
6051 }
6052 }
6053
Jeff Johnson295189b2012-06-20 16:38:30 -07006054 if( VOS_STATUS_SUCCESS == status )
6055 {
6056 //Add it to the hdd's session list.
6057 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6058 if( NULL == pHddAdapterNode )
6059 {
6060 status = VOS_STATUS_E_NOMEM;
6061 }
6062 else
6063 {
6064 pHddAdapterNode->pAdapter = pAdapter;
6065 status = hdd_add_adapter_back ( pHddCtx,
6066 pHddAdapterNode );
6067 }
6068 }
6069
6070 if( VOS_STATUS_SUCCESS != status )
6071 {
6072 if( NULL != pAdapter )
6073 {
6074 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6075 pAdapter = NULL;
6076 }
6077 if( NULL != pHddAdapterNode )
6078 {
6079 vos_mem_free( pHddAdapterNode );
6080 }
6081
6082 goto resume_bmps;
6083 }
6084
6085 if(VOS_STATUS_SUCCESS == status)
6086 {
6087 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6088
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006089 //Initialize the WoWL service
6090 if(!hdd_init_wowl(pAdapter))
6091 {
6092 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6093 goto err_free_netdev;
6094 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006095 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006096 return pAdapter;
6097
6098err_free_netdev:
6099 free_netdev(pAdapter->dev);
6100 wlan_hdd_release_intf_addr( pHddCtx,
6101 pAdapter->macAddressCurrent.bytes );
6102
6103resume_bmps:
6104 //If bmps disabled enable it
6105 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6106 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306107 if (pHddCtx->hdd_wlan_suspended)
6108 {
6109 hdd_set_pwrparams(pHddCtx);
6110 }
6111 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006112 }
6113 return NULL;
6114}
6115
6116VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6117 tANI_U8 rtnl_held )
6118{
6119 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6120 VOS_STATUS status;
6121
6122 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6123 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306124 {
6125 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6126 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006127 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306128 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006129
6130 while ( pCurrent->pAdapter != pAdapter )
6131 {
6132 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6133 if( VOS_STATUS_SUCCESS != status )
6134 break;
6135
6136 pCurrent = pNext;
6137 }
6138 pAdapterNode = pCurrent;
6139 if( VOS_STATUS_SUCCESS == status )
6140 {
6141 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6142 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306143
6144#ifdef FEATURE_WLAN_TDLS
6145
6146 /* A Mutex Lock is introduced while changing/initializing the mode to
6147 * protect the concurrent access for the Adapters by TDLS module.
6148 */
6149 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
6150 {
6151 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6152 "%s: unable to lock list", __func__);
6153 return VOS_STATUS_E_FAILURE;
6154 }
6155#endif
6156
Jeff Johnson295189b2012-06-20 16:38:30 -07006157 hdd_remove_adapter( pHddCtx, pAdapterNode );
6158 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006159 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006160
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306161#ifdef FEATURE_WLAN_TDLS
6162 mutex_unlock(&pHddCtx->tdls_lock);
6163#endif
6164
Jeff Johnson295189b2012-06-20 16:38:30 -07006165
6166 /* If there is a single session of STA/P2P client, re-enable BMPS */
6167 if ((!vos_concurrent_sessions_running()) &&
6168 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6169 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6170 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306171 if (pHddCtx->hdd_wlan_suspended)
6172 {
6173 hdd_set_pwrparams(pHddCtx);
6174 }
6175 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006176 }
6177
6178 return VOS_STATUS_SUCCESS;
6179 }
6180
6181 return VOS_STATUS_E_FAILURE;
6182}
6183
6184VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6185{
6186 hdd_adapter_list_node_t *pHddAdapterNode;
6187 VOS_STATUS status;
6188
6189 ENTER();
6190
6191 do
6192 {
6193 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6194 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6195 {
6196 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6197 vos_mem_free( pHddAdapterNode );
6198 }
6199 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6200
6201 EXIT();
6202
6203 return VOS_STATUS_SUCCESS;
6204}
6205
6206void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6207{
6208 v_U8_t addIE[1] = {0};
6209
6210 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6211 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6212 eANI_BOOLEAN_FALSE) )
6213 {
6214 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006215 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006216 }
6217
6218 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6219 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6220 eANI_BOOLEAN_FALSE) )
6221 {
6222 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006223 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006224 }
6225
6226 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6227 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6228 eANI_BOOLEAN_FALSE) )
6229 {
6230 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006231 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006232 }
6233}
6234
6235VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6236{
6237 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6238 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6239 union iwreq_data wrqu;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306240 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006241
6242 ENTER();
6243
6244 switch(pAdapter->device_mode)
6245 {
6246 case WLAN_HDD_INFRA_STATION:
6247 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006248 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006249 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6250 {
6251 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6252 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6253 pAdapter->sessionId,
6254 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6255 else
6256 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6257 pAdapter->sessionId,
6258 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6259 //success implies disconnect command got queued up successfully
6260 if(halStatus == eHAL_STATUS_SUCCESS)
6261 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306262 ret = wait_for_completion_interruptible_timeout(
6263 &pAdapter->disconnect_comp_var,
6264 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6265 if (ret <= 0)
6266 {
6267 hddLog(VOS_TRACE_LEVEL_ERROR,
6268 "%s: wait on disconnect_comp_var failed %ld",
6269 __func__, ret);
6270 }
6271 }
6272 else
6273 {
6274 hddLog(LOGE, "%s: failed to post disconnect event to SME",
6275 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006276 }
6277 memset(&wrqu, '\0', sizeof(wrqu));
6278 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6279 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6280 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6281 }
6282 else
6283 {
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306284 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
6285 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -07006286 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306287#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306288#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306289 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6290#endif
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306291 if (pAdapter->ipv6_notifier_registered)
6292 {
6293 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
6294 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
6295 pAdapter->ipv6_notifier_registered = false;
6296 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306297#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306298 if (pAdapter->ipv4_notifier_registered)
6299 {
6300 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6301 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6302 pAdapter->ipv4_notifier_registered = false;
6303 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306304#ifdef WLAN_OPEN_SOURCE
6305 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6306#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006307 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6308 {
6309 INIT_COMPLETION(pAdapter->session_close_comp_var);
6310 if (eHAL_STATUS_SUCCESS ==
6311 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6312 hdd_smeCloseSessionCallback, pAdapter))
6313 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306314 unsigned long ret;
6315
Jeff Johnson295189b2012-06-20 16:38:30 -07006316 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306317 ret = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006318 &pAdapter->session_close_comp_var,
6319 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306320 if ( 0 >= ret)
6321 {
6322 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
6323 __func__, ret);
6324 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006325 }
6326 }
6327
6328 break;
6329
6330 case WLAN_HDD_SOFTAP:
6331 case WLAN_HDD_P2P_GO:
6332 //Any softap specific cleanup here...
6333 mutex_lock(&pHddCtx->sap_lock);
6334 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6335 {
6336 VOS_STATUS status;
6337 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6338
6339 //Stop Bss.
6340 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6341 if (VOS_IS_STATUS_SUCCESS(status))
6342 {
6343 hdd_hostapd_state_t *pHostapdState =
6344 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6345
6346 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6347
6348 if (!VOS_IS_STATUS_SUCCESS(status))
6349 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306350 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
6351 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006352 }
6353 }
6354 else
6355 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006356 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006357 }
6358 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6359
6360 if (eHAL_STATUS_FAILURE ==
6361 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6362 0, NULL, eANI_BOOLEAN_FALSE))
6363 {
6364 hddLog(LOGE,
6365 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006366 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006367 }
6368
6369 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6370 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6371 eANI_BOOLEAN_FALSE) )
6372 {
6373 hddLog(LOGE,
6374 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6375 }
6376
6377 // Reset WNI_CFG_PROBE_RSP Flags
6378 wlan_hdd_reset_prob_rspies(pAdapter);
6379 kfree(pAdapter->sessionCtx.ap.beacon);
6380 pAdapter->sessionCtx.ap.beacon = NULL;
6381 }
6382 mutex_unlock(&pHddCtx->sap_lock);
6383 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006384
Jeff Johnson295189b2012-06-20 16:38:30 -07006385 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006386#ifdef WLAN_OPEN_SOURCE
6387 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6388#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006389 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006390
Jeff Johnson295189b2012-06-20 16:38:30 -07006391 default:
6392 break;
6393 }
6394
6395 EXIT();
6396 return VOS_STATUS_SUCCESS;
6397}
6398
6399VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6400{
6401 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6402 VOS_STATUS status;
6403 hdd_adapter_t *pAdapter;
6404
6405 ENTER();
6406
6407 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6408
6409 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6410 {
6411 pAdapter = pAdapterNode->pAdapter;
6412 netif_tx_disable(pAdapter->dev);
6413 netif_carrier_off(pAdapter->dev);
6414
6415 hdd_stop_adapter( pHddCtx, pAdapter );
6416
6417 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6418 pAdapterNode = pNext;
6419 }
6420
6421 EXIT();
6422
6423 return VOS_STATUS_SUCCESS;
6424}
6425
Rajeev Kumarf999e582014-01-09 17:33:29 -08006426
6427#ifdef FEATURE_WLAN_BATCH_SCAN
6428/**---------------------------------------------------------------------------
6429
6430 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
6431 structures
6432
6433 \param - pAdapter Pointer to HDD adapter
6434
6435 \return - None
6436
6437 --------------------------------------------------------------------------*/
6438void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
6439{
6440 tHddBatchScanRsp *pNode;
6441 tHddBatchScanRsp *pPrev;
6442
6443 if (pAdapter)
6444 {
6445 pNode = pAdapter->pBatchScanRsp;
6446 while (pNode)
6447 {
6448 pPrev = pNode;
6449 pNode = pNode->pNext;
6450 vos_mem_free((v_VOID_t * )pPrev);
6451 }
6452 pAdapter->pBatchScanRsp = NULL;
6453 }
6454
6455 pAdapter->pBatchScanRsp = NULL;
6456 pAdapter->numScanList = 0;
6457 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
6458 pAdapter->prev_batch_id = 0;
6459
6460 return;
6461}
6462#endif
6463
6464
Jeff Johnson295189b2012-06-20 16:38:30 -07006465VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6466{
6467 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6468 VOS_STATUS status;
6469 hdd_adapter_t *pAdapter;
6470
6471 ENTER();
6472
6473 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6474
6475 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6476 {
6477 pAdapter = pAdapterNode->pAdapter;
6478 netif_tx_disable(pAdapter->dev);
6479 netif_carrier_off(pAdapter->dev);
6480
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006481 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6482
Jeff Johnson295189b2012-06-20 16:38:30 -07006483 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306484 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6485 {
6486 hdd_wmm_adapter_close( pAdapter );
6487 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6488 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006489
Rajeev Kumarf999e582014-01-09 17:33:29 -08006490#ifdef FEATURE_WLAN_BATCH_SCAN
6491 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6492 {
6493 hdd_deinit_batch_scan(pAdapter);
6494 }
6495#endif
6496
Jeff Johnson295189b2012-06-20 16:38:30 -07006497 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6498 pAdapterNode = pNext;
6499 }
6500
6501 EXIT();
6502
6503 return VOS_STATUS_SUCCESS;
6504}
6505
6506VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6507{
6508 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6509 VOS_STATUS status;
6510 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306511 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006512
6513 ENTER();
6514
6515 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6516
6517 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6518 {
6519 pAdapter = pAdapterNode->pAdapter;
6520
6521 switch(pAdapter->device_mode)
6522 {
6523 case WLAN_HDD_INFRA_STATION:
6524 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006525 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306526
6527 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6528
Jeff Johnson295189b2012-06-20 16:38:30 -07006529 hdd_init_station_mode(pAdapter);
6530 /* Open the gates for HDD to receive Wext commands */
6531 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006532 pHddCtx->scan_info.mScanPending = FALSE;
6533 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006534
6535 //Trigger the initial scan
6536 hdd_wlan_initial_scan(pAdapter);
6537
6538 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306539 if (eConnectionState_Associated == connState ||
6540 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006541 {
6542 union iwreq_data wrqu;
6543 memset(&wrqu, '\0', sizeof(wrqu));
6544 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6545 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6546 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006547 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006548
Jeff Johnson295189b2012-06-20 16:38:30 -07006549 /* indicate disconnected event to nl80211 */
6550 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6551 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006552 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306553 else if (eConnectionState_Connecting == connState)
6554 {
6555 /*
6556 * Indicate connect failure to supplicant if we were in the
6557 * process of connecting
6558 */
6559 cfg80211_connect_result(pAdapter->dev, NULL,
6560 NULL, 0, NULL, 0,
6561 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6562 GFP_KERNEL);
6563 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006564 break;
6565
6566 case WLAN_HDD_SOFTAP:
6567 /* softAP can handle SSR */
6568 break;
6569
6570 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006571 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006572 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006573 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006574 break;
6575
6576 case WLAN_HDD_MONITOR:
6577 /* monitor interface start */
6578 break;
6579 default:
6580 break;
6581 }
6582
6583 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6584 pAdapterNode = pNext;
6585 }
6586
6587 EXIT();
6588
6589 return VOS_STATUS_SUCCESS;
6590}
6591
6592VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6593{
6594 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6595 hdd_adapter_t *pAdapter;
6596 VOS_STATUS status;
6597 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306598 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006599
6600 ENTER();
6601
6602 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6603
6604 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6605 {
6606 pAdapter = pAdapterNode->pAdapter;
6607
6608 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6609 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6610 {
6611 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6612 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6613
6614 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6615 init_completion(&pAdapter->disconnect_comp_var);
6616 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6617 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6618
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306619 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006620 &pAdapter->disconnect_comp_var,
6621 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306622 if (0 >= ret)
6623 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
6624 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07006625
6626 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6627 pHddCtx->isAmpAllowed = VOS_FALSE;
6628 sme_RoamConnect(pHddCtx->hHal,
6629 pAdapter->sessionId, &(pWextState->roamProfile),
6630 &roamId);
6631 }
6632
6633 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6634 pAdapterNode = pNext;
6635 }
6636
6637 EXIT();
6638
6639 return VOS_STATUS_SUCCESS;
6640}
6641
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006642void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6643{
6644 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6645 VOS_STATUS status;
6646 hdd_adapter_t *pAdapter;
6647 hdd_station_ctx_t *pHddStaCtx;
6648 hdd_ap_ctx_t *pHddApCtx;
6649 hdd_hostapd_state_t * pHostapdState;
6650 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6651 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6652 const char *p2pMode = "DEV";
6653 const char *ccMode = "Standalone";
6654 int n;
6655
6656 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6657 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6658 {
6659 pAdapter = pAdapterNode->pAdapter;
6660 switch (pAdapter->device_mode) {
6661 case WLAN_HDD_INFRA_STATION:
6662 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6663 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6664 staChannel = pHddStaCtx->conn_info.operationChannel;
6665 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6666 }
6667 break;
6668 case WLAN_HDD_P2P_CLIENT:
6669 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6670 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6671 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6672 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6673 p2pMode = "CLI";
6674 }
6675 break;
6676 case WLAN_HDD_P2P_GO:
6677 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6678 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6679 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6680 p2pChannel = pHddApCtx->operatingChannel;
6681 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6682 }
6683 p2pMode = "GO";
6684 break;
6685 case WLAN_HDD_SOFTAP:
6686 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6687 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6688 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6689 apChannel = pHddApCtx->operatingChannel;
6690 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6691 }
6692 break;
6693 default:
6694 break;
6695 }
6696 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6697 pAdapterNode = pNext;
6698 }
6699 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6700 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6701 }
6702 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6703 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6704 if (p2pChannel > 0) {
6705 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6706 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6707 }
6708 if (apChannel > 0) {
6709 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6710 apChannel, MAC_ADDR_ARRAY(apBssid));
6711 }
6712
6713 if (p2pChannel > 0 && apChannel > 0) {
6714 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6715 }
6716}
6717
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006718bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006719{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006720 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006721}
6722
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006723/* Once SSR is disabled then it cannot be set. */
6724void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006725{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006726 if (HDD_SSR_DISABLED == isSsrRequired)
6727 return;
6728
Jeff Johnson295189b2012-06-20 16:38:30 -07006729 isSsrRequired = value;
6730}
6731
6732VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6733 hdd_adapter_list_node_t** ppAdapterNode)
6734{
6735 VOS_STATUS status;
6736 spin_lock(&pHddCtx->hddAdapters.lock);
6737 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6738 (hdd_list_node_t**) ppAdapterNode );
6739 spin_unlock(&pHddCtx->hddAdapters.lock);
6740 return status;
6741}
6742
6743VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6744 hdd_adapter_list_node_t* pAdapterNode,
6745 hdd_adapter_list_node_t** pNextAdapterNode)
6746{
6747 VOS_STATUS status;
6748 spin_lock(&pHddCtx->hddAdapters.lock);
6749 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6750 (hdd_list_node_t*) pAdapterNode,
6751 (hdd_list_node_t**)pNextAdapterNode );
6752
6753 spin_unlock(&pHddCtx->hddAdapters.lock);
6754 return status;
6755}
6756
6757VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6758 hdd_adapter_list_node_t* pAdapterNode)
6759{
6760 VOS_STATUS status;
6761 spin_lock(&pHddCtx->hddAdapters.lock);
6762 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6763 &pAdapterNode->node );
6764 spin_unlock(&pHddCtx->hddAdapters.lock);
6765 return status;
6766}
6767
6768VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6769 hdd_adapter_list_node_t** ppAdapterNode)
6770{
6771 VOS_STATUS status;
6772 spin_lock(&pHddCtx->hddAdapters.lock);
6773 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6774 (hdd_list_node_t**) ppAdapterNode );
6775 spin_unlock(&pHddCtx->hddAdapters.lock);
6776 return status;
6777}
6778
6779VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6780 hdd_adapter_list_node_t* pAdapterNode)
6781{
6782 VOS_STATUS status;
6783 spin_lock(&pHddCtx->hddAdapters.lock);
6784 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6785 (hdd_list_node_t*) pAdapterNode );
6786 spin_unlock(&pHddCtx->hddAdapters.lock);
6787 return status;
6788}
6789
6790VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6791 hdd_adapter_list_node_t* pAdapterNode)
6792{
6793 VOS_STATUS status;
6794 spin_lock(&pHddCtx->hddAdapters.lock);
6795 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6796 (hdd_list_node_t*) pAdapterNode );
6797 spin_unlock(&pHddCtx->hddAdapters.lock);
6798 return status;
6799}
6800
6801hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6802 tSirMacAddr macAddr )
6803{
6804 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6805 hdd_adapter_t *pAdapter;
6806 VOS_STATUS status;
6807
6808 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6809
6810 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6811 {
6812 pAdapter = pAdapterNode->pAdapter;
6813
6814 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6815 macAddr, sizeof(tSirMacAddr) ) )
6816 {
6817 return pAdapter;
6818 }
6819 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6820 pAdapterNode = pNext;
6821 }
6822
6823 return NULL;
6824
6825}
6826
6827hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6828{
6829 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6830 hdd_adapter_t *pAdapter;
6831 VOS_STATUS status;
6832
6833 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6834
6835 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6836 {
6837 pAdapter = pAdapterNode->pAdapter;
6838
6839 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6840 IFNAMSIZ ) )
6841 {
6842 return pAdapter;
6843 }
6844 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6845 pAdapterNode = pNext;
6846 }
6847
6848 return NULL;
6849
6850}
6851
6852hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6853{
6854 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6855 hdd_adapter_t *pAdapter;
6856 VOS_STATUS status;
6857
6858 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6859
6860 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6861 {
6862 pAdapter = pAdapterNode->pAdapter;
6863
6864 if( pAdapter && (mode == pAdapter->device_mode) )
6865 {
6866 return pAdapter;
6867 }
6868 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6869 pAdapterNode = pNext;
6870 }
6871
6872 return NULL;
6873
6874}
6875
6876//Remove this function later
6877hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6878{
6879 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6880 hdd_adapter_t *pAdapter;
6881 VOS_STATUS status;
6882
6883 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6884
6885 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6886 {
6887 pAdapter = pAdapterNode->pAdapter;
6888
6889 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6890 {
6891 return pAdapter;
6892 }
6893
6894 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6895 pAdapterNode = pNext;
6896 }
6897
6898 return NULL;
6899
6900}
6901
Jeff Johnson295189b2012-06-20 16:38:30 -07006902/**---------------------------------------------------------------------------
6903
6904 \brief hdd_set_monitor_tx_adapter() -
6905
6906 This API initializes the adapter to be used while transmitting on monitor
6907 adapter.
6908
6909 \param - pHddCtx - Pointer to the HDD context.
6910 pAdapter - Adapter that will used for TX. This can be NULL.
6911 \return - None.
6912 --------------------------------------------------------------------------*/
6913void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6914{
6915 hdd_adapter_t *pMonAdapter;
6916
6917 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6918
6919 if( NULL != pMonAdapter )
6920 {
6921 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6922 }
6923}
Jeff Johnson295189b2012-06-20 16:38:30 -07006924/**---------------------------------------------------------------------------
6925
6926 \brief hdd_select_queue() -
6927
6928 This API returns the operating channel of the requested device mode
6929
6930 \param - pHddCtx - Pointer to the HDD context.
6931 - mode - Device mode for which operating channel is required
6932 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6933 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6934 \return - channel number. "0" id the requested device is not found OR it is not connected.
6935 --------------------------------------------------------------------------*/
6936v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6937{
6938 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6939 VOS_STATUS status;
6940 hdd_adapter_t *pAdapter;
6941 v_U8_t operatingChannel = 0;
6942
6943 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6944
6945 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6946 {
6947 pAdapter = pAdapterNode->pAdapter;
6948
6949 if( mode == pAdapter->device_mode )
6950 {
6951 switch(pAdapter->device_mode)
6952 {
6953 case WLAN_HDD_INFRA_STATION:
6954 case WLAN_HDD_P2P_CLIENT:
6955 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6956 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6957 break;
6958 case WLAN_HDD_SOFTAP:
6959 case WLAN_HDD_P2P_GO:
6960 /*softap connection info */
6961 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6962 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6963 break;
6964 default:
6965 break;
6966 }
6967
6968 break; //Found the device of interest. break the loop
6969 }
6970
6971 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6972 pAdapterNode = pNext;
6973 }
6974 return operatingChannel;
6975}
6976
6977#ifdef WLAN_FEATURE_PACKET_FILTERING
6978/**---------------------------------------------------------------------------
6979
6980 \brief hdd_set_multicast_list() -
6981
6982 This used to set the multicast address list.
6983
6984 \param - dev - Pointer to the WLAN device.
6985 - skb - Pointer to OS packet (sk_buff).
6986 \return - success/fail
6987
6988 --------------------------------------------------------------------------*/
6989static void hdd_set_multicast_list(struct net_device *dev)
6990{
6991 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006992 int mc_count;
6993 int i = 0;
6994 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306995
6996 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006997 {
6998 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306999 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007000 return;
7001 }
7002
7003 if (dev->flags & IFF_ALLMULTI)
7004 {
7005 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007006 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307007 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007008 }
7009 else
7010 {
7011 mc_count = netdev_mc_count(dev);
7012 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007013 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07007014 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
7015 {
7016 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007017 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307018 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007019 return;
7020 }
7021
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307022 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007023
7024 netdev_for_each_mc_addr(ha, dev) {
7025 if (i == mc_count)
7026 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307027 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7028 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007029 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007030 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307031 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007032 i++;
7033 }
7034 }
7035 return;
7036}
7037#endif
7038
7039/**---------------------------------------------------------------------------
7040
7041 \brief hdd_select_queue() -
7042
7043 This function is registered with the Linux OS for network
7044 core to decide which queue to use first.
7045
7046 \param - dev - Pointer to the WLAN device.
7047 - skb - Pointer to OS packet (sk_buff).
7048 \return - ac, Queue Index/access category corresponding to UP in IP header
7049
7050 --------------------------------------------------------------------------*/
7051v_U16_t hdd_select_queue(struct net_device *dev,
7052 struct sk_buff *skb)
7053{
7054 return hdd_wmm_select_queue(dev, skb);
7055}
7056
7057
7058/**---------------------------------------------------------------------------
7059
7060 \brief hdd_wlan_initial_scan() -
7061
7062 This function triggers the initial scan
7063
7064 \param - pAdapter - Pointer to the HDD adapter.
7065
7066 --------------------------------------------------------------------------*/
7067void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
7068{
7069 tCsrScanRequest scanReq;
7070 tCsrChannelInfo channelInfo;
7071 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07007072 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007073 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7074
7075 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
7076 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
7077 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
7078
7079 if(sme_Is11dSupported(pHddCtx->hHal))
7080 {
7081 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
7082 if ( HAL_STATUS_SUCCESS( halStatus ) )
7083 {
7084 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
7085 if( !scanReq.ChannelInfo.ChannelList )
7086 {
7087 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
7088 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007089 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007090 return;
7091 }
7092 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
7093 channelInfo.numOfChannels);
7094 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
7095 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007096 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007097 }
7098
7099 scanReq.scanType = eSIR_PASSIVE_SCAN;
7100 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
7101 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
7102 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7103 }
7104 else
7105 {
7106 scanReq.scanType = eSIR_ACTIVE_SCAN;
7107 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7108 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7109 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7110 }
7111
7112 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7113 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7114 {
7115 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7116 __func__, halStatus );
7117 }
7118
7119 if(sme_Is11dSupported(pHddCtx->hHal))
7120 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7121}
7122
Jeff Johnson295189b2012-06-20 16:38:30 -07007123/**---------------------------------------------------------------------------
7124
7125 \brief hdd_full_power_callback() - HDD full power callback function
7126
7127 This is the function invoked by SME to inform the result of a full power
7128 request issued by HDD
7129
7130 \param - callbackcontext - Pointer to cookie
7131 \param - status - result of request
7132
7133 \return - None
7134
7135 --------------------------------------------------------------------------*/
7136static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7137{
Jeff Johnson72a40512013-12-19 10:14:15 -08007138 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007139
7140 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307141 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007142
7143 if (NULL == callbackContext)
7144 {
7145 hddLog(VOS_TRACE_LEVEL_ERROR,
7146 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007147 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007148 return;
7149 }
7150
Jeff Johnson72a40512013-12-19 10:14:15 -08007151 /* there is a race condition that exists between this callback
7152 function and the caller since the caller could time out either
7153 before or while this code is executing. we use a spinlock to
7154 serialize these actions */
7155 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007156
7157 if (POWER_CONTEXT_MAGIC != pContext->magic)
7158 {
7159 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007160 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007161 hddLog(VOS_TRACE_LEVEL_WARN,
7162 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007163 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007164 return;
7165 }
7166
Jeff Johnson72a40512013-12-19 10:14:15 -08007167 /* context is valid so caller is still waiting */
7168
7169 /* paranoia: invalidate the magic */
7170 pContext->magic = 0;
7171
7172 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007173 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007174
7175 /* serialization is complete */
7176 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007177}
7178
7179/**---------------------------------------------------------------------------
7180
7181 \brief hdd_wlan_exit() - HDD WLAN exit function
7182
7183 This is the driver exit point (invoked during rmmod)
7184
7185 \param - pHddCtx - Pointer to the HDD Context
7186
7187 \return - None
7188
7189 --------------------------------------------------------------------------*/
7190void hdd_wlan_exit(hdd_context_t *pHddCtx)
7191{
7192 eHalStatus halStatus;
7193 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7194 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307195 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007196 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -08007197 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007198 long lrc;
7199
7200 ENTER();
7201
Jeff Johnson88ba7742013-02-27 14:36:02 -08007202 if (VOS_FTM_MODE != hdd_get_conparam())
7203 {
7204 // Unloading, restart logic is no more required.
7205 wlan_hdd_restart_deinit(pHddCtx);
7206 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007207
Jeff Johnson295189b2012-06-20 16:38:30 -07007208 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007209 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007210 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007211 {
7212 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
7213 WLAN_HDD_INFRA_STATION);
7214 if (pAdapter == NULL)
7215 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
7216
7217 if (pAdapter != NULL)
7218 {
7219 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
7220 hdd_UnregisterWext(pAdapter->dev);
7221 }
7222 }
7223 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007224
Jeff Johnson295189b2012-06-20 16:38:30 -07007225 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08007226 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307227 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08007228 wlan_hdd_ftm_close(pHddCtx);
7229 goto free_hdd_ctx;
7230 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007231 //Stop the Interface TX queue.
7232 //netif_tx_disable(pWlanDev);
7233 //netif_carrier_off(pWlanDev);
7234
Jeff Johnson295189b2012-06-20 16:38:30 -07007235 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7236 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307237 hddLog(VOS_TRACE_LEVEL_INFO,"%s: SAP MODE",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007238 pAdapter = hdd_get_adapter(pHddCtx,
7239 WLAN_HDD_SOFTAP);
7240 }
7241 else
7242 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007243 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007244 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307245 hddLog(VOS_TRACE_LEVEL_INFO,"%s: STA MODE",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007246 pAdapter = hdd_get_adapter(pHddCtx,
7247 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007248 if (pAdapter == NULL)
7249 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07007250 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007251 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307252
7253 if(NULL == pAdapter)
7254 {
7255 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: pAdapter is NULL",__func__);
7256 goto free_hdd_ctx;
7257 }
7258
Jeff Johnson295189b2012-06-20 16:38:30 -07007259 /* DeRegister with platform driver as client for Suspend/Resume */
7260 vosStatus = hddDeregisterPmOps(pHddCtx);
7261 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7262 {
7263 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7264 VOS_ASSERT(0);
7265 }
7266
7267 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7268 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7269 {
7270 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7271 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007272
7273 // Cancel any outstanding scan requests. We are about to close all
7274 // of our adapters, but an adapter structure is what SME passes back
7275 // to our callback function. Hence if there are any outstanding scan
7276 // requests then there is a race condition between when the adapter
7277 // is closed and when the callback is invoked. We try to resolve that
7278 // race condition here by canceling any outstanding scans before we
7279 // close the adapters.
7280 // Note that the scans may be cancelled in an asynchronous manner, so
7281 // ideally there needs to be some kind of synchronization. Rather than
7282 // introduce a new synchronization here, we will utilize the fact that
7283 // we are about to Request Full Power, and since that is synchronized,
7284 // the expectation is that by the time Request Full Power has completed,
7285 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007286 if (NULL != pAdapter)
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05307287 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId, eCSR_SCAN_ABORT_DEFAULT);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007288 else
7289 hddLog(VOS_TRACE_LEVEL_ERROR,
7290 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007291
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007292 //Stop the traffic monitor timer
7293 if ( VOS_TIMER_STATE_RUNNING ==
7294 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7295 {
7296 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7297 }
7298
7299 // Destroy the traffic monitor timer
7300 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7301 &pHddCtx->tx_rx_trafficTmr)))
7302 {
7303 hddLog(VOS_TRACE_LEVEL_ERROR,
7304 "%s: Cannot deallocate Traffic monitor timer", __func__);
7305 }
7306
Jeff Johnson295189b2012-06-20 16:38:30 -07007307 //Disable IMPS/BMPS as we do not want the device to enter any power
7308 //save mode during shutdown
7309 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7310 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7311 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7312
7313 //Ensure that device is in full power as we will touch H/W during vos_Stop
7314 init_completion(&powerContext.completion);
7315 powerContext.magic = POWER_CONTEXT_MAGIC;
7316
7317 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7318 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7319
7320 if (eHAL_STATUS_SUCCESS != halStatus)
7321 {
7322 if (eHAL_STATUS_PMC_PENDING == halStatus)
7323 {
7324 /* request was sent -- wait for the response */
7325 lrc = wait_for_completion_interruptible_timeout(
7326 &powerContext.completion,
7327 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007328 if (lrc <= 0)
7329 {
7330 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007331 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007332 }
7333 }
7334 else
7335 {
7336 hddLog(VOS_TRACE_LEVEL_ERROR,
7337 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007338 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007339 /* continue -- need to clean up as much as possible */
7340 }
7341 }
7342
Jeff Johnson72a40512013-12-19 10:14:15 -08007343 /* either we never sent a request, we sent a request and received a
7344 response or we sent a request and timed out. if we never sent a
7345 request or if we sent a request and got a response, we want to
7346 clear the magic out of paranoia. if we timed out there is a
7347 race condition such that the callback function could be
7348 executing at the same time we are. of primary concern is if the
7349 callback function had already verified the "magic" but had not
7350 yet set the completion variable when a timeout occurred. we
7351 serialize these activities by invalidating the magic while
7352 holding a shared spinlock which will cause us to block if the
7353 callback is currently executing */
7354 spin_lock(&hdd_context_lock);
7355 powerContext.magic = 0;
7356 spin_unlock(&hdd_context_lock);
7357
Yue Ma0d4891e2013-08-06 17:01:45 -07007358 hdd_debugfs_exit(pHddCtx);
7359
Jeff Johnson295189b2012-06-20 16:38:30 -07007360 // Unregister the Net Device Notifier
7361 unregister_netdevice_notifier(&hdd_netdev_notifier);
7362
Jeff Johnson295189b2012-06-20 16:38:30 -07007363 hdd_stop_all_adapters( pHddCtx );
7364
Jeff Johnson295189b2012-06-20 16:38:30 -07007365#ifdef WLAN_BTAMP_FEATURE
7366 vosStatus = WLANBAP_Stop(pVosContext);
7367 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7368 {
7369 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7370 "%s: Failed to stop BAP",__func__);
7371 }
7372#endif //WLAN_BTAMP_FEATURE
7373
7374 //Stop all the modules
7375 vosStatus = vos_stop( pVosContext );
7376 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7377 {
7378 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7379 "%s: Failed to stop VOSS",__func__);
7380 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7381 }
7382
Jeff Johnson295189b2012-06-20 16:38:30 -07007383 //Assert Deep sleep signal now to put Libra HW in lowest power state
7384 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7385 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7386
7387 //Vote off any PMIC voltage supplies
7388 vos_chipPowerDown(NULL, NULL, NULL);
7389
7390 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7391
Leo Chang59cdc7e2013-07-10 10:08:21 -07007392
Jeff Johnson295189b2012-06-20 16:38:30 -07007393 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007394 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007395
7396 //Close the scheduler before calling vos_close to make sure no thread is
7397 // scheduled after the each module close is called i.e after all the data
7398 // structures are freed.
7399 vosStatus = vos_sched_close( pVosContext );
7400 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7401 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7402 "%s: Failed to close VOSS Scheduler",__func__);
7403 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7404 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007405#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007406#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7407 /* Destroy the wake lock */
7408 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7409#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007410 /* Destroy the wake lock */
7411 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007412#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007413
Mihir Shete7a24b5f2013-12-21 12:18:31 +05307414#ifdef CONFIG_ENABLE_LINUX_REG
7415 vosStatus = vos_nv_close();
7416 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7417 {
7418 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7419 "%s: Failed to close NV", __func__);
7420 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7421 }
7422#endif
7423
Jeff Johnson295189b2012-06-20 16:38:30 -07007424 //Close VOSS
7425 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7426 vos_close(pVosContext);
7427
Jeff Johnson295189b2012-06-20 16:38:30 -07007428 //Close Watchdog
7429 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7430 vos_watchdog_close(pVosContext);
7431
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307432 //Clean up HDD Nlink Service
7433 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007434#ifdef WLAN_KD_READY_NOTIFIER
7435 nl_srv_exit(pHddCtx->ptt_pid);
7436#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307437 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007438#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307439
Jeff Johnson295189b2012-06-20 16:38:30 -07007440 /* Cancel the vote for XO Core ON.
7441 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7442 * exited at this point
7443 */
7444 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007445 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007446 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7447 {
7448 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7449 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007450 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007451 }
7452
7453 hdd_close_all_adapters( pHddCtx );
7454
7455
7456 //Free up dynamically allocated members inside HDD Adapter
7457 kfree(pHddCtx->cfg_ini);
7458 pHddCtx->cfg_ini= NULL;
7459
7460 /* free the power on lock from platform driver */
7461 if (free_riva_power_on_lock("wlan"))
7462 {
7463 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7464 __func__);
7465 }
7466
Jeff Johnson88ba7742013-02-27 14:36:02 -08007467free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007468 /* FTM mode, WIPHY did not registered
7469 If un-register here, system crash will happen */
7470 if (VOS_FTM_MODE != hdd_get_conparam())
7471 {
7472 wiphy_unregister(wiphy) ;
7473 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007474 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007475 if (hdd_is_ssr_required())
7476 {
7477 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007478 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007479 msleep(5000);
7480 }
7481 hdd_set_ssr_required (VOS_FALSE);
7482}
7483
7484
7485/**---------------------------------------------------------------------------
7486
7487 \brief hdd_update_config_from_nv() - Function to update the contents of
7488 the running configuration with parameters taken from NV storage
7489
7490 \param - pHddCtx - Pointer to the HDD global context
7491
7492 \return - VOS_STATUS_SUCCESS if successful
7493
7494 --------------------------------------------------------------------------*/
7495static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7496{
Jeff Johnson295189b2012-06-20 16:38:30 -07007497 v_BOOL_t itemIsValid = VOS_FALSE;
7498 VOS_STATUS status;
7499 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7500 v_U8_t macLoop;
7501
7502 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7503 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7504 if(status != VOS_STATUS_SUCCESS)
7505 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007506 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007507 return VOS_STATUS_E_FAILURE;
7508 }
7509
7510 if (itemIsValid == VOS_TRUE)
7511 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007512 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007513 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7514 VOS_MAX_CONCURRENCY_PERSONA);
7515 if(status != VOS_STATUS_SUCCESS)
7516 {
7517 /* Get MAC from NV fail, not update CFG info
7518 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08007519 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007520 return VOS_STATUS_E_FAILURE;
7521 }
7522
7523 /* If first MAC is not valid, treat all others are not valid
7524 * Then all MACs will be got from ini file */
7525 if(vos_is_macaddr_zero(&macFromNV[0]))
7526 {
7527 /* MAC address in NV file is not configured yet */
7528 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7529 return VOS_STATUS_E_INVAL;
7530 }
7531
7532 /* Get MAC address from NV, update CFG info */
7533 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7534 {
7535 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7536 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307537 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07007538 /* This MAC is not valid, skip it
7539 * This MAC will be got from ini file */
7540 }
7541 else
7542 {
7543 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7544 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7545 VOS_MAC_ADDR_SIZE);
7546 }
7547 }
7548 }
7549 else
7550 {
7551 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7552 return VOS_STATUS_E_FAILURE;
7553 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007554
Jeff Johnson295189b2012-06-20 16:38:30 -07007555
7556 return VOS_STATUS_SUCCESS;
7557}
7558
7559/**---------------------------------------------------------------------------
7560
7561 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7562
7563 \param - pAdapter - Pointer to the HDD
7564
7565 \return - None
7566
7567 --------------------------------------------------------------------------*/
7568VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7569{
7570 eHalStatus halStatus;
7571 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307572 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007573
Jeff Johnson295189b2012-06-20 16:38:30 -07007574
7575 // Send ready indication to the HDD. This will kick off the MAC
7576 // into a 'running' state and should kick off an initial scan.
7577 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7578 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7579 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307580 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007581 "code %08d [x%08x]",__func__, halStatus, halStatus );
7582 return VOS_STATUS_E_FAILURE;
7583 }
7584
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307585 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007586 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7587 // And RIVA will crash
7588 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7589 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307590 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7591 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7592
7593
Jeff Johnson295189b2012-06-20 16:38:30 -07007594 return VOS_STATUS_SUCCESS;
7595}
7596
Jeff Johnson295189b2012-06-20 16:38:30 -07007597/* wake lock APIs for HDD */
7598void hdd_prevent_suspend(void)
7599{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007600#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007601 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007602#else
7603 wcnss_prevent_suspend();
7604#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007605}
7606
7607void hdd_allow_suspend(void)
7608{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007609#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007610 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007611#else
7612 wcnss_allow_suspend();
7613#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007614}
7615
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05307616void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007617{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007618#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007619 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007620#else
7621 /* Do nothing as there is no API in wcnss for timeout*/
7622#endif
7623}
7624
Jeff Johnson295189b2012-06-20 16:38:30 -07007625/**---------------------------------------------------------------------------
7626
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007627 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7628 information between Host and Riva
7629
7630 This function gets reported version of FW
7631 It also finds the version of Riva headers used to compile the host
7632 It compares the above two and prints a warning if they are different
7633 It gets the SW and HW version string
7634 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7635 indicating the features they support through a bitmap
7636
7637 \param - pHddCtx - Pointer to HDD context
7638
7639 \return - void
7640
7641 --------------------------------------------------------------------------*/
7642
7643void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7644{
7645
7646 tSirVersionType versionCompiled;
7647 tSirVersionType versionReported;
7648 tSirVersionString versionString;
7649 tANI_U8 fwFeatCapsMsgSupported = 0;
7650 VOS_STATUS vstatus;
7651
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007652 memset(&versionCompiled, 0, sizeof(versionCompiled));
7653 memset(&versionReported, 0, sizeof(versionReported));
7654
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007655 /* retrieve and display WCNSS version information */
7656 do {
7657
7658 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7659 &versionCompiled);
7660 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7661 {
7662 hddLog(VOS_TRACE_LEVEL_FATAL,
7663 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007664 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007665 break;
7666 }
7667
7668 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7669 &versionReported);
7670 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7671 {
7672 hddLog(VOS_TRACE_LEVEL_FATAL,
7673 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007674 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007675 break;
7676 }
7677
7678 if ((versionCompiled.major != versionReported.major) ||
7679 (versionCompiled.minor != versionReported.minor) ||
7680 (versionCompiled.version != versionReported.version) ||
7681 (versionCompiled.revision != versionReported.revision))
7682 {
7683 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7684 "Host expected %u.%u.%u.%u\n",
7685 WLAN_MODULE_NAME,
7686 (int)versionReported.major,
7687 (int)versionReported.minor,
7688 (int)versionReported.version,
7689 (int)versionReported.revision,
7690 (int)versionCompiled.major,
7691 (int)versionCompiled.minor,
7692 (int)versionCompiled.version,
7693 (int)versionCompiled.revision);
7694 }
7695 else
7696 {
7697 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7698 WLAN_MODULE_NAME,
7699 (int)versionReported.major,
7700 (int)versionReported.minor,
7701 (int)versionReported.version,
7702 (int)versionReported.revision);
7703 }
7704
7705 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7706 versionString,
7707 sizeof(versionString));
7708 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7709 {
7710 hddLog(VOS_TRACE_LEVEL_FATAL,
7711 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007712 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007713 break;
7714 }
7715
7716 pr_info("%s: WCNSS software version %s\n",
7717 WLAN_MODULE_NAME, versionString);
7718
7719 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7720 versionString,
7721 sizeof(versionString));
7722 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7723 {
7724 hddLog(VOS_TRACE_LEVEL_FATAL,
7725 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007726 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007727 break;
7728 }
7729
7730 pr_info("%s: WCNSS hardware version %s\n",
7731 WLAN_MODULE_NAME, versionString);
7732
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007733 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7734 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007735 send the message only if it the riva is 1.1
7736 minor numbers for different riva branches:
7737 0 -> (1.0)Mainline Build
7738 1 -> (1.1)Mainline Build
7739 2->(1.04) Stability Build
7740 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007741 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007742 ((versionReported.minor>=1) && (versionReported.version>=1)))
7743 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7744 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007745
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007746 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007747 {
7748#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7749 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7750 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7751#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007752 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7753 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7754 {
7755 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7756 }
7757
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007758 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007759 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007760
7761 } while (0);
7762
7763}
7764
7765/**---------------------------------------------------------------------------
7766
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307767 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7768
7769 \param - pHddCtx - Pointer to the hdd context
7770
7771 \return - true if hardware supports 5GHz
7772
7773 --------------------------------------------------------------------------*/
7774static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7775{
7776 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7777 * then hardware support 5Ghz.
7778 */
7779 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7780 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05307781 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307782 return true;
7783 }
7784 else
7785 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05307786 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307787 __func__);
7788 return false;
7789 }
7790}
7791
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307792/**---------------------------------------------------------------------------
7793
7794 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
7795 generate function
7796
7797 This is generate the random mac address for WLAN interface
7798
7799 \param - pHddCtx - Pointer to HDD context
7800 idx - Start interface index to get auto
7801 generated mac addr.
7802 mac_addr - Mac address
7803
7804 \return - 0 for success, < 0 for failure
7805
7806 --------------------------------------------------------------------------*/
7807
7808static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
7809 int idx, v_MACADDR_t mac_addr)
7810{
7811 int i;
7812 unsigned int serialno;
7813 serialno = wcnss_get_serial_number();
7814
7815 if (0 != serialno)
7816 {
7817 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7818 bytes of the serial number that can be used to generate
7819 the other 3 bytes of the MAC address. Mask off all but
7820 the lower 3 bytes (this will also make sure we don't
7821 overflow in the next step) */
7822 serialno &= 0x00FFFFFF;
7823
7824 /* we need a unique address for each session */
7825 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7826
7827 /* autogen other Mac addresses */
7828 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7829 {
7830 /* start with the entire default address */
7831 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
7832 /* then replace the lower 3 bytes */
7833 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7834 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7835 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7836
7837 serialno++;
7838 hddLog(VOS_TRACE_LEVEL_ERROR,
7839 "%s: Derived Mac Addr: "
7840 MAC_ADDRESS_STR, __func__,
7841 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
7842 }
7843
7844 }
7845 else
7846 {
7847 hddLog(LOGE, FL("Failed to Get Serial NO"));
7848 return -1;
7849 }
7850 return 0;
7851}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307852
7853/**---------------------------------------------------------------------------
7854
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05307855 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
7856 completed to flush out the scan results
7857
7858 11d scan is done during driver load and is a passive scan on all
7859 channels supported by the device, 11d scans may find some APs on
7860 frequencies which are forbidden to be used in the regulatory domain
7861 the device is operating in. If these APs are notified to the supplicant
7862 it may try to connect to these APs, thus flush out all the scan results
7863 which are present in SME after 11d scan is done.
7864
7865 \return - eHalStatus
7866
7867 --------------------------------------------------------------------------*/
7868static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
7869 tANI_U32 scanId, eCsrScanStatus status)
7870{
7871 ENTER();
7872
7873 sme_ScanFlushResult(halHandle, 0);
7874
7875 EXIT();
7876
7877 return eHAL_STATUS_SUCCESS;
7878}
7879
7880/**---------------------------------------------------------------------------
7881
Jeff Johnson295189b2012-06-20 16:38:30 -07007882 \brief hdd_wlan_startup() - HDD init function
7883
7884 This is the driver startup code executed once a WLAN device has been detected
7885
7886 \param - dev - Pointer to the underlying device
7887
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007888 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007889
7890 --------------------------------------------------------------------------*/
7891
7892int hdd_wlan_startup(struct device *dev )
7893{
7894 VOS_STATUS status;
7895 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007896 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007897 hdd_context_t *pHddCtx = NULL;
7898 v_CONTEXT_t pVosContext= NULL;
7899#ifdef WLAN_BTAMP_FEATURE
7900 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7901 WLANBAP_ConfigType btAmpConfig;
7902 hdd_config_t *pConfig;
7903#endif
7904 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007905 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307906 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07007907
7908 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007909 /*
7910 * cfg80211: wiphy allocation
7911 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307912 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007913
7914 if(wiphy == NULL)
7915 {
7916 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007917 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007918 }
7919
7920 pHddCtx = wiphy_priv(wiphy);
7921
Jeff Johnson295189b2012-06-20 16:38:30 -07007922 //Initialize the adapter context to zeros.
7923 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7924
Jeff Johnson295189b2012-06-20 16:38:30 -07007925 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007926 hdd_prevent_suspend();
7927 pHddCtx->isLoadUnloadInProgress = TRUE;
7928
7929 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7930
7931 /*Get vos context here bcoz vos_open requires it*/
7932 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7933
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007934 if(pVosContext == NULL)
7935 {
7936 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7937 goto err_free_hdd_context;
7938 }
7939
Jeff Johnson295189b2012-06-20 16:38:30 -07007940 //Save the Global VOSS context in adapter context for future.
7941 pHddCtx->pvosContext = pVosContext;
7942
7943 //Save the adapter context in global context for future.
7944 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7945
Jeff Johnson295189b2012-06-20 16:38:30 -07007946 pHddCtx->parent_dev = dev;
7947
7948 init_completion(&pHddCtx->full_pwr_comp_var);
7949 init_completion(&pHddCtx->standby_comp_var);
7950 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007951 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007952 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307953 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007954
7955#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007956 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007957#else
7958 init_completion(&pHddCtx->driver_crda_req);
7959#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007960
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307961 spin_lock_init(&pHddCtx->schedScan_lock);
7962
Jeff Johnson295189b2012-06-20 16:38:30 -07007963 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7964
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307965#ifdef FEATURE_WLAN_TDLS
7966 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7967 * invoked by other instances also) to protect the concurrent
7968 * access for the Adapters by TDLS module.
7969 */
7970 mutex_init(&pHddCtx->tdls_lock);
7971#endif
7972
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307973 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007974 // Load all config first as TL config is needed during vos_open
7975 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7976 if(pHddCtx->cfg_ini == NULL)
7977 {
7978 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7979 goto err_free_hdd_context;
7980 }
7981
7982 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7983
7984 // Read and parse the qcom_cfg.ini file
7985 status = hdd_parse_config_ini( pHddCtx );
7986 if ( VOS_STATUS_SUCCESS != status )
7987 {
7988 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7989 __func__, WLAN_INI_FILE);
7990 goto err_config;
7991 }
Arif Hussaind5218912013-12-05 01:10:55 -08007992#ifdef MEMORY_DEBUG
7993 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
7994 vos_mem_init();
7995
7996 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
7997 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
7998#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007999
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05308000 /* INI has been read, initialise the configuredMcastBcastFilter with
8001 * INI value as this will serve as the default value
8002 */
8003 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
8004 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
8005 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308006
8007 if (false == hdd_is_5g_supported(pHddCtx))
8008 {
8009 //5Ghz is not supported.
8010 if (1 != pHddCtx->cfg_ini->nBandCapability)
8011 {
8012 hddLog(VOS_TRACE_LEVEL_INFO,
8013 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
8014 pHddCtx->cfg_ini->nBandCapability = 1;
8015 }
8016 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308017
8018 /* If SNR Monitoring is enabled, FW has to parse all beacons
8019 * for calcaluting and storing the average SNR, so set Nth beacon
8020 * filter to 1 to enable FW to parse all the beaocons
8021 */
8022 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
8023 {
8024 /* The log level is deliberately set to WARN as overriding
8025 * nthBeaconFilter to 1 will increase power cosumption and this
8026 * might just prove helpful to detect the power issue.
8027 */
8028 hddLog(VOS_TRACE_LEVEL_WARN,
8029 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
8030 pHddCtx->cfg_ini->nthBeaconFilter = 1;
8031 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008032 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308033 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07008034 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008035 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008036 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008037 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
8038 {
8039 hddLog(VOS_TRACE_LEVEL_FATAL,
8040 "%s: wlan_hdd_cfg80211_init return failure", __func__);
8041 goto err_config;
8042 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008043 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008044
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008045 // Update VOS trace levels based upon the cfg.ini
8046 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
8047 pHddCtx->cfg_ini->vosTraceEnableBAP);
8048 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
8049 pHddCtx->cfg_ini->vosTraceEnableTL);
8050 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
8051 pHddCtx->cfg_ini->vosTraceEnableWDI);
8052 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
8053 pHddCtx->cfg_ini->vosTraceEnableHDD);
8054 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
8055 pHddCtx->cfg_ini->vosTraceEnableSME);
8056 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
8057 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05308058 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
8059 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008060 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
8061 pHddCtx->cfg_ini->vosTraceEnableWDA);
8062 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
8063 pHddCtx->cfg_ini->vosTraceEnableSYS);
8064 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
8065 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008066 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
8067 pHddCtx->cfg_ini->vosTraceEnableSAP);
8068 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
8069 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008070
Jeff Johnson295189b2012-06-20 16:38:30 -07008071 // Update WDI trace levels based upon the cfg.ini
8072 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
8073 pHddCtx->cfg_ini->wdiTraceEnableDAL);
8074 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
8075 pHddCtx->cfg_ini->wdiTraceEnableCTL);
8076 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
8077 pHddCtx->cfg_ini->wdiTraceEnableDAT);
8078 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
8079 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008080
Jeff Johnson88ba7742013-02-27 14:36:02 -08008081 if (VOS_FTM_MODE == hdd_get_conparam())
8082 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008083 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
8084 {
8085 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
8086 goto err_free_hdd_context;
8087 }
8088 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
8089 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08008090 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008091
Jeff Johnson88ba7742013-02-27 14:36:02 -08008092 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07008093 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8094 {
8095 status = vos_watchdog_open(pVosContext,
8096 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
8097
8098 if(!VOS_IS_STATUS_SUCCESS( status ))
8099 {
8100 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308101 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008102 }
8103 }
8104
8105 pHddCtx->isLogpInProgress = FALSE;
8106 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8107
Jeff Johnson295189b2012-06-20 16:38:30 -07008108 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
8109 if(!VOS_IS_STATUS_SUCCESS(status))
8110 {
8111 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008112 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008113 }
8114
Amar Singhala49cbc52013-10-08 18:37:44 -07008115#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008116 /* initialize the NV module. This is required so that
8117 we can initialize the channel information in wiphy
8118 from the NV.bin data. The channel information in
8119 wiphy needs to be initialized before wiphy registration */
8120
8121 status = vos_nv_open();
8122 if (!VOS_IS_STATUS_SUCCESS(status))
8123 {
8124 /* NV module cannot be initialized */
8125 hddLog( VOS_TRACE_LEVEL_FATAL,
8126 "%s: vos_nv_open failed", __func__);
8127 goto err_clkvote;
8128 }
8129
8130 status = vos_init_wiphy_from_nv_bin();
8131 if (!VOS_IS_STATUS_SUCCESS(status))
8132 {
8133 /* NV module cannot be initialized */
8134 hddLog( VOS_TRACE_LEVEL_FATAL,
8135 "%s: vos_init_wiphy failed", __func__);
8136 goto err_vos_nv_close;
8137 }
8138
Amar Singhala49cbc52013-10-08 18:37:44 -07008139#endif
8140
Jeff Johnson295189b2012-06-20 16:38:30 -07008141 status = vos_open( &pVosContext, 0);
8142 if ( !VOS_IS_STATUS_SUCCESS( status ))
8143 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008144 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308145 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07008146 }
8147
Jeff Johnson295189b2012-06-20 16:38:30 -07008148 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8149
8150 if ( NULL == pHddCtx->hHal )
8151 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008152 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008153 goto err_vosclose;
8154 }
8155
Mihir Shetee1093ba2014-01-21 20:13:32 +05308156#ifdef CONFIG_ENABLE_LINUX_REG
8157 /* registration of wiphy dev with cfg80211 */
8158 if (0 > wlan_hdd_cfg80211_register(wiphy))
8159 {
8160 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8161 goto err_vosclose;
8162 }
8163
8164 status = wlan_hdd_init_channels(pHddCtx);
8165 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8166 {
8167 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
8168 __func__);
8169 goto err_wiphy_unregister;
8170 }
8171#endif
8172
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008173 status = vos_preStart( pHddCtx->pvosContext );
8174 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8175 {
8176 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308177 goto err_wiphy_unregister;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008178 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008179
Arif Hussaineaf68602013-12-30 23:10:44 -08008180 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8181 {
8182 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8183 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8184 __func__, enable_dfs_chan_scan);
8185 }
8186 if (0 == enable_11d || 1 == enable_11d)
8187 {
8188 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8189 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8190 __func__, enable_11d);
8191 }
8192
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008193 /* Note that the vos_preStart() sequence triggers the cfg download.
8194 The cfg download must occur before we update the SME config
8195 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008196 status = hdd_set_sme_config( pHddCtx );
8197
8198 if ( VOS_STATUS_SUCCESS != status )
8199 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008200 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308201 goto err_wiphy_unregister;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008202 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008203
8204 //Initialize the WMM module
8205 status = hdd_wmm_init(pHddCtx);
8206 if (!VOS_IS_STATUS_SUCCESS(status))
8207 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008208 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308209 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008210 }
8211
Jeff Johnson295189b2012-06-20 16:38:30 -07008212 /* In the integrated architecture we update the configuration from
8213 the INI file and from NV before vOSS has been started so that
8214 the final contents are available to send down to the cCPU */
8215
8216 // Apply the cfg.ini to cfg.dat
8217 if (FALSE == hdd_update_config_dat(pHddCtx))
8218 {
8219 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mihir Shetee1093ba2014-01-21 20:13:32 +05308220 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008221 }
8222
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308223 // Get mac addr from platform driver
8224 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8225
8226 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008227 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308228 /* Store the mac addr for first interface */
8229 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8230
8231 hddLog(VOS_TRACE_LEVEL_ERROR,
8232 "%s: WLAN Mac Addr: "
8233 MAC_ADDRESS_STR, __func__,
8234 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8235
8236 /* Here, passing Arg2 as 1 because we do not want to change the
8237 last 3 bytes (means non OUI bytes) of first interface mac
8238 addr.
8239 */
8240 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8241 {
8242 hddLog(VOS_TRACE_LEVEL_ERROR,
8243 "%s: Failed to generate wlan interface mac addr "
8244 "using MAC from ini file ", __func__);
8245 }
8246 }
8247 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8248 {
8249 // Apply the NV to cfg.dat
8250 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008251#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8252 /* There was not a valid set of MAC Addresses in NV. See if the
8253 default addresses were modified by the cfg.ini settings. If so,
8254 we'll use them, but if not, we'll autogenerate a set of MAC
8255 addresses based upon the device serial number */
8256
8257 static const v_MACADDR_t default_address =
8258 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008259
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308260 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8261 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008262 {
8263 /* cfg.ini has the default address, invoke autogen logic */
8264
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308265 /* Here, passing Arg2 as 0 because we want to change the
8266 last 3 bytes (means non OUI bytes) of all the interfaces
8267 mac addr.
8268 */
8269 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8270 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008271 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308272 hddLog(VOS_TRACE_LEVEL_ERROR,
8273 "%s: Failed to generate wlan interface mac addr "
8274 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8275 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008276 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008277 }
8278 else
8279#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8280 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008281 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008282 "%s: Invalid MAC address in NV, using MAC from ini file "
8283 MAC_ADDRESS_STR, __func__,
8284 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8285 }
8286 }
8287 {
8288 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308289
8290 /* Set the MAC Address Currently this is used by HAL to
8291 * add self sta. Remove this once self sta is added as
8292 * part of session open.
8293 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008294 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8295 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8296 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308297
Jeff Johnson295189b2012-06-20 16:38:30 -07008298 if (!HAL_STATUS_SUCCESS( halStatus ))
8299 {
8300 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8301 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mihir Shetee1093ba2014-01-21 20:13:32 +05308302 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008303 }
8304 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008305
8306 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8307 Note: Firmware image will be read and downloaded inside vos_start API */
8308 status = vos_start( pHddCtx->pvosContext );
8309 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8310 {
8311 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308312 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008313 }
8314
Leo Chang6cec3e22014-01-21 15:33:49 -08008315#ifdef FEATURE_WLAN_CH_AVOID
8316 /* Plug in avoid channel notification callback
8317 * This should happen before ADD_SELF_STA
8318 * FW will send first IND with ADD_SELF_STA REQ from host */
8319 sme_AddChAvoidCallback(pHddCtx->hHal,
8320 hdd_hostapd_ch_avoid_cb);
8321#endif /* FEATURE_WLAN_CH_AVOID */
8322
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008323 /* Exchange capability info between Host and FW and also get versioning info from FW */
8324 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008325
8326 status = hdd_post_voss_start_config( pHddCtx );
8327 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8328 {
8329 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
8330 __func__);
8331 goto err_vosstop;
8332 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008333
8334#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308335 wlan_hdd_cfg80211_update_reg_info( wiphy );
8336
8337 /* registration of wiphy dev with cfg80211 */
8338 if (0 > wlan_hdd_cfg80211_register(wiphy))
8339 {
8340 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8341 goto err_vosstop;
8342 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008343#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008344
Jeff Johnson295189b2012-06-20 16:38:30 -07008345 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8346 {
8347 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
8348 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8349 }
8350 else
8351 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008352 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
8353 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8354 if (pAdapter != NULL)
8355 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308356 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07008357 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308358 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
8359 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
8360 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07008361
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308362 /* Generate the P2P Device Address. This consists of the device's
8363 * primary MAC address with the locally administered bit set.
8364 */
8365 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07008366 }
8367 else
8368 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308369 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
8370 if (p2p_dev_addr != NULL)
8371 {
8372 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
8373 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
8374 }
8375 else
8376 {
8377 hddLog(VOS_TRACE_LEVEL_FATAL,
8378 "%s: Failed to allocate mac_address for p2p_device",
8379 __func__);
8380 goto err_close_adapter;
8381 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008382 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008383
8384 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
8385 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
8386 if ( NULL == pP2pAdapter )
8387 {
8388 hddLog(VOS_TRACE_LEVEL_FATAL,
8389 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008390 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008391 goto err_close_adapter;
8392 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008393 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008394 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008395
8396 if( pAdapter == NULL )
8397 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008398 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
8399 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008400 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008401
Arif Hussain66559122013-11-21 10:11:40 -08008402 if (country_code)
8403 {
8404 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08008405 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08008406 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8407#ifndef CONFIG_ENABLE_LINUX_REG
8408 hdd_checkandupdate_phymode(pAdapter, country_code);
8409#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08008410 ret = sme_ChangeCountryCode(pHddCtx->hHal,
8411 (void *)(tSmeChangeCountryCallback)
8412 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08008413 country_code,
8414 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308415 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008416 if (eHAL_STATUS_SUCCESS == ret)
8417 {
Arif Hussaincb607082013-12-20 11:57:42 -08008418 ret = wait_for_completion_interruptible_timeout(
8419 &pAdapter->change_country_code,
8420 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
8421
8422 if (0 >= ret)
8423 {
8424 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8425 "%s: SME while setting country code timed out", __func__);
8426 }
Arif Hussain66559122013-11-21 10:11:40 -08008427 }
8428 else
8429 {
Arif Hussaincb607082013-12-20 11:57:42 -08008430 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8431 "%s: SME Change Country code from module param fail ret=%d",
8432 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08008433 }
8434 }
8435
Jeff Johnson295189b2012-06-20 16:38:30 -07008436#ifdef WLAN_BTAMP_FEATURE
8437 vStatus = WLANBAP_Open(pVosContext);
8438 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8439 {
8440 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8441 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008442 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008443 }
8444
8445 vStatus = BSL_Init(pVosContext);
8446 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8447 {
8448 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8449 "%s: Failed to Init BSL",__func__);
8450 goto err_bap_close;
8451 }
8452 vStatus = WLANBAP_Start(pVosContext);
8453 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8454 {
8455 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8456 "%s: Failed to start TL",__func__);
8457 goto err_bap_close;
8458 }
8459
8460 pConfig = pHddCtx->cfg_ini;
8461 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8462 status = WLANBAP_SetConfig(&btAmpConfig);
8463
8464#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008465
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008466#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8467 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8468 {
8469 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8470 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8471 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8472 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8473 }
8474#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008475#ifdef FEATURE_WLAN_SCAN_PNO
8476 /*SME must send channel update configuration to RIVA*/
8477 sme_UpdateChannelConfig(pHddCtx->hHal);
8478#endif
8479
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308480 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
8481
Jeff Johnson295189b2012-06-20 16:38:30 -07008482 /* Register with platform driver as client for Suspend/Resume */
8483 status = hddRegisterPmOps(pHddCtx);
8484 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8485 {
8486 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8487#ifdef WLAN_BTAMP_FEATURE
8488 goto err_bap_stop;
8489#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008490 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008491#endif //WLAN_BTAMP_FEATURE
8492 }
8493
Yue Ma0d4891e2013-08-06 17:01:45 -07008494 /* Open debugfs interface */
8495 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8496 {
8497 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8498 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008499 }
8500
Jeff Johnson295189b2012-06-20 16:38:30 -07008501 /* Register TM level change handler function to the platform */
8502 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8503 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8504 {
8505 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8506 goto err_unregister_pmops;
8507 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008508
8509 /* register for riva power on lock to platform driver */
8510 if (req_riva_power_on_lock("wlan"))
8511 {
8512 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8513 __func__);
8514 goto err_unregister_pmops;
8515 }
8516
Jeff Johnson295189b2012-06-20 16:38:30 -07008517 // register net device notifier for device change notification
8518 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8519
8520 if(ret < 0)
8521 {
8522 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8523 goto err_free_power_on_lock;
8524 }
8525
8526 //Initialize the nlink service
8527 if(nl_srv_init() != 0)
8528 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308529 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008530 goto err_reg_netdev;
8531 }
8532
Leo Chang4ce1cc52013-10-21 18:27:15 -07008533#ifdef WLAN_KD_READY_NOTIFIER
8534 pHddCtx->kd_nl_init = 1;
8535#endif /* WLAN_KD_READY_NOTIFIER */
8536
Jeff Johnson295189b2012-06-20 16:38:30 -07008537 //Initialize the BTC service
8538 if(btc_activate_service(pHddCtx) != 0)
8539 {
8540 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8541 goto err_nl_srv;
8542 }
8543
8544#ifdef PTT_SOCK_SVC_ENABLE
8545 //Initialize the PTT service
8546 if(ptt_sock_activate_svc(pHddCtx) != 0)
8547 {
8548 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8549 goto err_nl_srv;
8550 }
8551#endif
8552
Jeff Johnson295189b2012-06-20 16:38:30 -07008553 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008554 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008555 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008556 /* Action frame registered in one adapter which will
8557 * applicable to all interfaces
8558 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008559 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008560 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008561
8562 mutex_init(&pHddCtx->sap_lock);
8563
8564 pHddCtx->isLoadUnloadInProgress = FALSE;
8565
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008566#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008567#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8568 /* Initialize the wake lcok */
8569 wake_lock_init(&pHddCtx->rx_wake_lock,
8570 WAKE_LOCK_SUSPEND,
8571 "qcom_rx_wakelock");
8572#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008573 /* Initialize the wake lcok */
8574 wake_lock_init(&pHddCtx->sap_wake_lock,
8575 WAKE_LOCK_SUSPEND,
8576 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008577#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008578
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008579 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8580 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008581
8582 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8583 hdd_allow_suspend();
Abhishek Singha306a442013-11-07 18:39:01 +05308584#ifndef CONFIG_ENABLE_LINUX_REG
8585 /*updating wiphy so that regulatory user hints can be processed*/
8586 if (wiphy)
8587 {
8588 regulatory_hint(wiphy, "00");
8589 }
8590#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008591 // Initialize the restart logic
8592 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308593
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008594 //Register the traffic monitor timer now
8595 if ( pHddCtx->cfg_ini->dynSplitscan)
8596 {
8597 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8598 VOS_TIMER_TYPE_SW,
8599 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8600 (void *)pHddCtx);
8601 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008602 goto success;
8603
8604err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008605#ifdef WLAN_KD_READY_NOTIFIER
8606 nl_srv_exit(pHddCtx->ptt_pid);
8607#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008608 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008609#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008610err_reg_netdev:
8611 unregister_netdevice_notifier(&hdd_netdev_notifier);
8612
8613err_free_power_on_lock:
8614 free_riva_power_on_lock("wlan");
8615
8616err_unregister_pmops:
8617 hddDevTmUnregisterNotifyCallback(pHddCtx);
8618 hddDeregisterPmOps(pHddCtx);
8619
Yue Ma0d4891e2013-08-06 17:01:45 -07008620 hdd_debugfs_exit(pHddCtx);
8621
Jeff Johnson295189b2012-06-20 16:38:30 -07008622#ifdef WLAN_BTAMP_FEATURE
8623err_bap_stop:
8624 WLANBAP_Stop(pVosContext);
8625#endif
8626
8627#ifdef WLAN_BTAMP_FEATURE
8628err_bap_close:
8629 WLANBAP_Close(pVosContext);
8630#endif
8631
Jeff Johnson295189b2012-06-20 16:38:30 -07008632err_close_adapter:
8633 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008634
8635#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308636 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008637#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008638
8639err_vosstop:
8640 vos_stop(pVosContext);
8641
Mihir Shetee1093ba2014-01-21 20:13:32 +05308642err_wiphy_unregister:
8643#ifdef CONFIG_ENABLE_LINUX_REG
8644 wiphy_unregister(wiphy);
8645#endif
8646
Amar Singhala49cbc52013-10-08 18:37:44 -07008647err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008648 status = vos_sched_close( pVosContext );
8649 if (!VOS_IS_STATUS_SUCCESS(status)) {
8650 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8651 "%s: Failed to close VOSS Scheduler", __func__);
8652 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8653 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008654 vos_close(pVosContext );
8655
Amar Singhala49cbc52013-10-08 18:37:44 -07008656#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008657err_vos_nv_close:
8658
8659 vos_nv_close();
8660
Jeff Johnson295189b2012-06-20 16:38:30 -07008661err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008662#endif
8663
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008664 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008665
8666err_wdclose:
8667 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8668 vos_watchdog_close(pVosContext);
8669
Jeff Johnson295189b2012-06-20 16:38:30 -07008670err_config:
8671 kfree(pHddCtx->cfg_ini);
8672 pHddCtx->cfg_ini= NULL;
8673
8674err_free_hdd_context:
8675 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008676 wiphy_free(wiphy) ;
8677 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008678 VOS_BUG(1);
8679
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008680 if (hdd_is_ssr_required())
8681 {
8682 /* WDI timeout had happened during load, so SSR is needed here */
8683 subsystem_restart("wcnss");
8684 msleep(5000);
8685 }
8686 hdd_set_ssr_required (VOS_FALSE);
8687
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008688 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008689
8690success:
8691 EXIT();
8692 return 0;
8693}
8694
8695/**---------------------------------------------------------------------------
8696
Jeff Johnson32d95a32012-09-10 13:15:23 -07008697 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008698
Jeff Johnson32d95a32012-09-10 13:15:23 -07008699 This is the driver entry point - called in different timeline depending
8700 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008701
8702 \param - None
8703
8704 \return - 0 for success, non zero for failure
8705
8706 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008707static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008708{
8709 VOS_STATUS status;
8710 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008711 struct device *dev = NULL;
8712 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008713#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8714 int max_retries = 0;
8715#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008716
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308717#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8718 vos_wconn_trace_init();
8719#endif
8720
Jeff Johnson295189b2012-06-20 16:38:30 -07008721 ENTER();
8722
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008723#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008724 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008725#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008726
8727 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8728 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8729
8730 //Power Up Libra WLAN card first if not already powered up
8731 status = vos_chipPowerUp(NULL,NULL,NULL);
8732 if (!VOS_IS_STATUS_SUCCESS(status))
8733 {
8734 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8735 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308736#ifdef WLAN_OPEN_SOURCE
8737 wake_lock_destroy(&wlan_wake_lock);
8738#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008739 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008740 }
8741
Jeff Johnson295189b2012-06-20 16:38:30 -07008742#ifdef ANI_BUS_TYPE_PCI
8743
8744 dev = wcnss_wlan_get_device();
8745
8746#endif // ANI_BUS_TYPE_PCI
8747
8748#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008749
8750#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8751 /* wait until WCNSS driver downloads NV */
8752 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8753 msleep(1000);
8754 }
8755 if (max_retries >= 5) {
8756 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308757#ifdef WLAN_OPEN_SOURCE
8758 wake_lock_destroy(&wlan_wake_lock);
8759#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008760 return -ENODEV;
8761 }
8762#endif
8763
Jeff Johnson295189b2012-06-20 16:38:30 -07008764 dev = wcnss_wlan_get_device();
8765#endif // ANI_BUS_TYPE_PLATFORM
8766
8767
8768 do {
8769 if (NULL == dev) {
8770 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8771 ret_status = -1;
8772 break;
8773 }
8774
Jeff Johnson295189b2012-06-20 16:38:30 -07008775#ifdef TIMER_MANAGER
8776 vos_timer_manager_init();
8777#endif
8778
8779 /* Preopen VOSS so that it is ready to start at least SAL */
8780 status = vos_preOpen(&pVosContext);
8781
8782 if (!VOS_IS_STATUS_SUCCESS(status))
8783 {
8784 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8785 ret_status = -1;
8786 break;
8787 }
8788
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008789#ifndef MODULE
8790 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8791 */
8792 hdd_set_conparam((v_UINT_t)con_mode);
8793#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008794
8795 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008796 if (hdd_wlan_startup(dev))
8797 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008798 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008799 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008800 vos_preClose( &pVosContext );
8801 ret_status = -1;
8802 break;
8803 }
8804
8805 /* Cancel the vote for XO Core ON
8806 * This is done here for safety purposes in case we re-initialize without turning
8807 * it OFF in any error scenario.
8808 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008809 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008810 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008811 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008812 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8813 {
8814 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08008815 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07008816 }
8817 } while (0);
8818
8819 if (0 != ret_status)
8820 {
8821 //Assert Deep sleep signal now to put Libra HW in lowest power state
8822 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8823 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8824
8825 //Vote off any PMIC voltage supplies
8826 vos_chipPowerDown(NULL, NULL, NULL);
8827#ifdef TIMER_MANAGER
8828 vos_timer_exit();
8829#endif
8830#ifdef MEMORY_DEBUG
8831 vos_mem_exit();
8832#endif
8833
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008834#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008835 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008836#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008837 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8838 }
8839 else
8840 {
8841 //Send WLAN UP indication to Nlink Service
8842 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8843
8844 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008845 }
8846
8847 EXIT();
8848
8849 return ret_status;
8850}
8851
Jeff Johnson32d95a32012-09-10 13:15:23 -07008852/**---------------------------------------------------------------------------
8853
8854 \brief hdd_module_init() - Init Function
8855
8856 This is the driver entry point (invoked when module is loaded using insmod)
8857
8858 \param - None
8859
8860 \return - 0 for success, non zero for failure
8861
8862 --------------------------------------------------------------------------*/
8863#ifdef MODULE
8864static int __init hdd_module_init ( void)
8865{
8866 return hdd_driver_init();
8867}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008868#else /* #ifdef MODULE */
8869static int __init hdd_module_init ( void)
8870{
8871 /* Driver initialization is delayed to fwpath_changed_handler */
8872 return 0;
8873}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008874#endif /* #ifdef MODULE */
8875
Jeff Johnson295189b2012-06-20 16:38:30 -07008876
8877/**---------------------------------------------------------------------------
8878
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008879 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008880
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008881 This is the driver exit point (invoked when module is unloaded using rmmod
8882 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008883
8884 \param - None
8885
8886 \return - None
8887
8888 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008889static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008890{
8891 hdd_context_t *pHddCtx = NULL;
8892 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008893 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008894
8895 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8896
8897 //Get the global vos context
8898 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8899
8900 if(!pVosContext)
8901 {
8902 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8903 goto done;
8904 }
8905
8906 //Get the HDD context.
8907 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8908
8909 if(!pHddCtx)
8910 {
8911 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8912 }
8913 else
8914 {
Sameer Thalappil14067972014-01-23 14:54:54 -08008915 while (pHddCtx->isLogpInProgress) {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008916 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8917 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008918 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008919
8920 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8921 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8922 "%s:SSR never completed, fatal error", __func__);
8923 VOS_BUG(0);
8924 }
8925 }
8926
Jeff Johnson295189b2012-06-20 16:38:30 -07008927
8928 pHddCtx->isLoadUnloadInProgress = TRUE;
8929 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8930
8931 //Do all the cleanup before deregistering the driver
8932 hdd_wlan_exit(pHddCtx);
8933 }
8934
Jeff Johnson295189b2012-06-20 16:38:30 -07008935 vos_preClose( &pVosContext );
8936
8937#ifdef TIMER_MANAGER
8938 vos_timer_exit();
8939#endif
8940#ifdef MEMORY_DEBUG
8941 vos_mem_exit();
8942#endif
8943
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308944#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8945 vos_wconn_trace_exit();
8946#endif
8947
Jeff Johnson295189b2012-06-20 16:38:30 -07008948done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008949#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008950 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008951#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008952 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8953}
8954
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008955/**---------------------------------------------------------------------------
8956
8957 \brief hdd_module_exit() - Exit function
8958
8959 This is the driver exit point (invoked when module is unloaded using rmmod)
8960
8961 \param - None
8962
8963 \return - None
8964
8965 --------------------------------------------------------------------------*/
8966static void __exit hdd_module_exit(void)
8967{
8968 hdd_driver_exit();
8969}
8970
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008971#ifdef MODULE
8972static int fwpath_changed_handler(const char *kmessage,
8973 struct kernel_param *kp)
8974{
Jeff Johnson76052702013-04-16 13:55:05 -07008975 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008976}
8977
8978static int con_mode_handler(const char *kmessage,
8979 struct kernel_param *kp)
8980{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008981 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008982}
8983#else /* #ifdef MODULE */
8984/**---------------------------------------------------------------------------
8985
Jeff Johnson76052702013-04-16 13:55:05 -07008986 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008987
Jeff Johnson76052702013-04-16 13:55:05 -07008988 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008989 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008990 - invoked when module parameter fwpath is modified from userspace to signal
8991 initializing the WLAN driver or when con_mode is modified from userspace
8992 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008993
8994 \return - 0 for success, non zero for failure
8995
8996 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008997static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008998{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008999 int ret_status;
9000
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009001 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009002 ret_status = hdd_driver_init();
9003 wlan_hdd_inited = ret_status ? 0 : 1;
9004 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009005 }
9006
9007 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07009008
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009009 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07009010
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009011 ret_status = hdd_driver_init();
9012 wlan_hdd_inited = ret_status ? 0 : 1;
9013 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009014}
9015
Jeff Johnson295189b2012-06-20 16:38:30 -07009016/**---------------------------------------------------------------------------
9017
Jeff Johnson76052702013-04-16 13:55:05 -07009018 \brief fwpath_changed_handler() - Handler Function
9019
9020 Handle changes to the fwpath parameter
9021
9022 \return - 0 for success, non zero for failure
9023
9024 --------------------------------------------------------------------------*/
9025static int fwpath_changed_handler(const char *kmessage,
9026 struct kernel_param *kp)
9027{
9028 int ret;
9029
9030 ret = param_set_copystring(kmessage, kp);
9031 if (0 == ret)
9032 ret = kickstart_driver();
9033 return ret;
9034}
9035
9036/**---------------------------------------------------------------------------
9037
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009038 \brief con_mode_handler() -
9039
9040 Handler function for module param con_mode when it is changed by userspace
9041 Dynamically linked - do nothing
9042 Statically linked - exit and init driver, as in rmmod and insmod
9043
Jeff Johnson76052702013-04-16 13:55:05 -07009044 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009045
Jeff Johnson76052702013-04-16 13:55:05 -07009046 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009047
9048 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009049static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009050{
Jeff Johnson76052702013-04-16 13:55:05 -07009051 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009052
Jeff Johnson76052702013-04-16 13:55:05 -07009053 ret = param_set_int(kmessage, kp);
9054 if (0 == ret)
9055 ret = kickstart_driver();
9056 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009057}
9058#endif /* #ifdef MODULE */
9059
9060/**---------------------------------------------------------------------------
9061
Jeff Johnson295189b2012-06-20 16:38:30 -07009062 \brief hdd_get_conparam() -
9063
9064 This is the driver exit point (invoked when module is unloaded using rmmod)
9065
9066 \param - None
9067
9068 \return - tVOS_CON_MODE
9069
9070 --------------------------------------------------------------------------*/
9071tVOS_CON_MODE hdd_get_conparam ( void )
9072{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009073#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07009074 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009075#else
9076 return (tVOS_CON_MODE)curr_con_mode;
9077#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009078}
9079void hdd_set_conparam ( v_UINT_t newParam )
9080{
9081 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009082#ifndef MODULE
9083 curr_con_mode = con_mode;
9084#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009085}
9086/**---------------------------------------------------------------------------
9087
9088 \brief hdd_softap_sta_deauth() - function
9089
9090 This to take counter measure to handle deauth req from HDD
9091
9092 \param - pAdapter - Pointer to the HDD
9093
9094 \param - enable - boolean value
9095
9096 \return - None
9097
9098 --------------------------------------------------------------------------*/
9099
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009100VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07009101{
Jeff Johnson295189b2012-06-20 16:38:30 -07009102 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009103 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07009104
9105 ENTER();
9106
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07009107 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
9108 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009109
9110 //Ignore request to deauth bcmc station
9111 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009112 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009113
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009114 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07009115
9116 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009117 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009118}
9119
9120/**---------------------------------------------------------------------------
9121
9122 \brief hdd_softap_sta_disassoc() - function
9123
9124 This to take counter measure to handle deauth req from HDD
9125
9126 \param - pAdapter - Pointer to the HDD
9127
9128 \param - enable - boolean value
9129
9130 \return - None
9131
9132 --------------------------------------------------------------------------*/
9133
9134void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
9135{
9136 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9137
9138 ENTER();
9139
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309140 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009141
9142 //Ignore request to disassoc bcmc station
9143 if( pDestMacAddress[0] & 0x1 )
9144 return;
9145
9146 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
9147}
9148
9149void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
9150{
9151 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9152
9153 ENTER();
9154
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309155 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009156
9157 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
9158}
9159
Jeff Johnson295189b2012-06-20 16:38:30 -07009160/**---------------------------------------------------------------------------
9161 *
9162 * \brief hdd_get__concurrency_mode() -
9163 *
9164 *
9165 * \param - None
9166 *
9167 * \return - CONCURRENCY MODE
9168 *
9169 * --------------------------------------------------------------------------*/
9170tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9171{
9172 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9173 hdd_context_t *pHddCtx;
9174
9175 if (NULL != pVosContext)
9176 {
9177 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9178 if (NULL != pHddCtx)
9179 {
9180 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9181 }
9182 }
9183
9184 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009185 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009186 return VOS_STA;
9187}
9188
9189/* Decide whether to allow/not the apps power collapse.
9190 * Allow apps power collapse if we are in connected state.
9191 * if not, allow only if we are in IMPS */
9192v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
9193{
9194 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08009195 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009196 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07009197 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9198 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9199 hdd_adapter_t *pAdapter = NULL;
9200 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08009201 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009202
Jeff Johnson295189b2012-06-20 16:38:30 -07009203 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9204 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009205
Yathish9f22e662012-12-10 14:21:35 -08009206 concurrent_state = hdd_get_concurrency_mode();
9207
9208#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
9209 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
9210 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
9211 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
9212 return TRUE;
9213#endif
9214
Jeff Johnson295189b2012-06-20 16:38:30 -07009215 /*loop through all adapters. TBD fix for Concurrency */
9216 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9217 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9218 {
9219 pAdapter = pAdapterNode->pAdapter;
9220 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
9221 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9222 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009223 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07009224 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08009225 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009226 (eANI_BOOLEAN_TRUE == scanRspPending) ||
9227 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07009228 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009229 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009230 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
9231 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07009232 return FALSE;
9233 }
9234 }
9235 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9236 pAdapterNode = pNext;
9237 }
9238 return TRUE;
9239}
9240
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08009241/* Decides whether to send suspend notification to Riva
9242 * if any adapter is in BMPS; then it is required */
9243v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
9244{
9245 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
9246 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9247
9248 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
9249 {
9250 return TRUE;
9251 }
9252 return FALSE;
9253}
9254
Jeff Johnson295189b2012-06-20 16:38:30 -07009255void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9256{
9257 switch(mode)
9258 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009259 case VOS_STA_MODE:
9260 case VOS_P2P_CLIENT_MODE:
9261 case VOS_P2P_GO_MODE:
9262 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07009263 pHddCtx->concurrency_mode |= (1 << mode);
9264 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07009265 break;
9266 default:
9267 break;
9268
9269 }
9270 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9271 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9272}
9273
9274
9275void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9276{
9277 switch(mode)
9278 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009279 case VOS_STA_MODE:
9280 case VOS_P2P_CLIENT_MODE:
9281 case VOS_P2P_GO_MODE:
9282 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07009283 pHddCtx->no_of_sessions[mode]--;
9284 if (!(pHddCtx->no_of_sessions[mode]))
9285 pHddCtx->concurrency_mode &= (~(1 << mode));
9286 break;
9287 default:
9288 break;
9289 }
9290 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9291 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9292}
9293
Jeff Johnsone7245742012-09-05 17:12:55 -07009294/**---------------------------------------------------------------------------
9295 *
9296 * \brief wlan_hdd_restart_init
9297 *
9298 * This function initalizes restart timer/flag. An internal function.
9299 *
9300 * \param - pHddCtx
9301 *
9302 * \return - None
9303 *
9304 * --------------------------------------------------------------------------*/
9305
9306static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
9307{
9308 /* Initialize */
9309 pHddCtx->hdd_restart_retries = 0;
9310 atomic_set(&pHddCtx->isRestartInProgress, 0);
9311 vos_timer_init(&pHddCtx->hdd_restart_timer,
9312 VOS_TIMER_TYPE_SW,
9313 wlan_hdd_restart_timer_cb,
9314 pHddCtx);
9315}
9316/**---------------------------------------------------------------------------
9317 *
9318 * \brief wlan_hdd_restart_deinit
9319 *
9320 * This function cleans up the resources used. An internal function.
9321 *
9322 * \param - pHddCtx
9323 *
9324 * \return - None
9325 *
9326 * --------------------------------------------------------------------------*/
9327
9328static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
9329{
9330
9331 VOS_STATUS vos_status;
9332 /* Block any further calls */
9333 atomic_set(&pHddCtx->isRestartInProgress, 1);
9334 /* Cleanup */
9335 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
9336 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309337 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009338 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
9339 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309340 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009341
9342}
9343
9344/**---------------------------------------------------------------------------
9345 *
9346 * \brief wlan_hdd_framework_restart
9347 *
9348 * This function uses a cfg80211 API to start a framework initiated WLAN
9349 * driver module unload/load.
9350 *
9351 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
9352 *
9353 *
9354 * \param - pHddCtx
9355 *
9356 * \return - VOS_STATUS_SUCCESS: Success
9357 * VOS_STATUS_E_EMPTY: Adapter is Empty
9358 * VOS_STATUS_E_NOMEM: No memory
9359
9360 * --------------------------------------------------------------------------*/
9361
9362static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
9363{
9364 VOS_STATUS status = VOS_STATUS_SUCCESS;
9365 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009366 int len = (sizeof (struct ieee80211_mgmt));
9367 struct ieee80211_mgmt *mgmt = NULL;
9368
9369 /* Prepare the DEAUTH managment frame with reason code */
9370 mgmt = kzalloc(len, GFP_KERNEL);
9371 if(mgmt == NULL)
9372 {
9373 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9374 "%s: memory allocation failed (%d bytes)", __func__, len);
9375 return VOS_STATUS_E_NOMEM;
9376 }
9377 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07009378
9379 /* Iterate over all adapters/devices */
9380 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9381 do
9382 {
9383 if( (status == VOS_STATUS_SUCCESS) &&
9384 pAdapterNode &&
9385 pAdapterNode->pAdapter)
9386 {
9387 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9388 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
9389 pAdapterNode->pAdapter->dev->name,
9390 pAdapterNode->pAdapter->device_mode,
9391 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009392 /*
9393 * CFG80211 event to restart the driver
9394 *
9395 * 'cfg80211_send_unprot_deauth' sends a
9396 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
9397 * of SME(Linux Kernel) state machine.
9398 *
9399 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
9400 * the driver.
9401 *
9402 */
9403
9404 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07009405 }
9406 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9407 pAdapterNode = pNext;
9408 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
9409
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009410
9411 /* Free the allocated management frame */
9412 kfree(mgmt);
9413
Jeff Johnsone7245742012-09-05 17:12:55 -07009414 /* Retry until we unload or reach max count */
9415 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
9416 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
9417
9418 return status;
9419
9420}
9421/**---------------------------------------------------------------------------
9422 *
9423 * \brief wlan_hdd_restart_timer_cb
9424 *
9425 * Restart timer callback. An internal function.
9426 *
9427 * \param - User data:
9428 *
9429 * \return - None
9430 *
9431 * --------------------------------------------------------------------------*/
9432
9433void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9434{
9435 hdd_context_t *pHddCtx = usrDataForCallback;
9436 wlan_hdd_framework_restart(pHddCtx);
9437 return;
9438
9439}
9440
9441
9442/**---------------------------------------------------------------------------
9443 *
9444 * \brief wlan_hdd_restart_driver
9445 *
9446 * This function sends an event to supplicant to restart the WLAN driver.
9447 *
9448 * This function is called from vos_wlanRestart.
9449 *
9450 * \param - pHddCtx
9451 *
9452 * \return - VOS_STATUS_SUCCESS: Success
9453 * VOS_STATUS_E_EMPTY: Adapter is Empty
9454 * VOS_STATUS_E_ALREADY: Request already in progress
9455
9456 * --------------------------------------------------------------------------*/
9457VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9458{
9459 VOS_STATUS status = VOS_STATUS_SUCCESS;
9460
9461 /* A tight check to make sure reentrancy */
9462 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9463 {
9464 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9465 "%s: WLAN restart is already in progress", __func__);
9466
9467 return VOS_STATUS_E_ALREADY;
9468 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009469 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009470#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009471 wcnss_reset_intr();
9472#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009473
Jeff Johnsone7245742012-09-05 17:12:55 -07009474 return status;
9475}
9476
Mihir Shetee1093ba2014-01-21 20:13:32 +05309477/**---------------------------------------------------------------------------
9478 *
9479 * \brief wlan_hdd_init_channels
9480 *
9481 * This function is used to initialize the channel list in CSR
9482 *
9483 * This function is called from hdd_wlan_startup
9484 *
9485 * \param - pHddCtx: HDD context
9486 *
9487 * \return - VOS_STATUS_SUCCESS: Success
9488 * VOS_STATUS_E_FAULT: Failure reported by SME
9489
9490 * --------------------------------------------------------------------------*/
9491static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
9492{
9493 eHalStatus status;
9494
9495 status = sme_InitChannels(pHddCtx->hHal);
9496 if (HAL_STATUS_SUCCESS(status))
9497 {
9498 return VOS_STATUS_SUCCESS;
9499 }
9500 else
9501 {
9502 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
9503 __func__, status);
9504 return VOS_STATUS_E_FAULT;
9505 }
9506}
9507
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009508/*
9509 * API to find if there is any STA or P2P-Client is connected
9510 */
9511VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9512{
9513 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9514}
Jeff Johnsone7245742012-09-05 17:12:55 -07009515
Jeff Johnson295189b2012-06-20 16:38:30 -07009516//Register the module init/exit functions
9517module_init(hdd_module_init);
9518module_exit(hdd_module_exit);
9519
9520MODULE_LICENSE("Dual BSD/GPL");
9521MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9522MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9523
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009524module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9525 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009526
Jeff Johnson76052702013-04-16 13:55:05 -07009527module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009528 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -08009529
9530module_param(enable_dfs_chan_scan, int,
9531 S_IRUSR | S_IRGRP | S_IROTH);
9532
9533module_param(enable_11d, int,
9534 S_IRUSR | S_IRGRP | S_IROTH);
9535
9536module_param(country_code, charp,
9537 S_IRUSR | S_IRGRP | S_IROTH);