blob: c7bc76c8b7f03adc3c472f44e830d0ea692044bd [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
112#include <mach/subsystem_restart.h>
113#include <wlan_hdd_hostapd.h>
114#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "wlan_hdd_dev_pwr.h"
117#ifdef WLAN_BTAMP_FEATURE
118#include "bap_hdd_misc.h"
119#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700120#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800122#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530123#ifdef FEATURE_WLAN_TDLS
124#include "wlan_hdd_tdls.h"
125#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
144
Yue Ma54db3d42013-04-19 16:44:28 -0700145#define MAX_RESTART_DRIVER_EVENT_LENGTH 30
146
Jeff Johnson295189b2012-06-20 16:38:30 -0700147/* the Android framework expects this param even though we don't use it */
148#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700149static char fwpath_buffer[BUF_LEN];
150static struct kparam_string fwpath = {
151 .string = fwpath_buffer,
152 .maxlen = BUF_LEN,
153};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700154#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700155static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700156#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700157
Jeff Johnsone7245742012-09-05 17:12:55 -0700158/*
159 * The rate at which the driver sends RESTART event to supplicant
160 * once the function 'vos_wlanRestart()' is called
161 *
162 */
163#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
164#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800165#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700166static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700167#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700168/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700169static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700170
171//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700172static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
173static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
174static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
175void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800176void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700177
Jeff Johnson295189b2012-06-20 16:38:30 -0700178v_U16_t hdd_select_queue(struct net_device *dev,
179 struct sk_buff *skb);
180
181#ifdef WLAN_FEATURE_PACKET_FILTERING
182static void hdd_set_multicast_list(struct net_device *dev);
183#endif
184
185void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700186int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700187
188extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800189#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
190void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
191static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
192static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700193static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
194 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
195 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800196#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700197static int hdd_netdev_notifier_call(struct notifier_block * nb,
198 unsigned long state,
199 void *ndev)
200{
201 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700202 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700203 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700204#ifdef WLAN_BTAMP_FEATURE
205 VOS_STATUS status;
206 hdd_context_t *pHddCtx;
207#endif
208
209 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700210 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700211 (strncmp(dev->name, "p2p", 3)))
212 return NOTIFY_DONE;
213
214 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700215 return NOTIFY_DONE;
216
Jeff Johnson295189b2012-06-20 16:38:30 -0700217 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700218 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700219
Jeff Johnson27cee452013-03-27 11:10:24 -0700220 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700221 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800222 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700223 VOS_ASSERT(0);
224 return NOTIFY_DONE;
225 }
226
Jeff Johnson27cee452013-03-27 11:10:24 -0700227 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
228 if (NULL == pHddCtx)
229 {
230 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
231 VOS_ASSERT(0);
232 return NOTIFY_DONE;
233 }
234
235 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
236 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700237
238 switch (state) {
239 case NETDEV_REGISTER:
240 break;
241
242 case NETDEV_UNREGISTER:
243 break;
244
245 case NETDEV_UP:
246 break;
247
248 case NETDEV_DOWN:
249 break;
250
251 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700252 if(TRUE == pAdapter->isLinkUpSvcNeeded)
253 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700254 break;
255
256 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700257 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700258 {
259 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800260 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700261 hdd_abort_mac_scan(pAdapter->pHddCtx);
262 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800263 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700264 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
265 if(!result)
266 {
267 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800268 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700269 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700270 }
271 }
272 else
273 {
274 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700275 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700276 }
277#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700278 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700279 status = WLANBAP_StopAmp();
280 if(VOS_STATUS_SUCCESS != status )
281 {
282 pHddCtx->isAmpAllowed = VOS_TRUE;
283 hddLog(VOS_TRACE_LEVEL_FATAL,
284 "%s: Failed to stop AMP", __func__);
285 }
286 else
287 {
288 //a state m/c implementation in PAL is TBD to avoid this delay
289 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700290 if ( pHddCtx->isAmpAllowed )
291 {
292 WLANBAP_DeregisterFromHCI();
293 pHddCtx->isAmpAllowed = VOS_FALSE;
294 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700295 }
296#endif //WLAN_BTAMP_FEATURE
297 break;
298
299 default:
300 break;
301 }
302
303 return NOTIFY_DONE;
304}
305
306struct notifier_block hdd_netdev_notifier = {
307 .notifier_call = hdd_netdev_notifier_call,
308};
309
310/*---------------------------------------------------------------------------
311 * Function definitions
312 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700313void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
314void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700315//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700316static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700317#ifndef MODULE
318/* current con_mode - used only for statically linked driver
319 * con_mode is changed by userspace to indicate a mode change which will
320 * result in calling the module exit and init functions. The module
321 * exit function will clean up based on the value of con_mode prior to it
322 * being changed by userspace. So curr_con_mode records the current con_mode
323 * for exit when con_mode becomes the next mode for init
324 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700325static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700326#endif
327
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800328/**---------------------------------------------------------------------------
329
330 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
331
332 Called immediately after the cfg.ini is read in order to configure
333 the desired trace levels.
334
335 \param - moduleId - module whose trace level is being configured
336 \param - bitmask - bitmask of log levels to be enabled
337
338 \return - void
339
340 --------------------------------------------------------------------------*/
341static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
342{
343 wpt_tracelevel level;
344
345 /* if the bitmask is the default value, then a bitmask was not
346 specified in cfg.ini, so leave the logging level alone (it
347 will remain at the "compiled in" default value) */
348 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
349 {
350 return;
351 }
352
353 /* a mask was specified. start by disabling all logging */
354 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
355
356 /* now cycle through the bitmask until all "set" bits are serviced */
357 level = VOS_TRACE_LEVEL_FATAL;
358 while (0 != bitmask)
359 {
360 if (bitmask & 1)
361 {
362 vos_trace_setValue(moduleId, level, 1);
363 }
364 level++;
365 bitmask >>= 1;
366 }
367}
368
369
Jeff Johnson295189b2012-06-20 16:38:30 -0700370/**---------------------------------------------------------------------------
371
372 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
373
374 Called immediately after the cfg.ini is read in order to configure
375 the desired trace levels in the WDI.
376
377 \param - moduleId - module whose trace level is being configured
378 \param - bitmask - bitmask of log levels to be enabled
379
380 \return - void
381
382 --------------------------------------------------------------------------*/
383static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
384{
385 wpt_tracelevel level;
386
387 /* if the bitmask is the default value, then a bitmask was not
388 specified in cfg.ini, so leave the logging level alone (it
389 will remain at the "compiled in" default value) */
390 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
391 {
392 return;
393 }
394
395 /* a mask was specified. start by disabling all logging */
396 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
397
398 /* now cycle through the bitmask until all "set" bits are serviced */
399 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
400 while (0 != bitmask)
401 {
402 if (bitmask & 1)
403 {
404 wpalTraceSetLevel(moduleId, level, 1);
405 }
406 level++;
407 bitmask >>= 1;
408 }
409}
Jeff Johnson295189b2012-06-20 16:38:30 -0700410
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700411void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
412{
413 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
414 hdd_config_t *cfg_param;
415
416 if (NULL == pHddCtx)
417 {
418 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
419 "HDD Context is null !!");
420 return ;
421 }
422
423 cfg_param = pHddCtx->cfg_ini;
424
425 if (NULL == cfg_param)
426 {
427 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
428 "cfg_params not available !!");
429 return ;
430 }
431
432 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
433 {
434 /*New country doesn't support DFS */
435 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
436 }
437 else
438 {
439 /*New country Supports DFS as well resetting value back from .ini*/
440 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
441 }
442
443}
444
Jeff Johnson295189b2012-06-20 16:38:30 -0700445int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
446{
447 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
448 hdd_priv_data_t priv_data;
449 tANI_U8 *command = NULL;
450 int ret = 0;
451
452 if (NULL == pAdapter)
453 {
454 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700455 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700456 ret = -ENODEV;
457 goto exit;
458 }
459
Jeff Johnsone7245742012-09-05 17:12:55 -0700460 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700461 {
462 ret = -EINVAL;
463 goto exit;
464 }
465
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700466 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
467 {
468 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
469 "%s:LOGP in Progress. Ignore!!!", __func__);
470 ret = -EBUSY;
471 goto exit;
472 }
473
Jeff Johnson295189b2012-06-20 16:38:30 -0700474 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
475 {
476 ret = -EFAULT;
477 goto exit;
478 }
479
480 command = kmalloc(priv_data.total_len, GFP_KERNEL);
481 if (!command)
482 {
483 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700484 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700485 ret = -ENOMEM;
486 goto exit;
487 }
488
489 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
490 {
491 ret = -EFAULT;
492 goto exit;
493 }
494
495 if ((SIOCDEVPRIVATE + 1) == cmd)
496 {
497 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
498
499 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700500 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700501
502 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
503 {
504 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
505 sizeof(tSirMacAddr)))
506 {
507 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700508 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700509 ret = -EFAULT;
510 }
511 }
Amar Singhal0974e402013-02-12 14:27:46 -0800512 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700513 {
Amar Singhal0974e402013-02-12 14:27:46 -0800514 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700515 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800516
Jeff Johnson295189b2012-06-20 16:38:30 -0700517 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800518
519 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700520 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700521 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800522 "%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 -0700523 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800524 ret = hdd_setBand_helper(dev, ptr);
525 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700526 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
527 {
528 char *country_code;
529
530 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700531
532 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700533 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
534 pAdapter, pHddCtx->pvosContext);
535 if( 0 != ret )
536 {
537 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
538 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
539
540 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700541 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800542#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
543 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
544 {
545 tANI_U8 *value = command;
546 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
547 tANI_U8 revision = 0;
548 eHalStatus status = eHAL_STATUS_SUCCESS;
549 v_REGDOMAIN_t regId;
550
551 status = hdd_parse_countryrev(value, countryCode, &revision);
552 if (eHAL_STATUS_SUCCESS != status)
553 {
554 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
555 "%s: Failed to parse country revision information", __func__);
556 ret = -EINVAL;
557 goto exit;
558 }
559
560 /* Validate country code */
561 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
562 if (eHAL_STATUS_SUCCESS != status)
563 {
564 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
565 "%s: Invalid country code %s", __func__, countryCode);
566 ret = -EINVAL;
567 goto exit;
568 }
569
570 /* Validate revision */
571 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
572 {
573 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
574 "%s: Invalid revision %d", __func__, revision);
575 ret = -EINVAL;
576 goto exit;
577 }
578
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700579 hdd_checkandupdate_dfssetting(pAdapter, countryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800580 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
581 pAdapter, pHddCtx->pvosContext);
582 if (0 != ret)
583 {
584 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
585 "%s: SME Change Country code fail ret=%d", __func__, ret);
586 ret = -EINVAL;
587 goto exit;
588 }
589
590 if (0 == strncmp(countryCode, "KR", 2))
591 {
592 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
593 revision);
594 if (eHAL_STATUS_SUCCESS != status)
595 {
596 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
597 "%s: Failed to build valid channel list", __func__);
598 ret = -EINVAL;
599 goto exit;
600 }
601 }
602 }
603#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700604 /*
605 command should be a string having format
606 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
607 */
Amar Singhal0974e402013-02-12 14:27:46 -0800608 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700609 {
Amar Singhal0974e402013-02-12 14:27:46 -0800610 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700611
612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700613 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700614
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800615 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700616 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800617 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
618 {
619 int suspend = 0;
620 tANI_U8 *ptr = (tANI_U8*)command + 15;
621
622 suspend = *ptr - '0';
623 hdd_set_wlan_suspend_mode(suspend);
624 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800625#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
626 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
627 {
628 tANI_U8 *value = command;
629 int rssi = 0;
630 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
631 eHalStatus status = eHAL_STATUS_SUCCESS;
632
633 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
634 value = value + 15;
635
636 sscanf(value, "%d", &rssi);
637 lookUpThreshold = abs(rssi);
638 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
639 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
640 {
641 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
642 "Neighbor lookup threshold value %d is out of range"
643 " (Min: %d Max: %d)", lookUpThreshold,
644 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
645 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
646 ret = -EINVAL;
647 goto exit;
648 }
649
650 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
651 "%s: Received Command to Set Roam trigger"
652 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
653
654 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
655 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
656 if (eHAL_STATUS_SUCCESS != status)
657 {
658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
659 "%s: Failed to set roam trigger, try again", __func__);
660 ret = -EPERM;
661 goto exit;
662 }
663
664 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
665 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
666 }
667 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
668 {
669 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
670 int rssi = (-1) * lookUpThreshold;
671 char extra[32];
672 tANI_U8 len = 0;
673
674 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
675 if (copy_to_user(priv_data.buf, &extra, len + 1))
676 {
677 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
678 "%s: failed to copy data to user buffer", __func__);
679 ret = -EFAULT;
680 goto exit;
681 }
682 }
683 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
684 {
685 tANI_U8 *value = command;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700686 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800687 /* input refresh period is in terms of seconds */
688 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
689 value = value + 18;
690 /* Convert the value from ascii to integer */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700691 ret = kstrtou16(value, 10, &neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800692 if (ret < 0)
693 {
694 /* If the input value is greater than max value of datatype, then also
695 kstrtou16 fails */
696 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
697 "%s: kstrtou16 failed ",
698 "Input value may be out of range[%d - %d]",
699 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700700 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
701 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800702 ret = -EINVAL;
703 goto exit;
704 }
705
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700706 neighborEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod * 1000;
707 if ((neighborEmptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
708 (neighborEmptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800709 {
710 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700711 "Neighbor empty scan results refresh period value %d is out of range"
712 " (Min: %d Max: %d)", neighborEmptyScanRefreshPeriod/1000,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700713 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
714 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800715 ret = -EINVAL;
716 goto exit;
717 }
718
719 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
720 "%s: Received Command to Set roam scan period"
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700721 " (Empty Scan refresh period) = %d", __func__, neighborEmptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800722
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700723 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
724 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800725 }
726 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
727 {
728 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
729 char extra[32];
730 tANI_U8 len = 0;
731
732 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
733 /* Returned value is in units of seconds */
734 if (copy_to_user(priv_data.buf, &extra, len + 1))
735 {
736 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
737 "%s: failed to copy data to user buffer", __func__);
738 ret = -EFAULT;
739 goto exit;
740 }
741 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700742 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
743 {
744 tANI_U8 *value = command;
745 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
746 /* input refresh period is in terms of seconds */
747 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
748 value = value + 25;
749 /* Convert the value from ascii to integer */
750 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
751 if (ret < 0)
752 {
753 /* If the input value is greater than max value of datatype, then also
754 kstrtou16 fails */
755 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
756 "%s: kstrtou16 failed ",
757 "Input value may be out of range[%d - %d]",
758 __func__,
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700759 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
760 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700761 ret = -EINVAL;
762 goto exit;
763 }
764
765 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700766 if ((neighborScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
767 (neighborScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700768 {
769 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
770 "Neighbor scan results refresh period value %d is out of range"
771 " (Min: %d Max: %d)", neighborScanRefreshPeriod/1000,
772 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
773 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
774 ret = -EINVAL;
775 goto exit;
776 }
777
778 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
779 "%s: Received Command to Set roam scan refresh period"
780 " (Scan refresh period) = %d", __func__, neighborScanRefreshPeriod/1000);
781
782 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
783 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
784 }
785 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
786 {
787 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
788 char extra[32];
789 tANI_U8 len = 0;
790
791 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
792 /* Returned value is in units of seconds */
793 if (copy_to_user(priv_data.buf, &extra, len + 1))
794 {
795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
796 "%s: failed to copy data to user buffer", __func__);
797 ret = -EFAULT;
798 goto exit;
799 }
800 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800801#endif
802#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
803 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
804 {
805 tANI_U8 *value = command;
806 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
807
808 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
809 value = value + 13;
810 /* Convert the value from ascii to integer */
811 ret = kstrtou8(value, 10, &roamRssiDiff);
812 if (ret < 0)
813 {
814 /* If the input value is greater than max value of datatype, then also
815 kstrtou8 fails */
816 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
817 "%s: kstrtou8 failed range [%d - %d]", __func__,
818 CFG_ROAM_RSSI_DIFF_MIN,
819 CFG_ROAM_RSSI_DIFF_MAX);
820 ret = -EINVAL;
821 goto exit;
822 }
823
824 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
825 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
826 {
827 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
828 "Roam rssi diff value %d is out of range"
829 " (Min: %d Max: %d)", roamRssiDiff,
830 CFG_ROAM_RSSI_DIFF_MIN,
831 CFG_ROAM_RSSI_DIFF_MAX);
832 ret = -EINVAL;
833 goto exit;
834 }
835
836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
837 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
838
839 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
840 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
841 }
842 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
843 {
844 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
845 char extra[32];
846 tANI_U8 len = 0;
847
848 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
849 if (copy_to_user(priv_data.buf, &extra, len + 1))
850 {
851 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
852 "%s: failed to copy data to user buffer", __func__);
853 ret = -EFAULT;
854 goto exit;
855 }
856 }
857#endif
858#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
859 else if (strncmp(command, "GETBAND", 7) == 0)
860 {
861 int band = -1;
862 char extra[32];
863 tANI_U8 len = 0;
864 hdd_getBand_helper(pHddCtx, &band);
865
866 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
867 if (copy_to_user(priv_data.buf, &extra, len + 1))
868 {
869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
870 "%s: failed to copy data to user buffer", __func__);
871 ret = -EFAULT;
872 goto exit;
873 }
874 }
875 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
876 {
877 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
878 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
879 tANI_U8 revision = 0;
880 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
881 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
882 char extra[32] = {0};
883 tANI_U8 len = 0;
884
885 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
886 {
887 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
888 "%s: failed to get country code", __func__);
889 ret = -EFAULT;
890 goto exit;
891 }
892 pBuf[uBufLen] = '\0';
893 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
894
895 if (0 == strncmp(pBuf, "KR", 2))
896 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
897 else
898 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
899
900 if (copy_to_user(priv_data.buf, &extra, len + 1))
901 {
902 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
903 "%s: failed to copy data to user buffer", __func__);
904 ret = -EFAULT;
905 goto exit;
906 }
907 }
908 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
909 {
910 tANI_U8 *value = command;
911 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
912 tANI_U8 numChannels = 0;
913 eHalStatus status = eHAL_STATUS_SUCCESS;
914
915 status = hdd_parse_channellist(value, ChannelList, &numChannels);
916 if (eHAL_STATUS_SUCCESS != status)
917 {
918 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
919 "%s: Failed to parse channel list information", __func__);
920 ret = -EINVAL;
921 goto exit;
922 }
923
924 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
925 {
926 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
927 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
928 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
929 ret = -EINVAL;
930 goto exit;
931 }
932 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
933 numChannels);
934 if (eHAL_STATUS_SUCCESS != status)
935 {
936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
937 "%s: Failed to update channel list information", __func__);
938 ret = -EINVAL;
939 goto exit;
940 }
941 }
942 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
943 {
944 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
945 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -0700946 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800947 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -0700948 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800949
950 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
951 ChannelList, &numChannels ))
952 {
953 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
954 "%s: failed to get roam scan channel list", __func__);
955 ret = -EFAULT;
956 goto exit;
957 }
958 /* output channel list is of the format
959 [Number of roam scan channels][Channel1][Channel2]... */
960 /* copy the number of channels in the 0th index */
961 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
962 for (j = 0; (j < numChannels); j++)
963 {
964 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
965 }
966
967 if (copy_to_user(priv_data.buf, &extra, len + 1))
968 {
969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
970 "%s: failed to copy data to user buffer", __func__);
971 ret = -EFAULT;
972 goto exit;
973 }
974 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700975 else if (strncmp(command, "GETCCXMODE", 10) == 0)
976 {
977 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
978 char extra[32];
979 tANI_U8 len = 0;
980
981 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
982 if (copy_to_user(priv_data.buf, &extra, len + 1))
983 {
984 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
985 "%s: failed to copy data to user buffer", __func__);
986 ret = -EFAULT;
987 goto exit;
988 }
989 }
990 else if (strncmp(command, "GETOKCMODE", 10) == 0)
991 {
992 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
993 char extra[32];
994 tANI_U8 len = 0;
995
996 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
997 if (copy_to_user(priv_data.buf, &extra, len + 1))
998 {
999 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1000 "%s: failed to copy data to user buffer", __func__);
1001 ret = -EFAULT;
1002 goto exit;
1003 }
1004 }
1005 else if (strncmp(command, "GETFASTROAM", 10) == 0)
1006 {
1007 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1008 char extra[32];
1009 tANI_U8 len = 0;
1010
1011 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1012 if (copy_to_user(priv_data.buf, &extra, len + 1))
1013 {
1014 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1015 "%s: failed to copy data to user buffer", __func__);
1016 ret = -EFAULT;
1017 goto exit;
1018 }
1019 }
1020 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1021 {
1022 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1023 char extra[32];
1024 tANI_U8 len = 0;
1025
1026 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1027 if (copy_to_user(priv_data.buf, &extra, len + 1))
1028 {
1029 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1030 "%s: failed to copy data to user buffer", __func__);
1031 ret = -EFAULT;
1032 goto exit;
1033 }
1034 }
1035 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1036 {
1037 tANI_U8 *value = command;
1038 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1039
1040 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1041 value = value + 26;
1042 /* Convert the value from ascii to integer */
1043 ret = kstrtou8(value, 10, &minTime);
1044 if (ret < 0)
1045 {
1046 /* If the input value is greater than max value of datatype, then also
1047 kstrtou8 fails */
1048 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1049 "%s: kstrtou8 failed range [%d - %d]", __func__,
1050 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1051 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1052 ret = -EINVAL;
1053 goto exit;
1054 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001055 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1056 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1057 {
1058 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1059 "scan min channel time value %d is out of range"
1060 " (Min: %d Max: %d)", minTime,
1061 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1062 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1063 ret = -EINVAL;
1064 goto exit;
1065 }
1066
1067 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1068 "%s: Received Command to change channel min time = %d", __func__, minTime);
1069
1070 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1071 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1072 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001073 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1074 {
1075 tANI_U8 *value = command;
1076 tANI_U8 channel = 0;
1077 tANI_U8 dwellTime = 0;
1078 tANI_U8 bufLen = 0;
1079 tANI_U8 *buf = NULL;
1080 tSirMacAddr targetApBssid;
1081 eHalStatus status = eHAL_STATUS_SUCCESS;
1082 struct ieee80211_channel chan;
1083 tANI_U8 finalLen = 0;
1084 tANI_U8 *finalBuf = NULL;
1085 tANI_U8 temp = 0;
1086 u64 cookie;
1087 hdd_station_ctx_t *pHddStaCtx = NULL;
1088 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1089
1090 /* if not associated, no need to send action frame */
1091 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1092 {
1093 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1094 ret = -EINVAL;
1095 goto exit;
1096 }
1097
1098 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1099 &dwellTime, &buf, &bufLen);
1100 if (eHAL_STATUS_SUCCESS != status)
1101 {
1102 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1103 "%s: Failed to parse send action frame data", __func__);
1104 ret = -EINVAL;
1105 goto exit;
1106 }
1107
1108 /* if the target bssid is different from currently associated AP,
1109 then no need to send action frame */
1110 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1111 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1112 {
1113 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1114 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001115 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001116 goto exit;
1117 }
1118
1119 /* if the channel number is different from operating channel then
1120 no need to send action frame */
1121 if (channel != pHddStaCtx->conn_info.operationChannel)
1122 {
1123 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1124 "%s: channel(%d) is different from operating channel(%d)",
1125 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1126 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001127 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001128 goto exit;
1129 }
1130 chan.center_freq = sme_ChnToFreq(channel);
1131
1132 finalLen = bufLen + 24;
1133 finalBuf = vos_mem_malloc(finalLen);
1134 if (NULL == finalBuf)
1135 {
1136 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1137 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001138 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001139 goto exit;
1140 }
1141 vos_mem_zero(finalBuf, finalLen);
1142
1143 /* Fill subtype */
1144 temp = SIR_MAC_MGMT_ACTION << 4;
1145 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1146
1147 /* Fill type */
1148 temp = SIR_MAC_MGMT_FRAME;
1149 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1150
1151 /* Fill destination address (bssid of the AP) */
1152 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1153
1154 /* Fill BSSID (STA mac address) */
1155 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1156
1157 /* Fill source address (STA mac address) */
1158 vos_mem_copy(finalBuf + 16, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1159
1160 /* Fill received buffer from 24th address */
1161 vos_mem_copy(finalBuf + 24, buf, bufLen);
1162
Jeff Johnson11c33152013-04-16 17:52:40 -07001163 /* done with the parsed buffer */
1164 vos_mem_free(buf);
1165
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001166 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1167 1, dwellTime, finalBuf, finalLen, 1,
1168 1, &cookie );
1169 vos_mem_free(finalBuf);
1170 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001171 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1172 {
1173 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1174 char extra[32];
1175 tANI_U8 len = 0;
1176
1177 /* value is interms of msec */
1178 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1179 if (copy_to_user(priv_data.buf, &extra, len + 1))
1180 {
1181 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1182 "%s: failed to copy data to user buffer", __func__);
1183 ret = -EFAULT;
1184 goto exit;
1185 }
1186 }
1187 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1188 {
1189 tANI_U8 *value = command;
1190 tANI_U8 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
1191
1192 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1193 value = value + 19;
1194 /* Convert the value from ascii to integer */
1195 ret = kstrtou8(value, 10, &maxTime);
1196 if (ret < 0)
1197 {
1198 /* If the input value is greater than max value of datatype, then also
1199 kstrtou8 fails */
1200 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1201 "%s: kstrtou8 failed range [%d - %d]", __func__,
1202 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1203 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1204 ret = -EINVAL;
1205 goto exit;
1206 }
1207
1208 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1209 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1210 {
1211 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1212 "lfr mode value %d is out of range"
1213 " (Min: %d Max: %d)", maxTime,
1214 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1215 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1216 ret = -EINVAL;
1217 goto exit;
1218 }
1219
1220 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1221 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1222
1223 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
1224 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1225 }
1226 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1227 {
1228 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1229 char extra[32];
1230 tANI_U8 len = 0;
1231
1232 /* value is interms of msec */
1233 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1234 if (copy_to_user(priv_data.buf, &extra, len + 1))
1235 {
1236 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1237 "%s: failed to copy data to user buffer", __func__);
1238 ret = -EFAULT;
1239 goto exit;
1240 }
1241 }
1242 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1243 {
1244 tANI_U8 *value = command;
1245 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1246
1247 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1248 value = value + 16;
1249 /* Convert the value from ascii to integer */
1250 ret = kstrtou16(value, 10, &val);
1251 if (ret < 0)
1252 {
1253 /* If the input value is greater than max value of datatype, then also
1254 kstrtou16 fails */
1255 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1256 "%s: kstrtou16 failed range [%d - %d]", __func__,
1257 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1258 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1259 ret = -EINVAL;
1260 goto exit;
1261 }
1262
1263 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1264 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1265 {
1266 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1267 "scan home time value %d is out of range"
1268 " (Min: %d Max: %d)", val,
1269 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1270 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1271 ret = -EINVAL;
1272 goto exit;
1273 }
1274
1275 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1276 "%s: Received Command to change scan home time = %d", __func__, val);
1277
1278 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1279 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1280 }
1281 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1282 {
1283 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1284 char extra[32];
1285 tANI_U8 len = 0;
1286
1287 /* value is interms of msec */
1288 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1289 if (copy_to_user(priv_data.buf, &extra, len + 1))
1290 {
1291 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1292 "%s: failed to copy data to user buffer", __func__);
1293 ret = -EFAULT;
1294 goto exit;
1295 }
1296 }
1297 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1298 {
1299 tANI_U8 *value = command;
1300 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1301
1302 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1303 value = value + 17;
1304 /* Convert the value from ascii to integer */
1305 ret = kstrtou8(value, 10, &val);
1306 if (ret < 0)
1307 {
1308 /* If the input value is greater than max value of datatype, then also
1309 kstrtou8 fails */
1310 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1311 "%s: kstrtou8 failed range [%d - %d]", __func__,
1312 CFG_ROAM_INTRA_BAND_MIN,
1313 CFG_ROAM_INTRA_BAND_MAX);
1314 ret = -EINVAL;
1315 goto exit;
1316 }
1317
1318 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1319 (val > CFG_ROAM_INTRA_BAND_MAX))
1320 {
1321 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1322 "intra band mode value %d is out of range"
1323 " (Min: %d Max: %d)", val,
1324 CFG_ROAM_INTRA_BAND_MIN,
1325 CFG_ROAM_INTRA_BAND_MAX);
1326 ret = -EINVAL;
1327 goto exit;
1328 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1330 "%s: Received Command to change intra band = %d", __func__, val);
1331
1332 pHddCtx->cfg_ini->nRoamIntraBand = val;
1333 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1334 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001335 else if (strncmp(command, "SETWESMODE", 10) == 0)
1336 {
1337 tANI_U8 *value = command;
1338 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
1339
1340 /* Move pointer to ahead of SETWESMODE<delimiter> */
1341 value = value + 11;
1342 /* Convert the value from ascii to integer */
1343 ret = kstrtou8(value, 10, &wesMode);
1344 if (ret < 0)
1345 {
1346 /* If the input value is greater than max value of datatype, then also
1347 kstrtou8 fails */
1348 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1349 "%s: kstrtou8 failed range [%d - %d]", __func__,
1350 CFG_ENABLE_WES_MODE_NAME_MIN,
1351 CFG_ENABLE_WES_MODE_NAME_MAX);
1352 ret = -EINVAL;
1353 goto exit;
1354 }
1355
1356 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
1357 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
1358 {
1359 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1360 "WES Mode value %d is out of range"
1361 " (Min: %d Max: %d)", wesMode,
1362 CFG_ENABLE_WES_MODE_NAME_MIN,
1363 CFG_ENABLE_WES_MODE_NAME_MAX);
1364 ret = -EINVAL;
1365 goto exit;
1366 }
1367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1368 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
1369
1370 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
1371 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
1372 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001373 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1374 {
1375 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1376 char extra[32];
1377 tANI_U8 len = 0;
1378
1379 /* value is interms of msec */
1380 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1381 if (copy_to_user(priv_data.buf, &extra, len + 1))
1382 {
1383 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1384 "%s: failed to copy data to user buffer", __func__);
1385 ret = -EFAULT;
1386 goto exit;
1387 }
1388 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001389 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
1390 {
1391 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1392 char extra[32];
1393 tANI_U8 len = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001394
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001395 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
1396 if (copy_to_user(priv_data.buf, &extra, len + 1))
1397 {
1398 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1399 "%s: failed to copy data to user buffer", __func__);
1400 ret = -EFAULT;
1401 goto exit;
1402 }
1403 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001404#endif
1405#ifdef FEATURE_WLAN_LFR
1406 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1407 {
1408 tANI_U8 *value = command;
1409 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1410
1411 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1412 value = value + 12;
1413 /* Convert the value from ascii to integer */
1414 ret = kstrtou8(value, 10, &lfrMode);
1415 if (ret < 0)
1416 {
1417 /* If the input value is greater than max value of datatype, then also
1418 kstrtou8 fails */
1419 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1420 "%s: kstrtou8 failed range [%d - %d]", __func__,
1421 CFG_LFR_FEATURE_ENABLED_MIN,
1422 CFG_LFR_FEATURE_ENABLED_MAX);
1423 ret = -EINVAL;
1424 goto exit;
1425 }
1426
1427 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1428 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1429 {
1430 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1431 "lfr mode value %d is out of range"
1432 " (Min: %d Max: %d)", lfrMode,
1433 CFG_LFR_FEATURE_ENABLED_MIN,
1434 CFG_LFR_FEATURE_ENABLED_MAX);
1435 ret = -EINVAL;
1436 goto exit;
1437 }
1438
1439 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1440 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1441
1442 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1443 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1444 }
1445#endif
1446#ifdef WLAN_FEATURE_VOWIFI_11R
1447 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1448 {
1449 tANI_U8 *value = command;
1450 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1451
1452 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1453 value = value + 18;
1454 /* Convert the value from ascii to integer */
1455 ret = kstrtou8(value, 10, &ft);
1456 if (ret < 0)
1457 {
1458 /* If the input value is greater than max value of datatype, then also
1459 kstrtou8 fails */
1460 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1461 "%s: kstrtou8 failed range [%d - %d]", __func__,
1462 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1463 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1464 ret = -EINVAL;
1465 goto exit;
1466 }
1467
1468 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1469 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1470 {
1471 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1472 "ft mode value %d is out of range"
1473 " (Min: %d Max: %d)", ft,
1474 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1475 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1476 ret = -EINVAL;
1477 goto exit;
1478 }
1479
1480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1481 "%s: Received Command to change ft mode = %d", __func__, ft);
1482
1483 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1484 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1485 }
1486#endif
1487#ifdef FEATURE_WLAN_CCX
1488 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1489 {
1490 tANI_U8 *value = command;
1491 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1492
1493 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1494 value = value + 11;
1495 /* Convert the value from ascii to integer */
1496 ret = kstrtou8(value, 10, &ccxMode);
1497 if (ret < 0)
1498 {
1499 /* If the input value is greater than max value of datatype, then also
1500 kstrtou8 fails */
1501 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1502 "%s: kstrtou8 failed range [%d - %d]", __func__,
1503 CFG_CCX_FEATURE_ENABLED_MIN,
1504 CFG_CCX_FEATURE_ENABLED_MAX);
1505 ret = -EINVAL;
1506 goto exit;
1507 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001508 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1509 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1510 {
1511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1512 "Ccx mode value %d is out of range"
1513 " (Min: %d Max: %d)", ccxMode,
1514 CFG_CCX_FEATURE_ENABLED_MIN,
1515 CFG_CCX_FEATURE_ENABLED_MAX);
1516 ret = -EINVAL;
1517 goto exit;
1518 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001519 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1520 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1521
1522 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1523 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1524 }
1525#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001526 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1527 {
1528 tANI_U8 *value = command;
1529 tANI_BOOLEAN roamScanControl = 0;
1530
1531 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1532 value = value + 19;
1533 /* Convert the value from ascii to integer */
1534 ret = kstrtou8(value, 10, &roamScanControl);
1535 if (ret < 0)
1536 {
1537 /* If the input value is greater than max value of datatype, then also
1538 kstrtou8 fails */
1539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1540 "%s: kstrtou8 failed ", __func__);
1541 ret = -EINVAL;
1542 goto exit;
1543 }
1544
1545 if (0 != roamScanControl)
1546 {
1547 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1548 "roam scan control invalid value = %d",
1549 roamScanControl);
1550 ret = -EINVAL;
1551 goto exit;
1552 }
1553 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1554 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1555
1556 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1557 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001558#ifdef FEATURE_WLAN_OKC
1559 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1560 {
1561 tANI_U8 *value = command;
1562 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1563
1564 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1565 value = value + 11;
1566 /* Convert the value from ascii to integer */
1567 ret = kstrtou8(value, 10, &okcMode);
1568 if (ret < 0)
1569 {
1570 /* If the input value is greater than max value of datatype, then also
1571 kstrtou8 fails */
1572 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1573 "%s: kstrtou8 failed range [%d - %d]", __func__,
1574 CFG_OKC_FEATURE_ENABLED_MIN,
1575 CFG_OKC_FEATURE_ENABLED_MAX);
1576 ret = -EINVAL;
1577 goto exit;
1578 }
1579
1580 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1581 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1582 {
1583 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1584 "Okc mode value %d is out of range"
1585 " (Min: %d Max: %d)", okcMode,
1586 CFG_OKC_FEATURE_ENABLED_MIN,
1587 CFG_OKC_FEATURE_ENABLED_MAX);
1588 ret = -EINVAL;
1589 goto exit;
1590 }
1591
1592 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1593 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1594
1595 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1596 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001597 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1598 {
1599 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1600 char extra[32];
1601 tANI_U8 len = 0;
1602
1603 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1604 if (copy_to_user(priv_data.buf, &extra, len + 1))
1605 {
1606 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1607 "%s: failed to copy data to user buffer", __func__);
1608 ret = -EFAULT;
1609 goto exit;
1610 }
1611 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001612#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001613 else {
1614 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1615 __func__, command);
1616 }
1617
Jeff Johnson295189b2012-06-20 16:38:30 -07001618 }
1619exit:
1620 if (command)
1621 {
1622 kfree(command);
1623 }
1624 return ret;
1625}
1626
Srinivas Girigowdade697412013-02-14 16:31:48 -08001627#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1628void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
1629{
1630 eCsrBand band = -1;
1631 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
1632 switch (band)
1633 {
1634 case eCSR_BAND_ALL:
1635 *pBand = WLAN_HDD_UI_BAND_AUTO;
1636 break;
1637
1638 case eCSR_BAND_24:
1639 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
1640 break;
1641
1642 case eCSR_BAND_5G:
1643 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
1644 break;
1645
1646 default:
1647 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
1648 *pBand = -1;
1649 break;
1650 }
1651}
1652
1653/**---------------------------------------------------------------------------
1654
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001655 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
1656
1657 This function parses the send action frame data passed in the format
1658 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
1659
1660 \param - pValue Pointer to input country code revision
1661 \param - pTargetApBssid Pointer to target Ap bssid
1662 \param - pChannel Pointer to the Target AP channel
1663 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
1664 \param - pBuf Pointer to data
1665 \param - pBufLen Pointer to data length
1666
1667 \return - 0 for success non-zero for failure
1668
1669 --------------------------------------------------------------------------*/
1670VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
1671 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
1672{
1673 tANI_U8 *inPtr = pValue;
1674 tANI_U8 *dataEnd;
1675 int tempInt;
1676 int j = 0;
1677 int i = 0;
1678 int v = 0;
1679 tANI_U8 tempBuf[32];
1680 tANI_U8 tempByte = 0;
1681
1682 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1683 /*no argument after the command*/
1684 if (NULL == inPtr)
1685 {
1686 return -EINVAL;
1687 }
1688
1689 /*no space after the command*/
1690 else if (SPACE_ASCII_VALUE != *inPtr)
1691 {
1692 return -EINVAL;
1693 }
1694
1695 /*removing empty spaces*/
1696 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1697
1698 /*no argument followed by spaces*/
1699 if ('\0' == *inPtr)
1700 {
1701 return -EINVAL;
1702 }
1703
1704 /*getting the first argument ie the target AP bssid */
1705 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
1706 {
1707 return -EINVAL;
1708 }
1709 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
1710 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
1711 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
1712
1713 /* point to the next argument */
1714 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1715 /*no argument after the command*/
1716 if (NULL == inPtr) return -EINVAL;
1717
1718 /*removing empty spaces*/
1719 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1720
1721 /*no argument followed by spaces*/
1722 if ('\0' == *inPtr)
1723 {
1724 return -EINVAL;
1725 }
1726
1727 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07001728 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001729 v = kstrtos32(tempBuf, 10, &tempInt);
1730 if ( v < 0) return -EINVAL;
1731
1732 *pChannel = tempInt;
1733
1734 /* point to the next argument */
1735 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1736 /*no argument after the command*/
1737 if (NULL == inPtr) return -EINVAL;
1738 /*removing empty spaces*/
1739 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1740
1741 /*no argument followed by spaces*/
1742 if ('\0' == *inPtr)
1743 {
1744 return -EINVAL;
1745 }
1746
1747 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07001748 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001749 v = kstrtos32(tempBuf, 10, &tempInt);
1750 if ( v < 0) return -EINVAL;
1751
1752 *pDwellTime = tempInt;
1753
1754 /* point to the next argument */
1755 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1756 /*no argument after the command*/
1757 if (NULL == inPtr) return -EINVAL;
1758 /*removing empty spaces*/
1759 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1760
1761 /*no argument followed by spaces*/
1762 if ('\0' == *inPtr)
1763 {
1764 return -EINVAL;
1765 }
1766
1767 /* find the length of data */
1768 dataEnd = inPtr;
1769 while(('\0' != *dataEnd) )
1770 {
1771 dataEnd++;
1772 ++(*pBufLen);
1773 }
1774 if ( *pBufLen <= 0) return -EINVAL;
1775
1776 *pBuf = vos_mem_malloc(sizeof(*pBufLen));
1777 if (NULL == *pBuf)
1778 {
1779 hddLog(VOS_TRACE_LEVEL_FATAL,
1780 "%s: vos_mem_alloc failed ", __func__);
1781 return -EINVAL;
1782 }
1783
1784 /* the buffer received from the upper layer is character buffer,
1785 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
1786 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
1787 and f0 in 3rd location */
1788 for (i = 0, j = 0; j < *pBufLen; j += 2)
1789 {
1790 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
1791 (*pBuf)[i++] = tempByte;
1792 }
1793 *pBufLen = i;
1794 return VOS_STATUS_SUCCESS;
1795}
1796
1797#endif
1798/**---------------------------------------------------------------------------
1799
Srinivas Girigowdade697412013-02-14 16:31:48 -08001800 \brief hdd_parse_countryrev() - HDD Parse country code revision
1801
1802 This function parses the country code revision passed in the format
1803 SETCOUNTRYREV<space><Country code><space>revision
1804
1805 \param - pValue Pointer to input country code revision
1806 \param - pCountryCode Pointer to local output array to record country code
1807 \param - pRevision Pointer to store revision integer number
1808
1809 \return - 0 for success non-zero for failure
1810
1811 --------------------------------------------------------------------------*/
1812VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
1813{
1814 tANI_U8 *inPtr = pValue;
1815 int tempInt;
1816
1817 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1818 /*no argument after the command*/
1819 if (NULL == inPtr)
1820 {
1821 return -EINVAL;
1822 }
1823
1824 /*no space after the command*/
1825 else if (SPACE_ASCII_VALUE != *inPtr)
1826 {
1827 return -EINVAL;
1828 }
1829
1830 /*removing empty spaces*/
1831 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1832
1833 /*no argument followed by spaces*/
1834 if ('\0' == *inPtr)
1835 {
1836 return -EINVAL;
1837 }
1838
1839 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07001840 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001841
1842 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1843 "Country code is : %s", pCountryCode);
1844
1845 /*inPtr pointing to the beginning of first space after country code */
1846 inPtr = strpbrk( inPtr, " " );
1847 /*no revision number after the country code argument */
1848 if (NULL == inPtr)
1849 {
1850 return -EINVAL;
1851 }
1852
1853 inPtr++;
1854
1855 /*removing empty space*/
1856 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1857
1858 /*no channel list after the number of channels argument and spaces*/
1859 if (0 == strncmp(pCountryCode, "KR", 2))
1860 {
1861 if ('\0' == *inPtr)
1862 {
1863 return -EINVAL;
1864 }
1865
1866 sscanf(inPtr, "%d", &tempInt);
1867 *pRevision = tempInt;
1868 }
1869 else
1870 {
1871 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1872 "Revision input is required only for Country KR");
1873 return -EINVAL;
1874 }
1875 return VOS_STATUS_SUCCESS;
1876}
1877
1878/**---------------------------------------------------------------------------
1879
1880 \brief hdd_parse_channellist() - HDD Parse channel list
1881
1882 This function parses the channel list passed in the format
1883 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001884 if the Number of channels (N) does not match with the actual number of channels passed
1885 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
1886 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
1887 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
1888 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08001889
1890 \param - pValue Pointer to input channel list
1891 \param - ChannelList Pointer to local output array to record channel list
1892 \param - pNumChannels Pointer to number of roam scan channels
1893
1894 \return - 0 for success non-zero for failure
1895
1896 --------------------------------------------------------------------------*/
1897VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
1898{
1899 tANI_U8 *inPtr = pValue;
1900 int tempInt;
1901 int j = 0;
1902 int v = 0;
1903 char buf[32];
1904
1905 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1906 /*no argument after the command*/
1907 if (NULL == inPtr)
1908 {
1909 return -EINVAL;
1910 }
1911
1912 /*no space after the command*/
1913 else if (SPACE_ASCII_VALUE != *inPtr)
1914 {
1915 return -EINVAL;
1916 }
1917
1918 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001919 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001920
1921 /*no argument followed by spaces*/
1922 if ('\0' == *inPtr)
1923 {
1924 return -EINVAL;
1925 }
1926
1927 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07001928 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001929 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001930 if ((v < 0) ||
1931 (tempInt <= 0) ||
1932 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
1933 {
1934 return -EINVAL;
1935 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001936
1937 *pNumChannels = tempInt;
1938
1939 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1940 "Number of channels are: %d", *pNumChannels);
1941
1942 for (j = 0; j < (*pNumChannels); j++)
1943 {
1944 /*inPtr pointing to the beginning of first space after number of channels*/
1945 inPtr = strpbrk( inPtr, " " );
1946 /*no channel list after the number of channels argument*/
1947 if (NULL == inPtr)
1948 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001949 if (0 != j)
1950 {
1951 *pNumChannels = j;
1952 return VOS_STATUS_SUCCESS;
1953 }
1954 else
1955 {
1956 return -EINVAL;
1957 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001958 }
1959
1960 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001961 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001962
1963 /*no channel list after the number of channels argument and spaces*/
1964 if ( '\0' == *inPtr )
1965 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001966 if (0 != j)
1967 {
1968 *pNumChannels = j;
1969 return VOS_STATUS_SUCCESS;
1970 }
1971 else
1972 {
1973 return -EINVAL;
1974 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001975 }
1976
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001977 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001978 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001979 if ((v < 0) ||
1980 (tempInt <= 0) ||
1981 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
1982 {
1983 return -EINVAL;
1984 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001985 pChannelList[j] = tempInt;
1986
1987 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1988 "Channel %d added to preferred channel list",
1989 pChannelList[j] );
1990 }
1991
Srinivas Girigowdade697412013-02-14 16:31:48 -08001992 return VOS_STATUS_SUCCESS;
1993}
1994
Jeff Johnson295189b2012-06-20 16:38:30 -07001995/**---------------------------------------------------------------------------
1996
1997 \brief hdd_open() - HDD Open function
1998
1999 This is called in response to ifconfig up
2000
2001 \param - dev Pointer to net_device structure
2002
2003 \return - 0 for success non-zero for failure
2004
2005 --------------------------------------------------------------------------*/
2006int hdd_open (struct net_device *dev)
2007{
2008 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2009 hdd_context_t *pHddCtx;
2010 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2011 VOS_STATUS status;
2012 v_BOOL_t in_standby = TRUE;
2013
2014 if (NULL == pAdapter)
2015 {
2016 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002017 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002018 return -ENODEV;
2019 }
2020
2021 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2022 if (NULL == pHddCtx)
2023 {
2024 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002025 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002026 return -ENODEV;
2027 }
2028
2029 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2030 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2031 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002032 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2033 {
2034 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302035 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002036 in_standby = FALSE;
2037 break;
2038 }
2039 else
2040 {
2041 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2042 pAdapterNode = pNext;
2043 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002044 }
2045
2046 if (TRUE == in_standby)
2047 {
2048 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2049 {
2050 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2051 "wlan out of power save", __func__);
2052 return -EINVAL;
2053 }
2054 }
2055
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002056 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002057 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2058 {
2059 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002060 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002061 /* Enable TX queues only when we are connected */
2062 netif_tx_start_all_queues(dev);
2063 }
2064
2065 return 0;
2066}
2067
2068int hdd_mon_open (struct net_device *dev)
2069{
2070 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2071
2072 if(pAdapter == NULL) {
2073 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002074 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002075 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002076 }
2077
2078 netif_start_queue(dev);
2079
2080 return 0;
2081}
2082/**---------------------------------------------------------------------------
2083
2084 \brief hdd_stop() - HDD stop function
2085
2086 This is called in response to ifconfig down
2087
2088 \param - dev Pointer to net_device structure
2089
2090 \return - 0 for success non-zero for failure
2091
2092 --------------------------------------------------------------------------*/
2093
2094int hdd_stop (struct net_device *dev)
2095{
2096 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2097 hdd_context_t *pHddCtx;
2098 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2099 VOS_STATUS status;
2100 v_BOOL_t enter_standby = TRUE;
2101
2102 ENTER();
2103
2104 if (NULL == pAdapter)
2105 {
2106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002107 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002108 return -ENODEV;
2109 }
2110
2111 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2112 if (NULL == pHddCtx)
2113 {
2114 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002115 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002116 return -ENODEV;
2117 }
2118
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002119 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002120 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2121 netif_tx_disable(pAdapter->dev);
2122 netif_carrier_off(pAdapter->dev);
2123
2124
2125 /* SoftAP ifaces should never go in power save mode
2126 making sure same here. */
2127 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2128 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002129 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002130 )
2131 {
2132 /* SoftAP mode, so return from here */
2133 EXIT();
2134 return 0;
2135 }
2136
2137 /* Find if any iface is up then
2138 if any iface is up then can't put device to sleep/ power save mode. */
2139 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2140 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2141 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002142 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2143 {
2144 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302145 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002146 enter_standby = FALSE;
2147 break;
2148 }
2149 else
2150 {
2151 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2152 pAdapterNode = pNext;
2153 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002154 }
2155
2156 if (TRUE == enter_standby)
2157 {
2158 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2159 "entering standby", __func__);
2160 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2161 {
2162 /*log and return success*/
2163 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2164 "wlan in power save", __func__);
2165 }
2166 }
2167
2168 EXIT();
2169 return 0;
2170}
2171
2172/**---------------------------------------------------------------------------
2173
2174 \brief hdd_uninit() - HDD uninit function
2175
2176 This is called during the netdev unregister to uninitialize all data
2177associated with the device
2178
2179 \param - dev Pointer to net_device structure
2180
2181 \return - void
2182
2183 --------------------------------------------------------------------------*/
2184static void hdd_uninit (struct net_device *dev)
2185{
2186 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2187
2188 ENTER();
2189
2190 do
2191 {
2192 if (NULL == pAdapter)
2193 {
2194 hddLog(VOS_TRACE_LEVEL_FATAL,
2195 "%s: NULL pAdapter", __func__);
2196 break;
2197 }
2198
2199 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2200 {
2201 hddLog(VOS_TRACE_LEVEL_FATAL,
2202 "%s: Invalid magic", __func__);
2203 break;
2204 }
2205
2206 if (NULL == pAdapter->pHddCtx)
2207 {
2208 hddLog(VOS_TRACE_LEVEL_FATAL,
2209 "%s: NULL pHddCtx", __func__);
2210 break;
2211 }
2212
2213 if (dev != pAdapter->dev)
2214 {
2215 hddLog(VOS_TRACE_LEVEL_FATAL,
2216 "%s: Invalid device reference", __func__);
2217 /* we haven't validated all cases so let this go for now */
2218 }
2219
2220 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2221
2222 /* after uninit our adapter structure will no longer be valid */
2223 pAdapter->dev = NULL;
2224 pAdapter->magic = 0;
2225 } while (0);
2226
2227 EXIT();
2228}
2229
2230/**---------------------------------------------------------------------------
2231
2232 \brief hdd_release_firmware() -
2233
2234 This function calls the release firmware API to free the firmware buffer.
2235
2236 \param - pFileName Pointer to the File Name.
2237 pCtx - Pointer to the adapter .
2238
2239
2240 \return - 0 for success, non zero for failure
2241
2242 --------------------------------------------------------------------------*/
2243
2244VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2245{
2246 VOS_STATUS status = VOS_STATUS_SUCCESS;
2247 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2248 ENTER();
2249
2250
2251 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2252
2253 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2254
2255 if(pHddCtx->fw) {
2256 release_firmware(pHddCtx->fw);
2257 pHddCtx->fw = NULL;
2258 }
2259 else
2260 status = VOS_STATUS_E_FAILURE;
2261 }
2262 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2263 if(pHddCtx->nv) {
2264 release_firmware(pHddCtx->nv);
2265 pHddCtx->nv = NULL;
2266 }
2267 else
2268 status = VOS_STATUS_E_FAILURE;
2269
2270 }
2271
2272 EXIT();
2273 return status;
2274}
2275
2276/**---------------------------------------------------------------------------
2277
2278 \brief hdd_request_firmware() -
2279
2280 This function reads the firmware file using the request firmware
2281 API and returns the the firmware data and the firmware file size.
2282
2283 \param - pfileName - Pointer to the file name.
2284 - pCtx - Pointer to the adapter .
2285 - ppfw_data - Pointer to the pointer of the firmware data.
2286 - pSize - Pointer to the file size.
2287
2288 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2289
2290 --------------------------------------------------------------------------*/
2291
2292
2293VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2294{
2295 int status;
2296 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2297 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2298 ENTER();
2299
2300 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2301
2302 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2303
2304 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2305 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2306 __func__, pfileName);
2307 retval = VOS_STATUS_E_FAILURE;
2308 }
2309
2310 else {
2311 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2312 *pSize = pHddCtx->fw->size;
2313 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2314 __func__, *pSize);
2315 }
2316 }
2317 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2318
2319 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2320
2321 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2322 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2323 __func__, pfileName);
2324 retval = VOS_STATUS_E_FAILURE;
2325 }
2326
2327 else {
2328 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2329 *pSize = pHddCtx->nv->size;
2330 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2331 __func__, *pSize);
2332 }
2333 }
2334
2335 EXIT();
2336 return retval;
2337}
2338/**---------------------------------------------------------------------------
2339 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2340
2341 This is the function invoked by SME to inform the result of a full power
2342 request issued by HDD
2343
2344 \param - callbackcontext - Pointer to cookie
2345 status - result of request
2346
2347 \return - None
2348
2349--------------------------------------------------------------------------*/
2350void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2351{
2352 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2353
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002354 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002355 if(&pHddCtx->full_pwr_comp_var)
2356 {
2357 complete(&pHddCtx->full_pwr_comp_var);
2358 }
2359}
2360
2361/**---------------------------------------------------------------------------
2362
2363 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2364
2365 This is the function invoked by SME to inform the result of BMPS
2366 request issued by HDD
2367
2368 \param - callbackcontext - Pointer to cookie
2369 status - result of request
2370
2371 \return - None
2372
2373--------------------------------------------------------------------------*/
2374void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2375{
2376
2377 struct completion *completion_var = (struct completion*) callbackContext;
2378
2379 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2380 if(completion_var != NULL)
2381 {
2382 complete(completion_var);
2383 }
2384}
2385
2386/**---------------------------------------------------------------------------
2387
2388 \brief hdd_get_cfg_file_size() -
2389
2390 This function reads the configuration file using the request firmware
2391 API and returns the configuration file size.
2392
2393 \param - pCtx - Pointer to the adapter .
2394 - pFileName - Pointer to the file name.
2395 - pBufSize - Pointer to the buffer size.
2396
2397 \return - 0 for success, non zero for failure
2398
2399 --------------------------------------------------------------------------*/
2400
2401VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2402{
2403 int status;
2404 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2405
2406 ENTER();
2407
2408 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2409
2410 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2411 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2412 status = VOS_STATUS_E_FAILURE;
2413 }
2414 else {
2415 *pBufSize = pHddCtx->fw->size;
2416 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2417 release_firmware(pHddCtx->fw);
2418 pHddCtx->fw = NULL;
2419 }
2420
2421 EXIT();
2422 return VOS_STATUS_SUCCESS;
2423}
2424
2425/**---------------------------------------------------------------------------
2426
2427 \brief hdd_read_cfg_file() -
2428
2429 This function reads the configuration file using the request firmware
2430 API and returns the cfg data and the buffer size of the configuration file.
2431
2432 \param - pCtx - Pointer to the adapter .
2433 - pFileName - Pointer to the file name.
2434 - pBuffer - Pointer to the data buffer.
2435 - pBufSize - Pointer to the buffer size.
2436
2437 \return - 0 for success, non zero for failure
2438
2439 --------------------------------------------------------------------------*/
2440
2441VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2442 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2443{
2444 int status;
2445 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2446
2447 ENTER();
2448
2449 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2450
2451 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2452 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2453 return VOS_STATUS_E_FAILURE;
2454 }
2455 else {
2456 if(*pBufSize != pHddCtx->fw->size) {
2457 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2458 "file size", __func__);
2459 release_firmware(pHddCtx->fw);
2460 pHddCtx->fw = NULL;
2461 return VOS_STATUS_E_FAILURE;
2462 }
2463 else {
2464 if(pBuffer) {
2465 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2466 }
2467 release_firmware(pHddCtx->fw);
2468 pHddCtx->fw = NULL;
2469 }
2470 }
2471
2472 EXIT();
2473
2474 return VOS_STATUS_SUCCESS;
2475}
2476
2477/**---------------------------------------------------------------------------
2478
Jeff Johnson295189b2012-06-20 16:38:30 -07002479 \brief hdd_set_mac_address() -
2480
2481 This function sets the user specified mac address using
2482 the command ifconfig wlanX hw ether <mac adress>.
2483
2484 \param - dev - Pointer to the net device.
2485 - addr - Pointer to the sockaddr.
2486 \return - 0 for success, non zero for failure
2487
2488 --------------------------------------------------------------------------*/
2489
2490static int hdd_set_mac_address(struct net_device *dev, void *addr)
2491{
2492 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2493 struct sockaddr *psta_mac_addr = addr;
2494 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2495
2496 ENTER();
2497
2498 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2499
2500#ifdef HDD_SESSIONIZE
2501 // set the MAC address though the STA ID CFG.
2502 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2503 (v_U8_t *)&pAdapter->macAddressCurrent,
2504 sizeof( pAdapter->macAddressCurrent ),
2505 hdd_set_mac_addr_cb, VOS_FALSE );
2506#endif
2507
2508 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2509
2510 EXIT();
2511 return halStatus;
2512}
2513
2514tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2515{
2516 int i;
2517 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2518 {
2519 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2520 break;
2521 }
2522
2523 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2524 return NULL;
2525
2526 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2527 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2528}
2529
2530void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2531{
2532 int i;
2533 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2534 {
2535 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2536 {
2537 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2538 break;
2539 }
2540 }
2541 return;
2542}
2543
2544#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2545 static struct net_device_ops wlan_drv_ops = {
2546 .ndo_open = hdd_open,
2547 .ndo_stop = hdd_stop,
2548 .ndo_uninit = hdd_uninit,
2549 .ndo_start_xmit = hdd_hard_start_xmit,
2550 .ndo_tx_timeout = hdd_tx_timeout,
2551 .ndo_get_stats = hdd_stats,
2552 .ndo_do_ioctl = hdd_ioctl,
2553 .ndo_set_mac_address = hdd_set_mac_address,
2554 .ndo_select_queue = hdd_select_queue,
2555#ifdef WLAN_FEATURE_PACKET_FILTERING
2556#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2557 .ndo_set_rx_mode = hdd_set_multicast_list,
2558#else
2559 .ndo_set_multicast_list = hdd_set_multicast_list,
2560#endif //LINUX_VERSION_CODE
2561#endif
2562 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002563 static struct net_device_ops wlan_mon_drv_ops = {
2564 .ndo_open = hdd_mon_open,
2565 .ndo_stop = hdd_stop,
2566 .ndo_uninit = hdd_uninit,
2567 .ndo_start_xmit = hdd_mon_hard_start_xmit,
2568 .ndo_tx_timeout = hdd_tx_timeout,
2569 .ndo_get_stats = hdd_stats,
2570 .ndo_do_ioctl = hdd_ioctl,
2571 .ndo_set_mac_address = hdd_set_mac_address,
2572 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002573
2574#endif
2575
2576void hdd_set_station_ops( struct net_device *pWlanDev )
2577{
2578#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2579 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
2580 pWlanDev->netdev_ops = &wlan_drv_ops;
2581#else
2582 pWlanDev->open = hdd_open;
2583 pWlanDev->stop = hdd_stop;
2584 pWlanDev->uninit = hdd_uninit;
2585 pWlanDev->hard_start_xmit = NULL;
2586 pWlanDev->tx_timeout = hdd_tx_timeout;
2587 pWlanDev->get_stats = hdd_stats;
2588 pWlanDev->do_ioctl = hdd_ioctl;
2589 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
2590 pWlanDev->set_mac_address = hdd_set_mac_address;
2591#endif
2592}
2593
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002594static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07002595{
2596 struct net_device *pWlanDev = NULL;
2597 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002598 /*
2599 * cfg80211 initialization and registration....
2600 */
2601 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
2602
Jeff Johnson295189b2012-06-20 16:38:30 -07002603 if(pWlanDev != NULL)
2604 {
2605
2606 //Save the pointer to the net_device in the HDD adapter
2607 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
2608
Jeff Johnson295189b2012-06-20 16:38:30 -07002609 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
2610
2611 pAdapter->dev = pWlanDev;
2612 pAdapter->pHddCtx = pHddCtx;
2613 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2614
2615 init_completion(&pAdapter->session_open_comp_var);
2616 init_completion(&pAdapter->session_close_comp_var);
2617 init_completion(&pAdapter->disconnect_comp_var);
2618 init_completion(&pAdapter->linkup_event_var);
2619 init_completion(&pAdapter->cancel_rem_on_chan_var);
2620 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07002621#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2622 init_completion(&pAdapter->offchannel_tx_event);
2623#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002624 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002625#ifdef FEATURE_WLAN_TDLS
2626 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002627 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002628 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002629#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002630 init_completion(&pHddCtx->mc_sus_event_var);
2631 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07002632 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07002633
Jeff Johnson295189b2012-06-20 16:38:30 -07002634 pAdapter->isLinkUpSvcNeeded = FALSE;
2635 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
2636 //Init the net_device structure
2637 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2638
2639 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
2640 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
2641 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
2642 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
2643
2644 hdd_set_station_ops( pAdapter->dev );
2645
2646 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002647 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
2648 pAdapter->wdev.wiphy = pHddCtx->wiphy;
2649 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002650 /* set pWlanDev's parent to underlying device */
2651 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
2652 }
2653
2654 return pAdapter;
2655}
2656
2657VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
2658{
2659 struct net_device *pWlanDev = pAdapter->dev;
2660 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2661 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2662 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2663
2664 if( rtnl_lock_held )
2665 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08002666 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07002667 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
2668 {
2669 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
2670 return VOS_STATUS_E_FAILURE;
2671 }
2672 }
2673 if (register_netdevice(pWlanDev))
2674 {
2675 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
2676 return VOS_STATUS_E_FAILURE;
2677 }
2678 }
2679 else
2680 {
2681 if(register_netdev(pWlanDev))
2682 {
2683 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
2684 return VOS_STATUS_E_FAILURE;
2685 }
2686 }
2687 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
2688
2689 return VOS_STATUS_SUCCESS;
2690}
2691
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002692static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07002693{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002694 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07002695
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002696 if (NULL == pAdapter)
2697 {
2698 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
2699 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07002700 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002701
2702 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2703 {
2704 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
2705 return eHAL_STATUS_NOT_INITIALIZED;
2706 }
2707
2708 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
2709
2710 /* need to make sure all of our scheduled work has completed.
2711 * This callback is called from MC thread context, so it is safe to
2712 * to call below flush workqueue API from here.
2713 */
2714 flush_scheduled_work();
2715
2716 /* We can be blocked while waiting for scheduled work to be
2717 * flushed, and the adapter structure can potentially be freed, in
2718 * which case the magic will have been reset. So make sure the
2719 * magic is still good, and hence the adapter structure is still
2720 * valid, before signaling completion */
2721 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
2722 {
2723 complete(&pAdapter->session_close_comp_var);
2724 }
2725
Jeff Johnson295189b2012-06-20 16:38:30 -07002726 return eHAL_STATUS_SUCCESS;
2727}
2728
2729VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
2730{
2731 struct net_device *pWlanDev = pAdapter->dev;
2732 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2733 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2734 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2735 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2736 int rc = 0;
2737
2738 INIT_COMPLETION(pAdapter->session_open_comp_var);
2739 //Open a SME session for future operation
2740 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
2741 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
2742 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2743 {
2744 hddLog(VOS_TRACE_LEVEL_FATAL,
2745 "sme_OpenSession() failed with status code %08d [x%08lx]",
2746 halStatus, halStatus );
2747 status = VOS_STATUS_E_FAILURE;
2748 goto error_sme_open;
2749 }
2750
2751 //Block on a completion variable. Can't wait forever though.
2752 rc = wait_for_completion_interruptible_timeout(
2753 &pAdapter->session_open_comp_var,
2754 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2755 if (!rc)
2756 {
2757 hddLog(VOS_TRACE_LEVEL_FATAL,
2758 "Session is not opened within timeout period code %08d", rc );
2759 status = VOS_STATUS_E_FAILURE;
2760 goto error_sme_open;
2761 }
2762
2763 // Register wireless extensions
2764 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
2765 {
2766 hddLog(VOS_TRACE_LEVEL_FATAL,
2767 "hdd_register_wext() failed with status code %08d [x%08lx]",
2768 halStatus, halStatus );
2769 status = VOS_STATUS_E_FAILURE;
2770 goto error_register_wext;
2771 }
2772 //Safe to register the hard_start_xmit function again
2773#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2774 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
2775#else
2776 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
2777#endif
2778
2779 //Set the Connection State to Not Connected
2780 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2781
2782 //Set the default operation channel
2783 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
2784
2785 /* Make the default Auth Type as OPEN*/
2786 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2787
2788 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
2789 {
2790 hddLog(VOS_TRACE_LEVEL_FATAL,
2791 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
2792 status, status );
2793 goto error_init_txrx;
2794 }
2795
2796 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2797
2798 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
2799 {
2800 hddLog(VOS_TRACE_LEVEL_FATAL,
2801 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
2802 status, status );
2803 goto error_wmm_init;
2804 }
2805
2806 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2807
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002808#ifdef FEATURE_WLAN_TDLS
2809 if(0 != wlan_hdd_tdls_init(pAdapter))
2810 {
2811 status = VOS_STATUS_E_FAILURE;
2812 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
2813 goto error_tdls_init;
2814 }
2815 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2816#endif
2817
Jeff Johnson295189b2012-06-20 16:38:30 -07002818 return VOS_STATUS_SUCCESS;
2819
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002820#ifdef FEATURE_WLAN_TDLS
2821error_tdls_init:
2822 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2823 hdd_wmm_adapter_close(pAdapter);
2824#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002825error_wmm_init:
2826 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2827 hdd_deinit_tx_rx(pAdapter);
2828error_init_txrx:
2829 hdd_UnregisterWext(pWlanDev);
2830error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002831 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07002832 {
2833 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002834 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002835 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002836 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07002837 {
2838 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002839 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07002840 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002841 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07002842 }
2843}
2844error_sme_open:
2845 return status;
2846}
2847
Jeff Johnson295189b2012-06-20 16:38:30 -07002848void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2849{
2850 hdd_cfg80211_state_t *cfgState;
2851
2852 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
2853
2854 if( NULL != cfgState->buf )
2855 {
2856 int rc;
2857 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
2858 rc = wait_for_completion_interruptible_timeout(
2859 &pAdapter->tx_action_cnf_event,
2860 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2861 if(!rc)
2862 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08002863 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002864 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
2865 }
2866 }
2867 return;
2868}
Jeff Johnson295189b2012-06-20 16:38:30 -07002869
2870void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2871{
2872 ENTER();
2873 switch ( pAdapter->device_mode )
2874 {
2875 case WLAN_HDD_INFRA_STATION:
2876 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002877 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002878 {
2879 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2880 {
2881 hdd_deinit_tx_rx( pAdapter );
2882 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2883 }
2884
2885 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
2886 {
2887 hdd_wmm_adapter_close( pAdapter );
2888 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2889 }
2890
Jeff Johnson295189b2012-06-20 16:38:30 -07002891 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002892#ifdef FEATURE_WLAN_TDLS
2893 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
2894 {
2895 wlan_hdd_tdls_exit(pAdapter);
2896 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2897 }
2898#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002899
2900 break;
2901 }
2902
2903 case WLAN_HDD_SOFTAP:
2904 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002905 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002906 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002907
2908 hdd_unregister_hostapd(pAdapter);
2909 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07002910 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07002911 break;
2912 }
2913
2914 case WLAN_HDD_MONITOR:
2915 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002916 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07002917 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2918 {
2919 hdd_deinit_tx_rx( pAdapter );
2920 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2921 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002922 if(NULL != pAdapterforTx)
2923 {
2924 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
2925 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002926 break;
2927 }
2928
2929
2930 default:
2931 break;
2932 }
2933
2934 EXIT();
2935}
2936
2937void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
2938{
2939 struct net_device *pWlanDev = pAdapter->dev;
2940
2941 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
2942 if( rtnl_held )
2943 {
2944 unregister_netdevice(pWlanDev);
2945 }
2946 else
2947 {
2948 unregister_netdev(pWlanDev);
2949 }
2950 // note that the pAdapter is no longer valid at this point
2951 // since the memory has been reclaimed
2952 }
2953
2954}
2955
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002956void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2957{
2958 tSirSetPowerParamsReq powerRequest = { 0 };
2959
2960 powerRequest.uIgnoreDTIM = 1;
2961
2962 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2963 {
2964 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2965 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2966 }
2967 else
2968 {
2969 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2970 }
2971
2972 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2973 *specified during Enter/Exit BMPS when LCD off*/
2974 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2975 NULL, eANI_BOOLEAN_FALSE);
2976 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2977 NULL, eANI_BOOLEAN_FALSE);
2978
2979 /* switch to the DTIM specified in cfg.ini */
2980 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2981 "Switch to DTIM%d", powerRequest.uListenInterval);
2982 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2983
2984}
2985
2986void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2987{
2988 /*Switch back to DTIM 1*/
2989 tSirSetPowerParamsReq powerRequest = { 0 };
2990
2991 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2992 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2993
2994 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2995 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2996 NULL, eANI_BOOLEAN_FALSE);
2997 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2998 NULL, eANI_BOOLEAN_FALSE);
2999
3000 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3001 "Switch to DTIM%d",powerRequest.uListenInterval);
3002 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3003
3004}
3005
Jeff Johnson295189b2012-06-20 16:38:30 -07003006VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3007{
3008 VOS_STATUS status = VOS_STATUS_SUCCESS;
3009
3010 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3011 {
3012 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3013 }
3014
3015 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3016 {
3017 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3018 }
3019
3020 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3021 {
3022 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3023 }
3024
3025 return status;
3026}
3027
3028VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3029{
3030 hdd_adapter_t *pAdapter = NULL;
3031 eHalStatus halStatus;
3032 VOS_STATUS status = VOS_STATUS_E_INVAL;
3033 v_BOOL_t disableBmps = FALSE;
3034 v_BOOL_t disableImps = FALSE;
3035
3036 switch(session_type)
3037 {
3038 case WLAN_HDD_INFRA_STATION:
3039 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003040 case WLAN_HDD_P2P_CLIENT:
3041 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003042 //Exit BMPS -> Is Sta/P2P Client is already connected
3043 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3044 if((NULL != pAdapter)&&
3045 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3046 {
3047 disableBmps = TRUE;
3048 }
3049
3050 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3051 if((NULL != pAdapter)&&
3052 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3053 {
3054 disableBmps = TRUE;
3055 }
3056
3057 //Exit both Bmps and Imps incase of Go/SAP Mode
3058 if((WLAN_HDD_SOFTAP == session_type) ||
3059 (WLAN_HDD_P2P_GO == session_type))
3060 {
3061 disableBmps = TRUE;
3062 disableImps = TRUE;
3063 }
3064
3065 if(TRUE == disableImps)
3066 {
3067 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3068 {
3069 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3070 }
3071 }
3072
3073 if(TRUE == disableBmps)
3074 {
3075 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3076 {
3077 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3078
3079 if(eHAL_STATUS_SUCCESS != halStatus)
3080 {
3081 status = VOS_STATUS_E_FAILURE;
3082 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3083 VOS_ASSERT(0);
3084 return status;
3085 }
3086 }
3087
3088 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3089 {
3090 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3091
3092 if(eHAL_STATUS_SUCCESS != halStatus)
3093 {
3094 status = VOS_STATUS_E_FAILURE;
3095 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3096 VOS_ASSERT(0);
3097 return status;
3098 }
3099 }
3100 }
3101
3102 if((TRUE == disableBmps) ||
3103 (TRUE == disableImps))
3104 {
3105 /* Now, get the chip into Full Power now */
3106 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3107 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3108 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3109
3110 if(halStatus != eHAL_STATUS_SUCCESS)
3111 {
3112 if(halStatus == eHAL_STATUS_PMC_PENDING)
3113 {
3114 //Block on a completion variable. Can't wait forever though
3115 wait_for_completion_interruptible_timeout(
3116 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3117 }
3118 else
3119 {
3120 status = VOS_STATUS_E_FAILURE;
3121 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3122 VOS_ASSERT(0);
3123 return status;
3124 }
3125 }
3126
3127 status = VOS_STATUS_SUCCESS;
3128 }
3129
3130 break;
3131 }
3132 return status;
3133}
3134
3135hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003136 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003137 tANI_U8 rtnl_held )
3138{
3139 hdd_adapter_t *pAdapter = NULL;
3140 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3141 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3142 VOS_STATUS exitbmpsStatus;
3143
3144 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3145
3146 //Disable BMPS incase of Concurrency
3147 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3148
3149 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3150 {
3151 //Fail to Exit BMPS
3152 VOS_ASSERT(0);
3153 return NULL;
3154 }
3155
3156 switch(session_type)
3157 {
3158 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003159 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003160 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003161 {
3162 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3163
3164 if( NULL == pAdapter )
3165 return NULL;
3166
Jeff Johnsone7245742012-09-05 17:12:55 -07003167 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3168 NL80211_IFTYPE_P2P_CLIENT:
3169 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003170
Jeff Johnson295189b2012-06-20 16:38:30 -07003171 pAdapter->device_mode = session_type;
3172
3173 status = hdd_init_station_mode( pAdapter );
3174 if( VOS_STATUS_SUCCESS != status )
3175 goto err_free_netdev;
3176
3177 status = hdd_register_interface( pAdapter, rtnl_held );
3178 if( VOS_STATUS_SUCCESS != status )
3179 {
3180 hdd_deinit_adapter(pHddCtx, pAdapter);
3181 goto err_free_netdev;
3182 }
3183 //Stop the Interface TX queue.
3184 netif_tx_disable(pAdapter->dev);
3185 //netif_tx_disable(pWlanDev);
3186 netif_carrier_off(pAdapter->dev);
3187
3188 break;
3189 }
3190
Jeff Johnson295189b2012-06-20 16:38:30 -07003191 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003192 case WLAN_HDD_SOFTAP:
3193 {
3194 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3195 if( NULL == pAdapter )
3196 return NULL;
3197
Jeff Johnson295189b2012-06-20 16:38:30 -07003198 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3199 NL80211_IFTYPE_AP:
3200 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003201 pAdapter->device_mode = session_type;
3202
3203 status = hdd_init_ap_mode(pAdapter);
3204 if( VOS_STATUS_SUCCESS != status )
3205 goto err_free_netdev;
3206
3207 status = hdd_register_hostapd( pAdapter, rtnl_held );
3208 if( VOS_STATUS_SUCCESS != status )
3209 {
3210 hdd_deinit_adapter(pHddCtx, pAdapter);
3211 goto err_free_netdev;
3212 }
3213
3214 netif_tx_disable(pAdapter->dev);
3215 netif_carrier_off(pAdapter->dev);
3216
3217 hdd_set_conparam( 1 );
3218 break;
3219 }
3220 case WLAN_HDD_MONITOR:
3221 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003222 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3223 if( NULL == pAdapter )
3224 return NULL;
3225
3226 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3227 pAdapter->device_mode = session_type;
3228 status = hdd_register_interface( pAdapter, rtnl_held );
3229#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3230 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3231#else
3232 pAdapter->dev->open = hdd_mon_open;
3233 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3234#endif
3235 hdd_init_tx_rx( pAdapter );
3236 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3237 //Set adapter to be used for data tx. It will use either GO or softap.
3238 pAdapter->sessionCtx.monitor.pAdapterForTx =
3239 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003240 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3241 {
3242 pAdapter->sessionCtx.monitor.pAdapterForTx =
3243 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3244 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003245 /* This workqueue will be used to transmit management packet over
3246 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003247 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3248 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3249 return NULL;
3250 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003251
Jeff Johnson295189b2012-06-20 16:38:30 -07003252 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3253 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003254 }
3255 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003256 case WLAN_HDD_FTM:
3257 {
3258 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3259
3260 if( NULL == pAdapter )
3261 return NULL;
3262 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3263 * message while loading driver in FTM mode. */
3264 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3265 pAdapter->device_mode = session_type;
3266 status = hdd_register_interface( pAdapter, rtnl_held );
3267 }
3268 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003269 default:
3270 {
3271 VOS_ASSERT(0);
3272 return NULL;
3273 }
3274 }
3275
3276
3277 if( VOS_STATUS_SUCCESS == status )
3278 {
3279 //Add it to the hdd's session list.
3280 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3281 if( NULL == pHddAdapterNode )
3282 {
3283 status = VOS_STATUS_E_NOMEM;
3284 }
3285 else
3286 {
3287 pHddAdapterNode->pAdapter = pAdapter;
3288 status = hdd_add_adapter_back ( pHddCtx,
3289 pHddAdapterNode );
3290 }
3291 }
3292
3293 if( VOS_STATUS_SUCCESS != status )
3294 {
3295 if( NULL != pAdapter )
3296 {
3297 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3298 pAdapter = NULL;
3299 }
3300 if( NULL != pHddAdapterNode )
3301 {
3302 vos_mem_free( pHddAdapterNode );
3303 }
3304
3305 goto resume_bmps;
3306 }
3307
3308 if(VOS_STATUS_SUCCESS == status)
3309 {
3310 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3311
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003312 //Initialize the WoWL service
3313 if(!hdd_init_wowl(pAdapter))
3314 {
3315 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3316 goto err_free_netdev;
3317 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003318 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003319 return pAdapter;
3320
3321err_free_netdev:
3322 free_netdev(pAdapter->dev);
3323 wlan_hdd_release_intf_addr( pHddCtx,
3324 pAdapter->macAddressCurrent.bytes );
3325
3326resume_bmps:
3327 //If bmps disabled enable it
3328 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3329 {
3330 hdd_enable_bmps_imps(pHddCtx);
3331 }
3332 return NULL;
3333}
3334
3335VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3336 tANI_U8 rtnl_held )
3337{
3338 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3339 VOS_STATUS status;
3340
3341 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3342 if( VOS_STATUS_SUCCESS != status )
3343 return status;
3344
3345 while ( pCurrent->pAdapter != pAdapter )
3346 {
3347 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3348 if( VOS_STATUS_SUCCESS != status )
3349 break;
3350
3351 pCurrent = pNext;
3352 }
3353 pAdapterNode = pCurrent;
3354 if( VOS_STATUS_SUCCESS == status )
3355 {
3356 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3357 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3358 hdd_remove_adapter( pHddCtx, pAdapterNode );
3359 vos_mem_free( pAdapterNode );
3360
Jeff Johnson295189b2012-06-20 16:38:30 -07003361
3362 /* If there is a single session of STA/P2P client, re-enable BMPS */
3363 if ((!vos_concurrent_sessions_running()) &&
3364 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3365 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3366 {
3367 hdd_enable_bmps_imps(pHddCtx);
3368 }
3369
3370 return VOS_STATUS_SUCCESS;
3371 }
3372
3373 return VOS_STATUS_E_FAILURE;
3374}
3375
3376VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3377{
3378 hdd_adapter_list_node_t *pHddAdapterNode;
3379 VOS_STATUS status;
3380
3381 ENTER();
3382
3383 do
3384 {
3385 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3386 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3387 {
3388 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3389 vos_mem_free( pHddAdapterNode );
3390 }
3391 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3392
3393 EXIT();
3394
3395 return VOS_STATUS_SUCCESS;
3396}
3397
3398void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3399{
3400 v_U8_t addIE[1] = {0};
3401
3402 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3403 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3404 eANI_BOOLEAN_FALSE) )
3405 {
3406 hddLog(LOGE,
3407 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3408 }
3409
3410 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3411 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3412 eANI_BOOLEAN_FALSE) )
3413 {
3414 hddLog(LOGE,
3415 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3416 }
3417
3418 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3419 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3420 eANI_BOOLEAN_FALSE) )
3421 {
3422 hddLog(LOGE,
3423 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3424 }
3425}
3426
3427VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3428{
3429 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3430 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3431 union iwreq_data wrqu;
3432
3433 ENTER();
3434
3435 switch(pAdapter->device_mode)
3436 {
3437 case WLAN_HDD_INFRA_STATION:
3438 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003439 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003440 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3441 {
3442 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3443 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3444 pAdapter->sessionId,
3445 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3446 else
3447 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3448 pAdapter->sessionId,
3449 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3450 //success implies disconnect command got queued up successfully
3451 if(halStatus == eHAL_STATUS_SUCCESS)
3452 {
3453 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3454 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3455 }
3456 memset(&wrqu, '\0', sizeof(wrqu));
3457 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3458 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3459 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3460 }
3461 else
3462 {
3463 hdd_abort_mac_scan(pHddCtx);
3464 }
3465
3466 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3467 {
3468 INIT_COMPLETION(pAdapter->session_close_comp_var);
3469 if (eHAL_STATUS_SUCCESS ==
3470 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3471 hdd_smeCloseSessionCallback, pAdapter))
3472 {
3473 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003474 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003475 &pAdapter->session_close_comp_var,
3476 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3477 }
3478 }
3479
3480 break;
3481
3482 case WLAN_HDD_SOFTAP:
3483 case WLAN_HDD_P2P_GO:
3484 //Any softap specific cleanup here...
3485 mutex_lock(&pHddCtx->sap_lock);
3486 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3487 {
3488 VOS_STATUS status;
3489 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3490
3491 //Stop Bss.
3492 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3493 if (VOS_IS_STATUS_SUCCESS(status))
3494 {
3495 hdd_hostapd_state_t *pHostapdState =
3496 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3497
3498 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3499
3500 if (!VOS_IS_STATUS_SUCCESS(status))
3501 {
3502 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003503 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003504 }
3505 }
3506 else
3507 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003508 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003509 }
3510 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3511
3512 if (eHAL_STATUS_FAILURE ==
3513 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3514 0, NULL, eANI_BOOLEAN_FALSE))
3515 {
3516 hddLog(LOGE,
3517 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003518 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003519 }
3520
3521 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3522 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3523 eANI_BOOLEAN_FALSE) )
3524 {
3525 hddLog(LOGE,
3526 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3527 }
3528
3529 // Reset WNI_CFG_PROBE_RSP Flags
3530 wlan_hdd_reset_prob_rspies(pAdapter);
3531 kfree(pAdapter->sessionCtx.ap.beacon);
3532 pAdapter->sessionCtx.ap.beacon = NULL;
3533 }
3534 mutex_unlock(&pHddCtx->sap_lock);
3535 break;
3536 case WLAN_HDD_MONITOR:
3537 break;
3538 default:
3539 break;
3540 }
3541
3542 EXIT();
3543 return VOS_STATUS_SUCCESS;
3544}
3545
3546VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3547{
3548 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3549 VOS_STATUS status;
3550 hdd_adapter_t *pAdapter;
3551
3552 ENTER();
3553
3554 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3555
3556 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3557 {
3558 pAdapter = pAdapterNode->pAdapter;
3559 netif_tx_disable(pAdapter->dev);
3560 netif_carrier_off(pAdapter->dev);
3561
3562 hdd_stop_adapter( pHddCtx, pAdapter );
3563
3564 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3565 pAdapterNode = pNext;
3566 }
3567
3568 EXIT();
3569
3570 return VOS_STATUS_SUCCESS;
3571}
3572
3573VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
3574{
3575 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3576 VOS_STATUS status;
3577 hdd_adapter_t *pAdapter;
3578
3579 ENTER();
3580
3581 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3582
3583 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3584 {
3585 pAdapter = pAdapterNode->pAdapter;
3586 netif_tx_disable(pAdapter->dev);
3587 netif_carrier_off(pAdapter->dev);
3588
3589 //Record whether STA is associated
3590 pAdapter->sessionCtx.station.bSendDisconnect =
3591 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
3592 VOS_TRUE : VOS_FALSE;
3593
3594 hdd_deinit_tx_rx(pAdapter);
3595 hdd_wmm_adapter_close(pAdapter);
3596
3597 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3598 pAdapterNode = pNext;
3599 }
3600
3601 EXIT();
3602
3603 return VOS_STATUS_SUCCESS;
3604}
3605
3606VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
3607{
3608 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3609 VOS_STATUS status;
3610 hdd_adapter_t *pAdapter;
3611 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
3612
3613 ENTER();
3614
3615 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3616
3617 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3618 {
3619 pAdapter = pAdapterNode->pAdapter;
3620
3621 switch(pAdapter->device_mode)
3622 {
3623 case WLAN_HDD_INFRA_STATION:
3624 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003625 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003626 hdd_init_station_mode(pAdapter);
3627 /* Open the gates for HDD to receive Wext commands */
3628 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003629 pHddCtx->scan_info.mScanPending = FALSE;
3630 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003631
3632 //Trigger the initial scan
3633 hdd_wlan_initial_scan(pAdapter);
3634
3635 //Indicate disconnect event to supplicant if associated previously
3636 if(pAdapter->sessionCtx.station.bSendDisconnect)
3637 {
3638 union iwreq_data wrqu;
3639 memset(&wrqu, '\0', sizeof(wrqu));
3640 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3641 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3642 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3643 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
3644
Jeff Johnson295189b2012-06-20 16:38:30 -07003645 /* indicate disconnected event to nl80211 */
3646 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
3647 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003648 }
3649 break;
3650
3651 case WLAN_HDD_SOFTAP:
3652 /* softAP can handle SSR */
3653 break;
3654
3655 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003656 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
3657 __func__);
3658 /* event supplicant to restart */
3659 cfg80211_del_sta(pAdapter->dev,
3660 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003661 break;
3662
3663 case WLAN_HDD_MONITOR:
3664 /* monitor interface start */
3665 break;
3666 default:
3667 break;
3668 }
3669
3670 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3671 pAdapterNode = pNext;
3672 }
3673
3674 EXIT();
3675
3676 return VOS_STATUS_SUCCESS;
3677}
3678
3679VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
3680{
3681 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3682 hdd_adapter_t *pAdapter;
3683 VOS_STATUS status;
3684 v_U32_t roamId;
3685
3686 ENTER();
3687
3688 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3689
3690 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3691 {
3692 pAdapter = pAdapterNode->pAdapter;
3693
3694 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3695 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
3696 {
3697 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3698 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3699
3700 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3701 init_completion(&pAdapter->disconnect_comp_var);
3702 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
3703 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3704
3705 wait_for_completion_interruptible_timeout(
3706 &pAdapter->disconnect_comp_var,
3707 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3708
3709 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
3710 pHddCtx->isAmpAllowed = VOS_FALSE;
3711 sme_RoamConnect(pHddCtx->hHal,
3712 pAdapter->sessionId, &(pWextState->roamProfile),
3713 &roamId);
3714 }
3715
3716 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3717 pAdapterNode = pNext;
3718 }
3719
3720 EXIT();
3721
3722 return VOS_STATUS_SUCCESS;
3723}
3724
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07003725void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
3726{
3727 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3728 VOS_STATUS status;
3729 hdd_adapter_t *pAdapter;
3730 hdd_station_ctx_t *pHddStaCtx;
3731 hdd_ap_ctx_t *pHddApCtx;
3732 hdd_hostapd_state_t * pHostapdState;
3733 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
3734 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
3735 const char *p2pMode = "DEV";
3736 const char *ccMode = "Standalone";
3737 int n;
3738
3739 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3740 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3741 {
3742 pAdapter = pAdapterNode->pAdapter;
3743 switch (pAdapter->device_mode) {
3744 case WLAN_HDD_INFRA_STATION:
3745 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3746 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3747 staChannel = pHddStaCtx->conn_info.operationChannel;
3748 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
3749 }
3750 break;
3751 case WLAN_HDD_P2P_CLIENT:
3752 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3753 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3754 p2pChannel = pHddStaCtx->conn_info.operationChannel;
3755 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
3756 p2pMode = "CLI";
3757 }
3758 break;
3759 case WLAN_HDD_P2P_GO:
3760 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3761 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3762 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3763 p2pChannel = pHddApCtx->operatingChannel;
3764 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
3765 }
3766 p2pMode = "GO";
3767 break;
3768 case WLAN_HDD_SOFTAP:
3769 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3770 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3771 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3772 apChannel = pHddApCtx->operatingChannel;
3773 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
3774 }
3775 break;
3776 default:
3777 break;
3778 }
3779 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3780 pAdapterNode = pNext;
3781 }
3782 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
3783 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
3784 }
3785 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
3786 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
3787 if (p2pChannel > 0) {
3788 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
3789 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
3790 }
3791 if (apChannel > 0) {
3792 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
3793 apChannel, MAC_ADDR_ARRAY(apBssid));
3794 }
3795
3796 if (p2pChannel > 0 && apChannel > 0) {
3797 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
3798 }
3799}
3800
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003801bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07003802{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003803 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07003804}
3805
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003806/* Once SSR is disabled then it cannot be set. */
3807void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07003808{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003809 if (HDD_SSR_DISABLED == isSsrRequired)
3810 return;
3811
Jeff Johnson295189b2012-06-20 16:38:30 -07003812 isSsrRequired = value;
3813}
3814
3815VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
3816 hdd_adapter_list_node_t** ppAdapterNode)
3817{
3818 VOS_STATUS status;
3819 spin_lock(&pHddCtx->hddAdapters.lock);
3820 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
3821 (hdd_list_node_t**) ppAdapterNode );
3822 spin_unlock(&pHddCtx->hddAdapters.lock);
3823 return status;
3824}
3825
3826VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
3827 hdd_adapter_list_node_t* pAdapterNode,
3828 hdd_adapter_list_node_t** pNextAdapterNode)
3829{
3830 VOS_STATUS status;
3831 spin_lock(&pHddCtx->hddAdapters.lock);
3832 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
3833 (hdd_list_node_t*) pAdapterNode,
3834 (hdd_list_node_t**)pNextAdapterNode );
3835
3836 spin_unlock(&pHddCtx->hddAdapters.lock);
3837 return status;
3838}
3839
3840VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
3841 hdd_adapter_list_node_t* pAdapterNode)
3842{
3843 VOS_STATUS status;
3844 spin_lock(&pHddCtx->hddAdapters.lock);
3845 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
3846 &pAdapterNode->node );
3847 spin_unlock(&pHddCtx->hddAdapters.lock);
3848 return status;
3849}
3850
3851VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
3852 hdd_adapter_list_node_t** ppAdapterNode)
3853{
3854 VOS_STATUS status;
3855 spin_lock(&pHddCtx->hddAdapters.lock);
3856 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
3857 (hdd_list_node_t**) ppAdapterNode );
3858 spin_unlock(&pHddCtx->hddAdapters.lock);
3859 return status;
3860}
3861
3862VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
3863 hdd_adapter_list_node_t* pAdapterNode)
3864{
3865 VOS_STATUS status;
3866 spin_lock(&pHddCtx->hddAdapters.lock);
3867 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
3868 (hdd_list_node_t*) pAdapterNode );
3869 spin_unlock(&pHddCtx->hddAdapters.lock);
3870 return status;
3871}
3872
3873VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
3874 hdd_adapter_list_node_t* pAdapterNode)
3875{
3876 VOS_STATUS status;
3877 spin_lock(&pHddCtx->hddAdapters.lock);
3878 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
3879 (hdd_list_node_t*) pAdapterNode );
3880 spin_unlock(&pHddCtx->hddAdapters.lock);
3881 return status;
3882}
3883
3884hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
3885 tSirMacAddr macAddr )
3886{
3887 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3888 hdd_adapter_t *pAdapter;
3889 VOS_STATUS status;
3890
3891 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3892
3893 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3894 {
3895 pAdapter = pAdapterNode->pAdapter;
3896
3897 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
3898 macAddr, sizeof(tSirMacAddr) ) )
3899 {
3900 return pAdapter;
3901 }
3902 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3903 pAdapterNode = pNext;
3904 }
3905
3906 return NULL;
3907
3908}
3909
3910hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
3911{
3912 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3913 hdd_adapter_t *pAdapter;
3914 VOS_STATUS status;
3915
3916 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3917
3918 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3919 {
3920 pAdapter = pAdapterNode->pAdapter;
3921
3922 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
3923 IFNAMSIZ ) )
3924 {
3925 return pAdapter;
3926 }
3927 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3928 pAdapterNode = pNext;
3929 }
3930
3931 return NULL;
3932
3933}
3934
3935hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
3936{
3937 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3938 hdd_adapter_t *pAdapter;
3939 VOS_STATUS status;
3940
3941 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3942
3943 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3944 {
3945 pAdapter = pAdapterNode->pAdapter;
3946
3947 if( pAdapter && (mode == pAdapter->device_mode) )
3948 {
3949 return pAdapter;
3950 }
3951 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3952 pAdapterNode = pNext;
3953 }
3954
3955 return NULL;
3956
3957}
3958
3959//Remove this function later
3960hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
3961{
3962 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3963 hdd_adapter_t *pAdapter;
3964 VOS_STATUS status;
3965
3966 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3967
3968 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3969 {
3970 pAdapter = pAdapterNode->pAdapter;
3971
3972 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
3973 {
3974 return pAdapter;
3975 }
3976
3977 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3978 pAdapterNode = pNext;
3979 }
3980
3981 return NULL;
3982
3983}
3984
Jeff Johnson295189b2012-06-20 16:38:30 -07003985/**---------------------------------------------------------------------------
3986
3987 \brief hdd_set_monitor_tx_adapter() -
3988
3989 This API initializes the adapter to be used while transmitting on monitor
3990 adapter.
3991
3992 \param - pHddCtx - Pointer to the HDD context.
3993 pAdapter - Adapter that will used for TX. This can be NULL.
3994 \return - None.
3995 --------------------------------------------------------------------------*/
3996void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3997{
3998 hdd_adapter_t *pMonAdapter;
3999
4000 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
4001
4002 if( NULL != pMonAdapter )
4003 {
4004 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4005 }
4006}
Jeff Johnson295189b2012-06-20 16:38:30 -07004007/**---------------------------------------------------------------------------
4008
4009 \brief hdd_select_queue() -
4010
4011 This API returns the operating channel of the requested device mode
4012
4013 \param - pHddCtx - Pointer to the HDD context.
4014 - mode - Device mode for which operating channel is required
4015 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4016 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4017 \return - channel number. "0" id the requested device is not found OR it is not connected.
4018 --------------------------------------------------------------------------*/
4019v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4020{
4021 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4022 VOS_STATUS status;
4023 hdd_adapter_t *pAdapter;
4024 v_U8_t operatingChannel = 0;
4025
4026 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4027
4028 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4029 {
4030 pAdapter = pAdapterNode->pAdapter;
4031
4032 if( mode == pAdapter->device_mode )
4033 {
4034 switch(pAdapter->device_mode)
4035 {
4036 case WLAN_HDD_INFRA_STATION:
4037 case WLAN_HDD_P2P_CLIENT:
4038 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4039 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4040 break;
4041 case WLAN_HDD_SOFTAP:
4042 case WLAN_HDD_P2P_GO:
4043 /*softap connection info */
4044 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4045 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4046 break;
4047 default:
4048 break;
4049 }
4050
4051 break; //Found the device of interest. break the loop
4052 }
4053
4054 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4055 pAdapterNode = pNext;
4056 }
4057 return operatingChannel;
4058}
4059
4060#ifdef WLAN_FEATURE_PACKET_FILTERING
4061/**---------------------------------------------------------------------------
4062
4063 \brief hdd_set_multicast_list() -
4064
4065 This used to set the multicast address list.
4066
4067 \param - dev - Pointer to the WLAN device.
4068 - skb - Pointer to OS packet (sk_buff).
4069 \return - success/fail
4070
4071 --------------------------------------------------------------------------*/
4072static void hdd_set_multicast_list(struct net_device *dev)
4073{
4074 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004075 int mc_count;
4076 int i = 0;
4077 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304078
4079 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004080 {
4081 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304082 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004083 return;
4084 }
4085
4086 if (dev->flags & IFF_ALLMULTI)
4087 {
4088 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004089 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304090 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004091 }
4092 else
4093 {
4094 mc_count = netdev_mc_count(dev);
4095 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004096 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004097 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4098 {
4099 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004100 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304101 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004102 return;
4103 }
4104
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304105 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004106
4107 netdev_for_each_mc_addr(ha, dev) {
4108 if (i == mc_count)
4109 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304110 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4111 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4112 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004113 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304114 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004115 i++;
4116 }
4117 }
4118 return;
4119}
4120#endif
4121
4122/**---------------------------------------------------------------------------
4123
4124 \brief hdd_select_queue() -
4125
4126 This function is registered with the Linux OS for network
4127 core to decide which queue to use first.
4128
4129 \param - dev - Pointer to the WLAN device.
4130 - skb - Pointer to OS packet (sk_buff).
4131 \return - ac, Queue Index/access category corresponding to UP in IP header
4132
4133 --------------------------------------------------------------------------*/
4134v_U16_t hdd_select_queue(struct net_device *dev,
4135 struct sk_buff *skb)
4136{
4137 return hdd_wmm_select_queue(dev, skb);
4138}
4139
4140
4141/**---------------------------------------------------------------------------
4142
4143 \brief hdd_wlan_initial_scan() -
4144
4145 This function triggers the initial scan
4146
4147 \param - pAdapter - Pointer to the HDD adapter.
4148
4149 --------------------------------------------------------------------------*/
4150void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4151{
4152 tCsrScanRequest scanReq;
4153 tCsrChannelInfo channelInfo;
4154 eHalStatus halStatus;
4155 unsigned long scanId;
4156 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4157
4158 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4159 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4160 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4161
4162 if(sme_Is11dSupported(pHddCtx->hHal))
4163 {
4164 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4165 if ( HAL_STATUS_SUCCESS( halStatus ) )
4166 {
4167 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4168 if( !scanReq.ChannelInfo.ChannelList )
4169 {
4170 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4171 vos_mem_free(channelInfo.ChannelList);
4172 return;
4173 }
4174 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4175 channelInfo.numOfChannels);
4176 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4177 vos_mem_free(channelInfo.ChannelList);
4178 }
4179
4180 scanReq.scanType = eSIR_PASSIVE_SCAN;
4181 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4182 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4183 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4184 }
4185 else
4186 {
4187 scanReq.scanType = eSIR_ACTIVE_SCAN;
4188 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4189 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4190 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4191 }
4192
4193 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4194 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4195 {
4196 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4197 __func__, halStatus );
4198 }
4199
4200 if(sme_Is11dSupported(pHddCtx->hHal))
4201 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4202}
4203
4204struct fullPowerContext
4205{
4206 struct completion completion;
4207 unsigned int magic;
4208};
4209#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4210
4211/**---------------------------------------------------------------------------
4212
4213 \brief hdd_full_power_callback() - HDD full power callback function
4214
4215 This is the function invoked by SME to inform the result of a full power
4216 request issued by HDD
4217
4218 \param - callbackcontext - Pointer to cookie
4219 \param - status - result of request
4220
4221 \return - None
4222
4223 --------------------------------------------------------------------------*/
4224static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4225{
4226 struct fullPowerContext *pContext = callbackContext;
4227
4228 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304229 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004230
4231 if (NULL == callbackContext)
4232 {
4233 hddLog(VOS_TRACE_LEVEL_ERROR,
4234 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004235 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004236 return;
4237 }
4238
4239 /* there is a race condition that exists between this callback function
4240 and the caller since the caller could time out either before or
4241 while this code is executing. we'll assume the timeout hasn't
4242 occurred, but we'll verify that right before we save our work */
4243
4244 if (POWER_CONTEXT_MAGIC != pContext->magic)
4245 {
4246 /* the caller presumably timed out so there is nothing we can do */
4247 hddLog(VOS_TRACE_LEVEL_WARN,
4248 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004249 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004250 return;
4251 }
4252
4253 /* the race is on. caller could have timed out immediately after
4254 we verified the magic, but if so, caller will wait a short time
4255 for us to notify the caller, so the context will stay valid */
4256 complete(&pContext->completion);
4257}
4258
4259/**---------------------------------------------------------------------------
4260
4261 \brief hdd_wlan_exit() - HDD WLAN exit function
4262
4263 This is the driver exit point (invoked during rmmod)
4264
4265 \param - pHddCtx - Pointer to the HDD Context
4266
4267 \return - None
4268
4269 --------------------------------------------------------------------------*/
4270void hdd_wlan_exit(hdd_context_t *pHddCtx)
4271{
4272 eHalStatus halStatus;
4273 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4274 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304275 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004276 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004277 struct fullPowerContext powerContext;
4278 long lrc;
4279
4280 ENTER();
4281
Jeff Johnson88ba7742013-02-27 14:36:02 -08004282 if (VOS_FTM_MODE != hdd_get_conparam())
4283 {
4284 // Unloading, restart logic is no more required.
4285 wlan_hdd_restart_deinit(pHddCtx);
4286 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004287
Jeff Johnson295189b2012-06-20 16:38:30 -07004288 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004289 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004290 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004291 {
4292 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4293 WLAN_HDD_INFRA_STATION);
4294 if (pAdapter == NULL)
4295 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4296
4297 if (pAdapter != NULL)
4298 {
4299 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4300 hdd_UnregisterWext(pAdapter->dev);
4301 }
4302 }
4303 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004304
Jeff Johnson295189b2012-06-20 16:38:30 -07004305 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004306 {
4307 wlan_hdd_ftm_close(pHddCtx);
4308 goto free_hdd_ctx;
4309 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004310 //Stop the Interface TX queue.
4311 //netif_tx_disable(pWlanDev);
4312 //netif_carrier_off(pWlanDev);
4313
Jeff Johnson295189b2012-06-20 16:38:30 -07004314 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4315 {
4316 pAdapter = hdd_get_adapter(pHddCtx,
4317 WLAN_HDD_SOFTAP);
4318 }
4319 else
4320 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004321 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004322 {
4323 pAdapter = hdd_get_adapter(pHddCtx,
4324 WLAN_HDD_INFRA_STATION);
4325 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004326 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004327 /* DeRegister with platform driver as client for Suspend/Resume */
4328 vosStatus = hddDeregisterPmOps(pHddCtx);
4329 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4330 {
4331 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4332 VOS_ASSERT(0);
4333 }
4334
4335 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4336 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4337 {
4338 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4339 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004340
4341 // Cancel any outstanding scan requests. We are about to close all
4342 // of our adapters, but an adapter structure is what SME passes back
4343 // to our callback function. Hence if there are any outstanding scan
4344 // requests then there is a race condition between when the adapter
4345 // is closed and when the callback is invoked. We try to resolve that
4346 // race condition here by canceling any outstanding scans before we
4347 // close the adapters.
4348 // Note that the scans may be cancelled in an asynchronous manner, so
4349 // ideally there needs to be some kind of synchronization. Rather than
4350 // introduce a new synchronization here, we will utilize the fact that
4351 // we are about to Request Full Power, and since that is synchronized,
4352 // the expectation is that by the time Request Full Power has completed,
4353 // all scans will be cancelled.
4354 hdd_abort_mac_scan( pHddCtx );
4355
4356 //Disable IMPS/BMPS as we do not want the device to enter any power
4357 //save mode during shutdown
4358 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4359 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4360 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4361
4362 //Ensure that device is in full power as we will touch H/W during vos_Stop
4363 init_completion(&powerContext.completion);
4364 powerContext.magic = POWER_CONTEXT_MAGIC;
4365
4366 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4367 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4368
4369 if (eHAL_STATUS_SUCCESS != halStatus)
4370 {
4371 if (eHAL_STATUS_PMC_PENDING == halStatus)
4372 {
4373 /* request was sent -- wait for the response */
4374 lrc = wait_for_completion_interruptible_timeout(
4375 &powerContext.completion,
4376 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4377 /* either we have a response or we timed out
4378 either way, first invalidate our magic */
4379 powerContext.magic = 0;
4380 if (lrc <= 0)
4381 {
4382 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004383 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004384 /* there is a race condition such that the callback
4385 function could be executing at the same time we are. of
4386 primary concern is if the callback function had already
4387 verified the "magic" but hasn't yet set the completion
4388 variable. Since the completion variable is on our
4389 stack, we'll delay just a bit to make sure the data is
4390 still valid if that is the case */
4391 msleep(50);
4392 }
4393 }
4394 else
4395 {
4396 hddLog(VOS_TRACE_LEVEL_ERROR,
4397 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004398 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004399 VOS_ASSERT(0);
4400 /* continue -- need to clean up as much as possible */
4401 }
4402 }
4403
4404 // Unregister the Net Device Notifier
4405 unregister_netdevice_notifier(&hdd_netdev_notifier);
4406
Jeff Johnson295189b2012-06-20 16:38:30 -07004407 hdd_stop_all_adapters( pHddCtx );
4408
Jeff Johnson295189b2012-06-20 16:38:30 -07004409#ifdef WLAN_BTAMP_FEATURE
4410 vosStatus = WLANBAP_Stop(pVosContext);
4411 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4412 {
4413 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4414 "%s: Failed to stop BAP",__func__);
4415 }
4416#endif //WLAN_BTAMP_FEATURE
4417
4418 //Stop all the modules
4419 vosStatus = vos_stop( pVosContext );
4420 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4421 {
4422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4423 "%s: Failed to stop VOSS",__func__);
4424 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4425 }
4426
Jeff Johnson295189b2012-06-20 16:38:30 -07004427 //Assert Deep sleep signal now to put Libra HW in lowest power state
4428 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4429 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4430
4431 //Vote off any PMIC voltage supplies
4432 vos_chipPowerDown(NULL, NULL, NULL);
4433
4434 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4435
4436 //Clean up HDD Nlink Service
4437 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4438 nl_srv_exit();
4439
4440 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004441 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004442
4443 //Close the scheduler before calling vos_close to make sure no thread is
4444 // scheduled after the each module close is called i.e after all the data
4445 // structures are freed.
4446 vosStatus = vos_sched_close( pVosContext );
4447 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4448 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4449 "%s: Failed to close VOSS Scheduler",__func__);
4450 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4451 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004452#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004453#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4454 /* Destroy the wake lock */
4455 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4456#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004457 /* Destroy the wake lock */
4458 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004459#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004460
4461 //Close VOSS
4462 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4463 vos_close(pVosContext);
4464
Jeff Johnson295189b2012-06-20 16:38:30 -07004465 //Close Watchdog
4466 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4467 vos_watchdog_close(pVosContext);
4468
4469 /* Cancel the vote for XO Core ON.
4470 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4471 * exited at this point
4472 */
4473 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4474 " when WLAN is turned OFF\n");
4475 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4476 {
4477 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4478 " Not returning failure."
4479 " Power consumed will be high\n");
4480 }
4481
4482 hdd_close_all_adapters( pHddCtx );
4483
4484
4485 //Free up dynamically allocated members inside HDD Adapter
4486 kfree(pHddCtx->cfg_ini);
4487 pHddCtx->cfg_ini= NULL;
4488
4489 /* free the power on lock from platform driver */
4490 if (free_riva_power_on_lock("wlan"))
4491 {
4492 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4493 __func__);
4494 }
4495
Jeff Johnson88ba7742013-02-27 14:36:02 -08004496free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004497 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004498 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004499 if (hdd_is_ssr_required())
4500 {
4501 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004502 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004503 msleep(5000);
4504 }
4505 hdd_set_ssr_required (VOS_FALSE);
4506}
4507
4508
4509/**---------------------------------------------------------------------------
4510
4511 \brief hdd_update_config_from_nv() - Function to update the contents of
4512 the running configuration with parameters taken from NV storage
4513
4514 \param - pHddCtx - Pointer to the HDD global context
4515
4516 \return - VOS_STATUS_SUCCESS if successful
4517
4518 --------------------------------------------------------------------------*/
4519static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4520{
Jeff Johnson295189b2012-06-20 16:38:30 -07004521 v_BOOL_t itemIsValid = VOS_FALSE;
4522 VOS_STATUS status;
4523 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4524 v_U8_t macLoop;
4525
4526 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4527 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4528 if(status != VOS_STATUS_SUCCESS)
4529 {
4530 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4531 return VOS_STATUS_E_FAILURE;
4532 }
4533
4534 if (itemIsValid == VOS_TRUE)
4535 {
4536 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4537 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4538 VOS_MAX_CONCURRENCY_PERSONA);
4539 if(status != VOS_STATUS_SUCCESS)
4540 {
4541 /* Get MAC from NV fail, not update CFG info
4542 * INI MAC value will be used for MAC setting */
4543 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4544 return VOS_STATUS_E_FAILURE;
4545 }
4546
4547 /* If first MAC is not valid, treat all others are not valid
4548 * Then all MACs will be got from ini file */
4549 if(vos_is_macaddr_zero(&macFromNV[0]))
4550 {
4551 /* MAC address in NV file is not configured yet */
4552 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4553 return VOS_STATUS_E_INVAL;
4554 }
4555
4556 /* Get MAC address from NV, update CFG info */
4557 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4558 {
4559 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
4560 {
4561 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
4562 /* This MAC is not valid, skip it
4563 * This MAC will be got from ini file */
4564 }
4565 else
4566 {
4567 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
4568 (v_U8_t *)&macFromNV[macLoop].bytes[0],
4569 VOS_MAC_ADDR_SIZE);
4570 }
4571 }
4572 }
4573 else
4574 {
4575 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
4576 return VOS_STATUS_E_FAILURE;
4577 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004578
Jeff Johnson295189b2012-06-20 16:38:30 -07004579
4580 return VOS_STATUS_SUCCESS;
4581}
4582
4583/**---------------------------------------------------------------------------
4584
4585 \brief hdd_post_voss_start_config() - HDD post voss start config helper
4586
4587 \param - pAdapter - Pointer to the HDD
4588
4589 \return - None
4590
4591 --------------------------------------------------------------------------*/
4592VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
4593{
4594 eHalStatus halStatus;
4595 v_U32_t listenInterval;
4596
Jeff Johnson295189b2012-06-20 16:38:30 -07004597
4598 // Send ready indication to the HDD. This will kick off the MAC
4599 // into a 'running' state and should kick off an initial scan.
4600 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
4601 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4602 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304603 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07004604 "code %08d [x%08x]",__func__, halStatus, halStatus );
4605 return VOS_STATUS_E_FAILURE;
4606 }
4607
4608 // Set default LI into HDD context,
4609 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
4610 // And RIVA will crash
4611 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
4612 pHddCtx->hdd_actual_LI_value = listenInterval;
4613
4614 return VOS_STATUS_SUCCESS;
4615}
4616
Jeff Johnson295189b2012-06-20 16:38:30 -07004617/* wake lock APIs for HDD */
4618void hdd_prevent_suspend(void)
4619{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004620#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004621 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004622#else
4623 wcnss_prevent_suspend();
4624#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004625}
4626
4627void hdd_allow_suspend(void)
4628{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004629#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004630 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004631#else
4632 wcnss_allow_suspend();
4633#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004634}
4635
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004636void hdd_allow_suspend_timeout(v_U32_t timeout)
4637{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004638#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07004639 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004640#else
4641 /* Do nothing as there is no API in wcnss for timeout*/
4642#endif
4643}
4644
Jeff Johnson295189b2012-06-20 16:38:30 -07004645/**---------------------------------------------------------------------------
4646
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004647 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
4648 information between Host and Riva
4649
4650 This function gets reported version of FW
4651 It also finds the version of Riva headers used to compile the host
4652 It compares the above two and prints a warning if they are different
4653 It gets the SW and HW version string
4654 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
4655 indicating the features they support through a bitmap
4656
4657 \param - pHddCtx - Pointer to HDD context
4658
4659 \return - void
4660
4661 --------------------------------------------------------------------------*/
4662
4663void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
4664{
4665
4666 tSirVersionType versionCompiled;
4667 tSirVersionType versionReported;
4668 tSirVersionString versionString;
4669 tANI_U8 fwFeatCapsMsgSupported = 0;
4670 VOS_STATUS vstatus;
4671
4672 /* retrieve and display WCNSS version information */
4673 do {
4674
4675 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
4676 &versionCompiled);
4677 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4678 {
4679 hddLog(VOS_TRACE_LEVEL_FATAL,
4680 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004681 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004682 break;
4683 }
4684
4685 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
4686 &versionReported);
4687 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4688 {
4689 hddLog(VOS_TRACE_LEVEL_FATAL,
4690 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004691 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004692 break;
4693 }
4694
4695 if ((versionCompiled.major != versionReported.major) ||
4696 (versionCompiled.minor != versionReported.minor) ||
4697 (versionCompiled.version != versionReported.version) ||
4698 (versionCompiled.revision != versionReported.revision))
4699 {
4700 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4701 "Host expected %u.%u.%u.%u\n",
4702 WLAN_MODULE_NAME,
4703 (int)versionReported.major,
4704 (int)versionReported.minor,
4705 (int)versionReported.version,
4706 (int)versionReported.revision,
4707 (int)versionCompiled.major,
4708 (int)versionCompiled.minor,
4709 (int)versionCompiled.version,
4710 (int)versionCompiled.revision);
4711 }
4712 else
4713 {
4714 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4715 WLAN_MODULE_NAME,
4716 (int)versionReported.major,
4717 (int)versionReported.minor,
4718 (int)versionReported.version,
4719 (int)versionReported.revision);
4720 }
4721
4722 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
4723 versionString,
4724 sizeof(versionString));
4725 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4726 {
4727 hddLog(VOS_TRACE_LEVEL_FATAL,
4728 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004729 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004730 break;
4731 }
4732
4733 pr_info("%s: WCNSS software version %s\n",
4734 WLAN_MODULE_NAME, versionString);
4735
4736 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
4737 versionString,
4738 sizeof(versionString));
4739 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4740 {
4741 hddLog(VOS_TRACE_LEVEL_FATAL,
4742 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004743 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004744 break;
4745 }
4746
4747 pr_info("%s: WCNSS hardware version %s\n",
4748 WLAN_MODULE_NAME, versionString);
4749
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004750 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
4751 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004752 send the message only if it the riva is 1.1
4753 minor numbers for different riva branches:
4754 0 -> (1.0)Mainline Build
4755 1 -> (1.1)Mainline Build
4756 2->(1.04) Stability Build
4757 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004758 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004759 ((versionReported.minor>=1) && (versionReported.version>=1)))
4760 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
4761 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004762
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004763 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08004764 {
4765#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4766 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
4767 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
4768#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004769 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08004770 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004771
4772 } while (0);
4773
4774}
4775
4776/**---------------------------------------------------------------------------
4777
Jeff Johnson295189b2012-06-20 16:38:30 -07004778 \brief hdd_wlan_startup() - HDD init function
4779
4780 This is the driver startup code executed once a WLAN device has been detected
4781
4782 \param - dev - Pointer to the underlying device
4783
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004784 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07004785
4786 --------------------------------------------------------------------------*/
4787
4788int hdd_wlan_startup(struct device *dev )
4789{
4790 VOS_STATUS status;
4791 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004792 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004793 hdd_context_t *pHddCtx = NULL;
4794 v_CONTEXT_t pVosContext= NULL;
4795#ifdef WLAN_BTAMP_FEATURE
4796 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
4797 WLANBAP_ConfigType btAmpConfig;
4798 hdd_config_t *pConfig;
4799#endif
4800 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07004801 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004802
4803 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004804 /*
4805 * cfg80211: wiphy allocation
4806 */
4807 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
4808
4809 if(wiphy == NULL)
4810 {
4811 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004812 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004813 }
4814
4815 pHddCtx = wiphy_priv(wiphy);
4816
Jeff Johnson295189b2012-06-20 16:38:30 -07004817 //Initialize the adapter context to zeros.
4818 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4819
Jeff Johnson295189b2012-06-20 16:38:30 -07004820 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004821 hdd_prevent_suspend();
4822 pHddCtx->isLoadUnloadInProgress = TRUE;
4823
4824 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4825
4826 /*Get vos context here bcoz vos_open requires it*/
4827 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4828
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08004829 if(pVosContext == NULL)
4830 {
4831 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
4832 goto err_free_hdd_context;
4833 }
4834
Jeff Johnson295189b2012-06-20 16:38:30 -07004835 //Save the Global VOSS context in adapter context for future.
4836 pHddCtx->pvosContext = pVosContext;
4837
4838 //Save the adapter context in global context for future.
4839 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
4840
Jeff Johnson295189b2012-06-20 16:38:30 -07004841 pHddCtx->parent_dev = dev;
4842
4843 init_completion(&pHddCtx->full_pwr_comp_var);
4844 init_completion(&pHddCtx->standby_comp_var);
4845 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004846 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004847 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004848
4849 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
4850
4851 // Load all config first as TL config is needed during vos_open
4852 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
4853 if(pHddCtx->cfg_ini == NULL)
4854 {
4855 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
4856 goto err_free_hdd_context;
4857 }
4858
4859 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
4860
4861 // Read and parse the qcom_cfg.ini file
4862 status = hdd_parse_config_ini( pHddCtx );
4863 if ( VOS_STATUS_SUCCESS != status )
4864 {
4865 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
4866 __func__, WLAN_INI_FILE);
4867 goto err_config;
4868 }
4869
Jeff Johnson295189b2012-06-20 16:38:30 -07004870 /*
4871 * cfg80211: Initialization and registration ...
4872 */
4873 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
4874 {
4875 hddLog(VOS_TRACE_LEVEL_FATAL,
4876 "%s: wlan_hdd_cfg80211_register return failure", __func__);
4877 goto err_wiphy_reg;
4878 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004879
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004880 // Update VOS trace levels based upon the cfg.ini
4881 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
4882 pHddCtx->cfg_ini->vosTraceEnableBAP);
4883 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
4884 pHddCtx->cfg_ini->vosTraceEnableTL);
4885 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
4886 pHddCtx->cfg_ini->vosTraceEnableWDI);
4887 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
4888 pHddCtx->cfg_ini->vosTraceEnableHDD);
4889 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
4890 pHddCtx->cfg_ini->vosTraceEnableSME);
4891 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
4892 pHddCtx->cfg_ini->vosTraceEnablePE);
4893 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
4894 pHddCtx->cfg_ini->vosTraceEnableWDA);
4895 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
4896 pHddCtx->cfg_ini->vosTraceEnableSYS);
4897 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
4898 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004899 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
4900 pHddCtx->cfg_ini->vosTraceEnableSAP);
4901 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
4902 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004903
Jeff Johnson295189b2012-06-20 16:38:30 -07004904 // Update WDI trace levels based upon the cfg.ini
4905 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
4906 pHddCtx->cfg_ini->wdiTraceEnableDAL);
4907 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
4908 pHddCtx->cfg_ini->wdiTraceEnableCTL);
4909 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
4910 pHddCtx->cfg_ini->wdiTraceEnableDAT);
4911 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
4912 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004913
Jeff Johnson88ba7742013-02-27 14:36:02 -08004914 if (VOS_FTM_MODE == hdd_get_conparam())
4915 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004916 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
4917 {
4918 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
4919 goto err_free_hdd_context;
4920 }
4921 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
4922 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08004923 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004924
Jeff Johnson88ba7742013-02-27 14:36:02 -08004925 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07004926 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4927 {
4928 status = vos_watchdog_open(pVosContext,
4929 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4930
4931 if(!VOS_IS_STATUS_SUCCESS( status ))
4932 {
4933 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004934 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07004935 }
4936 }
4937
4938 pHddCtx->isLogpInProgress = FALSE;
4939 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4940
Jeff Johnson295189b2012-06-20 16:38:30 -07004941 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
4942 if(!VOS_IS_STATUS_SUCCESS(status))
4943 {
4944 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004945 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004946 }
4947
Jeff Johnson295189b2012-06-20 16:38:30 -07004948 status = vos_open( &pVosContext, 0);
4949 if ( !VOS_IS_STATUS_SUCCESS( status ))
4950 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004951 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
4952 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07004953 }
4954
Jeff Johnson295189b2012-06-20 16:38:30 -07004955 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
4956
4957 if ( NULL == pHddCtx->hHal )
4958 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004959 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004960 goto err_vosclose;
4961 }
4962
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004963 status = vos_preStart( pHddCtx->pvosContext );
4964 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4965 {
4966 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
4967 goto err_vosclose;
4968 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004969
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004970 /* Note that the vos_preStart() sequence triggers the cfg download.
4971 The cfg download must occur before we update the SME config
4972 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07004973 status = hdd_set_sme_config( pHddCtx );
4974
4975 if ( VOS_STATUS_SUCCESS != status )
4976 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004977 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
4978 goto err_vosclose;
4979 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004980
4981 //Initialize the WMM module
4982 status = hdd_wmm_init(pHddCtx);
4983 if (!VOS_IS_STATUS_SUCCESS(status))
4984 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004985 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004986 goto err_vosclose;
4987 }
4988
Jeff Johnson295189b2012-06-20 16:38:30 -07004989 /* In the integrated architecture we update the configuration from
4990 the INI file and from NV before vOSS has been started so that
4991 the final contents are available to send down to the cCPU */
4992
4993 // Apply the cfg.ini to cfg.dat
4994 if (FALSE == hdd_update_config_dat(pHddCtx))
4995 {
4996 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4997 goto err_vosclose;
4998 }
4999
5000 // Apply the NV to cfg.dat
5001 /* Prima Update MAC address only at here */
5002 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5003 {
5004#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5005 /* There was not a valid set of MAC Addresses in NV. See if the
5006 default addresses were modified by the cfg.ini settings. If so,
5007 we'll use them, but if not, we'll autogenerate a set of MAC
5008 addresses based upon the device serial number */
5009
5010 static const v_MACADDR_t default_address =
5011 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5012 unsigned int serialno;
5013 int i;
5014
5015 serialno = wcnss_get_serial_number();
5016 if ((0 != serialno) &&
5017 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5018 sizeof(default_address))))
5019 {
5020 /* cfg.ini has the default address, invoke autogen logic */
5021
5022 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5023 bytes of the serial number that can be used to generate
5024 the other 3 bytes of the MAC address. Mask off all but
5025 the lower 3 bytes (this will also make sure we don't
5026 overflow in the next step) */
5027 serialno &= 0x00FFFFFF;
5028
5029 /* we need a unique address for each session */
5030 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5031
5032 /* autogen all addresses */
5033 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5034 {
5035 /* start with the entire default address */
5036 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5037 /* then replace the lower 3 bytes */
5038 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5039 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5040 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5041
5042 serialno++;
5043 }
5044
5045 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5046 MAC_ADDRESS_STR,
5047 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5048 }
5049 else
5050#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5051 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005052 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005053 "%s: Invalid MAC address in NV, using MAC from ini file "
5054 MAC_ADDRESS_STR, __func__,
5055 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5056 }
5057 }
5058 {
5059 eHalStatus halStatus;
5060 // Set the MAC Address
5061 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5062 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5063 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5064 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5065
5066 if (!HAL_STATUS_SUCCESS( halStatus ))
5067 {
5068 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5069 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005070 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005071 }
5072 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005073
5074 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5075 Note: Firmware image will be read and downloaded inside vos_start API */
5076 status = vos_start( pHddCtx->pvosContext );
5077 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5078 {
5079 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5080 goto err_vosclose;
5081 }
5082
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005083 /* Exchange capability info between Host and FW and also get versioning info from FW */
5084 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005085
5086 status = hdd_post_voss_start_config( pHddCtx );
5087 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5088 {
5089 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5090 __func__);
5091 goto err_vosstop;
5092 }
5093
Jeff Johnson295189b2012-06-20 16:38:30 -07005094 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5095 {
5096 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5097 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5098 }
5099 else
5100 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005101 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5102 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5103 if (pAdapter != NULL)
5104 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305105 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005106 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305107 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5108 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5109 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005110
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305111 /* Generate the P2P Device Address. This consists of the device's
5112 * primary MAC address with the locally administered bit set.
5113 */
5114 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005115 }
5116 else
5117 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305118 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5119 if (p2p_dev_addr != NULL)
5120 {
5121 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5122 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5123 }
5124 else
5125 {
5126 hddLog(VOS_TRACE_LEVEL_FATAL,
5127 "%s: Failed to allocate mac_address for p2p_device",
5128 __func__);
5129 goto err_close_adapter;
5130 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005131 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005132
5133 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5134 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5135 if ( NULL == pP2pAdapter )
5136 {
5137 hddLog(VOS_TRACE_LEVEL_FATAL,
5138 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005139 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005140 goto err_close_adapter;
5141 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005142 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005143 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005144
5145 if( pAdapter == NULL )
5146 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005147 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5148 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005149 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005150
Jeff Johnson295189b2012-06-20 16:38:30 -07005151#ifdef WLAN_BTAMP_FEATURE
5152 vStatus = WLANBAP_Open(pVosContext);
5153 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5154 {
5155 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5156 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005157 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005158 }
5159
5160 vStatus = BSL_Init(pVosContext);
5161 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5162 {
5163 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5164 "%s: Failed to Init BSL",__func__);
5165 goto err_bap_close;
5166 }
5167 vStatus = WLANBAP_Start(pVosContext);
5168 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5169 {
5170 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5171 "%s: Failed to start TL",__func__);
5172 goto err_bap_close;
5173 }
5174
5175 pConfig = pHddCtx->cfg_ini;
5176 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5177 status = WLANBAP_SetConfig(&btAmpConfig);
5178
5179#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005180
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005181#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5182 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5183 {
5184 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5185 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5186 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5187 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5188 }
5189#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005190#ifdef FEATURE_WLAN_SCAN_PNO
5191 /*SME must send channel update configuration to RIVA*/
5192 sme_UpdateChannelConfig(pHddCtx->hHal);
5193#endif
5194
Jeff Johnson295189b2012-06-20 16:38:30 -07005195 /* Register with platform driver as client for Suspend/Resume */
5196 status = hddRegisterPmOps(pHddCtx);
5197 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5198 {
5199 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5200#ifdef WLAN_BTAMP_FEATURE
5201 goto err_bap_stop;
5202#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005203 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005204#endif //WLAN_BTAMP_FEATURE
5205 }
5206
5207 /* Register TM level change handler function to the platform */
5208 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5209 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5210 {
5211 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5212 goto err_unregister_pmops;
5213 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005214
5215 /* register for riva power on lock to platform driver */
5216 if (req_riva_power_on_lock("wlan"))
5217 {
5218 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5219 __func__);
5220 goto err_unregister_pmops;
5221 }
5222
Jeff Johnson295189b2012-06-20 16:38:30 -07005223 // register net device notifier for device change notification
5224 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5225
5226 if(ret < 0)
5227 {
5228 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5229 goto err_free_power_on_lock;
5230 }
5231
5232 //Initialize the nlink service
5233 if(nl_srv_init() != 0)
5234 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305235 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005236 goto err_reg_netdev;
5237 }
5238
5239 //Initialize the BTC service
5240 if(btc_activate_service(pHddCtx) != 0)
5241 {
5242 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5243 goto err_nl_srv;
5244 }
5245
5246#ifdef PTT_SOCK_SVC_ENABLE
5247 //Initialize the PTT service
5248 if(ptt_sock_activate_svc(pHddCtx) != 0)
5249 {
5250 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5251 goto err_nl_srv;
5252 }
5253#endif
5254
Jeff Johnson295189b2012-06-20 16:38:30 -07005255 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005256 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005257 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005258 /* Action frame registered in one adapter which will
5259 * applicable to all interfaces
5260 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005261 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005262 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005263
5264 mutex_init(&pHddCtx->sap_lock);
5265
5266 pHddCtx->isLoadUnloadInProgress = FALSE;
5267
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005268#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005269#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5270 /* Initialize the wake lcok */
5271 wake_lock_init(&pHddCtx->rx_wake_lock,
5272 WAKE_LOCK_SUSPEND,
5273 "qcom_rx_wakelock");
5274#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005275 /* Initialize the wake lcok */
5276 wake_lock_init(&pHddCtx->sap_wake_lock,
5277 WAKE_LOCK_SUSPEND,
5278 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005279#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005280
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005281 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5282 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005283
5284 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5285 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005286
5287 // Initialize the restart logic
5288 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305289
Jeff Johnson295189b2012-06-20 16:38:30 -07005290 goto success;
5291
5292err_nl_srv:
5293 nl_srv_exit();
5294
5295err_reg_netdev:
5296 unregister_netdevice_notifier(&hdd_netdev_notifier);
5297
5298err_free_power_on_lock:
5299 free_riva_power_on_lock("wlan");
5300
5301err_unregister_pmops:
5302 hddDevTmUnregisterNotifyCallback(pHddCtx);
5303 hddDeregisterPmOps(pHddCtx);
5304
5305#ifdef WLAN_BTAMP_FEATURE
5306err_bap_stop:
5307 WLANBAP_Stop(pVosContext);
5308#endif
5309
5310#ifdef WLAN_BTAMP_FEATURE
5311err_bap_close:
5312 WLANBAP_Close(pVosContext);
5313#endif
5314
Jeff Johnson295189b2012-06-20 16:38:30 -07005315err_close_adapter:
5316 hdd_close_all_adapters( pHddCtx );
5317
5318err_vosstop:
5319 vos_stop(pVosContext);
5320
5321err_vosclose:
5322 status = vos_sched_close( pVosContext );
5323 if (!VOS_IS_STATUS_SUCCESS(status)) {
5324 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5325 "%s: Failed to close VOSS Scheduler", __func__);
5326 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5327 }
5328 vos_close(pVosContext );
5329
Jeff Johnson295189b2012-06-20 16:38:30 -07005330err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005331 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005332
5333err_wdclose:
5334 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5335 vos_watchdog_close(pVosContext);
5336
Jeff Johnson295189b2012-06-20 16:38:30 -07005337err_wiphy_reg:
5338 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005339
5340err_config:
5341 kfree(pHddCtx->cfg_ini);
5342 pHddCtx->cfg_ini= NULL;
5343
5344err_free_hdd_context:
5345 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005346 wiphy_free(wiphy) ;
5347 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005348 VOS_BUG(1);
5349
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005350 if (hdd_is_ssr_required())
5351 {
5352 /* WDI timeout had happened during load, so SSR is needed here */
5353 subsystem_restart("wcnss");
5354 msleep(5000);
5355 }
5356 hdd_set_ssr_required (VOS_FALSE);
5357
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005358 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005359
5360success:
5361 EXIT();
5362 return 0;
5363}
5364
5365/**---------------------------------------------------------------------------
5366
Jeff Johnson32d95a32012-09-10 13:15:23 -07005367 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005368
Jeff Johnson32d95a32012-09-10 13:15:23 -07005369 This is the driver entry point - called in different timeline depending
5370 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005371
5372 \param - None
5373
5374 \return - 0 for success, non zero for failure
5375
5376 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005377static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005378{
5379 VOS_STATUS status;
5380 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005381 struct device *dev = NULL;
5382 int ret_status = 0;
5383
5384 ENTER();
5385
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005386#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005387 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005388#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005389
5390 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5391 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5392
5393 //Power Up Libra WLAN card first if not already powered up
5394 status = vos_chipPowerUp(NULL,NULL,NULL);
5395 if (!VOS_IS_STATUS_SUCCESS(status))
5396 {
5397 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5398 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005399 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005400 }
5401
Jeff Johnson295189b2012-06-20 16:38:30 -07005402#ifdef ANI_BUS_TYPE_PCI
5403
5404 dev = wcnss_wlan_get_device();
5405
5406#endif // ANI_BUS_TYPE_PCI
5407
5408#ifdef ANI_BUS_TYPE_PLATFORM
5409 dev = wcnss_wlan_get_device();
5410#endif // ANI_BUS_TYPE_PLATFORM
5411
5412
5413 do {
5414 if (NULL == dev) {
5415 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
5416 ret_status = -1;
5417 break;
5418 }
5419
5420#ifdef MEMORY_DEBUG
5421 vos_mem_init();
5422#endif
5423
5424#ifdef TIMER_MANAGER
5425 vos_timer_manager_init();
5426#endif
5427
5428 /* Preopen VOSS so that it is ready to start at least SAL */
5429 status = vos_preOpen(&pVosContext);
5430
5431 if (!VOS_IS_STATUS_SUCCESS(status))
5432 {
5433 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5434 ret_status = -1;
5435 break;
5436 }
5437
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005438#ifndef MODULE
5439 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5440 */
5441 hdd_set_conparam((v_UINT_t)con_mode);
5442#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005443
5444 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005445 if (hdd_wlan_startup(dev))
5446 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005447 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005448 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005449 vos_preClose( &pVosContext );
5450 ret_status = -1;
5451 break;
5452 }
5453
5454 /* Cancel the vote for XO Core ON
5455 * This is done here for safety purposes in case we re-initialize without turning
5456 * it OFF in any error scenario.
5457 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005458 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005459 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005460 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005461 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5462 {
5463 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5464 " Power consumed will be high\n");
5465 }
5466 } while (0);
5467
5468 if (0 != ret_status)
5469 {
5470 //Assert Deep sleep signal now to put Libra HW in lowest power state
5471 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5472 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5473
5474 //Vote off any PMIC voltage supplies
5475 vos_chipPowerDown(NULL, NULL, NULL);
5476#ifdef TIMER_MANAGER
5477 vos_timer_exit();
5478#endif
5479#ifdef MEMORY_DEBUG
5480 vos_mem_exit();
5481#endif
5482
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005483#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005484 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005485#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005486 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5487 }
5488 else
5489 {
5490 //Send WLAN UP indication to Nlink Service
5491 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5492
5493 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5494
5495 }
5496
5497 EXIT();
5498
5499 return ret_status;
5500}
5501
Jeff Johnson32d95a32012-09-10 13:15:23 -07005502/**---------------------------------------------------------------------------
5503
5504 \brief hdd_module_init() - Init Function
5505
5506 This is the driver entry point (invoked when module is loaded using insmod)
5507
5508 \param - None
5509
5510 \return - 0 for success, non zero for failure
5511
5512 --------------------------------------------------------------------------*/
5513#ifdef MODULE
5514static int __init hdd_module_init ( void)
5515{
5516 return hdd_driver_init();
5517}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005518#else /* #ifdef MODULE */
5519static int __init hdd_module_init ( void)
5520{
5521 /* Driver initialization is delayed to fwpath_changed_handler */
5522 return 0;
5523}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005524#endif /* #ifdef MODULE */
5525
Jeff Johnson295189b2012-06-20 16:38:30 -07005526
5527/**---------------------------------------------------------------------------
5528
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005529 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005530
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005531 This is the driver exit point (invoked when module is unloaded using rmmod
5532 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005533
5534 \param - None
5535
5536 \return - None
5537
5538 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005539static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005540{
5541 hdd_context_t *pHddCtx = NULL;
5542 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005543
5544 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
5545
5546 //Get the global vos context
5547 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5548
5549 if(!pVosContext)
5550 {
5551 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
5552 goto done;
5553 }
5554
5555 //Get the HDD context.
5556 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
5557
5558 if(!pHddCtx)
5559 {
5560 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
5561 }
5562 else
5563 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005564 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005565 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07005566 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
5567 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07005568 }
5569
5570 pHddCtx->isLoadUnloadInProgress = TRUE;
5571 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5572
5573 //Do all the cleanup before deregistering the driver
5574 hdd_wlan_exit(pHddCtx);
5575 }
5576
Jeff Johnson295189b2012-06-20 16:38:30 -07005577 vos_preClose( &pVosContext );
5578
5579#ifdef TIMER_MANAGER
5580 vos_timer_exit();
5581#endif
5582#ifdef MEMORY_DEBUG
5583 vos_mem_exit();
5584#endif
5585
5586done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005587#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005588 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005589#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005590 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
5591}
5592
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005593/**---------------------------------------------------------------------------
5594
5595 \brief hdd_module_exit() - Exit function
5596
5597 This is the driver exit point (invoked when module is unloaded using rmmod)
5598
5599 \param - None
5600
5601 \return - None
5602
5603 --------------------------------------------------------------------------*/
5604static void __exit hdd_module_exit(void)
5605{
5606 hdd_driver_exit();
5607}
5608
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005609#ifdef MODULE
5610static int fwpath_changed_handler(const char *kmessage,
5611 struct kernel_param *kp)
5612{
Jeff Johnson76052702013-04-16 13:55:05 -07005613 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005614}
5615
5616static int con_mode_handler(const char *kmessage,
5617 struct kernel_param *kp)
5618{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005619 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005620}
5621#else /* #ifdef MODULE */
5622/**---------------------------------------------------------------------------
5623
Jeff Johnson76052702013-04-16 13:55:05 -07005624 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005625
Jeff Johnson76052702013-04-16 13:55:05 -07005626 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005627 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07005628 - invoked when module parameter fwpath is modified from userspace to signal
5629 initializing the WLAN driver or when con_mode is modified from userspace
5630 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005631
5632 \return - 0 for success, non zero for failure
5633
5634 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005635static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005636{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005637 int ret_status;
5638
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005639 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005640 ret_status = hdd_driver_init();
5641 wlan_hdd_inited = ret_status ? 0 : 1;
5642 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005643 }
5644
5645 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07005646
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005647 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07005648
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005649 ret_status = hdd_driver_init();
5650 wlan_hdd_inited = ret_status ? 0 : 1;
5651 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005652}
5653
Jeff Johnson295189b2012-06-20 16:38:30 -07005654/**---------------------------------------------------------------------------
5655
Jeff Johnson76052702013-04-16 13:55:05 -07005656 \brief fwpath_changed_handler() - Handler Function
5657
5658 Handle changes to the fwpath parameter
5659
5660 \return - 0 for success, non zero for failure
5661
5662 --------------------------------------------------------------------------*/
5663static int fwpath_changed_handler(const char *kmessage,
5664 struct kernel_param *kp)
5665{
5666 int ret;
5667
5668 ret = param_set_copystring(kmessage, kp);
5669 if (0 == ret)
5670 ret = kickstart_driver();
5671 return ret;
5672}
5673
5674/**---------------------------------------------------------------------------
5675
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005676 \brief con_mode_handler() -
5677
5678 Handler function for module param con_mode when it is changed by userspace
5679 Dynamically linked - do nothing
5680 Statically linked - exit and init driver, as in rmmod and insmod
5681
Jeff Johnson76052702013-04-16 13:55:05 -07005682 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005683
Jeff Johnson76052702013-04-16 13:55:05 -07005684 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005685
5686 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005687static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005688{
Jeff Johnson76052702013-04-16 13:55:05 -07005689 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005690
Jeff Johnson76052702013-04-16 13:55:05 -07005691 ret = param_set_int(kmessage, kp);
5692 if (0 == ret)
5693 ret = kickstart_driver();
5694 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005695}
5696#endif /* #ifdef MODULE */
5697
5698/**---------------------------------------------------------------------------
5699
Jeff Johnson295189b2012-06-20 16:38:30 -07005700 \brief hdd_get_conparam() -
5701
5702 This is the driver exit point (invoked when module is unloaded using rmmod)
5703
5704 \param - None
5705
5706 \return - tVOS_CON_MODE
5707
5708 --------------------------------------------------------------------------*/
5709tVOS_CON_MODE hdd_get_conparam ( void )
5710{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005711#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005712 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005713#else
5714 return (tVOS_CON_MODE)curr_con_mode;
5715#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005716}
5717void hdd_set_conparam ( v_UINT_t newParam )
5718{
5719 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005720#ifndef MODULE
5721 curr_con_mode = con_mode;
5722#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005723}
5724/**---------------------------------------------------------------------------
5725
5726 \brief hdd_softap_sta_deauth() - function
5727
5728 This to take counter measure to handle deauth req from HDD
5729
5730 \param - pAdapter - Pointer to the HDD
5731
5732 \param - enable - boolean value
5733
5734 \return - None
5735
5736 --------------------------------------------------------------------------*/
5737
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005738VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005739{
Jeff Johnson295189b2012-06-20 16:38:30 -07005740 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005741 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005742
5743 ENTER();
5744
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305745 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005746
5747 //Ignore request to deauth bcmc station
5748 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005749 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005750
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005751 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005752
5753 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005754 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005755}
5756
5757/**---------------------------------------------------------------------------
5758
5759 \brief hdd_softap_sta_disassoc() - function
5760
5761 This to take counter measure to handle deauth req from HDD
5762
5763 \param - pAdapter - Pointer to the HDD
5764
5765 \param - enable - boolean value
5766
5767 \return - None
5768
5769 --------------------------------------------------------------------------*/
5770
5771void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5772{
5773 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5774
5775 ENTER();
5776
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305777 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005778
5779 //Ignore request to disassoc bcmc station
5780 if( pDestMacAddress[0] & 0x1 )
5781 return;
5782
5783 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5784}
5785
5786void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5787{
5788 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5789
5790 ENTER();
5791
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305792 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005793
5794 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5795}
5796
Jeff Johnson295189b2012-06-20 16:38:30 -07005797/**---------------------------------------------------------------------------
5798 *
5799 * \brief hdd_get__concurrency_mode() -
5800 *
5801 *
5802 * \param - None
5803 *
5804 * \return - CONCURRENCY MODE
5805 *
5806 * --------------------------------------------------------------------------*/
5807tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
5808{
5809 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5810 hdd_context_t *pHddCtx;
5811
5812 if (NULL != pVosContext)
5813 {
5814 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5815 if (NULL != pHddCtx)
5816 {
5817 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
5818 }
5819 }
5820
5821 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005822 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005823 return VOS_STA;
5824}
5825
5826/* Decide whether to allow/not the apps power collapse.
5827 * Allow apps power collapse if we are in connected state.
5828 * if not, allow only if we are in IMPS */
5829v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
5830{
5831 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08005832 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005833 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005834 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5835 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5836 hdd_adapter_t *pAdapter = NULL;
5837 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08005838 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005839
Jeff Johnson295189b2012-06-20 16:38:30 -07005840 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5841 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005842
Yathish9f22e662012-12-10 14:21:35 -08005843 concurrent_state = hdd_get_concurrency_mode();
5844
5845#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5846 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
5847 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
5848 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
5849 return TRUE;
5850#endif
5851
Jeff Johnson295189b2012-06-20 16:38:30 -07005852 /*loop through all adapters. TBD fix for Concurrency */
5853 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5854 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5855 {
5856 pAdapter = pAdapterNode->pAdapter;
5857 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
5858 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5859 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005860 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07005861 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08005862 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005863 (eANI_BOOLEAN_TRUE == scanRspPending) ||
5864 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07005865 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005866 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005867 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
5868 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07005869 return FALSE;
5870 }
5871 }
5872 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5873 pAdapterNode = pNext;
5874 }
5875 return TRUE;
5876}
5877
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08005878/* Decides whether to send suspend notification to Riva
5879 * if any adapter is in BMPS; then it is required */
5880v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
5881{
5882 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
5883 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5884
5885 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
5886 {
5887 return TRUE;
5888 }
5889 return FALSE;
5890}
5891
Jeff Johnson295189b2012-06-20 16:38:30 -07005892void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5893{
5894 switch(mode)
5895 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005896 case VOS_STA_MODE:
5897 case VOS_P2P_CLIENT_MODE:
5898 case VOS_P2P_GO_MODE:
5899 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07005900 pHddCtx->concurrency_mode |= (1 << mode);
5901 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07005902 break;
5903 default:
5904 break;
5905
5906 }
5907 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5908 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5909}
5910
5911
5912void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5913{
5914 switch(mode)
5915 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005916 case VOS_STA_MODE:
5917 case VOS_P2P_CLIENT_MODE:
5918 case VOS_P2P_GO_MODE:
5919 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005920 pHddCtx->no_of_sessions[mode]--;
5921 if (!(pHddCtx->no_of_sessions[mode]))
5922 pHddCtx->concurrency_mode &= (~(1 << mode));
5923 break;
5924 default:
5925 break;
5926 }
5927 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5928 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5929}
5930
Jeff Johnsone7245742012-09-05 17:12:55 -07005931/**---------------------------------------------------------------------------
5932 *
5933 * \brief wlan_hdd_restart_init
5934 *
5935 * This function initalizes restart timer/flag. An internal function.
5936 *
5937 * \param - pHddCtx
5938 *
5939 * \return - None
5940 *
5941 * --------------------------------------------------------------------------*/
5942
5943static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
5944{
5945 /* Initialize */
5946 pHddCtx->hdd_restart_retries = 0;
5947 atomic_set(&pHddCtx->isRestartInProgress, 0);
5948 vos_timer_init(&pHddCtx->hdd_restart_timer,
5949 VOS_TIMER_TYPE_SW,
5950 wlan_hdd_restart_timer_cb,
5951 pHddCtx);
5952}
5953/**---------------------------------------------------------------------------
5954 *
5955 * \brief wlan_hdd_restart_deinit
5956 *
5957 * This function cleans up the resources used. An internal function.
5958 *
5959 * \param - pHddCtx
5960 *
5961 * \return - None
5962 *
5963 * --------------------------------------------------------------------------*/
5964
5965static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
5966{
5967
5968 VOS_STATUS vos_status;
5969 /* Block any further calls */
5970 atomic_set(&pHddCtx->isRestartInProgress, 1);
5971 /* Cleanup */
5972 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5973 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005974 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005975 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5976 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005977 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005978
5979}
5980
5981/**---------------------------------------------------------------------------
5982 *
5983 * \brief wlan_hdd_framework_restart
5984 *
5985 * This function uses a cfg80211 API to start a framework initiated WLAN
5986 * driver module unload/load.
5987 *
5988 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
5989 *
5990 *
5991 * \param - pHddCtx
5992 *
5993 * \return - VOS_STATUS_SUCCESS: Success
5994 * VOS_STATUS_E_EMPTY: Adapter is Empty
5995 * VOS_STATUS_E_NOMEM: No memory
5996
5997 * --------------------------------------------------------------------------*/
5998
5999static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6000{
6001 VOS_STATUS status = VOS_STATUS_SUCCESS;
6002 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Yue Ma54db3d42013-04-19 16:44:28 -07006003 unsigned char restart_notification[MAX_RESTART_DRIVER_EVENT_LENGTH + 1];
6004 union iwreq_data wrqu;
Jeff Johnsone7245742012-09-05 17:12:55 -07006005
6006 /* Iterate over all adapters/devices */
6007 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6008 do
6009 {
6010 if( (status == VOS_STATUS_SUCCESS) &&
6011 pAdapterNode &&
6012 pAdapterNode->pAdapter)
6013 {
6014 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6015 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6016 pAdapterNode->pAdapter->dev->name,
6017 pAdapterNode->pAdapter->device_mode,
6018 pHddCtx->hdd_restart_retries + 1);
Yue Ma54db3d42013-04-19 16:44:28 -07006019
6020 /* Notify the wpa supplicant of wcnss restart by sending the custom event */
6021 memset(&wrqu, 0 , sizeof(wrqu));
6022 memset(restart_notification, 0, sizeof(restart_notification));
6023
6024 strlcpy(restart_notification, "QCOM: RESTART_DRIVER_DXE", sizeof(restart_notification));
6025
6026 wrqu.data.pointer = restart_notification;
6027 wrqu.data.length = strlen(restart_notification);
6028
6029 wireless_send_event(pAdapterNode->pAdapter->dev, IWEVCUSTOM, &wrqu, restart_notification);
Jeff Johnsone7245742012-09-05 17:12:55 -07006030 }
6031 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6032 pAdapterNode = pNext;
6033 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6034
Jeff Johnsone7245742012-09-05 17:12:55 -07006035 /* Retry until we unload or reach max count */
6036 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6037 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6038
6039 return status;
6040
6041}
6042/**---------------------------------------------------------------------------
6043 *
6044 * \brief wlan_hdd_restart_timer_cb
6045 *
6046 * Restart timer callback. An internal function.
6047 *
6048 * \param - User data:
6049 *
6050 * \return - None
6051 *
6052 * --------------------------------------------------------------------------*/
6053
6054void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6055{
6056 hdd_context_t *pHddCtx = usrDataForCallback;
6057 wlan_hdd_framework_restart(pHddCtx);
6058 return;
6059
6060}
6061
6062
6063/**---------------------------------------------------------------------------
6064 *
6065 * \brief wlan_hdd_restart_driver
6066 *
6067 * This function sends an event to supplicant to restart the WLAN driver.
6068 *
6069 * This function is called from vos_wlanRestart.
6070 *
6071 * \param - pHddCtx
6072 *
6073 * \return - VOS_STATUS_SUCCESS: Success
6074 * VOS_STATUS_E_EMPTY: Adapter is Empty
6075 * VOS_STATUS_E_ALREADY: Request already in progress
6076
6077 * --------------------------------------------------------------------------*/
6078VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6079{
6080 VOS_STATUS status = VOS_STATUS_SUCCESS;
6081
6082 /* A tight check to make sure reentrancy */
6083 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6084 {
6085 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6086 "%s: WLAN restart is already in progress", __func__);
6087
6088 return VOS_STATUS_E_ALREADY;
6089 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006090 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006091#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006092 wcnss_reset_intr();
6093#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006094
Jeff Johnsone7245742012-09-05 17:12:55 -07006095 return status;
6096}
6097
6098
Jeff Johnson295189b2012-06-20 16:38:30 -07006099//Register the module init/exit functions
6100module_init(hdd_module_init);
6101module_exit(hdd_module_exit);
6102
6103MODULE_LICENSE("Dual BSD/GPL");
6104MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6105MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6106
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006107module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6108 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006109
Jeff Johnson76052702013-04-16 13:55:05 -07006110module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006111 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);