blob: 18d6a96f29703a96eeb7210f407d4c1ab5d87ef2 [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
145/* the Android framework expects this param even though we don't use it */
146#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700147static char fwpath_buffer[BUF_LEN];
148static struct kparam_string fwpath = {
149 .string = fwpath_buffer,
150 .maxlen = BUF_LEN,
151};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700152#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700153static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700154#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700155
Jeff Johnsone7245742012-09-05 17:12:55 -0700156/*
157 * The rate at which the driver sends RESTART event to supplicant
158 * once the function 'vos_wlanRestart()' is called
159 *
160 */
161#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
162#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800163#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700164static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700165#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700166/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700167static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700168
169//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700170static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
171static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
172static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
173void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800174void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700175
Jeff Johnson295189b2012-06-20 16:38:30 -0700176v_U16_t hdd_select_queue(struct net_device *dev,
177 struct sk_buff *skb);
178
179#ifdef WLAN_FEATURE_PACKET_FILTERING
180static void hdd_set_multicast_list(struct net_device *dev);
181#endif
182
183void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700184int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700185
186extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800187#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
188void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
189static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
190static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700191static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
192 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
193 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800194#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700195static int hdd_netdev_notifier_call(struct notifier_block * nb,
196 unsigned long state,
197 void *ndev)
198{
199 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700200 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700201 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700202#ifdef WLAN_BTAMP_FEATURE
203 VOS_STATUS status;
204 hdd_context_t *pHddCtx;
205#endif
206
207 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700208 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700209 (strncmp(dev->name, "p2p", 3)))
210 return NOTIFY_DONE;
211
212 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700213 return NOTIFY_DONE;
214
Jeff Johnson295189b2012-06-20 16:38:30 -0700215 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700216 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700217
Jeff Johnson27cee452013-03-27 11:10:24 -0700218 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700219 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800220 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700221 VOS_ASSERT(0);
222 return NOTIFY_DONE;
223 }
224
Jeff Johnson27cee452013-03-27 11:10:24 -0700225 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
226 if (NULL == pHddCtx)
227 {
228 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
229 VOS_ASSERT(0);
230 return NOTIFY_DONE;
231 }
232
233 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
234 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700235
236 switch (state) {
237 case NETDEV_REGISTER:
238 break;
239
240 case NETDEV_UNREGISTER:
241 break;
242
243 case NETDEV_UP:
244 break;
245
246 case NETDEV_DOWN:
247 break;
248
249 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700250 if(TRUE == pAdapter->isLinkUpSvcNeeded)
251 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700252 break;
253
254 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700255 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700256 {
257 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800258 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700259 hdd_abort_mac_scan(pAdapter->pHddCtx);
260 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800261 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700262 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
263 if(!result)
264 {
265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800266 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700267 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700268 }
269 }
270 else
271 {
272 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700273 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700274 }
275#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700276 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700277 status = WLANBAP_StopAmp();
278 if(VOS_STATUS_SUCCESS != status )
279 {
280 pHddCtx->isAmpAllowed = VOS_TRUE;
281 hddLog(VOS_TRACE_LEVEL_FATAL,
282 "%s: Failed to stop AMP", __func__);
283 }
284 else
285 {
286 //a state m/c implementation in PAL is TBD to avoid this delay
287 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700288 if ( pHddCtx->isAmpAllowed )
289 {
290 WLANBAP_DeregisterFromHCI();
291 pHddCtx->isAmpAllowed = VOS_FALSE;
292 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700293 }
294#endif //WLAN_BTAMP_FEATURE
295 break;
296
297 default:
298 break;
299 }
300
301 return NOTIFY_DONE;
302}
303
304struct notifier_block hdd_netdev_notifier = {
305 .notifier_call = hdd_netdev_notifier_call,
306};
307
308/*---------------------------------------------------------------------------
309 * Function definitions
310 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700311void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
312void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700313//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700314static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700315#ifndef MODULE
316/* current con_mode - used only for statically linked driver
317 * con_mode is changed by userspace to indicate a mode change which will
318 * result in calling the module exit and init functions. The module
319 * exit function will clean up based on the value of con_mode prior to it
320 * being changed by userspace. So curr_con_mode records the current con_mode
321 * for exit when con_mode becomes the next mode for init
322 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700323static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700324#endif
325
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800326/**---------------------------------------------------------------------------
327
328 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
329
330 Called immediately after the cfg.ini is read in order to configure
331 the desired trace levels.
332
333 \param - moduleId - module whose trace level is being configured
334 \param - bitmask - bitmask of log levels to be enabled
335
336 \return - void
337
338 --------------------------------------------------------------------------*/
339static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
340{
341 wpt_tracelevel level;
342
343 /* if the bitmask is the default value, then a bitmask was not
344 specified in cfg.ini, so leave the logging level alone (it
345 will remain at the "compiled in" default value) */
346 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
347 {
348 return;
349 }
350
351 /* a mask was specified. start by disabling all logging */
352 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
353
354 /* now cycle through the bitmask until all "set" bits are serviced */
355 level = VOS_TRACE_LEVEL_FATAL;
356 while (0 != bitmask)
357 {
358 if (bitmask & 1)
359 {
360 vos_trace_setValue(moduleId, level, 1);
361 }
362 level++;
363 bitmask >>= 1;
364 }
365}
366
367
Jeff Johnson295189b2012-06-20 16:38:30 -0700368/**---------------------------------------------------------------------------
369
370 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
371
372 Called immediately after the cfg.ini is read in order to configure
373 the desired trace levels in the WDI.
374
375 \param - moduleId - module whose trace level is being configured
376 \param - bitmask - bitmask of log levels to be enabled
377
378 \return - void
379
380 --------------------------------------------------------------------------*/
381static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
382{
383 wpt_tracelevel level;
384
385 /* if the bitmask is the default value, then a bitmask was not
386 specified in cfg.ini, so leave the logging level alone (it
387 will remain at the "compiled in" default value) */
388 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
389 {
390 return;
391 }
392
393 /* a mask was specified. start by disabling all logging */
394 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
395
396 /* now cycle through the bitmask until all "set" bits are serviced */
397 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
398 while (0 != bitmask)
399 {
400 if (bitmask & 1)
401 {
402 wpalTraceSetLevel(moduleId, level, 1);
403 }
404 level++;
405 bitmask >>= 1;
406 }
407}
Jeff Johnson295189b2012-06-20 16:38:30 -0700408
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700409void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
410{
411 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
412 hdd_config_t *cfg_param;
413
414 if (NULL == pHddCtx)
415 {
416 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
417 "HDD Context is null !!");
418 return ;
419 }
420
421 cfg_param = pHddCtx->cfg_ini;
422
423 if (NULL == cfg_param)
424 {
425 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
426 "cfg_params not available !!");
427 return ;
428 }
429
430 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
431 {
432 /*New country doesn't support DFS */
433 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
434 }
435 else
436 {
437 /*New country Supports DFS as well resetting value back from .ini*/
438 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
439 }
440
441}
442
Jeff Johnson295189b2012-06-20 16:38:30 -0700443int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
444{
445 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
446 hdd_priv_data_t priv_data;
447 tANI_U8 *command = NULL;
448 int ret = 0;
449
450 if (NULL == pAdapter)
451 {
452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700453 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700454 ret = -ENODEV;
455 goto exit;
456 }
457
Jeff Johnsone7245742012-09-05 17:12:55 -0700458 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700459 {
460 ret = -EINVAL;
461 goto exit;
462 }
463
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -0700464 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
465 {
466 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
467 "%s:LOGP in Progress. Ignore!!!", __func__);
468 ret = -EBUSY;
469 goto exit;
470 }
471
Jeff Johnson295189b2012-06-20 16:38:30 -0700472 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
473 {
474 ret = -EFAULT;
475 goto exit;
476 }
477
478 command = kmalloc(priv_data.total_len, GFP_KERNEL);
479 if (!command)
480 {
481 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700482 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700483 ret = -ENOMEM;
484 goto exit;
485 }
486
487 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
488 {
489 ret = -EFAULT;
490 goto exit;
491 }
492
493 if ((SIOCDEVPRIVATE + 1) == cmd)
494 {
495 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
496
497 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700498 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700499
500 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
501 {
502 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
503 sizeof(tSirMacAddr)))
504 {
505 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700506 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700507 ret = -EFAULT;
508 }
509 }
Amar Singhal0974e402013-02-12 14:27:46 -0800510 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700511 {
Amar Singhal0974e402013-02-12 14:27:46 -0800512 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700513 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800514
Jeff Johnson295189b2012-06-20 16:38:30 -0700515 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800516
517 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700518 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700519 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800520 "%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 -0700521 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800522 ret = hdd_setBand_helper(dev, ptr);
523 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700524 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
525 {
526 char *country_code;
527
528 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700529
530 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700531 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
532 pAdapter, pHddCtx->pvosContext);
533 if( 0 != ret )
534 {
535 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
536 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
537
538 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700539 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800540#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
541 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
542 {
543 tANI_U8 *value = command;
544 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
545 tANI_U8 revision = 0;
546 eHalStatus status = eHAL_STATUS_SUCCESS;
547 v_REGDOMAIN_t regId;
548
549 status = hdd_parse_countryrev(value, countryCode, &revision);
550 if (eHAL_STATUS_SUCCESS != status)
551 {
552 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
553 "%s: Failed to parse country revision information", __func__);
554 ret = -EINVAL;
555 goto exit;
556 }
557
558 /* Validate country code */
559 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
560 if (eHAL_STATUS_SUCCESS != status)
561 {
562 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
563 "%s: Invalid country code %s", __func__, countryCode);
564 ret = -EINVAL;
565 goto exit;
566 }
567
568 /* Validate revision */
569 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
570 {
571 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
572 "%s: Invalid revision %d", __func__, revision);
573 ret = -EINVAL;
574 goto exit;
575 }
576
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700577 hdd_checkandupdate_dfssetting(pAdapter, countryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800578 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
579 pAdapter, pHddCtx->pvosContext);
580 if (0 != ret)
581 {
582 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
583 "%s: SME Change Country code fail ret=%d", __func__, ret);
584 ret = -EINVAL;
585 goto exit;
586 }
587
588 if (0 == strncmp(countryCode, "KR", 2))
589 {
590 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
591 revision);
592 if (eHAL_STATUS_SUCCESS != status)
593 {
594 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
595 "%s: Failed to build valid channel list", __func__);
596 ret = -EINVAL;
597 goto exit;
598 }
599 }
600 }
601#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700602 /*
603 command should be a string having format
604 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
605 */
Amar Singhal0974e402013-02-12 14:27:46 -0800606 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700607 {
Amar Singhal0974e402013-02-12 14:27:46 -0800608 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700609
610 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700611 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700612
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800613 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700614 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800615 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
616 {
617 int suspend = 0;
618 tANI_U8 *ptr = (tANI_U8*)command + 15;
619
620 suspend = *ptr - '0';
621 hdd_set_wlan_suspend_mode(suspend);
622 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800623#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
624 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
625 {
626 tANI_U8 *value = command;
627 int rssi = 0;
628 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
629 eHalStatus status = eHAL_STATUS_SUCCESS;
630
631 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
632 value = value + 15;
633
634 sscanf(value, "%d", &rssi);
635 lookUpThreshold = abs(rssi);
636 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
637 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
638 {
639 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
640 "Neighbor lookup threshold value %d is out of range"
641 " (Min: %d Max: %d)", lookUpThreshold,
642 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
643 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
644 ret = -EINVAL;
645 goto exit;
646 }
647
648 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
649 "%s: Received Command to Set Roam trigger"
650 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
651
652 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
653 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
654 if (eHAL_STATUS_SUCCESS != status)
655 {
656 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
657 "%s: Failed to set roam trigger, try again", __func__);
658 ret = -EPERM;
659 goto exit;
660 }
661
662 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
663 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
664 }
665 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
666 {
667 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
668 int rssi = (-1) * lookUpThreshold;
669 char extra[32];
670 tANI_U8 len = 0;
671
672 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
673 if (copy_to_user(priv_data.buf, &extra, len + 1))
674 {
675 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
676 "%s: failed to copy data to user buffer", __func__);
677 ret = -EFAULT;
678 goto exit;
679 }
680 }
681 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
682 {
683 tANI_U8 *value = command;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700684 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800685 /* input refresh period is in terms of seconds */
686 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
687 value = value + 18;
688 /* Convert the value from ascii to integer */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700689 ret = kstrtou16(value, 10, &neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800690 if (ret < 0)
691 {
692 /* If the input value is greater than max value of datatype, then also
693 kstrtou16 fails */
694 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
695 "%s: kstrtou16 failed ",
696 "Input value may be out of range[%d - %d]",
697 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700698 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
699 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800700 ret = -EINVAL;
701 goto exit;
702 }
703
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700704 neighborEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod * 1000;
705 if ((neighborEmptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
706 (neighborEmptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800707 {
708 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700709 "Neighbor empty scan results refresh period value %d is out of range"
710 " (Min: %d Max: %d)", neighborEmptyScanRefreshPeriod/1000,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700711 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
712 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800713 ret = -EINVAL;
714 goto exit;
715 }
716
717 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
718 "%s: Received Command to Set roam scan period"
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700719 " (Empty Scan refresh period) = %d", __func__, neighborEmptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800720
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700721 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
722 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800723 }
724 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
725 {
726 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
727 char extra[32];
728 tANI_U8 len = 0;
729
730 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
731 /* Returned value is in units of seconds */
732 if (copy_to_user(priv_data.buf, &extra, len + 1))
733 {
734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
735 "%s: failed to copy data to user buffer", __func__);
736 ret = -EFAULT;
737 goto exit;
738 }
739 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700740 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
741 {
742 tANI_U8 *value = command;
743 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
744 /* input refresh period is in terms of seconds */
745 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
746 value = value + 25;
747 /* Convert the value from ascii to integer */
748 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
749 if (ret < 0)
750 {
751 /* If the input value is greater than max value of datatype, then also
752 kstrtou16 fails */
753 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
754 "%s: kstrtou16 failed ",
755 "Input value may be out of range[%d - %d]",
756 __func__,
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700757 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
758 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700759 ret = -EINVAL;
760 goto exit;
761 }
762
763 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700764 if ((neighborScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
765 (neighborScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700766 {
767 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
768 "Neighbor scan results refresh period value %d is out of range"
769 " (Min: %d Max: %d)", neighborScanRefreshPeriod/1000,
770 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
771 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
772 ret = -EINVAL;
773 goto exit;
774 }
775
776 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
777 "%s: Received Command to Set roam scan refresh period"
778 " (Scan refresh period) = %d", __func__, neighborScanRefreshPeriod/1000);
779
780 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
781 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
782 }
783 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
784 {
785 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
786 char extra[32];
787 tANI_U8 len = 0;
788
789 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
790 /* Returned value is in units of seconds */
791 if (copy_to_user(priv_data.buf, &extra, len + 1))
792 {
793 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
794 "%s: failed to copy data to user buffer", __func__);
795 ret = -EFAULT;
796 goto exit;
797 }
798 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800799#endif
800#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
801 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
802 {
803 tANI_U8 *value = command;
804 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
805
806 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
807 value = value + 13;
808 /* Convert the value from ascii to integer */
809 ret = kstrtou8(value, 10, &roamRssiDiff);
810 if (ret < 0)
811 {
812 /* If the input value is greater than max value of datatype, then also
813 kstrtou8 fails */
814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
815 "%s: kstrtou8 failed range [%d - %d]", __func__,
816 CFG_ROAM_RSSI_DIFF_MIN,
817 CFG_ROAM_RSSI_DIFF_MAX);
818 ret = -EINVAL;
819 goto exit;
820 }
821
822 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
823 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
824 {
825 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
826 "Roam rssi diff value %d is out of range"
827 " (Min: %d Max: %d)", roamRssiDiff,
828 CFG_ROAM_RSSI_DIFF_MIN,
829 CFG_ROAM_RSSI_DIFF_MAX);
830 ret = -EINVAL;
831 goto exit;
832 }
833
834 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
835 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
836
837 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
838 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
839 }
840 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
841 {
842 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
843 char extra[32];
844 tANI_U8 len = 0;
845
846 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
847 if (copy_to_user(priv_data.buf, &extra, len + 1))
848 {
849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
850 "%s: failed to copy data to user buffer", __func__);
851 ret = -EFAULT;
852 goto exit;
853 }
854 }
855#endif
856#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
857 else if (strncmp(command, "GETBAND", 7) == 0)
858 {
859 int band = -1;
860 char extra[32];
861 tANI_U8 len = 0;
862 hdd_getBand_helper(pHddCtx, &band);
863
864 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
865 if (copy_to_user(priv_data.buf, &extra, len + 1))
866 {
867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
868 "%s: failed to copy data to user buffer", __func__);
869 ret = -EFAULT;
870 goto exit;
871 }
872 }
873 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
874 {
875 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
876 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
877 tANI_U8 revision = 0;
878 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
879 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
880 char extra[32] = {0};
881 tANI_U8 len = 0;
882
883 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
884 {
885 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
886 "%s: failed to get country code", __func__);
887 ret = -EFAULT;
888 goto exit;
889 }
890 pBuf[uBufLen] = '\0';
891 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
892
893 if (0 == strncmp(pBuf, "KR", 2))
894 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
895 else
896 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
897
898 if (copy_to_user(priv_data.buf, &extra, len + 1))
899 {
900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
901 "%s: failed to copy data to user buffer", __func__);
902 ret = -EFAULT;
903 goto exit;
904 }
905 }
906 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
907 {
908 tANI_U8 *value = command;
909 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
910 tANI_U8 numChannels = 0;
911 eHalStatus status = eHAL_STATUS_SUCCESS;
912
913 status = hdd_parse_channellist(value, ChannelList, &numChannels);
914 if (eHAL_STATUS_SUCCESS != status)
915 {
916 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
917 "%s: Failed to parse channel list information", __func__);
918 ret = -EINVAL;
919 goto exit;
920 }
921
922 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
923 {
924 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
925 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
926 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
927 ret = -EINVAL;
928 goto exit;
929 }
930 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
931 numChannels);
932 if (eHAL_STATUS_SUCCESS != status)
933 {
934 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
935 "%s: Failed to update channel list information", __func__);
936 ret = -EINVAL;
937 goto exit;
938 }
939 }
940 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
941 {
942 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
943 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -0700944 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800945 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -0700946 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800947
948 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
949 ChannelList, &numChannels ))
950 {
951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
952 "%s: failed to get roam scan channel list", __func__);
953 ret = -EFAULT;
954 goto exit;
955 }
956 /* output channel list is of the format
957 [Number of roam scan channels][Channel1][Channel2]... */
958 /* copy the number of channels in the 0th index */
959 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
960 for (j = 0; (j < numChannels); j++)
961 {
962 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
963 }
964
965 if (copy_to_user(priv_data.buf, &extra, len + 1))
966 {
967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
968 "%s: failed to copy data to user buffer", __func__);
969 ret = -EFAULT;
970 goto exit;
971 }
972 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700973 else if (strncmp(command, "GETCCXMODE", 10) == 0)
974 {
975 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
976 char extra[32];
977 tANI_U8 len = 0;
978
979 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
980 if (copy_to_user(priv_data.buf, &extra, len + 1))
981 {
982 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
983 "%s: failed to copy data to user buffer", __func__);
984 ret = -EFAULT;
985 goto exit;
986 }
987 }
988 else if (strncmp(command, "GETOKCMODE", 10) == 0)
989 {
990 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
991 char extra[32];
992 tANI_U8 len = 0;
993
994 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
995 if (copy_to_user(priv_data.buf, &extra, len + 1))
996 {
997 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
998 "%s: failed to copy data to user buffer", __func__);
999 ret = -EFAULT;
1000 goto exit;
1001 }
1002 }
1003 else if (strncmp(command, "GETFASTROAM", 10) == 0)
1004 {
1005 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1006 char extra[32];
1007 tANI_U8 len = 0;
1008
1009 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
1010 if (copy_to_user(priv_data.buf, &extra, len + 1))
1011 {
1012 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1013 "%s: failed to copy data to user buffer", __func__);
1014 ret = -EFAULT;
1015 goto exit;
1016 }
1017 }
1018 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
1019 {
1020 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1021 char extra[32];
1022 tANI_U8 len = 0;
1023
1024 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
1025 if (copy_to_user(priv_data.buf, &extra, len + 1))
1026 {
1027 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1028 "%s: failed to copy data to user buffer", __func__);
1029 ret = -EFAULT;
1030 goto exit;
1031 }
1032 }
1033 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
1034 {
1035 tANI_U8 *value = command;
1036 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
1037
1038 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
1039 value = value + 26;
1040 /* Convert the value from ascii to integer */
1041 ret = kstrtou8(value, 10, &minTime);
1042 if (ret < 0)
1043 {
1044 /* If the input value is greater than max value of datatype, then also
1045 kstrtou8 fails */
1046 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1047 "%s: kstrtou8 failed range [%d - %d]", __func__,
1048 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1049 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1050 ret = -EINVAL;
1051 goto exit;
1052 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001053 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1054 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1055 {
1056 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1057 "scan min channel time value %d is out of range"
1058 " (Min: %d Max: %d)", minTime,
1059 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1060 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1061 ret = -EINVAL;
1062 goto exit;
1063 }
1064
1065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1066 "%s: Received Command to change channel min time = %d", __func__, minTime);
1067
1068 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1069 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1070 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001071 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
1072 {
1073 tANI_U8 *value = command;
1074 tANI_U8 channel = 0;
1075 tANI_U8 dwellTime = 0;
1076 tANI_U8 bufLen = 0;
1077 tANI_U8 *buf = NULL;
1078 tSirMacAddr targetApBssid;
1079 eHalStatus status = eHAL_STATUS_SUCCESS;
1080 struct ieee80211_channel chan;
1081 tANI_U8 finalLen = 0;
1082 tANI_U8 *finalBuf = NULL;
1083 tANI_U8 temp = 0;
1084 u64 cookie;
1085 hdd_station_ctx_t *pHddStaCtx = NULL;
1086 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1087
1088 /* if not associated, no need to send action frame */
1089 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
1090 {
1091 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
1092 ret = -EINVAL;
1093 goto exit;
1094 }
1095
1096 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
1097 &dwellTime, &buf, &bufLen);
1098 if (eHAL_STATUS_SUCCESS != status)
1099 {
1100 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1101 "%s: Failed to parse send action frame data", __func__);
1102 ret = -EINVAL;
1103 goto exit;
1104 }
1105
1106 /* if the target bssid is different from currently associated AP,
1107 then no need to send action frame */
1108 if (VOS_TRUE != vos_mem_compare(targetApBssid,
1109 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
1110 {
1111 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
1112 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001113 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001114 goto exit;
1115 }
1116
1117 /* if the channel number is different from operating channel then
1118 no need to send action frame */
1119 if (channel != pHddStaCtx->conn_info.operationChannel)
1120 {
1121 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1122 "%s: channel(%d) is different from operating channel(%d)",
1123 __func__, channel, pHddStaCtx->conn_info.operationChannel);
1124 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07001125 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001126 goto exit;
1127 }
1128 chan.center_freq = sme_ChnToFreq(channel);
1129
1130 finalLen = bufLen + 24;
1131 finalBuf = vos_mem_malloc(finalLen);
1132 if (NULL == finalBuf)
1133 {
1134 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
1135 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07001136 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001137 goto exit;
1138 }
1139 vos_mem_zero(finalBuf, finalLen);
1140
1141 /* Fill subtype */
1142 temp = SIR_MAC_MGMT_ACTION << 4;
1143 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
1144
1145 /* Fill type */
1146 temp = SIR_MAC_MGMT_FRAME;
1147 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
1148
1149 /* Fill destination address (bssid of the AP) */
1150 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
1151
1152 /* Fill BSSID (STA mac address) */
1153 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1154
1155 /* Fill source address (STA mac address) */
1156 vos_mem_copy(finalBuf + 16, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
1157
1158 /* Fill received buffer from 24th address */
1159 vos_mem_copy(finalBuf + 24, buf, bufLen);
1160
Jeff Johnson11c33152013-04-16 17:52:40 -07001161 /* done with the parsed buffer */
1162 vos_mem_free(buf);
1163
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001164 wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20,
1165 1, dwellTime, finalBuf, finalLen, 1,
1166 1, &cookie );
1167 vos_mem_free(finalBuf);
1168 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001169 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1170 {
1171 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1172 char extra[32];
1173 tANI_U8 len = 0;
1174
1175 /* value is interms of msec */
1176 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1177 if (copy_to_user(priv_data.buf, &extra, len + 1))
1178 {
1179 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1180 "%s: failed to copy data to user buffer", __func__);
1181 ret = -EFAULT;
1182 goto exit;
1183 }
1184 }
1185 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1186 {
1187 tANI_U8 *value = command;
1188 tANI_U8 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
1189
1190 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1191 value = value + 19;
1192 /* Convert the value from ascii to integer */
1193 ret = kstrtou8(value, 10, &maxTime);
1194 if (ret < 0)
1195 {
1196 /* If the input value is greater than max value of datatype, then also
1197 kstrtou8 fails */
1198 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1199 "%s: kstrtou8 failed range [%d - %d]", __func__,
1200 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1201 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1202 ret = -EINVAL;
1203 goto exit;
1204 }
1205
1206 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1207 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1208 {
1209 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1210 "lfr mode value %d is out of range"
1211 " (Min: %d Max: %d)", maxTime,
1212 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1213 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1214 ret = -EINVAL;
1215 goto exit;
1216 }
1217
1218 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1219 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1220
1221 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
1222 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1223 }
1224 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1225 {
1226 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1227 char extra[32];
1228 tANI_U8 len = 0;
1229
1230 /* value is interms of msec */
1231 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1232 if (copy_to_user(priv_data.buf, &extra, len + 1))
1233 {
1234 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1235 "%s: failed to copy data to user buffer", __func__);
1236 ret = -EFAULT;
1237 goto exit;
1238 }
1239 }
1240 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1241 {
1242 tANI_U8 *value = command;
1243 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1244
1245 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1246 value = value + 16;
1247 /* Convert the value from ascii to integer */
1248 ret = kstrtou16(value, 10, &val);
1249 if (ret < 0)
1250 {
1251 /* If the input value is greater than max value of datatype, then also
1252 kstrtou16 fails */
1253 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1254 "%s: kstrtou16 failed range [%d - %d]", __func__,
1255 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1256 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1257 ret = -EINVAL;
1258 goto exit;
1259 }
1260
1261 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1262 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1263 {
1264 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1265 "scan home time value %d is out of range"
1266 " (Min: %d Max: %d)", val,
1267 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1268 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1269 ret = -EINVAL;
1270 goto exit;
1271 }
1272
1273 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1274 "%s: Received Command to change scan home time = %d", __func__, val);
1275
1276 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1277 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1278 }
1279 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1280 {
1281 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1282 char extra[32];
1283 tANI_U8 len = 0;
1284
1285 /* value is interms of msec */
1286 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1287 if (copy_to_user(priv_data.buf, &extra, len + 1))
1288 {
1289 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1290 "%s: failed to copy data to user buffer", __func__);
1291 ret = -EFAULT;
1292 goto exit;
1293 }
1294 }
1295 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1296 {
1297 tANI_U8 *value = command;
1298 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1299
1300 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1301 value = value + 17;
1302 /* Convert the value from ascii to integer */
1303 ret = kstrtou8(value, 10, &val);
1304 if (ret < 0)
1305 {
1306 /* If the input value is greater than max value of datatype, then also
1307 kstrtou8 fails */
1308 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1309 "%s: kstrtou8 failed range [%d - %d]", __func__,
1310 CFG_ROAM_INTRA_BAND_MIN,
1311 CFG_ROAM_INTRA_BAND_MAX);
1312 ret = -EINVAL;
1313 goto exit;
1314 }
1315
1316 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1317 (val > CFG_ROAM_INTRA_BAND_MAX))
1318 {
1319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1320 "intra band mode value %d is out of range"
1321 " (Min: %d Max: %d)", val,
1322 CFG_ROAM_INTRA_BAND_MIN,
1323 CFG_ROAM_INTRA_BAND_MAX);
1324 ret = -EINVAL;
1325 goto exit;
1326 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001327 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1328 "%s: Received Command to change intra band = %d", __func__, val);
1329
1330 pHddCtx->cfg_ini->nRoamIntraBand = val;
1331 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1332 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001333 else if (strncmp(command, "SETWESMODE", 10) == 0)
1334 {
1335 tANI_U8 *value = command;
1336 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
1337
1338 /* Move pointer to ahead of SETWESMODE<delimiter> */
1339 value = value + 11;
1340 /* Convert the value from ascii to integer */
1341 ret = kstrtou8(value, 10, &wesMode);
1342 if (ret < 0)
1343 {
1344 /* If the input value is greater than max value of datatype, then also
1345 kstrtou8 fails */
1346 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1347 "%s: kstrtou8 failed range [%d - %d]", __func__,
1348 CFG_ENABLE_WES_MODE_NAME_MIN,
1349 CFG_ENABLE_WES_MODE_NAME_MAX);
1350 ret = -EINVAL;
1351 goto exit;
1352 }
1353
1354 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
1355 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
1356 {
1357 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1358 "WES Mode value %d is out of range"
1359 " (Min: %d Max: %d)", wesMode,
1360 CFG_ENABLE_WES_MODE_NAME_MIN,
1361 CFG_ENABLE_WES_MODE_NAME_MAX);
1362 ret = -EINVAL;
1363 goto exit;
1364 }
1365 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1366 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
1367
1368 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
1369 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
1370 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001371 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1372 {
1373 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1374 char extra[32];
1375 tANI_U8 len = 0;
1376
1377 /* value is interms of msec */
1378 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1379 if (copy_to_user(priv_data.buf, &extra, len + 1))
1380 {
1381 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1382 "%s: failed to copy data to user buffer", __func__);
1383 ret = -EFAULT;
1384 goto exit;
1385 }
1386 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001387 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
1388 {
1389 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
1390 char extra[32];
1391 tANI_U8 len = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001392
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001393 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
1394 if (copy_to_user(priv_data.buf, &extra, len + 1))
1395 {
1396 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1397 "%s: failed to copy data to user buffer", __func__);
1398 ret = -EFAULT;
1399 goto exit;
1400 }
1401 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001402#endif
1403#ifdef FEATURE_WLAN_LFR
1404 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1405 {
1406 tANI_U8 *value = command;
1407 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1408
1409 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1410 value = value + 12;
1411 /* Convert the value from ascii to integer */
1412 ret = kstrtou8(value, 10, &lfrMode);
1413 if (ret < 0)
1414 {
1415 /* If the input value is greater than max value of datatype, then also
1416 kstrtou8 fails */
1417 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1418 "%s: kstrtou8 failed range [%d - %d]", __func__,
1419 CFG_LFR_FEATURE_ENABLED_MIN,
1420 CFG_LFR_FEATURE_ENABLED_MAX);
1421 ret = -EINVAL;
1422 goto exit;
1423 }
1424
1425 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1426 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1427 {
1428 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1429 "lfr mode value %d is out of range"
1430 " (Min: %d Max: %d)", lfrMode,
1431 CFG_LFR_FEATURE_ENABLED_MIN,
1432 CFG_LFR_FEATURE_ENABLED_MAX);
1433 ret = -EINVAL;
1434 goto exit;
1435 }
1436
1437 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1438 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1439
1440 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1441 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1442 }
1443#endif
1444#ifdef WLAN_FEATURE_VOWIFI_11R
1445 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1446 {
1447 tANI_U8 *value = command;
1448 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1449
1450 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1451 value = value + 18;
1452 /* Convert the value from ascii to integer */
1453 ret = kstrtou8(value, 10, &ft);
1454 if (ret < 0)
1455 {
1456 /* If the input value is greater than max value of datatype, then also
1457 kstrtou8 fails */
1458 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1459 "%s: kstrtou8 failed range [%d - %d]", __func__,
1460 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1461 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1462 ret = -EINVAL;
1463 goto exit;
1464 }
1465
1466 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1467 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1468 {
1469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1470 "ft mode value %d is out of range"
1471 " (Min: %d Max: %d)", ft,
1472 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1473 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1474 ret = -EINVAL;
1475 goto exit;
1476 }
1477
1478 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1479 "%s: Received Command to change ft mode = %d", __func__, ft);
1480
1481 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1482 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1483 }
1484#endif
1485#ifdef FEATURE_WLAN_CCX
1486 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1487 {
1488 tANI_U8 *value = command;
1489 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1490
1491 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1492 value = value + 11;
1493 /* Convert the value from ascii to integer */
1494 ret = kstrtou8(value, 10, &ccxMode);
1495 if (ret < 0)
1496 {
1497 /* If the input value is greater than max value of datatype, then also
1498 kstrtou8 fails */
1499 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1500 "%s: kstrtou8 failed range [%d - %d]", __func__,
1501 CFG_CCX_FEATURE_ENABLED_MIN,
1502 CFG_CCX_FEATURE_ENABLED_MAX);
1503 ret = -EINVAL;
1504 goto exit;
1505 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001506 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1507 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1508 {
1509 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1510 "Ccx mode value %d is out of range"
1511 " (Min: %d Max: %d)", ccxMode,
1512 CFG_CCX_FEATURE_ENABLED_MIN,
1513 CFG_CCX_FEATURE_ENABLED_MAX);
1514 ret = -EINVAL;
1515 goto exit;
1516 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001517 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1518 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1519
1520 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1521 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1522 }
1523#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001524 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
1525 {
1526 tANI_U8 *value = command;
1527 tANI_BOOLEAN roamScanControl = 0;
1528
1529 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
1530 value = value + 19;
1531 /* Convert the value from ascii to integer */
1532 ret = kstrtou8(value, 10, &roamScanControl);
1533 if (ret < 0)
1534 {
1535 /* If the input value is greater than max value of datatype, then also
1536 kstrtou8 fails */
1537 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1538 "%s: kstrtou8 failed ", __func__);
1539 ret = -EINVAL;
1540 goto exit;
1541 }
1542
1543 if (0 != roamScanControl)
1544 {
1545 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1546 "roam scan control invalid value = %d",
1547 roamScanControl);
1548 ret = -EINVAL;
1549 goto exit;
1550 }
1551 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1552 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
1553
1554 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
1555 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001556#ifdef FEATURE_WLAN_OKC
1557 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1558 {
1559 tANI_U8 *value = command;
1560 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1561
1562 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1563 value = value + 11;
1564 /* Convert the value from ascii to integer */
1565 ret = kstrtou8(value, 10, &okcMode);
1566 if (ret < 0)
1567 {
1568 /* If the input value is greater than max value of datatype, then also
1569 kstrtou8 fails */
1570 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1571 "%s: kstrtou8 failed range [%d - %d]", __func__,
1572 CFG_OKC_FEATURE_ENABLED_MIN,
1573 CFG_OKC_FEATURE_ENABLED_MAX);
1574 ret = -EINVAL;
1575 goto exit;
1576 }
1577
1578 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1579 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1580 {
1581 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1582 "Okc mode value %d is out of range"
1583 " (Min: %d Max: %d)", okcMode,
1584 CFG_OKC_FEATURE_ENABLED_MIN,
1585 CFG_OKC_FEATURE_ENABLED_MAX);
1586 ret = -EINVAL;
1587 goto exit;
1588 }
1589
1590 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1591 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1592
1593 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1594 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001595 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
1596 {
1597 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
1598 char extra[32];
1599 tANI_U8 len = 0;
1600
1601 len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl);
1602 if (copy_to_user(priv_data.buf, &extra, len + 1))
1603 {
1604 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1605 "%s: failed to copy data to user buffer", __func__);
1606 ret = -EFAULT;
1607 goto exit;
1608 }
1609 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001610#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001611 else {
1612 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1613 __func__, command);
1614 }
1615
Jeff Johnson295189b2012-06-20 16:38:30 -07001616 }
1617exit:
1618 if (command)
1619 {
1620 kfree(command);
1621 }
1622 return ret;
1623}
1624
Srinivas Girigowdade697412013-02-14 16:31:48 -08001625#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1626void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
1627{
1628 eCsrBand band = -1;
1629 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
1630 switch (band)
1631 {
1632 case eCSR_BAND_ALL:
1633 *pBand = WLAN_HDD_UI_BAND_AUTO;
1634 break;
1635
1636 case eCSR_BAND_24:
1637 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
1638 break;
1639
1640 case eCSR_BAND_5G:
1641 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
1642 break;
1643
1644 default:
1645 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
1646 *pBand = -1;
1647 break;
1648 }
1649}
1650
1651/**---------------------------------------------------------------------------
1652
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001653 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
1654
1655 This function parses the send action frame data passed in the format
1656 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
1657
1658 \param - pValue Pointer to input country code revision
1659 \param - pTargetApBssid Pointer to target Ap bssid
1660 \param - pChannel Pointer to the Target AP channel
1661 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
1662 \param - pBuf Pointer to data
1663 \param - pBufLen Pointer to data length
1664
1665 \return - 0 for success non-zero for failure
1666
1667 --------------------------------------------------------------------------*/
1668VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
1669 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
1670{
1671 tANI_U8 *inPtr = pValue;
1672 tANI_U8 *dataEnd;
1673 int tempInt;
1674 int j = 0;
1675 int i = 0;
1676 int v = 0;
1677 tANI_U8 tempBuf[32];
1678 tANI_U8 tempByte = 0;
1679
1680 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1681 /*no argument after the command*/
1682 if (NULL == inPtr)
1683 {
1684 return -EINVAL;
1685 }
1686
1687 /*no space after the command*/
1688 else if (SPACE_ASCII_VALUE != *inPtr)
1689 {
1690 return -EINVAL;
1691 }
1692
1693 /*removing empty spaces*/
1694 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1695
1696 /*no argument followed by spaces*/
1697 if ('\0' == *inPtr)
1698 {
1699 return -EINVAL;
1700 }
1701
1702 /*getting the first argument ie the target AP bssid */
1703 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
1704 {
1705 return -EINVAL;
1706 }
1707 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
1708 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
1709 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
1710
1711 /* point to the next argument */
1712 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1713 /*no argument after the command*/
1714 if (NULL == inPtr) return -EINVAL;
1715
1716 /*removing empty spaces*/
1717 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1718
1719 /*no argument followed by spaces*/
1720 if ('\0' == *inPtr)
1721 {
1722 return -EINVAL;
1723 }
1724
1725 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07001726 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001727 v = kstrtos32(tempBuf, 10, &tempInt);
1728 if ( v < 0) return -EINVAL;
1729
1730 *pChannel = tempInt;
1731
1732 /* point to the next argument */
1733 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1734 /*no argument after the command*/
1735 if (NULL == inPtr) return -EINVAL;
1736 /*removing empty spaces*/
1737 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1738
1739 /*no argument followed by spaces*/
1740 if ('\0' == *inPtr)
1741 {
1742 return -EINVAL;
1743 }
1744
1745 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07001746 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07001747 v = kstrtos32(tempBuf, 10, &tempInt);
1748 if ( v < 0) return -EINVAL;
1749
1750 *pDwellTime = tempInt;
1751
1752 /* point to the next argument */
1753 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
1754 /*no argument after the command*/
1755 if (NULL == inPtr) return -EINVAL;
1756 /*removing empty spaces*/
1757 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1758
1759 /*no argument followed by spaces*/
1760 if ('\0' == *inPtr)
1761 {
1762 return -EINVAL;
1763 }
1764
1765 /* find the length of data */
1766 dataEnd = inPtr;
1767 while(('\0' != *dataEnd) )
1768 {
1769 dataEnd++;
1770 ++(*pBufLen);
1771 }
1772 if ( *pBufLen <= 0) return -EINVAL;
1773
1774 *pBuf = vos_mem_malloc(sizeof(*pBufLen));
1775 if (NULL == *pBuf)
1776 {
1777 hddLog(VOS_TRACE_LEVEL_FATAL,
1778 "%s: vos_mem_alloc failed ", __func__);
1779 return -EINVAL;
1780 }
1781
1782 /* the buffer received from the upper layer is character buffer,
1783 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
1784 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
1785 and f0 in 3rd location */
1786 for (i = 0, j = 0; j < *pBufLen; j += 2)
1787 {
1788 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
1789 (*pBuf)[i++] = tempByte;
1790 }
1791 *pBufLen = i;
1792 return VOS_STATUS_SUCCESS;
1793}
1794
1795#endif
1796/**---------------------------------------------------------------------------
1797
Srinivas Girigowdade697412013-02-14 16:31:48 -08001798 \brief hdd_parse_countryrev() - HDD Parse country code revision
1799
1800 This function parses the country code revision passed in the format
1801 SETCOUNTRYREV<space><Country code><space>revision
1802
1803 \param - pValue Pointer to input country code revision
1804 \param - pCountryCode Pointer to local output array to record country code
1805 \param - pRevision Pointer to store revision integer number
1806
1807 \return - 0 for success non-zero for failure
1808
1809 --------------------------------------------------------------------------*/
1810VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
1811{
1812 tANI_U8 *inPtr = pValue;
1813 int tempInt;
1814
1815 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1816 /*no argument after the command*/
1817 if (NULL == inPtr)
1818 {
1819 return -EINVAL;
1820 }
1821
1822 /*no space after the command*/
1823 else if (SPACE_ASCII_VALUE != *inPtr)
1824 {
1825 return -EINVAL;
1826 }
1827
1828 /*removing empty spaces*/
1829 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1830
1831 /*no argument followed by spaces*/
1832 if ('\0' == *inPtr)
1833 {
1834 return -EINVAL;
1835 }
1836
1837 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07001838 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001839
1840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1841 "Country code is : %s", pCountryCode);
1842
1843 /*inPtr pointing to the beginning of first space after country code */
1844 inPtr = strpbrk( inPtr, " " );
1845 /*no revision number after the country code argument */
1846 if (NULL == inPtr)
1847 {
1848 return -EINVAL;
1849 }
1850
1851 inPtr++;
1852
1853 /*removing empty space*/
1854 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1855
1856 /*no channel list after the number of channels argument and spaces*/
1857 if (0 == strncmp(pCountryCode, "KR", 2))
1858 {
1859 if ('\0' == *inPtr)
1860 {
1861 return -EINVAL;
1862 }
1863
1864 sscanf(inPtr, "%d", &tempInt);
1865 *pRevision = tempInt;
1866 }
1867 else
1868 {
1869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1870 "Revision input is required only for Country KR");
1871 return -EINVAL;
1872 }
1873 return VOS_STATUS_SUCCESS;
1874}
1875
1876/**---------------------------------------------------------------------------
1877
1878 \brief hdd_parse_channellist() - HDD Parse channel list
1879
1880 This function parses the channel list passed in the format
1881 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001882 if the Number of channels (N) does not match with the actual number of channels passed
1883 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
1884 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
1885 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
1886 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08001887
1888 \param - pValue Pointer to input channel list
1889 \param - ChannelList Pointer to local output array to record channel list
1890 \param - pNumChannels Pointer to number of roam scan channels
1891
1892 \return - 0 for success non-zero for failure
1893
1894 --------------------------------------------------------------------------*/
1895VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
1896{
1897 tANI_U8 *inPtr = pValue;
1898 int tempInt;
1899 int j = 0;
1900 int v = 0;
1901 char buf[32];
1902
1903 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1904 /*no argument after the command*/
1905 if (NULL == inPtr)
1906 {
1907 return -EINVAL;
1908 }
1909
1910 /*no space after the command*/
1911 else if (SPACE_ASCII_VALUE != *inPtr)
1912 {
1913 return -EINVAL;
1914 }
1915
1916 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001917 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001918
1919 /*no argument followed by spaces*/
1920 if ('\0' == *inPtr)
1921 {
1922 return -EINVAL;
1923 }
1924
1925 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07001926 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001927 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001928 if ((v < 0) ||
1929 (tempInt <= 0) ||
1930 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
1931 {
1932 return -EINVAL;
1933 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001934
1935 *pNumChannels = tempInt;
1936
1937 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1938 "Number of channels are: %d", *pNumChannels);
1939
1940 for (j = 0; j < (*pNumChannels); j++)
1941 {
1942 /*inPtr pointing to the beginning of first space after number of channels*/
1943 inPtr = strpbrk( inPtr, " " );
1944 /*no channel list after the number of channels argument*/
1945 if (NULL == inPtr)
1946 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001947 if (0 != j)
1948 {
1949 *pNumChannels = j;
1950 return VOS_STATUS_SUCCESS;
1951 }
1952 else
1953 {
1954 return -EINVAL;
1955 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001956 }
1957
1958 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001959 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001960
1961 /*no channel list after the number of channels argument and spaces*/
1962 if ( '\0' == *inPtr )
1963 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001964 if (0 != j)
1965 {
1966 *pNumChannels = j;
1967 return VOS_STATUS_SUCCESS;
1968 }
1969 else
1970 {
1971 return -EINVAL;
1972 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001973 }
1974
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001975 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001976 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001977 if ((v < 0) ||
1978 (tempInt <= 0) ||
1979 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
1980 {
1981 return -EINVAL;
1982 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001983 pChannelList[j] = tempInt;
1984
1985 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1986 "Channel %d added to preferred channel list",
1987 pChannelList[j] );
1988 }
1989
Srinivas Girigowdade697412013-02-14 16:31:48 -08001990 return VOS_STATUS_SUCCESS;
1991}
1992
Jeff Johnson295189b2012-06-20 16:38:30 -07001993/**---------------------------------------------------------------------------
1994
1995 \brief hdd_open() - HDD Open function
1996
1997 This is called in response to ifconfig up
1998
1999 \param - dev Pointer to net_device structure
2000
2001 \return - 0 for success non-zero for failure
2002
2003 --------------------------------------------------------------------------*/
2004int hdd_open (struct net_device *dev)
2005{
2006 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2007 hdd_context_t *pHddCtx;
2008 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2009 VOS_STATUS status;
2010 v_BOOL_t in_standby = TRUE;
2011
2012 if (NULL == pAdapter)
2013 {
2014 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002015 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002016 return -ENODEV;
2017 }
2018
2019 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2020 if (NULL == pHddCtx)
2021 {
2022 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002023 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002024 return -ENODEV;
2025 }
2026
2027 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2028 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2029 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002030 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2031 {
2032 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302033 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002034 in_standby = FALSE;
2035 break;
2036 }
2037 else
2038 {
2039 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2040 pAdapterNode = pNext;
2041 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002042 }
2043
2044 if (TRUE == in_standby)
2045 {
2046 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
2047 {
2048 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
2049 "wlan out of power save", __func__);
2050 return -EINVAL;
2051 }
2052 }
2053
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002054 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002055 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2056 {
2057 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002058 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002059 /* Enable TX queues only when we are connected */
2060 netif_tx_start_all_queues(dev);
2061 }
2062
2063 return 0;
2064}
2065
2066int hdd_mon_open (struct net_device *dev)
2067{
2068 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2069
2070 if(pAdapter == NULL) {
2071 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002072 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002073 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002074 }
2075
2076 netif_start_queue(dev);
2077
2078 return 0;
2079}
2080/**---------------------------------------------------------------------------
2081
2082 \brief hdd_stop() - HDD stop function
2083
2084 This is called in response to ifconfig down
2085
2086 \param - dev Pointer to net_device structure
2087
2088 \return - 0 for success non-zero for failure
2089
2090 --------------------------------------------------------------------------*/
2091
2092int hdd_stop (struct net_device *dev)
2093{
2094 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2095 hdd_context_t *pHddCtx;
2096 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2097 VOS_STATUS status;
2098 v_BOOL_t enter_standby = TRUE;
2099
2100 ENTER();
2101
2102 if (NULL == pAdapter)
2103 {
2104 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002105 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002106 return -ENODEV;
2107 }
2108
2109 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2110 if (NULL == pHddCtx)
2111 {
2112 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002113 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002114 return -ENODEV;
2115 }
2116
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002117 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07002118 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
2119 netif_tx_disable(pAdapter->dev);
2120 netif_carrier_off(pAdapter->dev);
2121
2122
2123 /* SoftAP ifaces should never go in power save mode
2124 making sure same here. */
2125 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
2126 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002127 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07002128 )
2129 {
2130 /* SoftAP mode, so return from here */
2131 EXIT();
2132 return 0;
2133 }
2134
2135 /* Find if any iface is up then
2136 if any iface is up then can't put device to sleep/ power save mode. */
2137 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2138 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
2139 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002140 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
2141 {
2142 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05302143 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07002144 enter_standby = FALSE;
2145 break;
2146 }
2147 else
2148 {
2149 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2150 pAdapterNode = pNext;
2151 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002152 }
2153
2154 if (TRUE == enter_standby)
2155 {
2156 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
2157 "entering standby", __func__);
2158 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
2159 {
2160 /*log and return success*/
2161 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
2162 "wlan in power save", __func__);
2163 }
2164 }
2165
2166 EXIT();
2167 return 0;
2168}
2169
2170/**---------------------------------------------------------------------------
2171
2172 \brief hdd_uninit() - HDD uninit function
2173
2174 This is called during the netdev unregister to uninitialize all data
2175associated with the device
2176
2177 \param - dev Pointer to net_device structure
2178
2179 \return - void
2180
2181 --------------------------------------------------------------------------*/
2182static void hdd_uninit (struct net_device *dev)
2183{
2184 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2185
2186 ENTER();
2187
2188 do
2189 {
2190 if (NULL == pAdapter)
2191 {
2192 hddLog(VOS_TRACE_LEVEL_FATAL,
2193 "%s: NULL pAdapter", __func__);
2194 break;
2195 }
2196
2197 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2198 {
2199 hddLog(VOS_TRACE_LEVEL_FATAL,
2200 "%s: Invalid magic", __func__);
2201 break;
2202 }
2203
2204 if (NULL == pAdapter->pHddCtx)
2205 {
2206 hddLog(VOS_TRACE_LEVEL_FATAL,
2207 "%s: NULL pHddCtx", __func__);
2208 break;
2209 }
2210
2211 if (dev != pAdapter->dev)
2212 {
2213 hddLog(VOS_TRACE_LEVEL_FATAL,
2214 "%s: Invalid device reference", __func__);
2215 /* we haven't validated all cases so let this go for now */
2216 }
2217
2218 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
2219
2220 /* after uninit our adapter structure will no longer be valid */
2221 pAdapter->dev = NULL;
2222 pAdapter->magic = 0;
2223 } while (0);
2224
2225 EXIT();
2226}
2227
2228/**---------------------------------------------------------------------------
2229
2230 \brief hdd_release_firmware() -
2231
2232 This function calls the release firmware API to free the firmware buffer.
2233
2234 \param - pFileName Pointer to the File Name.
2235 pCtx - Pointer to the adapter .
2236
2237
2238 \return - 0 for success, non zero for failure
2239
2240 --------------------------------------------------------------------------*/
2241
2242VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
2243{
2244 VOS_STATUS status = VOS_STATUS_SUCCESS;
2245 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2246 ENTER();
2247
2248
2249 if (!strcmp(WLAN_FW_FILE, pFileName)) {
2250
2251 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
2252
2253 if(pHddCtx->fw) {
2254 release_firmware(pHddCtx->fw);
2255 pHddCtx->fw = NULL;
2256 }
2257 else
2258 status = VOS_STATUS_E_FAILURE;
2259 }
2260 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
2261 if(pHddCtx->nv) {
2262 release_firmware(pHddCtx->nv);
2263 pHddCtx->nv = NULL;
2264 }
2265 else
2266 status = VOS_STATUS_E_FAILURE;
2267
2268 }
2269
2270 EXIT();
2271 return status;
2272}
2273
2274/**---------------------------------------------------------------------------
2275
2276 \brief hdd_request_firmware() -
2277
2278 This function reads the firmware file using the request firmware
2279 API and returns the the firmware data and the firmware file size.
2280
2281 \param - pfileName - Pointer to the file name.
2282 - pCtx - Pointer to the adapter .
2283 - ppfw_data - Pointer to the pointer of the firmware data.
2284 - pSize - Pointer to the file size.
2285
2286 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
2287
2288 --------------------------------------------------------------------------*/
2289
2290
2291VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
2292{
2293 int status;
2294 VOS_STATUS retval = VOS_STATUS_SUCCESS;
2295 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2296 ENTER();
2297
2298 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
2299
2300 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
2301
2302 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2303 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
2304 __func__, pfileName);
2305 retval = VOS_STATUS_E_FAILURE;
2306 }
2307
2308 else {
2309 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
2310 *pSize = pHddCtx->fw->size;
2311 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
2312 __func__, *pSize);
2313 }
2314 }
2315 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
2316
2317 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
2318
2319 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
2320 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
2321 __func__, pfileName);
2322 retval = VOS_STATUS_E_FAILURE;
2323 }
2324
2325 else {
2326 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
2327 *pSize = pHddCtx->nv->size;
2328 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
2329 __func__, *pSize);
2330 }
2331 }
2332
2333 EXIT();
2334 return retval;
2335}
2336/**---------------------------------------------------------------------------
2337 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
2338
2339 This is the function invoked by SME to inform the result of a full power
2340 request issued by HDD
2341
2342 \param - callbackcontext - Pointer to cookie
2343 status - result of request
2344
2345 \return - None
2346
2347--------------------------------------------------------------------------*/
2348void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
2349{
2350 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
2351
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002352 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07002353 if(&pHddCtx->full_pwr_comp_var)
2354 {
2355 complete(&pHddCtx->full_pwr_comp_var);
2356 }
2357}
2358
2359/**---------------------------------------------------------------------------
2360
2361 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
2362
2363 This is the function invoked by SME to inform the result of BMPS
2364 request issued by HDD
2365
2366 \param - callbackcontext - Pointer to cookie
2367 status - result of request
2368
2369 \return - None
2370
2371--------------------------------------------------------------------------*/
2372void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
2373{
2374
2375 struct completion *completion_var = (struct completion*) callbackContext;
2376
2377 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
2378 if(completion_var != NULL)
2379 {
2380 complete(completion_var);
2381 }
2382}
2383
2384/**---------------------------------------------------------------------------
2385
2386 \brief hdd_get_cfg_file_size() -
2387
2388 This function reads the configuration file using the request firmware
2389 API and returns the configuration file size.
2390
2391 \param - pCtx - Pointer to the adapter .
2392 - pFileName - Pointer to the file name.
2393 - pBufSize - Pointer to the buffer size.
2394
2395 \return - 0 for success, non zero for failure
2396
2397 --------------------------------------------------------------------------*/
2398
2399VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2400{
2401 int status;
2402 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2403
2404 ENTER();
2405
2406 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2407
2408 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2409 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2410 status = VOS_STATUS_E_FAILURE;
2411 }
2412 else {
2413 *pBufSize = pHddCtx->fw->size;
2414 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2415 release_firmware(pHddCtx->fw);
2416 pHddCtx->fw = NULL;
2417 }
2418
2419 EXIT();
2420 return VOS_STATUS_SUCCESS;
2421}
2422
2423/**---------------------------------------------------------------------------
2424
2425 \brief hdd_read_cfg_file() -
2426
2427 This function reads the configuration file using the request firmware
2428 API and returns the cfg data and the buffer size of the configuration file.
2429
2430 \param - pCtx - Pointer to the adapter .
2431 - pFileName - Pointer to the file name.
2432 - pBuffer - Pointer to the data buffer.
2433 - pBufSize - Pointer to the buffer size.
2434
2435 \return - 0 for success, non zero for failure
2436
2437 --------------------------------------------------------------------------*/
2438
2439VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2440 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2441{
2442 int status;
2443 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2444
2445 ENTER();
2446
2447 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2448
2449 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2450 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2451 return VOS_STATUS_E_FAILURE;
2452 }
2453 else {
2454 if(*pBufSize != pHddCtx->fw->size) {
2455 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2456 "file size", __func__);
2457 release_firmware(pHddCtx->fw);
2458 pHddCtx->fw = NULL;
2459 return VOS_STATUS_E_FAILURE;
2460 }
2461 else {
2462 if(pBuffer) {
2463 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2464 }
2465 release_firmware(pHddCtx->fw);
2466 pHddCtx->fw = NULL;
2467 }
2468 }
2469
2470 EXIT();
2471
2472 return VOS_STATUS_SUCCESS;
2473}
2474
2475/**---------------------------------------------------------------------------
2476
Jeff Johnson295189b2012-06-20 16:38:30 -07002477 \brief hdd_set_mac_address() -
2478
2479 This function sets the user specified mac address using
2480 the command ifconfig wlanX hw ether <mac adress>.
2481
2482 \param - dev - Pointer to the net device.
2483 - addr - Pointer to the sockaddr.
2484 \return - 0 for success, non zero for failure
2485
2486 --------------------------------------------------------------------------*/
2487
2488static int hdd_set_mac_address(struct net_device *dev, void *addr)
2489{
2490 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2491 struct sockaddr *psta_mac_addr = addr;
2492 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2493
2494 ENTER();
2495
2496 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2497
2498#ifdef HDD_SESSIONIZE
2499 // set the MAC address though the STA ID CFG.
2500 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2501 (v_U8_t *)&pAdapter->macAddressCurrent,
2502 sizeof( pAdapter->macAddressCurrent ),
2503 hdd_set_mac_addr_cb, VOS_FALSE );
2504#endif
2505
2506 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2507
2508 EXIT();
2509 return halStatus;
2510}
2511
2512tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2513{
2514 int i;
2515 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2516 {
2517 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2518 break;
2519 }
2520
2521 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2522 return NULL;
2523
2524 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2525 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2526}
2527
2528void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2529{
2530 int i;
2531 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2532 {
2533 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2534 {
2535 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2536 break;
2537 }
2538 }
2539 return;
2540}
2541
2542#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2543 static struct net_device_ops wlan_drv_ops = {
2544 .ndo_open = hdd_open,
2545 .ndo_stop = hdd_stop,
2546 .ndo_uninit = hdd_uninit,
2547 .ndo_start_xmit = hdd_hard_start_xmit,
2548 .ndo_tx_timeout = hdd_tx_timeout,
2549 .ndo_get_stats = hdd_stats,
2550 .ndo_do_ioctl = hdd_ioctl,
2551 .ndo_set_mac_address = hdd_set_mac_address,
2552 .ndo_select_queue = hdd_select_queue,
2553#ifdef WLAN_FEATURE_PACKET_FILTERING
2554#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2555 .ndo_set_rx_mode = hdd_set_multicast_list,
2556#else
2557 .ndo_set_multicast_list = hdd_set_multicast_list,
2558#endif //LINUX_VERSION_CODE
2559#endif
2560 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002561 static struct net_device_ops wlan_mon_drv_ops = {
2562 .ndo_open = hdd_mon_open,
2563 .ndo_stop = hdd_stop,
2564 .ndo_uninit = hdd_uninit,
2565 .ndo_start_xmit = hdd_mon_hard_start_xmit,
2566 .ndo_tx_timeout = hdd_tx_timeout,
2567 .ndo_get_stats = hdd_stats,
2568 .ndo_do_ioctl = hdd_ioctl,
2569 .ndo_set_mac_address = hdd_set_mac_address,
2570 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002571
2572#endif
2573
2574void hdd_set_station_ops( struct net_device *pWlanDev )
2575{
2576#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2577 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
2578 pWlanDev->netdev_ops = &wlan_drv_ops;
2579#else
2580 pWlanDev->open = hdd_open;
2581 pWlanDev->stop = hdd_stop;
2582 pWlanDev->uninit = hdd_uninit;
2583 pWlanDev->hard_start_xmit = NULL;
2584 pWlanDev->tx_timeout = hdd_tx_timeout;
2585 pWlanDev->get_stats = hdd_stats;
2586 pWlanDev->do_ioctl = hdd_ioctl;
2587 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
2588 pWlanDev->set_mac_address = hdd_set_mac_address;
2589#endif
2590}
2591
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002592static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07002593{
2594 struct net_device *pWlanDev = NULL;
2595 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002596 /*
2597 * cfg80211 initialization and registration....
2598 */
2599 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
2600
Jeff Johnson295189b2012-06-20 16:38:30 -07002601 if(pWlanDev != NULL)
2602 {
2603
2604 //Save the pointer to the net_device in the HDD adapter
2605 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
2606
Jeff Johnson295189b2012-06-20 16:38:30 -07002607 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
2608
2609 pAdapter->dev = pWlanDev;
2610 pAdapter->pHddCtx = pHddCtx;
2611 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2612
2613 init_completion(&pAdapter->session_open_comp_var);
2614 init_completion(&pAdapter->session_close_comp_var);
2615 init_completion(&pAdapter->disconnect_comp_var);
2616 init_completion(&pAdapter->linkup_event_var);
2617 init_completion(&pAdapter->cancel_rem_on_chan_var);
2618 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07002619#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2620 init_completion(&pAdapter->offchannel_tx_event);
2621#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002622 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002623#ifdef FEATURE_WLAN_TDLS
2624 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002625 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002626 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002627#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002628 init_completion(&pHddCtx->mc_sus_event_var);
2629 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07002630 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07002631
Jeff Johnson295189b2012-06-20 16:38:30 -07002632 pAdapter->isLinkUpSvcNeeded = FALSE;
2633 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
2634 //Init the net_device structure
2635 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2636
2637 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
2638 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
2639 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
2640 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
2641
2642 hdd_set_station_ops( pAdapter->dev );
2643
2644 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002645 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
2646 pAdapter->wdev.wiphy = pHddCtx->wiphy;
2647 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002648 /* set pWlanDev's parent to underlying device */
2649 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
2650 }
2651
2652 return pAdapter;
2653}
2654
2655VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
2656{
2657 struct net_device *pWlanDev = pAdapter->dev;
2658 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2659 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2660 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2661
2662 if( rtnl_lock_held )
2663 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08002664 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07002665 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
2666 {
2667 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
2668 return VOS_STATUS_E_FAILURE;
2669 }
2670 }
2671 if (register_netdevice(pWlanDev))
2672 {
2673 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
2674 return VOS_STATUS_E_FAILURE;
2675 }
2676 }
2677 else
2678 {
2679 if(register_netdev(pWlanDev))
2680 {
2681 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
2682 return VOS_STATUS_E_FAILURE;
2683 }
2684 }
2685 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
2686
2687 return VOS_STATUS_SUCCESS;
2688}
2689
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002690static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07002691{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002692 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07002693
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002694 if (NULL == pAdapter)
2695 {
2696 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
2697 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07002698 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002699
2700 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2701 {
2702 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
2703 return eHAL_STATUS_NOT_INITIALIZED;
2704 }
2705
2706 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
2707
2708 /* need to make sure all of our scheduled work has completed.
2709 * This callback is called from MC thread context, so it is safe to
2710 * to call below flush workqueue API from here.
2711 */
2712 flush_scheduled_work();
2713
2714 /* We can be blocked while waiting for scheduled work to be
2715 * flushed, and the adapter structure can potentially be freed, in
2716 * which case the magic will have been reset. So make sure the
2717 * magic is still good, and hence the adapter structure is still
2718 * valid, before signaling completion */
2719 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
2720 {
2721 complete(&pAdapter->session_close_comp_var);
2722 }
2723
Jeff Johnson295189b2012-06-20 16:38:30 -07002724 return eHAL_STATUS_SUCCESS;
2725}
2726
2727VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
2728{
2729 struct net_device *pWlanDev = pAdapter->dev;
2730 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2731 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2732 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2733 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2734 int rc = 0;
2735
2736 INIT_COMPLETION(pAdapter->session_open_comp_var);
2737 //Open a SME session for future operation
2738 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
2739 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
2740 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2741 {
2742 hddLog(VOS_TRACE_LEVEL_FATAL,
2743 "sme_OpenSession() failed with status code %08d [x%08lx]",
2744 halStatus, halStatus );
2745 status = VOS_STATUS_E_FAILURE;
2746 goto error_sme_open;
2747 }
2748
2749 //Block on a completion variable. Can't wait forever though.
2750 rc = wait_for_completion_interruptible_timeout(
2751 &pAdapter->session_open_comp_var,
2752 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2753 if (!rc)
2754 {
2755 hddLog(VOS_TRACE_LEVEL_FATAL,
2756 "Session is not opened within timeout period code %08d", rc );
2757 status = VOS_STATUS_E_FAILURE;
2758 goto error_sme_open;
2759 }
2760
2761 // Register wireless extensions
2762 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
2763 {
2764 hddLog(VOS_TRACE_LEVEL_FATAL,
2765 "hdd_register_wext() failed with status code %08d [x%08lx]",
2766 halStatus, halStatus );
2767 status = VOS_STATUS_E_FAILURE;
2768 goto error_register_wext;
2769 }
2770 //Safe to register the hard_start_xmit function again
2771#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2772 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
2773#else
2774 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
2775#endif
2776
2777 //Set the Connection State to Not Connected
2778 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2779
2780 //Set the default operation channel
2781 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
2782
2783 /* Make the default Auth Type as OPEN*/
2784 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2785
2786 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
2787 {
2788 hddLog(VOS_TRACE_LEVEL_FATAL,
2789 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
2790 status, status );
2791 goto error_init_txrx;
2792 }
2793
2794 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2795
2796 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
2797 {
2798 hddLog(VOS_TRACE_LEVEL_FATAL,
2799 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
2800 status, status );
2801 goto error_wmm_init;
2802 }
2803
2804 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2805
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002806#ifdef FEATURE_WLAN_TDLS
2807 if(0 != wlan_hdd_tdls_init(pAdapter))
2808 {
2809 status = VOS_STATUS_E_FAILURE;
2810 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
2811 goto error_tdls_init;
2812 }
2813 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2814#endif
2815
Jeff Johnson295189b2012-06-20 16:38:30 -07002816 return VOS_STATUS_SUCCESS;
2817
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002818#ifdef FEATURE_WLAN_TDLS
2819error_tdls_init:
2820 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2821 hdd_wmm_adapter_close(pAdapter);
2822#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002823error_wmm_init:
2824 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2825 hdd_deinit_tx_rx(pAdapter);
2826error_init_txrx:
2827 hdd_UnregisterWext(pWlanDev);
2828error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002829 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07002830 {
2831 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002832 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07002833 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002834 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07002835 {
2836 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002837 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07002838 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07002839 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07002840 }
2841}
2842error_sme_open:
2843 return status;
2844}
2845
Jeff Johnson295189b2012-06-20 16:38:30 -07002846void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2847{
2848 hdd_cfg80211_state_t *cfgState;
2849
2850 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
2851
2852 if( NULL != cfgState->buf )
2853 {
2854 int rc;
2855 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
2856 rc = wait_for_completion_interruptible_timeout(
2857 &pAdapter->tx_action_cnf_event,
2858 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2859 if(!rc)
2860 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08002861 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002862 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
2863 }
2864 }
2865 return;
2866}
Jeff Johnson295189b2012-06-20 16:38:30 -07002867
2868void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2869{
2870 ENTER();
2871 switch ( pAdapter->device_mode )
2872 {
2873 case WLAN_HDD_INFRA_STATION:
2874 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002875 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002876 {
2877 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2878 {
2879 hdd_deinit_tx_rx( pAdapter );
2880 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2881 }
2882
2883 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
2884 {
2885 hdd_wmm_adapter_close( pAdapter );
2886 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2887 }
2888
Jeff Johnson295189b2012-06-20 16:38:30 -07002889 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002890#ifdef FEATURE_WLAN_TDLS
2891 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
2892 {
2893 wlan_hdd_tdls_exit(pAdapter);
2894 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2895 }
2896#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002897
2898 break;
2899 }
2900
2901 case WLAN_HDD_SOFTAP:
2902 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002903 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002904 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002905
2906 hdd_unregister_hostapd(pAdapter);
2907 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07002908 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07002909 break;
2910 }
2911
2912 case WLAN_HDD_MONITOR:
2913 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002914 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07002915 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2916 {
2917 hdd_deinit_tx_rx( pAdapter );
2918 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2919 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002920 if(NULL != pAdapterforTx)
2921 {
2922 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
2923 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002924 break;
2925 }
2926
2927
2928 default:
2929 break;
2930 }
2931
2932 EXIT();
2933}
2934
2935void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
2936{
2937 struct net_device *pWlanDev = pAdapter->dev;
2938
2939 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
2940 if( rtnl_held )
2941 {
2942 unregister_netdevice(pWlanDev);
2943 }
2944 else
2945 {
2946 unregister_netdev(pWlanDev);
2947 }
2948 // note that the pAdapter is no longer valid at this point
2949 // since the memory has been reclaimed
2950 }
2951
2952}
2953
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002954void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2955{
2956 tSirSetPowerParamsReq powerRequest = { 0 };
2957
2958 powerRequest.uIgnoreDTIM = 1;
2959
2960 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2961 {
2962 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2963 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2964 }
2965 else
2966 {
2967 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2968 }
2969
2970 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2971 *specified during Enter/Exit BMPS when LCD off*/
2972 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2973 NULL, eANI_BOOLEAN_FALSE);
2974 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2975 NULL, eANI_BOOLEAN_FALSE);
2976
2977 /* switch to the DTIM specified in cfg.ini */
2978 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2979 "Switch to DTIM%d", powerRequest.uListenInterval);
2980 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2981
2982}
2983
2984void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2985{
2986 /*Switch back to DTIM 1*/
2987 tSirSetPowerParamsReq powerRequest = { 0 };
2988
2989 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2990 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2991
2992 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2993 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2994 NULL, eANI_BOOLEAN_FALSE);
2995 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2996 NULL, eANI_BOOLEAN_FALSE);
2997
2998 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2999 "Switch to DTIM%d",powerRequest.uListenInterval);
3000 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
3001
3002}
3003
Jeff Johnson295189b2012-06-20 16:38:30 -07003004VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
3005{
3006 VOS_STATUS status = VOS_STATUS_SUCCESS;
3007
3008 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3009 {
3010 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3011 }
3012
3013 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3014 {
3015 sme_StartAutoBmpsTimer(pHddCtx->hHal);
3016 }
3017
3018 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3019 {
3020 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3021 }
3022
3023 return status;
3024}
3025
3026VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
3027{
3028 hdd_adapter_t *pAdapter = NULL;
3029 eHalStatus halStatus;
3030 VOS_STATUS status = VOS_STATUS_E_INVAL;
3031 v_BOOL_t disableBmps = FALSE;
3032 v_BOOL_t disableImps = FALSE;
3033
3034 switch(session_type)
3035 {
3036 case WLAN_HDD_INFRA_STATION:
3037 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07003038 case WLAN_HDD_P2P_CLIENT:
3039 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003040 //Exit BMPS -> Is Sta/P2P Client is already connected
3041 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
3042 if((NULL != pAdapter)&&
3043 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3044 {
3045 disableBmps = TRUE;
3046 }
3047
3048 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3049 if((NULL != pAdapter)&&
3050 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3051 {
3052 disableBmps = TRUE;
3053 }
3054
3055 //Exit both Bmps and Imps incase of Go/SAP Mode
3056 if((WLAN_HDD_SOFTAP == session_type) ||
3057 (WLAN_HDD_P2P_GO == session_type))
3058 {
3059 disableBmps = TRUE;
3060 disableImps = TRUE;
3061 }
3062
3063 if(TRUE == disableImps)
3064 {
3065 if (pHddCtx->cfg_ini->fIsImpsEnabled)
3066 {
3067 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3068 }
3069 }
3070
3071 if(TRUE == disableBmps)
3072 {
3073 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
3074 {
3075 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3076
3077 if(eHAL_STATUS_SUCCESS != halStatus)
3078 {
3079 status = VOS_STATUS_E_FAILURE;
3080 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
3081 VOS_ASSERT(0);
3082 return status;
3083 }
3084 }
3085
3086 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
3087 {
3088 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
3089
3090 if(eHAL_STATUS_SUCCESS != halStatus)
3091 {
3092 status = VOS_STATUS_E_FAILURE;
3093 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
3094 VOS_ASSERT(0);
3095 return status;
3096 }
3097 }
3098 }
3099
3100 if((TRUE == disableBmps) ||
3101 (TRUE == disableImps))
3102 {
3103 /* Now, get the chip into Full Power now */
3104 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
3105 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
3106 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
3107
3108 if(halStatus != eHAL_STATUS_SUCCESS)
3109 {
3110 if(halStatus == eHAL_STATUS_PMC_PENDING)
3111 {
3112 //Block on a completion variable. Can't wait forever though
3113 wait_for_completion_interruptible_timeout(
3114 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
3115 }
3116 else
3117 {
3118 status = VOS_STATUS_E_FAILURE;
3119 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
3120 VOS_ASSERT(0);
3121 return status;
3122 }
3123 }
3124
3125 status = VOS_STATUS_SUCCESS;
3126 }
3127
3128 break;
3129 }
3130 return status;
3131}
3132
3133hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08003134 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07003135 tANI_U8 rtnl_held )
3136{
3137 hdd_adapter_t *pAdapter = NULL;
3138 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
3139 VOS_STATUS status = VOS_STATUS_E_FAILURE;
3140 VOS_STATUS exitbmpsStatus;
3141
3142 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
3143
3144 //Disable BMPS incase of Concurrency
3145 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
3146
3147 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
3148 {
3149 //Fail to Exit BMPS
3150 VOS_ASSERT(0);
3151 return NULL;
3152 }
3153
3154 switch(session_type)
3155 {
3156 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07003157 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003158 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003159 {
3160 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3161
3162 if( NULL == pAdapter )
3163 return NULL;
3164
Jeff Johnsone7245742012-09-05 17:12:55 -07003165 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
3166 NL80211_IFTYPE_P2P_CLIENT:
3167 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07003168
Jeff Johnson295189b2012-06-20 16:38:30 -07003169 pAdapter->device_mode = session_type;
3170
3171 status = hdd_init_station_mode( pAdapter );
3172 if( VOS_STATUS_SUCCESS != status )
3173 goto err_free_netdev;
3174
3175 status = hdd_register_interface( pAdapter, rtnl_held );
3176 if( VOS_STATUS_SUCCESS != status )
3177 {
3178 hdd_deinit_adapter(pHddCtx, pAdapter);
3179 goto err_free_netdev;
3180 }
3181 //Stop the Interface TX queue.
3182 netif_tx_disable(pAdapter->dev);
3183 //netif_tx_disable(pWlanDev);
3184 netif_carrier_off(pAdapter->dev);
3185
3186 break;
3187 }
3188
Jeff Johnson295189b2012-06-20 16:38:30 -07003189 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003190 case WLAN_HDD_SOFTAP:
3191 {
3192 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
3193 if( NULL == pAdapter )
3194 return NULL;
3195
Jeff Johnson295189b2012-06-20 16:38:30 -07003196 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
3197 NL80211_IFTYPE_AP:
3198 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003199 pAdapter->device_mode = session_type;
3200
3201 status = hdd_init_ap_mode(pAdapter);
3202 if( VOS_STATUS_SUCCESS != status )
3203 goto err_free_netdev;
3204
3205 status = hdd_register_hostapd( pAdapter, rtnl_held );
3206 if( VOS_STATUS_SUCCESS != status )
3207 {
3208 hdd_deinit_adapter(pHddCtx, pAdapter);
3209 goto err_free_netdev;
3210 }
3211
3212 netif_tx_disable(pAdapter->dev);
3213 netif_carrier_off(pAdapter->dev);
3214
3215 hdd_set_conparam( 1 );
3216 break;
3217 }
3218 case WLAN_HDD_MONITOR:
3219 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003220 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3221 if( NULL == pAdapter )
3222 return NULL;
3223
3224 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
3225 pAdapter->device_mode = session_type;
3226 status = hdd_register_interface( pAdapter, rtnl_held );
3227#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
3228 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
3229#else
3230 pAdapter->dev->open = hdd_mon_open;
3231 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
3232#endif
3233 hdd_init_tx_rx( pAdapter );
3234 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
3235 //Set adapter to be used for data tx. It will use either GO or softap.
3236 pAdapter->sessionCtx.monitor.pAdapterForTx =
3237 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07003238 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
3239 {
3240 pAdapter->sessionCtx.monitor.pAdapterForTx =
3241 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
3242 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003243 /* This workqueue will be used to transmit management packet over
3244 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07003245 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
3246 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
3247 return NULL;
3248 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07003249
Jeff Johnson295189b2012-06-20 16:38:30 -07003250 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
3251 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07003252 }
3253 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003254 case WLAN_HDD_FTM:
3255 {
3256 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
3257
3258 if( NULL == pAdapter )
3259 return NULL;
3260 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
3261 * message while loading driver in FTM mode. */
3262 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
3263 pAdapter->device_mode = session_type;
3264 status = hdd_register_interface( pAdapter, rtnl_held );
3265 }
3266 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07003267 default:
3268 {
3269 VOS_ASSERT(0);
3270 return NULL;
3271 }
3272 }
3273
3274
3275 if( VOS_STATUS_SUCCESS == status )
3276 {
3277 //Add it to the hdd's session list.
3278 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
3279 if( NULL == pHddAdapterNode )
3280 {
3281 status = VOS_STATUS_E_NOMEM;
3282 }
3283 else
3284 {
3285 pHddAdapterNode->pAdapter = pAdapter;
3286 status = hdd_add_adapter_back ( pHddCtx,
3287 pHddAdapterNode );
3288 }
3289 }
3290
3291 if( VOS_STATUS_SUCCESS != status )
3292 {
3293 if( NULL != pAdapter )
3294 {
3295 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
3296 pAdapter = NULL;
3297 }
3298 if( NULL != pHddAdapterNode )
3299 {
3300 vos_mem_free( pHddAdapterNode );
3301 }
3302
3303 goto resume_bmps;
3304 }
3305
3306 if(VOS_STATUS_SUCCESS == status)
3307 {
3308 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
3309
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07003310 //Initialize the WoWL service
3311 if(!hdd_init_wowl(pAdapter))
3312 {
3313 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
3314 goto err_free_netdev;
3315 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003316 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003317 return pAdapter;
3318
3319err_free_netdev:
3320 free_netdev(pAdapter->dev);
3321 wlan_hdd_release_intf_addr( pHddCtx,
3322 pAdapter->macAddressCurrent.bytes );
3323
3324resume_bmps:
3325 //If bmps disabled enable it
3326 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
3327 {
3328 hdd_enable_bmps_imps(pHddCtx);
3329 }
3330 return NULL;
3331}
3332
3333VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
3334 tANI_U8 rtnl_held )
3335{
3336 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
3337 VOS_STATUS status;
3338
3339 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
3340 if( VOS_STATUS_SUCCESS != status )
3341 return status;
3342
3343 while ( pCurrent->pAdapter != pAdapter )
3344 {
3345 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
3346 if( VOS_STATUS_SUCCESS != status )
3347 break;
3348
3349 pCurrent = pNext;
3350 }
3351 pAdapterNode = pCurrent;
3352 if( VOS_STATUS_SUCCESS == status )
3353 {
3354 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
3355 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
3356 hdd_remove_adapter( pHddCtx, pAdapterNode );
3357 vos_mem_free( pAdapterNode );
3358
Jeff Johnson295189b2012-06-20 16:38:30 -07003359
3360 /* If there is a single session of STA/P2P client, re-enable BMPS */
3361 if ((!vos_concurrent_sessions_running()) &&
3362 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
3363 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
3364 {
3365 hdd_enable_bmps_imps(pHddCtx);
3366 }
3367
3368 return VOS_STATUS_SUCCESS;
3369 }
3370
3371 return VOS_STATUS_E_FAILURE;
3372}
3373
3374VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
3375{
3376 hdd_adapter_list_node_t *pHddAdapterNode;
3377 VOS_STATUS status;
3378
3379 ENTER();
3380
3381 do
3382 {
3383 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
3384 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
3385 {
3386 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
3387 vos_mem_free( pHddAdapterNode );
3388 }
3389 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
3390
3391 EXIT();
3392
3393 return VOS_STATUS_SUCCESS;
3394}
3395
3396void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
3397{
3398 v_U8_t addIE[1] = {0};
3399
3400 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3401 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
3402 eANI_BOOLEAN_FALSE) )
3403 {
3404 hddLog(LOGE,
3405 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
3406 }
3407
3408 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3409 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3410 eANI_BOOLEAN_FALSE) )
3411 {
3412 hddLog(LOGE,
3413 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3414 }
3415
3416 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3417 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3418 eANI_BOOLEAN_FALSE) )
3419 {
3420 hddLog(LOGE,
3421 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3422 }
3423}
3424
3425VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3426{
3427 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3428 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3429 union iwreq_data wrqu;
3430
3431 ENTER();
3432
3433 switch(pAdapter->device_mode)
3434 {
3435 case WLAN_HDD_INFRA_STATION:
3436 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003437 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003438 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3439 {
3440 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3441 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3442 pAdapter->sessionId,
3443 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3444 else
3445 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3446 pAdapter->sessionId,
3447 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3448 //success implies disconnect command got queued up successfully
3449 if(halStatus == eHAL_STATUS_SUCCESS)
3450 {
3451 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3452 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3453 }
3454 memset(&wrqu, '\0', sizeof(wrqu));
3455 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3456 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3457 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3458 }
3459 else
3460 {
3461 hdd_abort_mac_scan(pHddCtx);
3462 }
3463
3464 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3465 {
3466 INIT_COMPLETION(pAdapter->session_close_comp_var);
3467 if (eHAL_STATUS_SUCCESS ==
3468 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3469 hdd_smeCloseSessionCallback, pAdapter))
3470 {
3471 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07003472 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07003473 &pAdapter->session_close_comp_var,
3474 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3475 }
3476 }
3477
3478 break;
3479
3480 case WLAN_HDD_SOFTAP:
3481 case WLAN_HDD_P2P_GO:
3482 //Any softap specific cleanup here...
3483 mutex_lock(&pHddCtx->sap_lock);
3484 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3485 {
3486 VOS_STATUS status;
3487 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3488
3489 //Stop Bss.
3490 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3491 if (VOS_IS_STATUS_SUCCESS(status))
3492 {
3493 hdd_hostapd_state_t *pHostapdState =
3494 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3495
3496 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3497
3498 if (!VOS_IS_STATUS_SUCCESS(status))
3499 {
3500 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003501 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003502 }
3503 }
3504 else
3505 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003506 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003507 }
3508 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3509
3510 if (eHAL_STATUS_FAILURE ==
3511 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3512 0, NULL, eANI_BOOLEAN_FALSE))
3513 {
3514 hddLog(LOGE,
3515 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003516 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003517 }
3518
3519 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3520 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3521 eANI_BOOLEAN_FALSE) )
3522 {
3523 hddLog(LOGE,
3524 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3525 }
3526
3527 // Reset WNI_CFG_PROBE_RSP Flags
3528 wlan_hdd_reset_prob_rspies(pAdapter);
3529 kfree(pAdapter->sessionCtx.ap.beacon);
3530 pAdapter->sessionCtx.ap.beacon = NULL;
3531 }
3532 mutex_unlock(&pHddCtx->sap_lock);
3533 break;
3534 case WLAN_HDD_MONITOR:
3535 break;
3536 default:
3537 break;
3538 }
3539
3540 EXIT();
3541 return VOS_STATUS_SUCCESS;
3542}
3543
3544VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3545{
3546 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3547 VOS_STATUS status;
3548 hdd_adapter_t *pAdapter;
3549
3550 ENTER();
3551
3552 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3553
3554 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3555 {
3556 pAdapter = pAdapterNode->pAdapter;
3557 netif_tx_disable(pAdapter->dev);
3558 netif_carrier_off(pAdapter->dev);
3559
3560 hdd_stop_adapter( pHddCtx, pAdapter );
3561
3562 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3563 pAdapterNode = pNext;
3564 }
3565
3566 EXIT();
3567
3568 return VOS_STATUS_SUCCESS;
3569}
3570
3571VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
3572{
3573 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3574 VOS_STATUS status;
3575 hdd_adapter_t *pAdapter;
3576
3577 ENTER();
3578
3579 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3580
3581 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3582 {
3583 pAdapter = pAdapterNode->pAdapter;
3584 netif_tx_disable(pAdapter->dev);
3585 netif_carrier_off(pAdapter->dev);
3586
3587 //Record whether STA is associated
3588 pAdapter->sessionCtx.station.bSendDisconnect =
3589 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
3590 VOS_TRUE : VOS_FALSE;
3591
3592 hdd_deinit_tx_rx(pAdapter);
3593 hdd_wmm_adapter_close(pAdapter);
3594
3595 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3596 pAdapterNode = pNext;
3597 }
3598
3599 EXIT();
3600
3601 return VOS_STATUS_SUCCESS;
3602}
3603
3604VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
3605{
3606 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3607 VOS_STATUS status;
3608 hdd_adapter_t *pAdapter;
3609 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
3610
3611 ENTER();
3612
3613 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3614
3615 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3616 {
3617 pAdapter = pAdapterNode->pAdapter;
3618
3619 switch(pAdapter->device_mode)
3620 {
3621 case WLAN_HDD_INFRA_STATION:
3622 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003623 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003624 hdd_init_station_mode(pAdapter);
3625 /* Open the gates for HDD to receive Wext commands */
3626 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003627 pHddCtx->scan_info.mScanPending = FALSE;
3628 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003629
3630 //Trigger the initial scan
3631 hdd_wlan_initial_scan(pAdapter);
3632
3633 //Indicate disconnect event to supplicant if associated previously
3634 if(pAdapter->sessionCtx.station.bSendDisconnect)
3635 {
3636 union iwreq_data wrqu;
3637 memset(&wrqu, '\0', sizeof(wrqu));
3638 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3639 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3640 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3641 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
3642
Jeff Johnson295189b2012-06-20 16:38:30 -07003643 /* indicate disconnected event to nl80211 */
3644 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
3645 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003646 }
3647 break;
3648
3649 case WLAN_HDD_SOFTAP:
3650 /* softAP can handle SSR */
3651 break;
3652
3653 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003654 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
3655 __func__);
3656 /* event supplicant to restart */
3657 cfg80211_del_sta(pAdapter->dev,
3658 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003659 break;
3660
3661 case WLAN_HDD_MONITOR:
3662 /* monitor interface start */
3663 break;
3664 default:
3665 break;
3666 }
3667
3668 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3669 pAdapterNode = pNext;
3670 }
3671
3672 EXIT();
3673
3674 return VOS_STATUS_SUCCESS;
3675}
3676
3677VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
3678{
3679 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3680 hdd_adapter_t *pAdapter;
3681 VOS_STATUS status;
3682 v_U32_t roamId;
3683
3684 ENTER();
3685
3686 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3687
3688 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3689 {
3690 pAdapter = pAdapterNode->pAdapter;
3691
3692 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3693 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
3694 {
3695 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3696 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3697
3698 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3699 init_completion(&pAdapter->disconnect_comp_var);
3700 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
3701 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3702
3703 wait_for_completion_interruptible_timeout(
3704 &pAdapter->disconnect_comp_var,
3705 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3706
3707 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
3708 pHddCtx->isAmpAllowed = VOS_FALSE;
3709 sme_RoamConnect(pHddCtx->hHal,
3710 pAdapter->sessionId, &(pWextState->roamProfile),
3711 &roamId);
3712 }
3713
3714 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3715 pAdapterNode = pNext;
3716 }
3717
3718 EXIT();
3719
3720 return VOS_STATUS_SUCCESS;
3721}
3722
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07003723void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
3724{
3725 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3726 VOS_STATUS status;
3727 hdd_adapter_t *pAdapter;
3728 hdd_station_ctx_t *pHddStaCtx;
3729 hdd_ap_ctx_t *pHddApCtx;
3730 hdd_hostapd_state_t * pHostapdState;
3731 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
3732 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
3733 const char *p2pMode = "DEV";
3734 const char *ccMode = "Standalone";
3735 int n;
3736
3737 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3738 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3739 {
3740 pAdapter = pAdapterNode->pAdapter;
3741 switch (pAdapter->device_mode) {
3742 case WLAN_HDD_INFRA_STATION:
3743 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3744 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3745 staChannel = pHddStaCtx->conn_info.operationChannel;
3746 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
3747 }
3748 break;
3749 case WLAN_HDD_P2P_CLIENT:
3750 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3751 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3752 p2pChannel = pHddStaCtx->conn_info.operationChannel;
3753 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
3754 p2pMode = "CLI";
3755 }
3756 break;
3757 case WLAN_HDD_P2P_GO:
3758 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3759 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3760 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3761 p2pChannel = pHddApCtx->operatingChannel;
3762 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
3763 }
3764 p2pMode = "GO";
3765 break;
3766 case WLAN_HDD_SOFTAP:
3767 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3768 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3769 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3770 apChannel = pHddApCtx->operatingChannel;
3771 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
3772 }
3773 break;
3774 default:
3775 break;
3776 }
3777 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3778 pAdapterNode = pNext;
3779 }
3780 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
3781 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
3782 }
3783 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
3784 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
3785 if (p2pChannel > 0) {
3786 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
3787 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
3788 }
3789 if (apChannel > 0) {
3790 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
3791 apChannel, MAC_ADDR_ARRAY(apBssid));
3792 }
3793
3794 if (p2pChannel > 0 && apChannel > 0) {
3795 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
3796 }
3797}
3798
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003799bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07003800{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003801 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07003802}
3803
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003804/* Once SSR is disabled then it cannot be set. */
3805void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07003806{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003807 if (HDD_SSR_DISABLED == isSsrRequired)
3808 return;
3809
Jeff Johnson295189b2012-06-20 16:38:30 -07003810 isSsrRequired = value;
3811}
3812
3813VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
3814 hdd_adapter_list_node_t** ppAdapterNode)
3815{
3816 VOS_STATUS status;
3817 spin_lock(&pHddCtx->hddAdapters.lock);
3818 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
3819 (hdd_list_node_t**) ppAdapterNode );
3820 spin_unlock(&pHddCtx->hddAdapters.lock);
3821 return status;
3822}
3823
3824VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
3825 hdd_adapter_list_node_t* pAdapterNode,
3826 hdd_adapter_list_node_t** pNextAdapterNode)
3827{
3828 VOS_STATUS status;
3829 spin_lock(&pHddCtx->hddAdapters.lock);
3830 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
3831 (hdd_list_node_t*) pAdapterNode,
3832 (hdd_list_node_t**)pNextAdapterNode );
3833
3834 spin_unlock(&pHddCtx->hddAdapters.lock);
3835 return status;
3836}
3837
3838VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
3839 hdd_adapter_list_node_t* pAdapterNode)
3840{
3841 VOS_STATUS status;
3842 spin_lock(&pHddCtx->hddAdapters.lock);
3843 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
3844 &pAdapterNode->node );
3845 spin_unlock(&pHddCtx->hddAdapters.lock);
3846 return status;
3847}
3848
3849VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
3850 hdd_adapter_list_node_t** ppAdapterNode)
3851{
3852 VOS_STATUS status;
3853 spin_lock(&pHddCtx->hddAdapters.lock);
3854 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
3855 (hdd_list_node_t**) ppAdapterNode );
3856 spin_unlock(&pHddCtx->hddAdapters.lock);
3857 return status;
3858}
3859
3860VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
3861 hdd_adapter_list_node_t* pAdapterNode)
3862{
3863 VOS_STATUS status;
3864 spin_lock(&pHddCtx->hddAdapters.lock);
3865 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
3866 (hdd_list_node_t*) pAdapterNode );
3867 spin_unlock(&pHddCtx->hddAdapters.lock);
3868 return status;
3869}
3870
3871VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
3872 hdd_adapter_list_node_t* pAdapterNode)
3873{
3874 VOS_STATUS status;
3875 spin_lock(&pHddCtx->hddAdapters.lock);
3876 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
3877 (hdd_list_node_t*) pAdapterNode );
3878 spin_unlock(&pHddCtx->hddAdapters.lock);
3879 return status;
3880}
3881
3882hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
3883 tSirMacAddr macAddr )
3884{
3885 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3886 hdd_adapter_t *pAdapter;
3887 VOS_STATUS status;
3888
3889 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3890
3891 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3892 {
3893 pAdapter = pAdapterNode->pAdapter;
3894
3895 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
3896 macAddr, sizeof(tSirMacAddr) ) )
3897 {
3898 return pAdapter;
3899 }
3900 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3901 pAdapterNode = pNext;
3902 }
3903
3904 return NULL;
3905
3906}
3907
3908hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
3909{
3910 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3911 hdd_adapter_t *pAdapter;
3912 VOS_STATUS status;
3913
3914 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3915
3916 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3917 {
3918 pAdapter = pAdapterNode->pAdapter;
3919
3920 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
3921 IFNAMSIZ ) )
3922 {
3923 return pAdapter;
3924 }
3925 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3926 pAdapterNode = pNext;
3927 }
3928
3929 return NULL;
3930
3931}
3932
3933hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
3934{
3935 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3936 hdd_adapter_t *pAdapter;
3937 VOS_STATUS status;
3938
3939 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3940
3941 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3942 {
3943 pAdapter = pAdapterNode->pAdapter;
3944
3945 if( pAdapter && (mode == pAdapter->device_mode) )
3946 {
3947 return pAdapter;
3948 }
3949 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3950 pAdapterNode = pNext;
3951 }
3952
3953 return NULL;
3954
3955}
3956
3957//Remove this function later
3958hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
3959{
3960 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3961 hdd_adapter_t *pAdapter;
3962 VOS_STATUS status;
3963
3964 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3965
3966 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3967 {
3968 pAdapter = pAdapterNode->pAdapter;
3969
3970 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
3971 {
3972 return pAdapter;
3973 }
3974
3975 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3976 pAdapterNode = pNext;
3977 }
3978
3979 return NULL;
3980
3981}
3982
Jeff Johnson295189b2012-06-20 16:38:30 -07003983/**---------------------------------------------------------------------------
3984
3985 \brief hdd_set_monitor_tx_adapter() -
3986
3987 This API initializes the adapter to be used while transmitting on monitor
3988 adapter.
3989
3990 \param - pHddCtx - Pointer to the HDD context.
3991 pAdapter - Adapter that will used for TX. This can be NULL.
3992 \return - None.
3993 --------------------------------------------------------------------------*/
3994void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3995{
3996 hdd_adapter_t *pMonAdapter;
3997
3998 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
3999
4000 if( NULL != pMonAdapter )
4001 {
4002 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
4003 }
4004}
Jeff Johnson295189b2012-06-20 16:38:30 -07004005/**---------------------------------------------------------------------------
4006
4007 \brief hdd_select_queue() -
4008
4009 This API returns the operating channel of the requested device mode
4010
4011 \param - pHddCtx - Pointer to the HDD context.
4012 - mode - Device mode for which operating channel is required
4013 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
4014 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
4015 \return - channel number. "0" id the requested device is not found OR it is not connected.
4016 --------------------------------------------------------------------------*/
4017v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
4018{
4019 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4020 VOS_STATUS status;
4021 hdd_adapter_t *pAdapter;
4022 v_U8_t operatingChannel = 0;
4023
4024 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4025
4026 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4027 {
4028 pAdapter = pAdapterNode->pAdapter;
4029
4030 if( mode == pAdapter->device_mode )
4031 {
4032 switch(pAdapter->device_mode)
4033 {
4034 case WLAN_HDD_INFRA_STATION:
4035 case WLAN_HDD_P2P_CLIENT:
4036 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
4037 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
4038 break;
4039 case WLAN_HDD_SOFTAP:
4040 case WLAN_HDD_P2P_GO:
4041 /*softap connection info */
4042 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
4043 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
4044 break;
4045 default:
4046 break;
4047 }
4048
4049 break; //Found the device of interest. break the loop
4050 }
4051
4052 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4053 pAdapterNode = pNext;
4054 }
4055 return operatingChannel;
4056}
4057
4058#ifdef WLAN_FEATURE_PACKET_FILTERING
4059/**---------------------------------------------------------------------------
4060
4061 \brief hdd_set_multicast_list() -
4062
4063 This used to set the multicast address list.
4064
4065 \param - dev - Pointer to the WLAN device.
4066 - skb - Pointer to OS packet (sk_buff).
4067 \return - success/fail
4068
4069 --------------------------------------------------------------------------*/
4070static void hdd_set_multicast_list(struct net_device *dev)
4071{
4072 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07004073 int mc_count;
4074 int i = 0;
4075 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304076
4077 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004078 {
4079 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304080 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004081 return;
4082 }
4083
4084 if (dev->flags & IFF_ALLMULTI)
4085 {
4086 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004087 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304088 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004089 }
4090 else
4091 {
4092 mc_count = netdev_mc_count(dev);
4093 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004094 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07004095 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
4096 {
4097 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004098 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304099 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004100 return;
4101 }
4102
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304103 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07004104
4105 netdev_for_each_mc_addr(ha, dev) {
4106 if (i == mc_count)
4107 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304108 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
4109 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
4110 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004111 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05304112 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07004113 i++;
4114 }
4115 }
4116 return;
4117}
4118#endif
4119
4120/**---------------------------------------------------------------------------
4121
4122 \brief hdd_select_queue() -
4123
4124 This function is registered with the Linux OS for network
4125 core to decide which queue to use first.
4126
4127 \param - dev - Pointer to the WLAN device.
4128 - skb - Pointer to OS packet (sk_buff).
4129 \return - ac, Queue Index/access category corresponding to UP in IP header
4130
4131 --------------------------------------------------------------------------*/
4132v_U16_t hdd_select_queue(struct net_device *dev,
4133 struct sk_buff *skb)
4134{
4135 return hdd_wmm_select_queue(dev, skb);
4136}
4137
4138
4139/**---------------------------------------------------------------------------
4140
4141 \brief hdd_wlan_initial_scan() -
4142
4143 This function triggers the initial scan
4144
4145 \param - pAdapter - Pointer to the HDD adapter.
4146
4147 --------------------------------------------------------------------------*/
4148void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
4149{
4150 tCsrScanRequest scanReq;
4151 tCsrChannelInfo channelInfo;
4152 eHalStatus halStatus;
4153 unsigned long scanId;
4154 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4155
4156 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
4157 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
4158 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
4159
4160 if(sme_Is11dSupported(pHddCtx->hHal))
4161 {
4162 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
4163 if ( HAL_STATUS_SUCCESS( halStatus ) )
4164 {
4165 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
4166 if( !scanReq.ChannelInfo.ChannelList )
4167 {
4168 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
4169 vos_mem_free(channelInfo.ChannelList);
4170 return;
4171 }
4172 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
4173 channelInfo.numOfChannels);
4174 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
4175 vos_mem_free(channelInfo.ChannelList);
4176 }
4177
4178 scanReq.scanType = eSIR_PASSIVE_SCAN;
4179 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
4180 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
4181 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
4182 }
4183 else
4184 {
4185 scanReq.scanType = eSIR_ACTIVE_SCAN;
4186 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
4187 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
4188 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
4189 }
4190
4191 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
4192 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4193 {
4194 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
4195 __func__, halStatus );
4196 }
4197
4198 if(sme_Is11dSupported(pHddCtx->hHal))
4199 vos_mem_free(scanReq.ChannelInfo.ChannelList);
4200}
4201
4202struct fullPowerContext
4203{
4204 struct completion completion;
4205 unsigned int magic;
4206};
4207#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
4208
4209/**---------------------------------------------------------------------------
4210
4211 \brief hdd_full_power_callback() - HDD full power callback function
4212
4213 This is the function invoked by SME to inform the result of a full power
4214 request issued by HDD
4215
4216 \param - callbackcontext - Pointer to cookie
4217 \param - status - result of request
4218
4219 \return - None
4220
4221 --------------------------------------------------------------------------*/
4222static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
4223{
4224 struct fullPowerContext *pContext = callbackContext;
4225
4226 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304227 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004228
4229 if (NULL == callbackContext)
4230 {
4231 hddLog(VOS_TRACE_LEVEL_ERROR,
4232 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004233 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07004234 return;
4235 }
4236
4237 /* there is a race condition that exists between this callback function
4238 and the caller since the caller could time out either before or
4239 while this code is executing. we'll assume the timeout hasn't
4240 occurred, but we'll verify that right before we save our work */
4241
4242 if (POWER_CONTEXT_MAGIC != pContext->magic)
4243 {
4244 /* the caller presumably timed out so there is nothing we can do */
4245 hddLog(VOS_TRACE_LEVEL_WARN,
4246 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004247 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07004248 return;
4249 }
4250
4251 /* the race is on. caller could have timed out immediately after
4252 we verified the magic, but if so, caller will wait a short time
4253 for us to notify the caller, so the context will stay valid */
4254 complete(&pContext->completion);
4255}
4256
4257/**---------------------------------------------------------------------------
4258
4259 \brief hdd_wlan_exit() - HDD WLAN exit function
4260
4261 This is the driver exit point (invoked during rmmod)
4262
4263 \param - pHddCtx - Pointer to the HDD Context
4264
4265 \return - None
4266
4267 --------------------------------------------------------------------------*/
4268void hdd_wlan_exit(hdd_context_t *pHddCtx)
4269{
4270 eHalStatus halStatus;
4271 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
4272 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05304273 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004274 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004275 struct fullPowerContext powerContext;
4276 long lrc;
4277
4278 ENTER();
4279
Jeff Johnson88ba7742013-02-27 14:36:02 -08004280 if (VOS_FTM_MODE != hdd_get_conparam())
4281 {
4282 // Unloading, restart logic is no more required.
4283 wlan_hdd_restart_deinit(pHddCtx);
4284 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004285
Jeff Johnson295189b2012-06-20 16:38:30 -07004286 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004287 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004288 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004289 {
4290 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
4291 WLAN_HDD_INFRA_STATION);
4292 if (pAdapter == NULL)
4293 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4294
4295 if (pAdapter != NULL)
4296 {
4297 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
4298 hdd_UnregisterWext(pAdapter->dev);
4299 }
4300 }
4301 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004302
Jeff Johnson295189b2012-06-20 16:38:30 -07004303 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08004304 {
4305 wlan_hdd_ftm_close(pHddCtx);
4306 goto free_hdd_ctx;
4307 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004308 //Stop the Interface TX queue.
4309 //netif_tx_disable(pWlanDev);
4310 //netif_carrier_off(pWlanDev);
4311
Jeff Johnson295189b2012-06-20 16:38:30 -07004312 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4313 {
4314 pAdapter = hdd_get_adapter(pHddCtx,
4315 WLAN_HDD_SOFTAP);
4316 }
4317 else
4318 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004319 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004320 {
4321 pAdapter = hdd_get_adapter(pHddCtx,
4322 WLAN_HDD_INFRA_STATION);
4323 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004324 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004325 /* DeRegister with platform driver as client for Suspend/Resume */
4326 vosStatus = hddDeregisterPmOps(pHddCtx);
4327 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4328 {
4329 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
4330 VOS_ASSERT(0);
4331 }
4332
4333 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
4334 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
4335 {
4336 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
4337 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004338
4339 // Cancel any outstanding scan requests. We are about to close all
4340 // of our adapters, but an adapter structure is what SME passes back
4341 // to our callback function. Hence if there are any outstanding scan
4342 // requests then there is a race condition between when the adapter
4343 // is closed and when the callback is invoked. We try to resolve that
4344 // race condition here by canceling any outstanding scans before we
4345 // close the adapters.
4346 // Note that the scans may be cancelled in an asynchronous manner, so
4347 // ideally there needs to be some kind of synchronization. Rather than
4348 // introduce a new synchronization here, we will utilize the fact that
4349 // we are about to Request Full Power, and since that is synchronized,
4350 // the expectation is that by the time Request Full Power has completed,
4351 // all scans will be cancelled.
4352 hdd_abort_mac_scan( pHddCtx );
4353
4354 //Disable IMPS/BMPS as we do not want the device to enter any power
4355 //save mode during shutdown
4356 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4357 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4358 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
4359
4360 //Ensure that device is in full power as we will touch H/W during vos_Stop
4361 init_completion(&powerContext.completion);
4362 powerContext.magic = POWER_CONTEXT_MAGIC;
4363
4364 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
4365 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
4366
4367 if (eHAL_STATUS_SUCCESS != halStatus)
4368 {
4369 if (eHAL_STATUS_PMC_PENDING == halStatus)
4370 {
4371 /* request was sent -- wait for the response */
4372 lrc = wait_for_completion_interruptible_timeout(
4373 &powerContext.completion,
4374 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
4375 /* either we have a response or we timed out
4376 either way, first invalidate our magic */
4377 powerContext.magic = 0;
4378 if (lrc <= 0)
4379 {
4380 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004381 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07004382 /* there is a race condition such that the callback
4383 function could be executing at the same time we are. of
4384 primary concern is if the callback function had already
4385 verified the "magic" but hasn't yet set the completion
4386 variable. Since the completion variable is on our
4387 stack, we'll delay just a bit to make sure the data is
4388 still valid if that is the case */
4389 msleep(50);
4390 }
4391 }
4392 else
4393 {
4394 hddLog(VOS_TRACE_LEVEL_ERROR,
4395 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004396 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07004397 VOS_ASSERT(0);
4398 /* continue -- need to clean up as much as possible */
4399 }
4400 }
4401
4402 // Unregister the Net Device Notifier
4403 unregister_netdevice_notifier(&hdd_netdev_notifier);
4404
Jeff Johnson295189b2012-06-20 16:38:30 -07004405 hdd_stop_all_adapters( pHddCtx );
4406
Jeff Johnson295189b2012-06-20 16:38:30 -07004407#ifdef WLAN_BTAMP_FEATURE
4408 vosStatus = WLANBAP_Stop(pVosContext);
4409 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4410 {
4411 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4412 "%s: Failed to stop BAP",__func__);
4413 }
4414#endif //WLAN_BTAMP_FEATURE
4415
4416 //Stop all the modules
4417 vosStatus = vos_stop( pVosContext );
4418 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4419 {
4420 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4421 "%s: Failed to stop VOSS",__func__);
4422 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4423 }
4424
Jeff Johnson295189b2012-06-20 16:38:30 -07004425 //Assert Deep sleep signal now to put Libra HW in lowest power state
4426 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4427 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4428
4429 //Vote off any PMIC voltage supplies
4430 vos_chipPowerDown(NULL, NULL, NULL);
4431
4432 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4433
4434 //Clean up HDD Nlink Service
4435 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4436 nl_srv_exit();
4437
4438 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004439 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004440
4441 //Close the scheduler before calling vos_close to make sure no thread is
4442 // scheduled after the each module close is called i.e after all the data
4443 // structures are freed.
4444 vosStatus = vos_sched_close( pVosContext );
4445 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4446 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4447 "%s: Failed to close VOSS Scheduler",__func__);
4448 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4449 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004450#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004451#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4452 /* Destroy the wake lock */
4453 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4454#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004455 /* Destroy the wake lock */
4456 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004457#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004458
4459 //Close VOSS
4460 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4461 vos_close(pVosContext);
4462
Jeff Johnson295189b2012-06-20 16:38:30 -07004463 //Close Watchdog
4464 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4465 vos_watchdog_close(pVosContext);
4466
4467 /* Cancel the vote for XO Core ON.
4468 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4469 * exited at this point
4470 */
4471 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4472 " when WLAN is turned OFF\n");
4473 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4474 {
4475 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4476 " Not returning failure."
4477 " Power consumed will be high\n");
4478 }
4479
4480 hdd_close_all_adapters( pHddCtx );
4481
4482
4483 //Free up dynamically allocated members inside HDD Adapter
4484 kfree(pHddCtx->cfg_ini);
4485 pHddCtx->cfg_ini= NULL;
4486
4487 /* free the power on lock from platform driver */
4488 if (free_riva_power_on_lock("wlan"))
4489 {
4490 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4491 __func__);
4492 }
4493
Jeff Johnson88ba7742013-02-27 14:36:02 -08004494free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004495 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004496 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004497 if (hdd_is_ssr_required())
4498 {
4499 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004500 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004501 msleep(5000);
4502 }
4503 hdd_set_ssr_required (VOS_FALSE);
4504}
4505
4506
4507/**---------------------------------------------------------------------------
4508
4509 \brief hdd_update_config_from_nv() - Function to update the contents of
4510 the running configuration with parameters taken from NV storage
4511
4512 \param - pHddCtx - Pointer to the HDD global context
4513
4514 \return - VOS_STATUS_SUCCESS if successful
4515
4516 --------------------------------------------------------------------------*/
4517static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4518{
Jeff Johnson295189b2012-06-20 16:38:30 -07004519 v_BOOL_t itemIsValid = VOS_FALSE;
4520 VOS_STATUS status;
4521 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4522 v_U8_t macLoop;
4523
4524 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4525 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4526 if(status != VOS_STATUS_SUCCESS)
4527 {
4528 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4529 return VOS_STATUS_E_FAILURE;
4530 }
4531
4532 if (itemIsValid == VOS_TRUE)
4533 {
4534 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4535 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4536 VOS_MAX_CONCURRENCY_PERSONA);
4537 if(status != VOS_STATUS_SUCCESS)
4538 {
4539 /* Get MAC from NV fail, not update CFG info
4540 * INI MAC value will be used for MAC setting */
4541 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4542 return VOS_STATUS_E_FAILURE;
4543 }
4544
4545 /* If first MAC is not valid, treat all others are not valid
4546 * Then all MACs will be got from ini file */
4547 if(vos_is_macaddr_zero(&macFromNV[0]))
4548 {
4549 /* MAC address in NV file is not configured yet */
4550 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4551 return VOS_STATUS_E_INVAL;
4552 }
4553
4554 /* Get MAC address from NV, update CFG info */
4555 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4556 {
4557 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
4558 {
4559 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
4560 /* This MAC is not valid, skip it
4561 * This MAC will be got from ini file */
4562 }
4563 else
4564 {
4565 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
4566 (v_U8_t *)&macFromNV[macLoop].bytes[0],
4567 VOS_MAC_ADDR_SIZE);
4568 }
4569 }
4570 }
4571 else
4572 {
4573 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
4574 return VOS_STATUS_E_FAILURE;
4575 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004576
Jeff Johnson295189b2012-06-20 16:38:30 -07004577
4578 return VOS_STATUS_SUCCESS;
4579}
4580
4581/**---------------------------------------------------------------------------
4582
4583 \brief hdd_post_voss_start_config() - HDD post voss start config helper
4584
4585 \param - pAdapter - Pointer to the HDD
4586
4587 \return - None
4588
4589 --------------------------------------------------------------------------*/
4590VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
4591{
4592 eHalStatus halStatus;
4593 v_U32_t listenInterval;
4594
Jeff Johnson295189b2012-06-20 16:38:30 -07004595
4596 // Send ready indication to the HDD. This will kick off the MAC
4597 // into a 'running' state and should kick off an initial scan.
4598 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
4599 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4600 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304601 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07004602 "code %08d [x%08x]",__func__, halStatus, halStatus );
4603 return VOS_STATUS_E_FAILURE;
4604 }
4605
4606 // Set default LI into HDD context,
4607 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
4608 // And RIVA will crash
4609 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
4610 pHddCtx->hdd_actual_LI_value = listenInterval;
4611
4612 return VOS_STATUS_SUCCESS;
4613}
4614
Jeff Johnson295189b2012-06-20 16:38:30 -07004615/* wake lock APIs for HDD */
4616void hdd_prevent_suspend(void)
4617{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004618#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004619 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004620#else
4621 wcnss_prevent_suspend();
4622#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004623}
4624
4625void hdd_allow_suspend(void)
4626{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004627#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004628 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004629#else
4630 wcnss_allow_suspend();
4631#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004632}
4633
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004634void hdd_allow_suspend_timeout(v_U32_t timeout)
4635{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004636#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07004637 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004638#else
4639 /* Do nothing as there is no API in wcnss for timeout*/
4640#endif
4641}
4642
Jeff Johnson295189b2012-06-20 16:38:30 -07004643/**---------------------------------------------------------------------------
4644
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004645 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
4646 information between Host and Riva
4647
4648 This function gets reported version of FW
4649 It also finds the version of Riva headers used to compile the host
4650 It compares the above two and prints a warning if they are different
4651 It gets the SW and HW version string
4652 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
4653 indicating the features they support through a bitmap
4654
4655 \param - pHddCtx - Pointer to HDD context
4656
4657 \return - void
4658
4659 --------------------------------------------------------------------------*/
4660
4661void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
4662{
4663
4664 tSirVersionType versionCompiled;
4665 tSirVersionType versionReported;
4666 tSirVersionString versionString;
4667 tANI_U8 fwFeatCapsMsgSupported = 0;
4668 VOS_STATUS vstatus;
4669
4670 /* retrieve and display WCNSS version information */
4671 do {
4672
4673 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
4674 &versionCompiled);
4675 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4676 {
4677 hddLog(VOS_TRACE_LEVEL_FATAL,
4678 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004679 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004680 break;
4681 }
4682
4683 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
4684 &versionReported);
4685 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4686 {
4687 hddLog(VOS_TRACE_LEVEL_FATAL,
4688 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004689 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004690 break;
4691 }
4692
4693 if ((versionCompiled.major != versionReported.major) ||
4694 (versionCompiled.minor != versionReported.minor) ||
4695 (versionCompiled.version != versionReported.version) ||
4696 (versionCompiled.revision != versionReported.revision))
4697 {
4698 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4699 "Host expected %u.%u.%u.%u\n",
4700 WLAN_MODULE_NAME,
4701 (int)versionReported.major,
4702 (int)versionReported.minor,
4703 (int)versionReported.version,
4704 (int)versionReported.revision,
4705 (int)versionCompiled.major,
4706 (int)versionCompiled.minor,
4707 (int)versionCompiled.version,
4708 (int)versionCompiled.revision);
4709 }
4710 else
4711 {
4712 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4713 WLAN_MODULE_NAME,
4714 (int)versionReported.major,
4715 (int)versionReported.minor,
4716 (int)versionReported.version,
4717 (int)versionReported.revision);
4718 }
4719
4720 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
4721 versionString,
4722 sizeof(versionString));
4723 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4724 {
4725 hddLog(VOS_TRACE_LEVEL_FATAL,
4726 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004727 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004728 break;
4729 }
4730
4731 pr_info("%s: WCNSS software version %s\n",
4732 WLAN_MODULE_NAME, versionString);
4733
4734 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
4735 versionString,
4736 sizeof(versionString));
4737 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4738 {
4739 hddLog(VOS_TRACE_LEVEL_FATAL,
4740 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004741 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004742 break;
4743 }
4744
4745 pr_info("%s: WCNSS hardware version %s\n",
4746 WLAN_MODULE_NAME, versionString);
4747
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004748 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
4749 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004750 send the message only if it the riva is 1.1
4751 minor numbers for different riva branches:
4752 0 -> (1.0)Mainline Build
4753 1 -> (1.1)Mainline Build
4754 2->(1.04) Stability Build
4755 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004756 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004757 ((versionReported.minor>=1) && (versionReported.version>=1)))
4758 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
4759 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004760
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004761 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08004762 {
4763#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4764 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
4765 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
4766#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004767 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08004768 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004769
4770 } while (0);
4771
4772}
4773
4774/**---------------------------------------------------------------------------
4775
Jeff Johnson295189b2012-06-20 16:38:30 -07004776 \brief hdd_wlan_startup() - HDD init function
4777
4778 This is the driver startup code executed once a WLAN device has been detected
4779
4780 \param - dev - Pointer to the underlying device
4781
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004782 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07004783
4784 --------------------------------------------------------------------------*/
4785
4786int hdd_wlan_startup(struct device *dev )
4787{
4788 VOS_STATUS status;
4789 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004790 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004791 hdd_context_t *pHddCtx = NULL;
4792 v_CONTEXT_t pVosContext= NULL;
4793#ifdef WLAN_BTAMP_FEATURE
4794 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
4795 WLANBAP_ConfigType btAmpConfig;
4796 hdd_config_t *pConfig;
4797#endif
4798 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07004799 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004800
4801 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004802 /*
4803 * cfg80211: wiphy allocation
4804 */
4805 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
4806
4807 if(wiphy == NULL)
4808 {
4809 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004810 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004811 }
4812
4813 pHddCtx = wiphy_priv(wiphy);
4814
Jeff Johnson295189b2012-06-20 16:38:30 -07004815 //Initialize the adapter context to zeros.
4816 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4817
Jeff Johnson295189b2012-06-20 16:38:30 -07004818 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004819 hdd_prevent_suspend();
4820 pHddCtx->isLoadUnloadInProgress = TRUE;
4821
4822 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4823
4824 /*Get vos context here bcoz vos_open requires it*/
4825 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4826
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08004827 if(pVosContext == NULL)
4828 {
4829 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
4830 goto err_free_hdd_context;
4831 }
4832
Jeff Johnson295189b2012-06-20 16:38:30 -07004833 //Save the Global VOSS context in adapter context for future.
4834 pHddCtx->pvosContext = pVosContext;
4835
4836 //Save the adapter context in global context for future.
4837 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
4838
Jeff Johnson295189b2012-06-20 16:38:30 -07004839 pHddCtx->parent_dev = dev;
4840
4841 init_completion(&pHddCtx->full_pwr_comp_var);
4842 init_completion(&pHddCtx->standby_comp_var);
4843 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004844 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004845 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004846
4847 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
4848
4849 // Load all config first as TL config is needed during vos_open
4850 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
4851 if(pHddCtx->cfg_ini == NULL)
4852 {
4853 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
4854 goto err_free_hdd_context;
4855 }
4856
4857 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
4858
4859 // Read and parse the qcom_cfg.ini file
4860 status = hdd_parse_config_ini( pHddCtx );
4861 if ( VOS_STATUS_SUCCESS != status )
4862 {
4863 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
4864 __func__, WLAN_INI_FILE);
4865 goto err_config;
4866 }
4867
Jeff Johnson295189b2012-06-20 16:38:30 -07004868 /*
4869 * cfg80211: Initialization and registration ...
4870 */
4871 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
4872 {
4873 hddLog(VOS_TRACE_LEVEL_FATAL,
4874 "%s: wlan_hdd_cfg80211_register return failure", __func__);
4875 goto err_wiphy_reg;
4876 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004877
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004878 // Update VOS trace levels based upon the cfg.ini
4879 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
4880 pHddCtx->cfg_ini->vosTraceEnableBAP);
4881 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
4882 pHddCtx->cfg_ini->vosTraceEnableTL);
4883 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
4884 pHddCtx->cfg_ini->vosTraceEnableWDI);
4885 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
4886 pHddCtx->cfg_ini->vosTraceEnableHDD);
4887 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
4888 pHddCtx->cfg_ini->vosTraceEnableSME);
4889 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
4890 pHddCtx->cfg_ini->vosTraceEnablePE);
4891 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
4892 pHddCtx->cfg_ini->vosTraceEnableWDA);
4893 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
4894 pHddCtx->cfg_ini->vosTraceEnableSYS);
4895 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
4896 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004897 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
4898 pHddCtx->cfg_ini->vosTraceEnableSAP);
4899 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
4900 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004901
Jeff Johnson295189b2012-06-20 16:38:30 -07004902 // Update WDI trace levels based upon the cfg.ini
4903 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
4904 pHddCtx->cfg_ini->wdiTraceEnableDAL);
4905 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
4906 pHddCtx->cfg_ini->wdiTraceEnableCTL);
4907 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
4908 pHddCtx->cfg_ini->wdiTraceEnableDAT);
4909 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
4910 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004911
Jeff Johnson88ba7742013-02-27 14:36:02 -08004912 if (VOS_FTM_MODE == hdd_get_conparam())
4913 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004914 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
4915 {
4916 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
4917 goto err_free_hdd_context;
4918 }
4919 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
4920 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08004921 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004922
Jeff Johnson88ba7742013-02-27 14:36:02 -08004923 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07004924 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4925 {
4926 status = vos_watchdog_open(pVosContext,
4927 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4928
4929 if(!VOS_IS_STATUS_SUCCESS( status ))
4930 {
4931 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004932 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07004933 }
4934 }
4935
4936 pHddCtx->isLogpInProgress = FALSE;
4937 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4938
Jeff Johnson295189b2012-06-20 16:38:30 -07004939 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
4940 if(!VOS_IS_STATUS_SUCCESS(status))
4941 {
4942 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004943 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004944 }
4945
Jeff Johnson295189b2012-06-20 16:38:30 -07004946 status = vos_open( &pVosContext, 0);
4947 if ( !VOS_IS_STATUS_SUCCESS( status ))
4948 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004949 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
4950 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07004951 }
4952
Jeff Johnson295189b2012-06-20 16:38:30 -07004953 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
4954
4955 if ( NULL == pHddCtx->hHal )
4956 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004957 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004958 goto err_vosclose;
4959 }
4960
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004961 status = vos_preStart( pHddCtx->pvosContext );
4962 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4963 {
4964 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
4965 goto err_vosclose;
4966 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004967
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004968 /* Note that the vos_preStart() sequence triggers the cfg download.
4969 The cfg download must occur before we update the SME config
4970 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07004971 status = hdd_set_sme_config( pHddCtx );
4972
4973 if ( VOS_STATUS_SUCCESS != status )
4974 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004975 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
4976 goto err_vosclose;
4977 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004978
4979 //Initialize the WMM module
4980 status = hdd_wmm_init(pHddCtx);
4981 if (!VOS_IS_STATUS_SUCCESS(status))
4982 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004983 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004984 goto err_vosclose;
4985 }
4986
Jeff Johnson295189b2012-06-20 16:38:30 -07004987 /* In the integrated architecture we update the configuration from
4988 the INI file and from NV before vOSS has been started so that
4989 the final contents are available to send down to the cCPU */
4990
4991 // Apply the cfg.ini to cfg.dat
4992 if (FALSE == hdd_update_config_dat(pHddCtx))
4993 {
4994 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4995 goto err_vosclose;
4996 }
4997
4998 // Apply the NV to cfg.dat
4999 /* Prima Update MAC address only at here */
5000 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
5001 {
5002#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
5003 /* There was not a valid set of MAC Addresses in NV. See if the
5004 default addresses were modified by the cfg.ini settings. If so,
5005 we'll use them, but if not, we'll autogenerate a set of MAC
5006 addresses based upon the device serial number */
5007
5008 static const v_MACADDR_t default_address =
5009 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
5010 unsigned int serialno;
5011 int i;
5012
5013 serialno = wcnss_get_serial_number();
5014 if ((0 != serialno) &&
5015 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
5016 sizeof(default_address))))
5017 {
5018 /* cfg.ini has the default address, invoke autogen logic */
5019
5020 /* MAC address has 3 bytes of OUI so we have a maximum of 3
5021 bytes of the serial number that can be used to generate
5022 the other 3 bytes of the MAC address. Mask off all but
5023 the lower 3 bytes (this will also make sure we don't
5024 overflow in the next step) */
5025 serialno &= 0x00FFFFFF;
5026
5027 /* we need a unique address for each session */
5028 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
5029
5030 /* autogen all addresses */
5031 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5032 {
5033 /* start with the entire default address */
5034 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
5035 /* then replace the lower 3 bytes */
5036 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
5037 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
5038 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
5039
5040 serialno++;
5041 }
5042
5043 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
5044 MAC_ADDRESS_STR,
5045 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5046 }
5047 else
5048#endif //WLAN_AUTOGEN_MACADDR_FEATURE
5049 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005050 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005051 "%s: Invalid MAC address in NV, using MAC from ini file "
5052 MAC_ADDRESS_STR, __func__,
5053 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
5054 }
5055 }
5056 {
5057 eHalStatus halStatus;
5058 // Set the MAC Address
5059 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
5060 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
5061 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
5062 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
5063
5064 if (!HAL_STATUS_SUCCESS( halStatus ))
5065 {
5066 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
5067 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08005068 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07005069 }
5070 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005071
5072 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
5073 Note: Firmware image will be read and downloaded inside vos_start API */
5074 status = vos_start( pHddCtx->pvosContext );
5075 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5076 {
5077 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
5078 goto err_vosclose;
5079 }
5080
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07005081 /* Exchange capability info between Host and FW and also get versioning info from FW */
5082 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005083
5084 status = hdd_post_voss_start_config( pHddCtx );
5085 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5086 {
5087 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
5088 __func__);
5089 goto err_vosstop;
5090 }
5091
Jeff Johnson295189b2012-06-20 16:38:30 -07005092 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5093 {
5094 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
5095 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5096 }
5097 else
5098 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005099 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
5100 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
5101 if (pAdapter != NULL)
5102 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305103 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07005104 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305105 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
5106 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
5107 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07005108
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305109 /* Generate the P2P Device Address. This consists of the device's
5110 * primary MAC address with the locally administered bit set.
5111 */
5112 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07005113 }
5114 else
5115 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05305116 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
5117 if (p2p_dev_addr != NULL)
5118 {
5119 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
5120 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
5121 }
5122 else
5123 {
5124 hddLog(VOS_TRACE_LEVEL_FATAL,
5125 "%s: Failed to allocate mac_address for p2p_device",
5126 __func__);
5127 goto err_close_adapter;
5128 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005129 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005130
5131 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5132 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
5133 if ( NULL == pP2pAdapter )
5134 {
5135 hddLog(VOS_TRACE_LEVEL_FATAL,
5136 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005137 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005138 goto err_close_adapter;
5139 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005140 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005141 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005142
5143 if( pAdapter == NULL )
5144 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005145 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
5146 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005147 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005148
Jeff Johnson295189b2012-06-20 16:38:30 -07005149#ifdef WLAN_BTAMP_FEATURE
5150 vStatus = WLANBAP_Open(pVosContext);
5151 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5152 {
5153 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5154 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07005155 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005156 }
5157
5158 vStatus = BSL_Init(pVosContext);
5159 if(!VOS_IS_STATUS_SUCCESS(vStatus))
5160 {
5161 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5162 "%s: Failed to Init BSL",__func__);
5163 goto err_bap_close;
5164 }
5165 vStatus = WLANBAP_Start(pVosContext);
5166 if (!VOS_IS_STATUS_SUCCESS(vStatus))
5167 {
5168 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
5169 "%s: Failed to start TL",__func__);
5170 goto err_bap_close;
5171 }
5172
5173 pConfig = pHddCtx->cfg_ini;
5174 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
5175 status = WLANBAP_SetConfig(&btAmpConfig);
5176
5177#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07005178
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07005179#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
5180 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
5181 {
5182 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
5183 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
5184 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
5185 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
5186 }
5187#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005188#ifdef FEATURE_WLAN_SCAN_PNO
5189 /*SME must send channel update configuration to RIVA*/
5190 sme_UpdateChannelConfig(pHddCtx->hHal);
5191#endif
5192
Jeff Johnson295189b2012-06-20 16:38:30 -07005193 /* Register with platform driver as client for Suspend/Resume */
5194 status = hddRegisterPmOps(pHddCtx);
5195 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5196 {
5197 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
5198#ifdef WLAN_BTAMP_FEATURE
5199 goto err_bap_stop;
5200#else
Jeff Johnsone7245742012-09-05 17:12:55 -07005201 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07005202#endif //WLAN_BTAMP_FEATURE
5203 }
5204
5205 /* Register TM level change handler function to the platform */
5206 status = hddDevTmRegisterNotifyCallback(pHddCtx);
5207 if ( !VOS_IS_STATUS_SUCCESS( status ) )
5208 {
5209 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
5210 goto err_unregister_pmops;
5211 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005212
5213 /* register for riva power on lock to platform driver */
5214 if (req_riva_power_on_lock("wlan"))
5215 {
5216 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
5217 __func__);
5218 goto err_unregister_pmops;
5219 }
5220
Jeff Johnson295189b2012-06-20 16:38:30 -07005221 // register net device notifier for device change notification
5222 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5223
5224 if(ret < 0)
5225 {
5226 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
5227 goto err_free_power_on_lock;
5228 }
5229
5230 //Initialize the nlink service
5231 if(nl_srv_init() != 0)
5232 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305233 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005234 goto err_reg_netdev;
5235 }
5236
5237 //Initialize the BTC service
5238 if(btc_activate_service(pHddCtx) != 0)
5239 {
5240 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
5241 goto err_nl_srv;
5242 }
5243
5244#ifdef PTT_SOCK_SVC_ENABLE
5245 //Initialize the PTT service
5246 if(ptt_sock_activate_svc(pHddCtx) != 0)
5247 {
5248 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
5249 goto err_nl_srv;
5250 }
5251#endif
5252
Jeff Johnson295189b2012-06-20 16:38:30 -07005253 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005254 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07005255 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07005256 /* Action frame registered in one adapter which will
5257 * applicable to all interfaces
5258 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07005259 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005260 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005261
5262 mutex_init(&pHddCtx->sap_lock);
5263
5264 pHddCtx->isLoadUnloadInProgress = FALSE;
5265
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005266#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07005267#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5268 /* Initialize the wake lcok */
5269 wake_lock_init(&pHddCtx->rx_wake_lock,
5270 WAKE_LOCK_SUSPEND,
5271 "qcom_rx_wakelock");
5272#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08005273 /* Initialize the wake lcok */
5274 wake_lock_init(&pHddCtx->sap_wake_lock,
5275 WAKE_LOCK_SUSPEND,
5276 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005277#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07005278
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005279 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
5280 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07005281
5282 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
5283 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07005284
5285 // Initialize the restart logic
5286 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05305287
Jeff Johnson295189b2012-06-20 16:38:30 -07005288 goto success;
5289
5290err_nl_srv:
5291 nl_srv_exit();
5292
5293err_reg_netdev:
5294 unregister_netdevice_notifier(&hdd_netdev_notifier);
5295
5296err_free_power_on_lock:
5297 free_riva_power_on_lock("wlan");
5298
5299err_unregister_pmops:
5300 hddDevTmUnregisterNotifyCallback(pHddCtx);
5301 hddDeregisterPmOps(pHddCtx);
5302
5303#ifdef WLAN_BTAMP_FEATURE
5304err_bap_stop:
5305 WLANBAP_Stop(pVosContext);
5306#endif
5307
5308#ifdef WLAN_BTAMP_FEATURE
5309err_bap_close:
5310 WLANBAP_Close(pVosContext);
5311#endif
5312
Jeff Johnson295189b2012-06-20 16:38:30 -07005313err_close_adapter:
5314 hdd_close_all_adapters( pHddCtx );
5315
5316err_vosstop:
5317 vos_stop(pVosContext);
5318
5319err_vosclose:
5320 status = vos_sched_close( pVosContext );
5321 if (!VOS_IS_STATUS_SUCCESS(status)) {
5322 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
5323 "%s: Failed to close VOSS Scheduler", __func__);
5324 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
5325 }
5326 vos_close(pVosContext );
5327
Jeff Johnson295189b2012-06-20 16:38:30 -07005328err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005329 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005330
5331err_wdclose:
5332 if(pHddCtx->cfg_ini->fIsLogpEnabled)
5333 vos_watchdog_close(pVosContext);
5334
Jeff Johnson295189b2012-06-20 16:38:30 -07005335err_wiphy_reg:
5336 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005337
5338err_config:
5339 kfree(pHddCtx->cfg_ini);
5340 pHddCtx->cfg_ini= NULL;
5341
5342err_free_hdd_context:
5343 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07005344 wiphy_free(wiphy) ;
5345 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07005346 VOS_BUG(1);
5347
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08005348 if (hdd_is_ssr_required())
5349 {
5350 /* WDI timeout had happened during load, so SSR is needed here */
5351 subsystem_restart("wcnss");
5352 msleep(5000);
5353 }
5354 hdd_set_ssr_required (VOS_FALSE);
5355
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005356 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005357
5358success:
5359 EXIT();
5360 return 0;
5361}
5362
5363/**---------------------------------------------------------------------------
5364
Jeff Johnson32d95a32012-09-10 13:15:23 -07005365 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07005366
Jeff Johnson32d95a32012-09-10 13:15:23 -07005367 This is the driver entry point - called in different timeline depending
5368 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07005369
5370 \param - None
5371
5372 \return - 0 for success, non zero for failure
5373
5374 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07005375static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005376{
5377 VOS_STATUS status;
5378 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005379 struct device *dev = NULL;
5380 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005381#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5382 int max_retries = 0;
5383#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005384
5385 ENTER();
5386
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005387#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005388 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07005389#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005390
5391 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5392 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5393
5394 //Power Up Libra WLAN card first if not already powered up
5395 status = vos_chipPowerUp(NULL,NULL,NULL);
5396 if (!VOS_IS_STATUS_SUCCESS(status))
5397 {
5398 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
5399 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005400 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005401 }
5402
Jeff Johnson295189b2012-06-20 16:38:30 -07005403#ifdef ANI_BUS_TYPE_PCI
5404
5405 dev = wcnss_wlan_get_device();
5406
5407#endif // ANI_BUS_TYPE_PCI
5408
5409#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07005410
5411#ifdef HAVE_WCNSS_CAL_DOWNLOAD
5412 /* wait until WCNSS driver downloads NV */
5413 while (!wcnss_device_ready() && 5 >= ++max_retries) {
5414 msleep(1000);
5415 }
5416 if (max_retries >= 5) {
5417 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
5418 return -ENODEV;
5419 }
5420#endif
5421
Jeff Johnson295189b2012-06-20 16:38:30 -07005422 dev = wcnss_wlan_get_device();
5423#endif // ANI_BUS_TYPE_PLATFORM
5424
5425
5426 do {
5427 if (NULL == dev) {
5428 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
5429 ret_status = -1;
5430 break;
5431 }
5432
5433#ifdef MEMORY_DEBUG
5434 vos_mem_init();
5435#endif
5436
5437#ifdef TIMER_MANAGER
5438 vos_timer_manager_init();
5439#endif
5440
5441 /* Preopen VOSS so that it is ready to start at least SAL */
5442 status = vos_preOpen(&pVosContext);
5443
5444 if (!VOS_IS_STATUS_SUCCESS(status))
5445 {
5446 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5447 ret_status = -1;
5448 break;
5449 }
5450
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005451#ifndef MODULE
5452 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5453 */
5454 hdd_set_conparam((v_UINT_t)con_mode);
5455#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005456
5457 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005458 if (hdd_wlan_startup(dev))
5459 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005460 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005461 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005462 vos_preClose( &pVosContext );
5463 ret_status = -1;
5464 break;
5465 }
5466
5467 /* Cancel the vote for XO Core ON
5468 * This is done here for safety purposes in case we re-initialize without turning
5469 * it OFF in any error scenario.
5470 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005471 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005472 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005473 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005474 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5475 {
5476 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5477 " Power consumed will be high\n");
5478 }
5479 } while (0);
5480
5481 if (0 != ret_status)
5482 {
5483 //Assert Deep sleep signal now to put Libra HW in lowest power state
5484 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5485 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5486
5487 //Vote off any PMIC voltage supplies
5488 vos_chipPowerDown(NULL, NULL, NULL);
5489#ifdef TIMER_MANAGER
5490 vos_timer_exit();
5491#endif
5492#ifdef MEMORY_DEBUG
5493 vos_mem_exit();
5494#endif
5495
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005496#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005497 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005498#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005499 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5500 }
5501 else
5502 {
5503 //Send WLAN UP indication to Nlink Service
5504 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5505
5506 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5507
5508 }
5509
5510 EXIT();
5511
5512 return ret_status;
5513}
5514
Jeff Johnson32d95a32012-09-10 13:15:23 -07005515/**---------------------------------------------------------------------------
5516
5517 \brief hdd_module_init() - Init Function
5518
5519 This is the driver entry point (invoked when module is loaded using insmod)
5520
5521 \param - None
5522
5523 \return - 0 for success, non zero for failure
5524
5525 --------------------------------------------------------------------------*/
5526#ifdef MODULE
5527static int __init hdd_module_init ( void)
5528{
5529 return hdd_driver_init();
5530}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005531#else /* #ifdef MODULE */
5532static int __init hdd_module_init ( void)
5533{
5534 /* Driver initialization is delayed to fwpath_changed_handler */
5535 return 0;
5536}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005537#endif /* #ifdef MODULE */
5538
Jeff Johnson295189b2012-06-20 16:38:30 -07005539
5540/**---------------------------------------------------------------------------
5541
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005542 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005543
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005544 This is the driver exit point (invoked when module is unloaded using rmmod
5545 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005546
5547 \param - None
5548
5549 \return - None
5550
5551 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005552static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005553{
5554 hdd_context_t *pHddCtx = NULL;
5555 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005556
5557 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
5558
5559 //Get the global vos context
5560 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5561
5562 if(!pVosContext)
5563 {
5564 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
5565 goto done;
5566 }
5567
5568 //Get the HDD context.
5569 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
5570
5571 if(!pHddCtx)
5572 {
5573 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
5574 }
5575 else
5576 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005577 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005578 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07005579 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
5580 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07005581 }
5582
5583 pHddCtx->isLoadUnloadInProgress = TRUE;
5584 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5585
5586 //Do all the cleanup before deregistering the driver
5587 hdd_wlan_exit(pHddCtx);
5588 }
5589
Jeff Johnson295189b2012-06-20 16:38:30 -07005590 vos_preClose( &pVosContext );
5591
5592#ifdef TIMER_MANAGER
5593 vos_timer_exit();
5594#endif
5595#ifdef MEMORY_DEBUG
5596 vos_mem_exit();
5597#endif
5598
5599done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005600#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005601 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005602#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005603 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
5604}
5605
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005606/**---------------------------------------------------------------------------
5607
5608 \brief hdd_module_exit() - Exit function
5609
5610 This is the driver exit point (invoked when module is unloaded using rmmod)
5611
5612 \param - None
5613
5614 \return - None
5615
5616 --------------------------------------------------------------------------*/
5617static void __exit hdd_module_exit(void)
5618{
5619 hdd_driver_exit();
5620}
5621
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005622#ifdef MODULE
5623static int fwpath_changed_handler(const char *kmessage,
5624 struct kernel_param *kp)
5625{
Jeff Johnson76052702013-04-16 13:55:05 -07005626 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005627}
5628
5629static int con_mode_handler(const char *kmessage,
5630 struct kernel_param *kp)
5631{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005632 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005633}
5634#else /* #ifdef MODULE */
5635/**---------------------------------------------------------------------------
5636
Jeff Johnson76052702013-04-16 13:55:05 -07005637 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005638
Jeff Johnson76052702013-04-16 13:55:05 -07005639 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005640 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07005641 - invoked when module parameter fwpath is modified from userspace to signal
5642 initializing the WLAN driver or when con_mode is modified from userspace
5643 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005644
5645 \return - 0 for success, non zero for failure
5646
5647 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005648static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005649{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005650 int ret_status;
5651
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005652 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005653 ret_status = hdd_driver_init();
5654 wlan_hdd_inited = ret_status ? 0 : 1;
5655 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005656 }
5657
5658 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07005659
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005660 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07005661
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005662 ret_status = hdd_driver_init();
5663 wlan_hdd_inited = ret_status ? 0 : 1;
5664 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005665}
5666
Jeff Johnson295189b2012-06-20 16:38:30 -07005667/**---------------------------------------------------------------------------
5668
Jeff Johnson76052702013-04-16 13:55:05 -07005669 \brief fwpath_changed_handler() - Handler Function
5670
5671 Handle changes to the fwpath parameter
5672
5673 \return - 0 for success, non zero for failure
5674
5675 --------------------------------------------------------------------------*/
5676static int fwpath_changed_handler(const char *kmessage,
5677 struct kernel_param *kp)
5678{
5679 int ret;
5680
5681 ret = param_set_copystring(kmessage, kp);
5682 if (0 == ret)
5683 ret = kickstart_driver();
5684 return ret;
5685}
5686
5687/**---------------------------------------------------------------------------
5688
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005689 \brief con_mode_handler() -
5690
5691 Handler function for module param con_mode when it is changed by userspace
5692 Dynamically linked - do nothing
5693 Statically linked - exit and init driver, as in rmmod and insmod
5694
Jeff Johnson76052702013-04-16 13:55:05 -07005695 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005696
Jeff Johnson76052702013-04-16 13:55:05 -07005697 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005698
5699 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07005700static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005701{
Jeff Johnson76052702013-04-16 13:55:05 -07005702 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005703
Jeff Johnson76052702013-04-16 13:55:05 -07005704 ret = param_set_int(kmessage, kp);
5705 if (0 == ret)
5706 ret = kickstart_driver();
5707 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005708}
5709#endif /* #ifdef MODULE */
5710
5711/**---------------------------------------------------------------------------
5712
Jeff Johnson295189b2012-06-20 16:38:30 -07005713 \brief hdd_get_conparam() -
5714
5715 This is the driver exit point (invoked when module is unloaded using rmmod)
5716
5717 \param - None
5718
5719 \return - tVOS_CON_MODE
5720
5721 --------------------------------------------------------------------------*/
5722tVOS_CON_MODE hdd_get_conparam ( void )
5723{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005724#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005725 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005726#else
5727 return (tVOS_CON_MODE)curr_con_mode;
5728#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005729}
5730void hdd_set_conparam ( v_UINT_t newParam )
5731{
5732 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005733#ifndef MODULE
5734 curr_con_mode = con_mode;
5735#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005736}
5737/**---------------------------------------------------------------------------
5738
5739 \brief hdd_softap_sta_deauth() - function
5740
5741 This to take counter measure to handle deauth req from HDD
5742
5743 \param - pAdapter - Pointer to the HDD
5744
5745 \param - enable - boolean value
5746
5747 \return - None
5748
5749 --------------------------------------------------------------------------*/
5750
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005751VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005752{
Jeff Johnson295189b2012-06-20 16:38:30 -07005753 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005754 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005755
5756 ENTER();
5757
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305758 hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005759
5760 //Ignore request to deauth bcmc station
5761 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005762 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005763
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005764 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005765
5766 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005767 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005768}
5769
5770/**---------------------------------------------------------------------------
5771
5772 \brief hdd_softap_sta_disassoc() - function
5773
5774 This to take counter measure to handle deauth req from HDD
5775
5776 \param - pAdapter - Pointer to the HDD
5777
5778 \param - enable - boolean value
5779
5780 \return - None
5781
5782 --------------------------------------------------------------------------*/
5783
5784void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5785{
5786 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5787
5788 ENTER();
5789
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305790 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005791
5792 //Ignore request to disassoc bcmc station
5793 if( pDestMacAddress[0] & 0x1 )
5794 return;
5795
5796 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5797}
5798
5799void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5800{
5801 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5802
5803 ENTER();
5804
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305805 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07005806
5807 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5808}
5809
Jeff Johnson295189b2012-06-20 16:38:30 -07005810/**---------------------------------------------------------------------------
5811 *
5812 * \brief hdd_get__concurrency_mode() -
5813 *
5814 *
5815 * \param - None
5816 *
5817 * \return - CONCURRENCY MODE
5818 *
5819 * --------------------------------------------------------------------------*/
5820tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
5821{
5822 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5823 hdd_context_t *pHddCtx;
5824
5825 if (NULL != pVosContext)
5826 {
5827 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5828 if (NULL != pHddCtx)
5829 {
5830 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
5831 }
5832 }
5833
5834 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005835 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005836 return VOS_STA;
5837}
5838
5839/* Decide whether to allow/not the apps power collapse.
5840 * Allow apps power collapse if we are in connected state.
5841 * if not, allow only if we are in IMPS */
5842v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
5843{
5844 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08005845 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005846 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005847 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5848 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5849 hdd_adapter_t *pAdapter = NULL;
5850 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08005851 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005852
Jeff Johnson295189b2012-06-20 16:38:30 -07005853 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5854 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005855
Yathish9f22e662012-12-10 14:21:35 -08005856 concurrent_state = hdd_get_concurrency_mode();
5857
5858#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5859 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
5860 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
5861 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
5862 return TRUE;
5863#endif
5864
Jeff Johnson295189b2012-06-20 16:38:30 -07005865 /*loop through all adapters. TBD fix for Concurrency */
5866 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5867 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5868 {
5869 pAdapter = pAdapterNode->pAdapter;
5870 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
5871 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5872 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005873 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07005874 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08005875 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005876 (eANI_BOOLEAN_TRUE == scanRspPending) ||
5877 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07005878 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005879 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005880 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
5881 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07005882 return FALSE;
5883 }
5884 }
5885 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5886 pAdapterNode = pNext;
5887 }
5888 return TRUE;
5889}
5890
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08005891/* Decides whether to send suspend notification to Riva
5892 * if any adapter is in BMPS; then it is required */
5893v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
5894{
5895 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
5896 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5897
5898 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
5899 {
5900 return TRUE;
5901 }
5902 return FALSE;
5903}
5904
Jeff Johnson295189b2012-06-20 16:38:30 -07005905void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5906{
5907 switch(mode)
5908 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005909 case VOS_STA_MODE:
5910 case VOS_P2P_CLIENT_MODE:
5911 case VOS_P2P_GO_MODE:
5912 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07005913 pHddCtx->concurrency_mode |= (1 << mode);
5914 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07005915 break;
5916 default:
5917 break;
5918
5919 }
5920 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5921 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5922}
5923
5924
5925void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5926{
5927 switch(mode)
5928 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005929 case VOS_STA_MODE:
5930 case VOS_P2P_CLIENT_MODE:
5931 case VOS_P2P_GO_MODE:
5932 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005933 pHddCtx->no_of_sessions[mode]--;
5934 if (!(pHddCtx->no_of_sessions[mode]))
5935 pHddCtx->concurrency_mode &= (~(1 << mode));
5936 break;
5937 default:
5938 break;
5939 }
5940 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5941 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5942}
5943
Jeff Johnsone7245742012-09-05 17:12:55 -07005944/**---------------------------------------------------------------------------
5945 *
5946 * \brief wlan_hdd_restart_init
5947 *
5948 * This function initalizes restart timer/flag. An internal function.
5949 *
5950 * \param - pHddCtx
5951 *
5952 * \return - None
5953 *
5954 * --------------------------------------------------------------------------*/
5955
5956static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
5957{
5958 /* Initialize */
5959 pHddCtx->hdd_restart_retries = 0;
5960 atomic_set(&pHddCtx->isRestartInProgress, 0);
5961 vos_timer_init(&pHddCtx->hdd_restart_timer,
5962 VOS_TIMER_TYPE_SW,
5963 wlan_hdd_restart_timer_cb,
5964 pHddCtx);
5965}
5966/**---------------------------------------------------------------------------
5967 *
5968 * \brief wlan_hdd_restart_deinit
5969 *
5970 * This function cleans up the resources used. An internal function.
5971 *
5972 * \param - pHddCtx
5973 *
5974 * \return - None
5975 *
5976 * --------------------------------------------------------------------------*/
5977
5978static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
5979{
5980
5981 VOS_STATUS vos_status;
5982 /* Block any further calls */
5983 atomic_set(&pHddCtx->isRestartInProgress, 1);
5984 /* Cleanup */
5985 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5986 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005987 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005988 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5989 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005990 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005991
5992}
5993
5994/**---------------------------------------------------------------------------
5995 *
5996 * \brief wlan_hdd_framework_restart
5997 *
5998 * This function uses a cfg80211 API to start a framework initiated WLAN
5999 * driver module unload/load.
6000 *
6001 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
6002 *
6003 *
6004 * \param - pHddCtx
6005 *
6006 * \return - VOS_STATUS_SUCCESS: Success
6007 * VOS_STATUS_E_EMPTY: Adapter is Empty
6008 * VOS_STATUS_E_NOMEM: No memory
6009
6010 * --------------------------------------------------------------------------*/
6011
6012static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
6013{
6014 VOS_STATUS status = VOS_STATUS_SUCCESS;
6015 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006016 int len = (sizeof (struct ieee80211_mgmt));
6017 struct ieee80211_mgmt *mgmt = NULL;
6018
6019 /* Prepare the DEAUTH managment frame with reason code */
6020 mgmt = kzalloc(len, GFP_KERNEL);
6021 if(mgmt == NULL)
6022 {
6023 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6024 "%s: memory allocation failed (%d bytes)", __func__, len);
6025 return VOS_STATUS_E_NOMEM;
6026 }
6027 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07006028
6029 /* Iterate over all adapters/devices */
6030 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6031 do
6032 {
6033 if( (status == VOS_STATUS_SUCCESS) &&
6034 pAdapterNode &&
6035 pAdapterNode->pAdapter)
6036 {
6037 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6038 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
6039 pAdapterNode->pAdapter->dev->name,
6040 pAdapterNode->pAdapter->device_mode,
6041 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006042 /*
6043 * CFG80211 event to restart the driver
6044 *
6045 * 'cfg80211_send_unprot_deauth' sends a
6046 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
6047 * of SME(Linux Kernel) state machine.
6048 *
6049 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
6050 * the driver.
6051 *
6052 */
6053
6054 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07006055 }
6056 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6057 pAdapterNode = pNext;
6058 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
6059
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07006060
6061 /* Free the allocated management frame */
6062 kfree(mgmt);
6063
Jeff Johnsone7245742012-09-05 17:12:55 -07006064 /* Retry until we unload or reach max count */
6065 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
6066 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
6067
6068 return status;
6069
6070}
6071/**---------------------------------------------------------------------------
6072 *
6073 * \brief wlan_hdd_restart_timer_cb
6074 *
6075 * Restart timer callback. An internal function.
6076 *
6077 * \param - User data:
6078 *
6079 * \return - None
6080 *
6081 * --------------------------------------------------------------------------*/
6082
6083void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
6084{
6085 hdd_context_t *pHddCtx = usrDataForCallback;
6086 wlan_hdd_framework_restart(pHddCtx);
6087 return;
6088
6089}
6090
6091
6092/**---------------------------------------------------------------------------
6093 *
6094 * \brief wlan_hdd_restart_driver
6095 *
6096 * This function sends an event to supplicant to restart the WLAN driver.
6097 *
6098 * This function is called from vos_wlanRestart.
6099 *
6100 * \param - pHddCtx
6101 *
6102 * \return - VOS_STATUS_SUCCESS: Success
6103 * VOS_STATUS_E_EMPTY: Adapter is Empty
6104 * VOS_STATUS_E_ALREADY: Request already in progress
6105
6106 * --------------------------------------------------------------------------*/
6107VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
6108{
6109 VOS_STATUS status = VOS_STATUS_SUCCESS;
6110
6111 /* A tight check to make sure reentrancy */
6112 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
6113 {
6114 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6115 "%s: WLAN restart is already in progress", __func__);
6116
6117 return VOS_STATUS_E_ALREADY;
6118 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07006119 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08006120#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07006121 wcnss_reset_intr();
6122#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006123
Jeff Johnsone7245742012-09-05 17:12:55 -07006124 return status;
6125}
6126
6127
Jeff Johnson295189b2012-06-20 16:38:30 -07006128//Register the module init/exit functions
6129module_init(hdd_module_init);
6130module_exit(hdd_module_exit);
6131
6132MODULE_LICENSE("Dual BSD/GPL");
6133MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6134MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6135
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07006136module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6137 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07006138
Jeff Johnson76052702013-04-16 13:55:05 -07006139module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07006140 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);