blob: 178a233fc31bc6ea63b7786e435dda390c8a5870 [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
147static char fwpath[BUF_LEN];
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700148#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700149static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700150#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700151
Jeff Johnsone7245742012-09-05 17:12:55 -0700152/*
153 * The rate at which the driver sends RESTART event to supplicant
154 * once the function 'vos_wlanRestart()' is called
155 *
156 */
157#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
158#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800159#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700160static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700161#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700162/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700163static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700164
165//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700166static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
167static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
168static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
169void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800170void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700171
Jeff Johnson295189b2012-06-20 16:38:30 -0700172v_U16_t hdd_select_queue(struct net_device *dev,
173 struct sk_buff *skb);
174
175#ifdef WLAN_FEATURE_PACKET_FILTERING
176static void hdd_set_multicast_list(struct net_device *dev);
177#endif
178
179void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700180int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700181
182extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800183#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
184void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
185static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
186static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
187#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700188static int hdd_netdev_notifier_call(struct notifier_block * nb,
189 unsigned long state,
190 void *ndev)
191{
192 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700193 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700194 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700195#ifdef WLAN_BTAMP_FEATURE
196 VOS_STATUS status;
197 hdd_context_t *pHddCtx;
198#endif
199
200 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700201 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700202 (strncmp(dev->name, "p2p", 3)))
203 return NOTIFY_DONE;
204
205 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700206 return NOTIFY_DONE;
207
Jeff Johnson295189b2012-06-20 16:38:30 -0700208 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700209 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700210
Jeff Johnson27cee452013-03-27 11:10:24 -0700211 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700212 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800213 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700214 VOS_ASSERT(0);
215 return NOTIFY_DONE;
216 }
217
Jeff Johnson27cee452013-03-27 11:10:24 -0700218 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
219 if (NULL == pHddCtx)
220 {
221 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
222 VOS_ASSERT(0);
223 return NOTIFY_DONE;
224 }
225
226 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
227 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700228
229 switch (state) {
230 case NETDEV_REGISTER:
231 break;
232
233 case NETDEV_UNREGISTER:
234 break;
235
236 case NETDEV_UP:
237 break;
238
239 case NETDEV_DOWN:
240 break;
241
242 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700243 if(TRUE == pAdapter->isLinkUpSvcNeeded)
244 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700245 break;
246
247 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700248 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700249 {
250 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800251 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700252 hdd_abort_mac_scan(pAdapter->pHddCtx);
253 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800254 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700255 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
256 if(!result)
257 {
258 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800259 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700260 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700261 }
262 }
263 else
264 {
265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700266 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700267 }
268#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700269 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700270 status = WLANBAP_StopAmp();
271 if(VOS_STATUS_SUCCESS != status )
272 {
273 pHddCtx->isAmpAllowed = VOS_TRUE;
274 hddLog(VOS_TRACE_LEVEL_FATAL,
275 "%s: Failed to stop AMP", __func__);
276 }
277 else
278 {
279 //a state m/c implementation in PAL is TBD to avoid this delay
280 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700281 if ( pHddCtx->isAmpAllowed )
282 {
283 WLANBAP_DeregisterFromHCI();
284 pHddCtx->isAmpAllowed = VOS_FALSE;
285 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700286 }
287#endif //WLAN_BTAMP_FEATURE
288 break;
289
290 default:
291 break;
292 }
293
294 return NOTIFY_DONE;
295}
296
297struct notifier_block hdd_netdev_notifier = {
298 .notifier_call = hdd_netdev_notifier_call,
299};
300
301/*---------------------------------------------------------------------------
302 * Function definitions
303 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700304void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
305void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700306//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700307static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700308#ifndef MODULE
309/* current con_mode - used only for statically linked driver
310 * con_mode is changed by userspace to indicate a mode change which will
311 * result in calling the module exit and init functions. The module
312 * exit function will clean up based on the value of con_mode prior to it
313 * being changed by userspace. So curr_con_mode records the current con_mode
314 * for exit when con_mode becomes the next mode for init
315 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700316static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700317#endif
318
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800319/**---------------------------------------------------------------------------
320
321 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
322
323 Called immediately after the cfg.ini is read in order to configure
324 the desired trace levels.
325
326 \param - moduleId - module whose trace level is being configured
327 \param - bitmask - bitmask of log levels to be enabled
328
329 \return - void
330
331 --------------------------------------------------------------------------*/
332static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
333{
334 wpt_tracelevel level;
335
336 /* if the bitmask is the default value, then a bitmask was not
337 specified in cfg.ini, so leave the logging level alone (it
338 will remain at the "compiled in" default value) */
339 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
340 {
341 return;
342 }
343
344 /* a mask was specified. start by disabling all logging */
345 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
346
347 /* now cycle through the bitmask until all "set" bits are serviced */
348 level = VOS_TRACE_LEVEL_FATAL;
349 while (0 != bitmask)
350 {
351 if (bitmask & 1)
352 {
353 vos_trace_setValue(moduleId, level, 1);
354 }
355 level++;
356 bitmask >>= 1;
357 }
358}
359
360
Jeff Johnson295189b2012-06-20 16:38:30 -0700361/**---------------------------------------------------------------------------
362
363 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
364
365 Called immediately after the cfg.ini is read in order to configure
366 the desired trace levels in the WDI.
367
368 \param - moduleId - module whose trace level is being configured
369 \param - bitmask - bitmask of log levels to be enabled
370
371 \return - void
372
373 --------------------------------------------------------------------------*/
374static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
375{
376 wpt_tracelevel level;
377
378 /* if the bitmask is the default value, then a bitmask was not
379 specified in cfg.ini, so leave the logging level alone (it
380 will remain at the "compiled in" default value) */
381 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
382 {
383 return;
384 }
385
386 /* a mask was specified. start by disabling all logging */
387 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
388
389 /* now cycle through the bitmask until all "set" bits are serviced */
390 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
391 while (0 != bitmask)
392 {
393 if (bitmask & 1)
394 {
395 wpalTraceSetLevel(moduleId, level, 1);
396 }
397 level++;
398 bitmask >>= 1;
399 }
400}
Jeff Johnson295189b2012-06-20 16:38:30 -0700401
402int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
403{
404 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
405 hdd_priv_data_t priv_data;
406 tANI_U8 *command = NULL;
407 int ret = 0;
408
409 if (NULL == pAdapter)
410 {
411 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700412 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700413 ret = -ENODEV;
414 goto exit;
415 }
416
Jeff Johnsone7245742012-09-05 17:12:55 -0700417 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700418 {
419 ret = -EINVAL;
420 goto exit;
421 }
422
423 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
424 {
425 ret = -EFAULT;
426 goto exit;
427 }
428
429 command = kmalloc(priv_data.total_len, GFP_KERNEL);
430 if (!command)
431 {
432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700433 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700434 ret = -ENOMEM;
435 goto exit;
436 }
437
438 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
439 {
440 ret = -EFAULT;
441 goto exit;
442 }
443
444 if ((SIOCDEVPRIVATE + 1) == cmd)
445 {
446 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
447
448 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700449 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700450
451 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
452 {
453 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
454 sizeof(tSirMacAddr)))
455 {
456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700457 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700458 ret = -EFAULT;
459 }
460 }
Amar Singhal0974e402013-02-12 14:27:46 -0800461 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700462 {
Amar Singhal0974e402013-02-12 14:27:46 -0800463 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700464 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800465
Jeff Johnson295189b2012-06-20 16:38:30 -0700466 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800467
468 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700469 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700470 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800471 "%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 -0700472 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800473 ret = hdd_setBand_helper(dev, ptr);
474 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700475 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
476 {
477 char *country_code;
478
479 country_code = command + 8;
480 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
481 pAdapter, pHddCtx->pvosContext);
482 if( 0 != ret )
483 {
484 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
485 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
486
487 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700488 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800489#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
490 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
491 {
492 tANI_U8 *value = command;
493 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
494 tANI_U8 revision = 0;
495 eHalStatus status = eHAL_STATUS_SUCCESS;
496 v_REGDOMAIN_t regId;
497
498 status = hdd_parse_countryrev(value, countryCode, &revision);
499 if (eHAL_STATUS_SUCCESS != status)
500 {
501 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
502 "%s: Failed to parse country revision information", __func__);
503 ret = -EINVAL;
504 goto exit;
505 }
506
507 /* Validate country code */
508 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
509 if (eHAL_STATUS_SUCCESS != status)
510 {
511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
512 "%s: Invalid country code %s", __func__, countryCode);
513 ret = -EINVAL;
514 goto exit;
515 }
516
517 /* Validate revision */
518 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
519 {
520 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
521 "%s: Invalid revision %d", __func__, revision);
522 ret = -EINVAL;
523 goto exit;
524 }
525
526 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
527 pAdapter, pHddCtx->pvosContext);
528 if (0 != ret)
529 {
530 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
531 "%s: SME Change Country code fail ret=%d", __func__, ret);
532 ret = -EINVAL;
533 goto exit;
534 }
535
536 if (0 == strncmp(countryCode, "KR", 2))
537 {
538 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
539 revision);
540 if (eHAL_STATUS_SUCCESS != status)
541 {
542 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
543 "%s: Failed to build valid channel list", __func__);
544 ret = -EINVAL;
545 goto exit;
546 }
547 }
548 }
549#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700550 /*
551 command should be a string having format
552 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
553 */
Amar Singhal0974e402013-02-12 14:27:46 -0800554 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700555 {
Amar Singhal0974e402013-02-12 14:27:46 -0800556 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700557
558 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700559 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700560
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800561 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700562 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800563 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
564 {
565 int suspend = 0;
566 tANI_U8 *ptr = (tANI_U8*)command + 15;
567
568 suspend = *ptr - '0';
569 hdd_set_wlan_suspend_mode(suspend);
570 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800571#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
572 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
573 {
574 tANI_U8 *value = command;
575 int rssi = 0;
576 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
577 eHalStatus status = eHAL_STATUS_SUCCESS;
578
579 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
580 value = value + 15;
581
582 sscanf(value, "%d", &rssi);
583 lookUpThreshold = abs(rssi);
584 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
585 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
586 {
587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
588 "Neighbor lookup threshold value %d is out of range"
589 " (Min: %d Max: %d)", lookUpThreshold,
590 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
591 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
592 ret = -EINVAL;
593 goto exit;
594 }
595
596 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
597 "%s: Received Command to Set Roam trigger"
598 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
599
600 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
601 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
602 if (eHAL_STATUS_SUCCESS != status)
603 {
604 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
605 "%s: Failed to set roam trigger, try again", __func__);
606 ret = -EPERM;
607 goto exit;
608 }
609
610 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
611 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
612 }
613 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
614 {
615 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
616 int rssi = (-1) * lookUpThreshold;
617 char extra[32];
618 tANI_U8 len = 0;
619
620 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
621 if (copy_to_user(priv_data.buf, &extra, len + 1))
622 {
623 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
624 "%s: failed to copy data to user buffer", __func__);
625 ret = -EFAULT;
626 goto exit;
627 }
628 }
629 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
630 {
631 tANI_U8 *value = command;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700632 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800633 /* input refresh period is in terms of seconds */
634 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
635 value = value + 18;
636 /* Convert the value from ascii to integer */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700637 ret = kstrtou16(value, 10, &neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800638 if (ret < 0)
639 {
640 /* If the input value is greater than max value of datatype, then also
641 kstrtou16 fails */
642 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
643 "%s: kstrtou16 failed ",
644 "Input value may be out of range[%d - %d]",
645 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700646 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
647 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800648 ret = -EINVAL;
649 goto exit;
650 }
651
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700652 neighborEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod * 1000;
653 if ((neighborEmptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) ||
654 (neighborEmptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX))
Srinivas Girigowdade697412013-02-14 16:31:48 -0800655 {
656 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700657 "Neighbor empty scan results refresh period value %d is out of range"
658 " (Min: %d Max: %d)", neighborEmptyScanRefreshPeriod/1000,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -0700659 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
660 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -0800661 ret = -EINVAL;
662 goto exit;
663 }
664
665 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
666 "%s: Received Command to Set roam scan period"
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700667 " (Empty Scan refresh period) = %d", __func__, neighborEmptyScanRefreshPeriod/1000);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800668
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700669 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
670 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800671 }
672 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
673 {
674 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
675 char extra[32];
676 tANI_U8 len = 0;
677
678 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
679 /* Returned value is in units of seconds */
680 if (copy_to_user(priv_data.buf, &extra, len + 1))
681 {
682 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
683 "%s: failed to copy data to user buffer", __func__);
684 ret = -EFAULT;
685 goto exit;
686 }
687 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700688 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
689 {
690 tANI_U8 *value = command;
691 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
692 /* input refresh period is in terms of seconds */
693 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
694 value = value + 25;
695 /* Convert the value from ascii to integer */
696 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
697 if (ret < 0)
698 {
699 /* If the input value is greater than max value of datatype, then also
700 kstrtou16 fails */
701 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
702 "%s: kstrtou16 failed ",
703 "Input value may be out of range[%d - %d]",
704 __func__,
705 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
706 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
707 ret = -EINVAL;
708 goto exit;
709 }
710
711 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
712 if ((neighborScanRefreshPeriod < CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN) ||
713 (neighborScanRefreshPeriod > CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX))
714 {
715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
716 "Neighbor scan results refresh period value %d is out of range"
717 " (Min: %d Max: %d)", neighborScanRefreshPeriod/1000,
718 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
719 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
720 ret = -EINVAL;
721 goto exit;
722 }
723
724 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
725 "%s: Received Command to Set roam scan refresh period"
726 " (Scan refresh period) = %d", __func__, neighborScanRefreshPeriod/1000);
727
728 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
729 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
730 }
731 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
732 {
733 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
734 char extra[32];
735 tANI_U8 len = 0;
736
737 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANREFRESHPERIOD", (value/1000));
738 /* Returned value is in units of seconds */
739 if (copy_to_user(priv_data.buf, &extra, len + 1))
740 {
741 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
742 "%s: failed to copy data to user buffer", __func__);
743 ret = -EFAULT;
744 goto exit;
745 }
746 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800747#endif
748#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
749 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
750 {
751 tANI_U8 *value = command;
752 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
753
754 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
755 value = value + 13;
756 /* Convert the value from ascii to integer */
757 ret = kstrtou8(value, 10, &roamRssiDiff);
758 if (ret < 0)
759 {
760 /* If the input value is greater than max value of datatype, then also
761 kstrtou8 fails */
762 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
763 "%s: kstrtou8 failed range [%d - %d]", __func__,
764 CFG_ROAM_RSSI_DIFF_MIN,
765 CFG_ROAM_RSSI_DIFF_MAX);
766 ret = -EINVAL;
767 goto exit;
768 }
769
770 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
771 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
772 {
773 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
774 "Roam rssi diff value %d is out of range"
775 " (Min: %d Max: %d)", roamRssiDiff,
776 CFG_ROAM_RSSI_DIFF_MIN,
777 CFG_ROAM_RSSI_DIFF_MAX);
778 ret = -EINVAL;
779 goto exit;
780 }
781
782 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
783 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
784
785 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
786 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
787 }
788 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
789 {
790 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
791 char extra[32];
792 tANI_U8 len = 0;
793
794 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
795 if (copy_to_user(priv_data.buf, &extra, len + 1))
796 {
797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
798 "%s: failed to copy data to user buffer", __func__);
799 ret = -EFAULT;
800 goto exit;
801 }
802 }
803#endif
804#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
805 else if (strncmp(command, "GETBAND", 7) == 0)
806 {
807 int band = -1;
808 char extra[32];
809 tANI_U8 len = 0;
810 hdd_getBand_helper(pHddCtx, &band);
811
812 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
813 if (copy_to_user(priv_data.buf, &extra, len + 1))
814 {
815 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
816 "%s: failed to copy data to user buffer", __func__);
817 ret = -EFAULT;
818 goto exit;
819 }
820 }
821 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
822 {
823 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
824 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
825 tANI_U8 revision = 0;
826 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
827 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
828 char extra[32] = {0};
829 tANI_U8 len = 0;
830
831 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
832 {
833 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
834 "%s: failed to get country code", __func__);
835 ret = -EFAULT;
836 goto exit;
837 }
838 pBuf[uBufLen] = '\0';
839 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
840
841 if (0 == strncmp(pBuf, "KR", 2))
842 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
843 else
844 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
845
846 if (copy_to_user(priv_data.buf, &extra, len + 1))
847 {
848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
849 "%s: failed to copy data to user buffer", __func__);
850 ret = -EFAULT;
851 goto exit;
852 }
853 }
854 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
855 {
856 tANI_U8 *value = command;
857 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
858 tANI_U8 numChannels = 0;
859 eHalStatus status = eHAL_STATUS_SUCCESS;
860
861 status = hdd_parse_channellist(value, ChannelList, &numChannels);
862 if (eHAL_STATUS_SUCCESS != status)
863 {
864 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
865 "%s: Failed to parse channel list information", __func__);
866 ret = -EINVAL;
867 goto exit;
868 }
869
870 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
871 {
872 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
873 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
874 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
875 ret = -EINVAL;
876 goto exit;
877 }
878 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
879 numChannels);
880 if (eHAL_STATUS_SUCCESS != status)
881 {
882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
883 "%s: Failed to update channel list information", __func__);
884 ret = -EINVAL;
885 goto exit;
886 }
887 }
888 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
889 {
890 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
891 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -0700892 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800893 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -0700894 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800895
896 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
897 ChannelList, &numChannels ))
898 {
899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
900 "%s: failed to get roam scan channel list", __func__);
901 ret = -EFAULT;
902 goto exit;
903 }
904 /* output channel list is of the format
905 [Number of roam scan channels][Channel1][Channel2]... */
906 /* copy the number of channels in the 0th index */
907 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
908 for (j = 0; (j < numChannels); j++)
909 {
910 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
911 }
912
913 if (copy_to_user(priv_data.buf, &extra, len + 1))
914 {
915 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
916 "%s: failed to copy data to user buffer", __func__);
917 ret = -EFAULT;
918 goto exit;
919 }
920 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700921 else if (strncmp(command, "GETCCXMODE", 10) == 0)
922 {
923 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
924 char extra[32];
925 tANI_U8 len = 0;
926
927 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
928 if (copy_to_user(priv_data.buf, &extra, len + 1))
929 {
930 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
931 "%s: failed to copy data to user buffer", __func__);
932 ret = -EFAULT;
933 goto exit;
934 }
935 }
936 else if (strncmp(command, "GETOKCMODE", 10) == 0)
937 {
938 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
939 char extra[32];
940 tANI_U8 len = 0;
941
942 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
943 if (copy_to_user(priv_data.buf, &extra, len + 1))
944 {
945 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
946 "%s: failed to copy data to user buffer", __func__);
947 ret = -EFAULT;
948 goto exit;
949 }
950 }
951 else if (strncmp(command, "GETFASTROAM", 10) == 0)
952 {
953 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
954 char extra[32];
955 tANI_U8 len = 0;
956
957 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
958 if (copy_to_user(priv_data.buf, &extra, len + 1))
959 {
960 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
961 "%s: failed to copy data to user buffer", __func__);
962 ret = -EFAULT;
963 goto exit;
964 }
965 }
966 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
967 {
968 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
969 char extra[32];
970 tANI_U8 len = 0;
971
972 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
973 if (copy_to_user(priv_data.buf, &extra, len + 1))
974 {
975 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
976 "%s: failed to copy data to user buffer", __func__);
977 ret = -EFAULT;
978 goto exit;
979 }
980 }
981 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
982 {
983 tANI_U8 *value = command;
984 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
985
986 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
987 value = value + 26;
988 /* Convert the value from ascii to integer */
989 ret = kstrtou8(value, 10, &minTime);
990 if (ret < 0)
991 {
992 /* If the input value is greater than max value of datatype, then also
993 kstrtou8 fails */
994 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
995 "%s: kstrtou8 failed range [%d - %d]", __func__,
996 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
997 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
998 ret = -EINVAL;
999 goto exit;
1000 }
1001
1002 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1003 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1004 {
1005 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1006 "scan min channel time value %d is out of range"
1007 " (Min: %d Max: %d)", minTime,
1008 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1009 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1010 ret = -EINVAL;
1011 goto exit;
1012 }
1013
1014 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1015 "%s: Received Command to change channel min time = %d", __func__, minTime);
1016
1017 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1018 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1019 }
1020 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1021 {
1022 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1023 char extra[32];
1024 tANI_U8 len = 0;
1025
1026 /* value is interms of msec */
1027 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1028 if (copy_to_user(priv_data.buf, &extra, len + 1))
1029 {
1030 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1031 "%s: failed to copy data to user buffer", __func__);
1032 ret = -EFAULT;
1033 goto exit;
1034 }
1035 }
1036 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1037 {
1038 tANI_U8 *value = command;
1039 tANI_U8 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
1040
1041 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1042 value = value + 19;
1043 /* Convert the value from ascii to integer */
1044 ret = kstrtou8(value, 10, &maxTime);
1045 if (ret < 0)
1046 {
1047 /* If the input value is greater than max value of datatype, then also
1048 kstrtou8 fails */
1049 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1050 "%s: kstrtou8 failed range [%d - %d]", __func__,
1051 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1052 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1053 ret = -EINVAL;
1054 goto exit;
1055 }
1056
1057 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1058 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1059 {
1060 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1061 "lfr mode value %d is out of range"
1062 " (Min: %d Max: %d)", maxTime,
1063 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1064 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1065 ret = -EINVAL;
1066 goto exit;
1067 }
1068
1069 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1070 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1071
1072 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
1073 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1074 }
1075 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1076 {
1077 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1078 char extra[32];
1079 tANI_U8 len = 0;
1080
1081 /* value is interms of msec */
1082 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1083 if (copy_to_user(priv_data.buf, &extra, len + 1))
1084 {
1085 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1086 "%s: failed to copy data to user buffer", __func__);
1087 ret = -EFAULT;
1088 goto exit;
1089 }
1090 }
1091 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1092 {
1093 tANI_U8 *value = command;
1094 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1095
1096 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1097 value = value + 16;
1098 /* Convert the value from ascii to integer */
1099 ret = kstrtou16(value, 10, &val);
1100 if (ret < 0)
1101 {
1102 /* If the input value is greater than max value of datatype, then also
1103 kstrtou16 fails */
1104 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1105 "%s: kstrtou16 failed range [%d - %d]", __func__,
1106 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1107 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1108 ret = -EINVAL;
1109 goto exit;
1110 }
1111
1112 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1113 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1114 {
1115 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1116 "scan home time value %d is out of range"
1117 " (Min: %d Max: %d)", val,
1118 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1119 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1120 ret = -EINVAL;
1121 goto exit;
1122 }
1123
1124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1125 "%s: Received Command to change scan home time = %d", __func__, val);
1126
1127 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1128 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1129 }
1130 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1131 {
1132 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1133 char extra[32];
1134 tANI_U8 len = 0;
1135
1136 /* value is interms of msec */
1137 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1138 if (copy_to_user(priv_data.buf, &extra, len + 1))
1139 {
1140 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1141 "%s: failed to copy data to user buffer", __func__);
1142 ret = -EFAULT;
1143 goto exit;
1144 }
1145 }
1146 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1147 {
1148 tANI_U8 *value = command;
1149 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1150
1151 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1152 value = value + 17;
1153 /* Convert the value from ascii to integer */
1154 ret = kstrtou8(value, 10, &val);
1155 if (ret < 0)
1156 {
1157 /* If the input value is greater than max value of datatype, then also
1158 kstrtou8 fails */
1159 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1160 "%s: kstrtou8 failed range [%d - %d]", __func__,
1161 CFG_ROAM_INTRA_BAND_MIN,
1162 CFG_ROAM_INTRA_BAND_MAX);
1163 ret = -EINVAL;
1164 goto exit;
1165 }
1166
1167 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1168 (val > CFG_ROAM_INTRA_BAND_MAX))
1169 {
1170 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1171 "intra band mode value %d is out of range"
1172 " (Min: %d Max: %d)", val,
1173 CFG_ROAM_INTRA_BAND_MIN,
1174 CFG_ROAM_INTRA_BAND_MAX);
1175 ret = -EINVAL;
1176 goto exit;
1177 }
1178
1179 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1180 "%s: Received Command to change intra band = %d", __func__, val);
1181
1182 pHddCtx->cfg_ini->nRoamIntraBand = val;
1183 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1184 }
1185 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1186 {
1187 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1188 char extra[32];
1189 tANI_U8 len = 0;
1190
1191 /* value is interms of msec */
1192 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1193 if (copy_to_user(priv_data.buf, &extra, len + 1))
1194 {
1195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1196 "%s: failed to copy data to user buffer", __func__);
1197 ret = -EFAULT;
1198 goto exit;
1199 }
1200 }
1201
1202#endif
1203#ifdef FEATURE_WLAN_LFR
1204 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1205 {
1206 tANI_U8 *value = command;
1207 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1208
1209 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1210 value = value + 12;
1211 /* Convert the value from ascii to integer */
1212 ret = kstrtou8(value, 10, &lfrMode);
1213 if (ret < 0)
1214 {
1215 /* If the input value is greater than max value of datatype, then also
1216 kstrtou8 fails */
1217 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1218 "%s: kstrtou8 failed range [%d - %d]", __func__,
1219 CFG_LFR_FEATURE_ENABLED_MIN,
1220 CFG_LFR_FEATURE_ENABLED_MAX);
1221 ret = -EINVAL;
1222 goto exit;
1223 }
1224
1225 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1226 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1227 {
1228 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1229 "lfr mode value %d is out of range"
1230 " (Min: %d Max: %d)", lfrMode,
1231 CFG_LFR_FEATURE_ENABLED_MIN,
1232 CFG_LFR_FEATURE_ENABLED_MAX);
1233 ret = -EINVAL;
1234 goto exit;
1235 }
1236
1237 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1238 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1239
1240 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1241 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1242 }
1243#endif
1244#ifdef WLAN_FEATURE_VOWIFI_11R
1245 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1246 {
1247 tANI_U8 *value = command;
1248 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1249
1250 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1251 value = value + 18;
1252 /* Convert the value from ascii to integer */
1253 ret = kstrtou8(value, 10, &ft);
1254 if (ret < 0)
1255 {
1256 /* If the input value is greater than max value of datatype, then also
1257 kstrtou8 fails */
1258 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1259 "%s: kstrtou8 failed range [%d - %d]", __func__,
1260 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1261 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1262 ret = -EINVAL;
1263 goto exit;
1264 }
1265
1266 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1267 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1268 {
1269 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1270 "ft mode value %d is out of range"
1271 " (Min: %d Max: %d)", ft,
1272 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1273 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1274 ret = -EINVAL;
1275 goto exit;
1276 }
1277
1278 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1279 "%s: Received Command to change ft mode = %d", __func__, ft);
1280
1281 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1282 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1283 }
1284#endif
1285#ifdef FEATURE_WLAN_CCX
1286 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1287 {
1288 tANI_U8 *value = command;
1289 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1290
1291 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1292 value = value + 11;
1293 /* Convert the value from ascii to integer */
1294 ret = kstrtou8(value, 10, &ccxMode);
1295 if (ret < 0)
1296 {
1297 /* If the input value is greater than max value of datatype, then also
1298 kstrtou8 fails */
1299 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1300 "%s: kstrtou8 failed range [%d - %d]", __func__,
1301 CFG_CCX_FEATURE_ENABLED_MIN,
1302 CFG_CCX_FEATURE_ENABLED_MAX);
1303 ret = -EINVAL;
1304 goto exit;
1305 }
1306
1307 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1308 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1309 {
1310 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1311 "Ccx mode value %d is out of range"
1312 " (Min: %d Max: %d)", ccxMode,
1313 CFG_CCX_FEATURE_ENABLED_MIN,
1314 CFG_CCX_FEATURE_ENABLED_MAX);
1315 ret = -EINVAL;
1316 goto exit;
1317 }
1318
1319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1320 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1321
1322 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1323 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1324 }
1325#endif
1326#ifdef FEATURE_WLAN_OKC
1327 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1328 {
1329 tANI_U8 *value = command;
1330 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1331
1332 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1333 value = value + 11;
1334 /* Convert the value from ascii to integer */
1335 ret = kstrtou8(value, 10, &okcMode);
1336 if (ret < 0)
1337 {
1338 /* If the input value is greater than max value of datatype, then also
1339 kstrtou8 fails */
1340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1341 "%s: kstrtou8 failed range [%d - %d]", __func__,
1342 CFG_OKC_FEATURE_ENABLED_MIN,
1343 CFG_OKC_FEATURE_ENABLED_MAX);
1344 ret = -EINVAL;
1345 goto exit;
1346 }
1347
1348 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1349 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1350 {
1351 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1352 "Okc mode value %d is out of range"
1353 " (Min: %d Max: %d)", okcMode,
1354 CFG_OKC_FEATURE_ENABLED_MIN,
1355 CFG_OKC_FEATURE_ENABLED_MAX);
1356 ret = -EINVAL;
1357 goto exit;
1358 }
1359
1360 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1361 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1362
1363 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1364 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001365#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001366 else {
1367 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1368 __func__, command);
1369 }
1370
Jeff Johnson295189b2012-06-20 16:38:30 -07001371 }
1372exit:
1373 if (command)
1374 {
1375 kfree(command);
1376 }
1377 return ret;
1378}
1379
Srinivas Girigowdade697412013-02-14 16:31:48 -08001380#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1381void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
1382{
1383 eCsrBand band = -1;
1384 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
1385 switch (band)
1386 {
1387 case eCSR_BAND_ALL:
1388 *pBand = WLAN_HDD_UI_BAND_AUTO;
1389 break;
1390
1391 case eCSR_BAND_24:
1392 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
1393 break;
1394
1395 case eCSR_BAND_5G:
1396 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
1397 break;
1398
1399 default:
1400 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
1401 *pBand = -1;
1402 break;
1403 }
1404}
1405
1406/**---------------------------------------------------------------------------
1407
1408 \brief hdd_parse_countryrev() - HDD Parse country code revision
1409
1410 This function parses the country code revision passed in the format
1411 SETCOUNTRYREV<space><Country code><space>revision
1412
1413 \param - pValue Pointer to input country code revision
1414 \param - pCountryCode Pointer to local output array to record country code
1415 \param - pRevision Pointer to store revision integer number
1416
1417 \return - 0 for success non-zero for failure
1418
1419 --------------------------------------------------------------------------*/
1420VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
1421{
1422 tANI_U8 *inPtr = pValue;
1423 int tempInt;
1424
1425 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1426 /*no argument after the command*/
1427 if (NULL == inPtr)
1428 {
1429 return -EINVAL;
1430 }
1431
1432 /*no space after the command*/
1433 else if (SPACE_ASCII_VALUE != *inPtr)
1434 {
1435 return -EINVAL;
1436 }
1437
1438 /*removing empty spaces*/
1439 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1440
1441 /*no argument followed by spaces*/
1442 if ('\0' == *inPtr)
1443 {
1444 return -EINVAL;
1445 }
1446
1447 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07001448 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001449
1450 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1451 "Country code is : %s", pCountryCode);
1452
1453 /*inPtr pointing to the beginning of first space after country code */
1454 inPtr = strpbrk( inPtr, " " );
1455 /*no revision number after the country code argument */
1456 if (NULL == inPtr)
1457 {
1458 return -EINVAL;
1459 }
1460
1461 inPtr++;
1462
1463 /*removing empty space*/
1464 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1465
1466 /*no channel list after the number of channels argument and spaces*/
1467 if (0 == strncmp(pCountryCode, "KR", 2))
1468 {
1469 if ('\0' == *inPtr)
1470 {
1471 return -EINVAL;
1472 }
1473
1474 sscanf(inPtr, "%d", &tempInt);
1475 *pRevision = tempInt;
1476 }
1477 else
1478 {
1479 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1480 "Revision input is required only for Country KR");
1481 return -EINVAL;
1482 }
1483 return VOS_STATUS_SUCCESS;
1484}
1485
1486/**---------------------------------------------------------------------------
1487
1488 \brief hdd_parse_channellist() - HDD Parse channel list
1489
1490 This function parses the channel list passed in the format
1491 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001492 if the Number of channels (N) does not match with the actual number of channels passed
1493 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
1494 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
1495 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
1496 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08001497
1498 \param - pValue Pointer to input channel list
1499 \param - ChannelList Pointer to local output array to record channel list
1500 \param - pNumChannels Pointer to number of roam scan channels
1501
1502 \return - 0 for success non-zero for failure
1503
1504 --------------------------------------------------------------------------*/
1505VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
1506{
1507 tANI_U8 *inPtr = pValue;
1508 int tempInt;
1509 int j = 0;
1510 int v = 0;
1511 char buf[32];
1512
1513 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1514 /*no argument after the command*/
1515 if (NULL == inPtr)
1516 {
1517 return -EINVAL;
1518 }
1519
1520 /*no space after the command*/
1521 else if (SPACE_ASCII_VALUE != *inPtr)
1522 {
1523 return -EINVAL;
1524 }
1525
1526 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001527 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001528
1529 /*no argument followed by spaces*/
1530 if ('\0' == *inPtr)
1531 {
1532 return -EINVAL;
1533 }
1534
1535 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07001536 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001537 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001538 if ((v < 0) ||
1539 (tempInt <= 0) ||
1540 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
1541 {
1542 return -EINVAL;
1543 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001544
1545 *pNumChannels = tempInt;
1546
1547 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1548 "Number of channels are: %d", *pNumChannels);
1549
1550 for (j = 0; j < (*pNumChannels); j++)
1551 {
1552 /*inPtr pointing to the beginning of first space after number of channels*/
1553 inPtr = strpbrk( inPtr, " " );
1554 /*no channel list after the number of channels argument*/
1555 if (NULL == inPtr)
1556 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001557 if (0 != j)
1558 {
1559 *pNumChannels = j;
1560 return VOS_STATUS_SUCCESS;
1561 }
1562 else
1563 {
1564 return -EINVAL;
1565 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001566 }
1567
1568 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001569 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001570
1571 /*no channel list after the number of channels argument and spaces*/
1572 if ( '\0' == *inPtr )
1573 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001574 if (0 != j)
1575 {
1576 *pNumChannels = j;
1577 return VOS_STATUS_SUCCESS;
1578 }
1579 else
1580 {
1581 return -EINVAL;
1582 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001583 }
1584
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001585 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001586 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001587 if ((v < 0) ||
1588 (tempInt <= 0) ||
1589 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
1590 {
1591 return -EINVAL;
1592 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001593 pChannelList[j] = tempInt;
1594
1595 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1596 "Channel %d added to preferred channel list",
1597 pChannelList[j] );
1598 }
1599
Srinivas Girigowdade697412013-02-14 16:31:48 -08001600 return VOS_STATUS_SUCCESS;
1601}
1602
1603#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001604/**---------------------------------------------------------------------------
1605
1606 \brief hdd_open() - HDD Open function
1607
1608 This is called in response to ifconfig up
1609
1610 \param - dev Pointer to net_device structure
1611
1612 \return - 0 for success non-zero for failure
1613
1614 --------------------------------------------------------------------------*/
1615int hdd_open (struct net_device *dev)
1616{
1617 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1618 hdd_context_t *pHddCtx;
1619 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1620 VOS_STATUS status;
1621 v_BOOL_t in_standby = TRUE;
1622
1623 if (NULL == pAdapter)
1624 {
1625 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001626 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001627 return -ENODEV;
1628 }
1629
1630 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1631 if (NULL == pHddCtx)
1632 {
1633 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001634 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001635 return -ENODEV;
1636 }
1637
1638 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1639 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1640 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07001641 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
1642 {
1643 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
1644 __func__, pAdapter->device_mode);
1645 in_standby = FALSE;
1646 break;
1647 }
1648 else
1649 {
1650 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1651 pAdapterNode = pNext;
1652 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001653 }
1654
1655 if (TRUE == in_standby)
1656 {
1657 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
1658 {
1659 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
1660 "wlan out of power save", __func__);
1661 return -EINVAL;
1662 }
1663 }
1664
Jeff Johnson6a81ca42013-04-05 10:37:08 -07001665 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07001666 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1667 {
1668 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001669 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001670 /* Enable TX queues only when we are connected */
1671 netif_tx_start_all_queues(dev);
1672 }
1673
1674 return 0;
1675}
1676
1677int hdd_mon_open (struct net_device *dev)
1678{
1679 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1680
1681 if(pAdapter == NULL) {
1682 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001683 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001684 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001685 }
1686
1687 netif_start_queue(dev);
1688
1689 return 0;
1690}
1691/**---------------------------------------------------------------------------
1692
1693 \brief hdd_stop() - HDD stop function
1694
1695 This is called in response to ifconfig down
1696
1697 \param - dev Pointer to net_device structure
1698
1699 \return - 0 for success non-zero for failure
1700
1701 --------------------------------------------------------------------------*/
1702
1703int hdd_stop (struct net_device *dev)
1704{
1705 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1706 hdd_context_t *pHddCtx;
1707 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1708 VOS_STATUS status;
1709 v_BOOL_t enter_standby = TRUE;
1710
1711 ENTER();
1712
1713 if (NULL == pAdapter)
1714 {
1715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001716 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001717 return -ENODEV;
1718 }
1719
1720 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1721 if (NULL == pHddCtx)
1722 {
1723 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001724 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001725 return -ENODEV;
1726 }
1727
Jeff Johnson6a81ca42013-04-05 10:37:08 -07001728 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07001729 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
1730 netif_tx_disable(pAdapter->dev);
1731 netif_carrier_off(pAdapter->dev);
1732
1733
1734 /* SoftAP ifaces should never go in power save mode
1735 making sure same here. */
1736 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
1737 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001738 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001739 )
1740 {
1741 /* SoftAP mode, so return from here */
1742 EXIT();
1743 return 0;
1744 }
1745
1746 /* Find if any iface is up then
1747 if any iface is up then can't put device to sleep/ power save mode. */
1748 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1749 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1750 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07001751 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
1752 {
1753 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
1754 "put device to sleep", __func__, pAdapter->device_mode);
1755 enter_standby = FALSE;
1756 break;
1757 }
1758 else
1759 {
1760 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1761 pAdapterNode = pNext;
1762 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001763 }
1764
1765 if (TRUE == enter_standby)
1766 {
1767 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
1768 "entering standby", __func__);
1769 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
1770 {
1771 /*log and return success*/
1772 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
1773 "wlan in power save", __func__);
1774 }
1775 }
1776
1777 EXIT();
1778 return 0;
1779}
1780
1781/**---------------------------------------------------------------------------
1782
1783 \brief hdd_uninit() - HDD uninit function
1784
1785 This is called during the netdev unregister to uninitialize all data
1786associated with the device
1787
1788 \param - dev Pointer to net_device structure
1789
1790 \return - void
1791
1792 --------------------------------------------------------------------------*/
1793static void hdd_uninit (struct net_device *dev)
1794{
1795 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1796
1797 ENTER();
1798
1799 do
1800 {
1801 if (NULL == pAdapter)
1802 {
1803 hddLog(VOS_TRACE_LEVEL_FATAL,
1804 "%s: NULL pAdapter", __func__);
1805 break;
1806 }
1807
1808 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1809 {
1810 hddLog(VOS_TRACE_LEVEL_FATAL,
1811 "%s: Invalid magic", __func__);
1812 break;
1813 }
1814
1815 if (NULL == pAdapter->pHddCtx)
1816 {
1817 hddLog(VOS_TRACE_LEVEL_FATAL,
1818 "%s: NULL pHddCtx", __func__);
1819 break;
1820 }
1821
1822 if (dev != pAdapter->dev)
1823 {
1824 hddLog(VOS_TRACE_LEVEL_FATAL,
1825 "%s: Invalid device reference", __func__);
1826 /* we haven't validated all cases so let this go for now */
1827 }
1828
1829 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
1830
1831 /* after uninit our adapter structure will no longer be valid */
1832 pAdapter->dev = NULL;
1833 pAdapter->magic = 0;
1834 } while (0);
1835
1836 EXIT();
1837}
1838
1839/**---------------------------------------------------------------------------
1840
1841 \brief hdd_release_firmware() -
1842
1843 This function calls the release firmware API to free the firmware buffer.
1844
1845 \param - pFileName Pointer to the File Name.
1846 pCtx - Pointer to the adapter .
1847
1848
1849 \return - 0 for success, non zero for failure
1850
1851 --------------------------------------------------------------------------*/
1852
1853VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
1854{
1855 VOS_STATUS status = VOS_STATUS_SUCCESS;
1856 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1857 ENTER();
1858
1859
1860 if (!strcmp(WLAN_FW_FILE, pFileName)) {
1861
1862 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
1863
1864 if(pHddCtx->fw) {
1865 release_firmware(pHddCtx->fw);
1866 pHddCtx->fw = NULL;
1867 }
1868 else
1869 status = VOS_STATUS_E_FAILURE;
1870 }
1871 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
1872 if(pHddCtx->nv) {
1873 release_firmware(pHddCtx->nv);
1874 pHddCtx->nv = NULL;
1875 }
1876 else
1877 status = VOS_STATUS_E_FAILURE;
1878
1879 }
1880
1881 EXIT();
1882 return status;
1883}
1884
1885/**---------------------------------------------------------------------------
1886
1887 \brief hdd_request_firmware() -
1888
1889 This function reads the firmware file using the request firmware
1890 API and returns the the firmware data and the firmware file size.
1891
1892 \param - pfileName - Pointer to the file name.
1893 - pCtx - Pointer to the adapter .
1894 - ppfw_data - Pointer to the pointer of the firmware data.
1895 - pSize - Pointer to the file size.
1896
1897 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
1898
1899 --------------------------------------------------------------------------*/
1900
1901
1902VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
1903{
1904 int status;
1905 VOS_STATUS retval = VOS_STATUS_SUCCESS;
1906 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1907 ENTER();
1908
1909 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
1910
1911 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
1912
1913 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1914 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
1915 __func__, pfileName);
1916 retval = VOS_STATUS_E_FAILURE;
1917 }
1918
1919 else {
1920 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
1921 *pSize = pHddCtx->fw->size;
1922 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
1923 __func__, *pSize);
1924 }
1925 }
1926 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
1927
1928 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
1929
1930 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
1931 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
1932 __func__, pfileName);
1933 retval = VOS_STATUS_E_FAILURE;
1934 }
1935
1936 else {
1937 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
1938 *pSize = pHddCtx->nv->size;
1939 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
1940 __func__, *pSize);
1941 }
1942 }
1943
1944 EXIT();
1945 return retval;
1946}
1947/**---------------------------------------------------------------------------
1948 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
1949
1950 This is the function invoked by SME to inform the result of a full power
1951 request issued by HDD
1952
1953 \param - callbackcontext - Pointer to cookie
1954 status - result of request
1955
1956 \return - None
1957
1958--------------------------------------------------------------------------*/
1959void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
1960{
1961 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
1962
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001963 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001964 if(&pHddCtx->full_pwr_comp_var)
1965 {
1966 complete(&pHddCtx->full_pwr_comp_var);
1967 }
1968}
1969
1970/**---------------------------------------------------------------------------
1971
1972 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
1973
1974 This is the function invoked by SME to inform the result of BMPS
1975 request issued by HDD
1976
1977 \param - callbackcontext - Pointer to cookie
1978 status - result of request
1979
1980 \return - None
1981
1982--------------------------------------------------------------------------*/
1983void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
1984{
1985
1986 struct completion *completion_var = (struct completion*) callbackContext;
1987
1988 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
1989 if(completion_var != NULL)
1990 {
1991 complete(completion_var);
1992 }
1993}
1994
1995/**---------------------------------------------------------------------------
1996
1997 \brief hdd_get_cfg_file_size() -
1998
1999 This function reads the configuration file using the request firmware
2000 API and returns the configuration file size.
2001
2002 \param - pCtx - Pointer to the adapter .
2003 - pFileName - Pointer to the file name.
2004 - pBufSize - Pointer to the buffer size.
2005
2006 \return - 0 for success, non zero for failure
2007
2008 --------------------------------------------------------------------------*/
2009
2010VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2011{
2012 int status;
2013 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2014
2015 ENTER();
2016
2017 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2018
2019 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2020 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2021 status = VOS_STATUS_E_FAILURE;
2022 }
2023 else {
2024 *pBufSize = pHddCtx->fw->size;
2025 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2026 release_firmware(pHddCtx->fw);
2027 pHddCtx->fw = NULL;
2028 }
2029
2030 EXIT();
2031 return VOS_STATUS_SUCCESS;
2032}
2033
2034/**---------------------------------------------------------------------------
2035
2036 \brief hdd_read_cfg_file() -
2037
2038 This function reads the configuration file using the request firmware
2039 API and returns the cfg data and the buffer size of the configuration file.
2040
2041 \param - pCtx - Pointer to the adapter .
2042 - pFileName - Pointer to the file name.
2043 - pBuffer - Pointer to the data buffer.
2044 - pBufSize - Pointer to the buffer size.
2045
2046 \return - 0 for success, non zero for failure
2047
2048 --------------------------------------------------------------------------*/
2049
2050VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2051 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2052{
2053 int status;
2054 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2055
2056 ENTER();
2057
2058 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2059
2060 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2061 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2062 return VOS_STATUS_E_FAILURE;
2063 }
2064 else {
2065 if(*pBufSize != pHddCtx->fw->size) {
2066 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2067 "file size", __func__);
2068 release_firmware(pHddCtx->fw);
2069 pHddCtx->fw = NULL;
2070 return VOS_STATUS_E_FAILURE;
2071 }
2072 else {
2073 if(pBuffer) {
2074 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2075 }
2076 release_firmware(pHddCtx->fw);
2077 pHddCtx->fw = NULL;
2078 }
2079 }
2080
2081 EXIT();
2082
2083 return VOS_STATUS_SUCCESS;
2084}
2085
2086/**---------------------------------------------------------------------------
2087
Jeff Johnson295189b2012-06-20 16:38:30 -07002088 \brief hdd_set_mac_address() -
2089
2090 This function sets the user specified mac address using
2091 the command ifconfig wlanX hw ether <mac adress>.
2092
2093 \param - dev - Pointer to the net device.
2094 - addr - Pointer to the sockaddr.
2095 \return - 0 for success, non zero for failure
2096
2097 --------------------------------------------------------------------------*/
2098
2099static int hdd_set_mac_address(struct net_device *dev, void *addr)
2100{
2101 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2102 struct sockaddr *psta_mac_addr = addr;
2103 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2104
2105 ENTER();
2106
2107 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2108
2109#ifdef HDD_SESSIONIZE
2110 // set the MAC address though the STA ID CFG.
2111 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2112 (v_U8_t *)&pAdapter->macAddressCurrent,
2113 sizeof( pAdapter->macAddressCurrent ),
2114 hdd_set_mac_addr_cb, VOS_FALSE );
2115#endif
2116
2117 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2118
2119 EXIT();
2120 return halStatus;
2121}
2122
2123tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2124{
2125 int i;
2126 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2127 {
2128 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2129 break;
2130 }
2131
2132 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2133 return NULL;
2134
2135 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2136 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2137}
2138
2139void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2140{
2141 int i;
2142 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2143 {
2144 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2145 {
2146 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2147 break;
2148 }
2149 }
2150 return;
2151}
2152
2153#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2154 static struct net_device_ops wlan_drv_ops = {
2155 .ndo_open = hdd_open,
2156 .ndo_stop = hdd_stop,
2157 .ndo_uninit = hdd_uninit,
2158 .ndo_start_xmit = hdd_hard_start_xmit,
2159 .ndo_tx_timeout = hdd_tx_timeout,
2160 .ndo_get_stats = hdd_stats,
2161 .ndo_do_ioctl = hdd_ioctl,
2162 .ndo_set_mac_address = hdd_set_mac_address,
2163 .ndo_select_queue = hdd_select_queue,
2164#ifdef WLAN_FEATURE_PACKET_FILTERING
2165#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2166 .ndo_set_rx_mode = hdd_set_multicast_list,
2167#else
2168 .ndo_set_multicast_list = hdd_set_multicast_list,
2169#endif //LINUX_VERSION_CODE
2170#endif
2171 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002172 static struct net_device_ops wlan_mon_drv_ops = {
2173 .ndo_open = hdd_mon_open,
2174 .ndo_stop = hdd_stop,
2175 .ndo_uninit = hdd_uninit,
2176 .ndo_start_xmit = hdd_mon_hard_start_xmit,
2177 .ndo_tx_timeout = hdd_tx_timeout,
2178 .ndo_get_stats = hdd_stats,
2179 .ndo_do_ioctl = hdd_ioctl,
2180 .ndo_set_mac_address = hdd_set_mac_address,
2181 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002182
2183#endif
2184
2185void hdd_set_station_ops( struct net_device *pWlanDev )
2186{
2187#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2188 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
2189 pWlanDev->netdev_ops = &wlan_drv_ops;
2190#else
2191 pWlanDev->open = hdd_open;
2192 pWlanDev->stop = hdd_stop;
2193 pWlanDev->uninit = hdd_uninit;
2194 pWlanDev->hard_start_xmit = NULL;
2195 pWlanDev->tx_timeout = hdd_tx_timeout;
2196 pWlanDev->get_stats = hdd_stats;
2197 pWlanDev->do_ioctl = hdd_ioctl;
2198 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
2199 pWlanDev->set_mac_address = hdd_set_mac_address;
2200#endif
2201}
2202
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002203static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07002204{
2205 struct net_device *pWlanDev = NULL;
2206 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002207 /*
2208 * cfg80211 initialization and registration....
2209 */
2210 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
2211
Jeff Johnson295189b2012-06-20 16:38:30 -07002212 if(pWlanDev != NULL)
2213 {
2214
2215 //Save the pointer to the net_device in the HDD adapter
2216 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
2217
Jeff Johnson295189b2012-06-20 16:38:30 -07002218 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
2219
2220 pAdapter->dev = pWlanDev;
2221 pAdapter->pHddCtx = pHddCtx;
2222 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2223
2224 init_completion(&pAdapter->session_open_comp_var);
2225 init_completion(&pAdapter->session_close_comp_var);
2226 init_completion(&pAdapter->disconnect_comp_var);
2227 init_completion(&pAdapter->linkup_event_var);
2228 init_completion(&pAdapter->cancel_rem_on_chan_var);
2229 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07002230#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2231 init_completion(&pAdapter->offchannel_tx_event);
2232#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002233 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002234#ifdef FEATURE_WLAN_TDLS
2235 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002236 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002237 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002238#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002239 init_completion(&pHddCtx->mc_sus_event_var);
2240 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07002241 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07002242
Jeff Johnson295189b2012-06-20 16:38:30 -07002243 pAdapter->isLinkUpSvcNeeded = FALSE;
2244 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
2245 //Init the net_device structure
2246 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2247
2248 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
2249 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
2250 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
2251 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
2252
2253 hdd_set_station_ops( pAdapter->dev );
2254
2255 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002256 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
2257 pAdapter->wdev.wiphy = pHddCtx->wiphy;
2258 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002259 /* set pWlanDev's parent to underlying device */
2260 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
2261 }
2262
2263 return pAdapter;
2264}
2265
2266VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
2267{
2268 struct net_device *pWlanDev = pAdapter->dev;
2269 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2270 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2271 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2272
2273 if( rtnl_lock_held )
2274 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08002275 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07002276 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
2277 {
2278 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
2279 return VOS_STATUS_E_FAILURE;
2280 }
2281 }
2282 if (register_netdevice(pWlanDev))
2283 {
2284 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
2285 return VOS_STATUS_E_FAILURE;
2286 }
2287 }
2288 else
2289 {
2290 if(register_netdev(pWlanDev))
2291 {
2292 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
2293 return VOS_STATUS_E_FAILURE;
2294 }
2295 }
2296 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
2297
2298 return VOS_STATUS_SUCCESS;
2299}
2300
2301eHalStatus hdd_smeCloseSessionCallback(void *pContext)
2302{
2303 if(pContext != NULL)
2304 {
2305 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
2306
2307 /* need to make sure all of our scheduled work has completed.
2308 * This callback is called from MC thread context, so it is safe to
2309 * to call below flush workqueue API from here.
2310 */
2311 flush_scheduled_work();
2312 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
2313 }
2314 return eHAL_STATUS_SUCCESS;
2315}
2316
2317VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
2318{
2319 struct net_device *pWlanDev = pAdapter->dev;
2320 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2321 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2322 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2323 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2324 int rc = 0;
2325
2326 INIT_COMPLETION(pAdapter->session_open_comp_var);
2327 //Open a SME session for future operation
2328 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
2329 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
2330 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2331 {
2332 hddLog(VOS_TRACE_LEVEL_FATAL,
2333 "sme_OpenSession() failed with status code %08d [x%08lx]",
2334 halStatus, halStatus );
2335 status = VOS_STATUS_E_FAILURE;
2336 goto error_sme_open;
2337 }
2338
2339 //Block on a completion variable. Can't wait forever though.
2340 rc = wait_for_completion_interruptible_timeout(
2341 &pAdapter->session_open_comp_var,
2342 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2343 if (!rc)
2344 {
2345 hddLog(VOS_TRACE_LEVEL_FATAL,
2346 "Session is not opened within timeout period code %08d", rc );
2347 status = VOS_STATUS_E_FAILURE;
2348 goto error_sme_open;
2349 }
2350
2351 // Register wireless extensions
2352 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
2353 {
2354 hddLog(VOS_TRACE_LEVEL_FATAL,
2355 "hdd_register_wext() failed with status code %08d [x%08lx]",
2356 halStatus, halStatus );
2357 status = VOS_STATUS_E_FAILURE;
2358 goto error_register_wext;
2359 }
2360 //Safe to register the hard_start_xmit function again
2361#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2362 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
2363#else
2364 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
2365#endif
2366
2367 //Set the Connection State to Not Connected
2368 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2369
2370 //Set the default operation channel
2371 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
2372
2373 /* Make the default Auth Type as OPEN*/
2374 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2375
2376 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
2377 {
2378 hddLog(VOS_TRACE_LEVEL_FATAL,
2379 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
2380 status, status );
2381 goto error_init_txrx;
2382 }
2383
2384 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2385
2386 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
2387 {
2388 hddLog(VOS_TRACE_LEVEL_FATAL,
2389 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
2390 status, status );
2391 goto error_wmm_init;
2392 }
2393
2394 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2395
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002396#ifdef FEATURE_WLAN_TDLS
2397 if(0 != wlan_hdd_tdls_init(pAdapter))
2398 {
2399 status = VOS_STATUS_E_FAILURE;
2400 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
2401 goto error_tdls_init;
2402 }
2403 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2404#endif
2405
Jeff Johnson295189b2012-06-20 16:38:30 -07002406 return VOS_STATUS_SUCCESS;
2407
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002408#ifdef FEATURE_WLAN_TDLS
2409error_tdls_init:
2410 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2411 hdd_wmm_adapter_close(pAdapter);
2412#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002413error_wmm_init:
2414 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2415 hdd_deinit_tx_rx(pAdapter);
2416error_init_txrx:
2417 hdd_UnregisterWext(pWlanDev);
2418error_register_wext:
2419 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2420 {
2421 INIT_COMPLETION(pAdapter->session_close_comp_var);
2422 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
2423 pAdapter->sessionId,
2424 hdd_smeCloseSessionCallback, pAdapter ) )
2425 {
2426 //Block on a completion variable. Can't wait forever though.
2427 wait_for_completion_interruptible_timeout(
2428 &pAdapter->session_close_comp_var,
2429 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2430 }
2431}
2432error_sme_open:
2433 return status;
2434}
2435
Jeff Johnson295189b2012-06-20 16:38:30 -07002436void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2437{
2438 hdd_cfg80211_state_t *cfgState;
2439
2440 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
2441
2442 if( NULL != cfgState->buf )
2443 {
2444 int rc;
2445 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
2446 rc = wait_for_completion_interruptible_timeout(
2447 &pAdapter->tx_action_cnf_event,
2448 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2449 if(!rc)
2450 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08002451 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002452 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
2453 }
2454 }
2455 return;
2456}
Jeff Johnson295189b2012-06-20 16:38:30 -07002457
2458void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2459{
2460 ENTER();
2461 switch ( pAdapter->device_mode )
2462 {
2463 case WLAN_HDD_INFRA_STATION:
2464 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002465 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002466 {
2467 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2468 {
2469 hdd_deinit_tx_rx( pAdapter );
2470 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2471 }
2472
2473 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
2474 {
2475 hdd_wmm_adapter_close( pAdapter );
2476 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2477 }
2478
Jeff Johnson295189b2012-06-20 16:38:30 -07002479 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002480#ifdef FEATURE_WLAN_TDLS
2481 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
2482 {
2483 wlan_hdd_tdls_exit(pAdapter);
2484 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2485 }
2486#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002487
2488 break;
2489 }
2490
2491 case WLAN_HDD_SOFTAP:
2492 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002493 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002494 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002495
2496 hdd_unregister_hostapd(pAdapter);
2497 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07002498 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07002499 break;
2500 }
2501
2502 case WLAN_HDD_MONITOR:
2503 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002504 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07002505 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2506 {
2507 hdd_deinit_tx_rx( pAdapter );
2508 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2509 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002510 if(NULL != pAdapterforTx)
2511 {
2512 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
2513 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002514 break;
2515 }
2516
2517
2518 default:
2519 break;
2520 }
2521
2522 EXIT();
2523}
2524
2525void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
2526{
2527 struct net_device *pWlanDev = pAdapter->dev;
2528
2529 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
2530 if( rtnl_held )
2531 {
2532 unregister_netdevice(pWlanDev);
2533 }
2534 else
2535 {
2536 unregister_netdev(pWlanDev);
2537 }
2538 // note that the pAdapter is no longer valid at this point
2539 // since the memory has been reclaimed
2540 }
2541
2542}
2543
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002544void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2545{
2546 tSirSetPowerParamsReq powerRequest = { 0 };
2547
2548 powerRequest.uIgnoreDTIM = 1;
2549
2550 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2551 {
2552 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2553 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2554 }
2555 else
2556 {
2557 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2558 }
2559
2560 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2561 *specified during Enter/Exit BMPS when LCD off*/
2562 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2563 NULL, eANI_BOOLEAN_FALSE);
2564 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2565 NULL, eANI_BOOLEAN_FALSE);
2566
2567 /* switch to the DTIM specified in cfg.ini */
2568 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2569 "Switch to DTIM%d", powerRequest.uListenInterval);
2570 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2571
2572}
2573
2574void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2575{
2576 /*Switch back to DTIM 1*/
2577 tSirSetPowerParamsReq powerRequest = { 0 };
2578
2579 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2580 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2581
2582 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2583 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2584 NULL, eANI_BOOLEAN_FALSE);
2585 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2586 NULL, eANI_BOOLEAN_FALSE);
2587
2588 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2589 "Switch to DTIM%d",powerRequest.uListenInterval);
2590 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2591
2592}
2593
Jeff Johnson295189b2012-06-20 16:38:30 -07002594VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2595{
2596 VOS_STATUS status = VOS_STATUS_SUCCESS;
2597
2598 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2599 {
2600 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2601 }
2602
2603 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2604 {
2605 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2606 }
2607
2608 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2609 {
2610 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2611 }
2612
2613 return status;
2614}
2615
2616VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2617{
2618 hdd_adapter_t *pAdapter = NULL;
2619 eHalStatus halStatus;
2620 VOS_STATUS status = VOS_STATUS_E_INVAL;
2621 v_BOOL_t disableBmps = FALSE;
2622 v_BOOL_t disableImps = FALSE;
2623
2624 switch(session_type)
2625 {
2626 case WLAN_HDD_INFRA_STATION:
2627 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002628 case WLAN_HDD_P2P_CLIENT:
2629 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002630 //Exit BMPS -> Is Sta/P2P Client is already connected
2631 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2632 if((NULL != pAdapter)&&
2633 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2634 {
2635 disableBmps = TRUE;
2636 }
2637
2638 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2639 if((NULL != pAdapter)&&
2640 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2641 {
2642 disableBmps = TRUE;
2643 }
2644
2645 //Exit both Bmps and Imps incase of Go/SAP Mode
2646 if((WLAN_HDD_SOFTAP == session_type) ||
2647 (WLAN_HDD_P2P_GO == session_type))
2648 {
2649 disableBmps = TRUE;
2650 disableImps = TRUE;
2651 }
2652
2653 if(TRUE == disableImps)
2654 {
2655 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2656 {
2657 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2658 }
2659 }
2660
2661 if(TRUE == disableBmps)
2662 {
2663 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2664 {
2665 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2666
2667 if(eHAL_STATUS_SUCCESS != halStatus)
2668 {
2669 status = VOS_STATUS_E_FAILURE;
2670 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
2671 VOS_ASSERT(0);
2672 return status;
2673 }
2674 }
2675
2676 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2677 {
2678 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
2679
2680 if(eHAL_STATUS_SUCCESS != halStatus)
2681 {
2682 status = VOS_STATUS_E_FAILURE;
2683 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
2684 VOS_ASSERT(0);
2685 return status;
2686 }
2687 }
2688 }
2689
2690 if((TRUE == disableBmps) ||
2691 (TRUE == disableImps))
2692 {
2693 /* Now, get the chip into Full Power now */
2694 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
2695 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
2696 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
2697
2698 if(halStatus != eHAL_STATUS_SUCCESS)
2699 {
2700 if(halStatus == eHAL_STATUS_PMC_PENDING)
2701 {
2702 //Block on a completion variable. Can't wait forever though
2703 wait_for_completion_interruptible_timeout(
2704 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
2705 }
2706 else
2707 {
2708 status = VOS_STATUS_E_FAILURE;
2709 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
2710 VOS_ASSERT(0);
2711 return status;
2712 }
2713 }
2714
2715 status = VOS_STATUS_SUCCESS;
2716 }
2717
2718 break;
2719 }
2720 return status;
2721}
2722
2723hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002724 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07002725 tANI_U8 rtnl_held )
2726{
2727 hdd_adapter_t *pAdapter = NULL;
2728 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
2729 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2730 VOS_STATUS exitbmpsStatus;
2731
2732 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
2733
2734 //Disable BMPS incase of Concurrency
2735 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
2736
2737 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
2738 {
2739 //Fail to Exit BMPS
2740 VOS_ASSERT(0);
2741 return NULL;
2742 }
2743
2744 switch(session_type)
2745 {
2746 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002747 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002748 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002749 {
2750 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2751
2752 if( NULL == pAdapter )
2753 return NULL;
2754
Jeff Johnsone7245742012-09-05 17:12:55 -07002755 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
2756 NL80211_IFTYPE_P2P_CLIENT:
2757 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07002758
Jeff Johnson295189b2012-06-20 16:38:30 -07002759 pAdapter->device_mode = session_type;
2760
2761 status = hdd_init_station_mode( pAdapter );
2762 if( VOS_STATUS_SUCCESS != status )
2763 goto err_free_netdev;
2764
2765 status = hdd_register_interface( pAdapter, rtnl_held );
2766 if( VOS_STATUS_SUCCESS != status )
2767 {
2768 hdd_deinit_adapter(pHddCtx, pAdapter);
2769 goto err_free_netdev;
2770 }
2771 //Stop the Interface TX queue.
2772 netif_tx_disable(pAdapter->dev);
2773 //netif_tx_disable(pWlanDev);
2774 netif_carrier_off(pAdapter->dev);
2775
2776 break;
2777 }
2778
Jeff Johnson295189b2012-06-20 16:38:30 -07002779 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002780 case WLAN_HDD_SOFTAP:
2781 {
2782 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
2783 if( NULL == pAdapter )
2784 return NULL;
2785
Jeff Johnson295189b2012-06-20 16:38:30 -07002786 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
2787 NL80211_IFTYPE_AP:
2788 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002789 pAdapter->device_mode = session_type;
2790
2791 status = hdd_init_ap_mode(pAdapter);
2792 if( VOS_STATUS_SUCCESS != status )
2793 goto err_free_netdev;
2794
2795 status = hdd_register_hostapd( pAdapter, rtnl_held );
2796 if( VOS_STATUS_SUCCESS != status )
2797 {
2798 hdd_deinit_adapter(pHddCtx, pAdapter);
2799 goto err_free_netdev;
2800 }
2801
2802 netif_tx_disable(pAdapter->dev);
2803 netif_carrier_off(pAdapter->dev);
2804
2805 hdd_set_conparam( 1 );
2806 break;
2807 }
2808 case WLAN_HDD_MONITOR:
2809 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002810 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2811 if( NULL == pAdapter )
2812 return NULL;
2813
2814 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
2815 pAdapter->device_mode = session_type;
2816 status = hdd_register_interface( pAdapter, rtnl_held );
2817#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2818 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
2819#else
2820 pAdapter->dev->open = hdd_mon_open;
2821 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
2822#endif
2823 hdd_init_tx_rx( pAdapter );
2824 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2825 //Set adapter to be used for data tx. It will use either GO or softap.
2826 pAdapter->sessionCtx.monitor.pAdapterForTx =
2827 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07002828 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
2829 {
2830 pAdapter->sessionCtx.monitor.pAdapterForTx =
2831 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
2832 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002833 /* This workqueue will be used to transmit management packet over
2834 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07002835 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
2836 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
2837 return NULL;
2838 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07002839
Jeff Johnson295189b2012-06-20 16:38:30 -07002840 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
2841 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07002842 }
2843 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002844 case WLAN_HDD_FTM:
2845 {
2846 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2847
2848 if( NULL == pAdapter )
2849 return NULL;
2850 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
2851 * message while loading driver in FTM mode. */
2852 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
2853 pAdapter->device_mode = session_type;
2854 status = hdd_register_interface( pAdapter, rtnl_held );
2855 }
2856 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002857 default:
2858 {
2859 VOS_ASSERT(0);
2860 return NULL;
2861 }
2862 }
2863
2864
2865 if( VOS_STATUS_SUCCESS == status )
2866 {
2867 //Add it to the hdd's session list.
2868 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
2869 if( NULL == pHddAdapterNode )
2870 {
2871 status = VOS_STATUS_E_NOMEM;
2872 }
2873 else
2874 {
2875 pHddAdapterNode->pAdapter = pAdapter;
2876 status = hdd_add_adapter_back ( pHddCtx,
2877 pHddAdapterNode );
2878 }
2879 }
2880
2881 if( VOS_STATUS_SUCCESS != status )
2882 {
2883 if( NULL != pAdapter )
2884 {
2885 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
2886 pAdapter = NULL;
2887 }
2888 if( NULL != pHddAdapterNode )
2889 {
2890 vos_mem_free( pHddAdapterNode );
2891 }
2892
2893 goto resume_bmps;
2894 }
2895
2896 if(VOS_STATUS_SUCCESS == status)
2897 {
2898 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
2899
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002900 //Initialize the WoWL service
2901 if(!hdd_init_wowl(pAdapter))
2902 {
2903 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
2904 goto err_free_netdev;
2905 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002906 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002907 return pAdapter;
2908
2909err_free_netdev:
2910 free_netdev(pAdapter->dev);
2911 wlan_hdd_release_intf_addr( pHddCtx,
2912 pAdapter->macAddressCurrent.bytes );
2913
2914resume_bmps:
2915 //If bmps disabled enable it
2916 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
2917 {
2918 hdd_enable_bmps_imps(pHddCtx);
2919 }
2920 return NULL;
2921}
2922
2923VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
2924 tANI_U8 rtnl_held )
2925{
2926 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
2927 VOS_STATUS status;
2928
2929 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
2930 if( VOS_STATUS_SUCCESS != status )
2931 return status;
2932
2933 while ( pCurrent->pAdapter != pAdapter )
2934 {
2935 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
2936 if( VOS_STATUS_SUCCESS != status )
2937 break;
2938
2939 pCurrent = pNext;
2940 }
2941 pAdapterNode = pCurrent;
2942 if( VOS_STATUS_SUCCESS == status )
2943 {
2944 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2945 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
2946 hdd_remove_adapter( pHddCtx, pAdapterNode );
2947 vos_mem_free( pAdapterNode );
2948
Jeff Johnson295189b2012-06-20 16:38:30 -07002949
2950 /* If there is a single session of STA/P2P client, re-enable BMPS */
2951 if ((!vos_concurrent_sessions_running()) &&
2952 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
2953 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
2954 {
2955 hdd_enable_bmps_imps(pHddCtx);
2956 }
2957
2958 return VOS_STATUS_SUCCESS;
2959 }
2960
2961 return VOS_STATUS_E_FAILURE;
2962}
2963
2964VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
2965{
2966 hdd_adapter_list_node_t *pHddAdapterNode;
2967 VOS_STATUS status;
2968
2969 ENTER();
2970
2971 do
2972 {
2973 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
2974 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
2975 {
2976 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
2977 vos_mem_free( pHddAdapterNode );
2978 }
2979 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
2980
2981 EXIT();
2982
2983 return VOS_STATUS_SUCCESS;
2984}
2985
2986void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
2987{
2988 v_U8_t addIE[1] = {0};
2989
2990 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2991 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
2992 eANI_BOOLEAN_FALSE) )
2993 {
2994 hddLog(LOGE,
2995 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
2996 }
2997
2998 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2999 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
3000 eANI_BOOLEAN_FALSE) )
3001 {
3002 hddLog(LOGE,
3003 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3004 }
3005
3006 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3007 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3008 eANI_BOOLEAN_FALSE) )
3009 {
3010 hddLog(LOGE,
3011 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3012 }
3013}
3014
3015VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3016{
3017 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3018 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3019 union iwreq_data wrqu;
3020
3021 ENTER();
3022
3023 switch(pAdapter->device_mode)
3024 {
3025 case WLAN_HDD_INFRA_STATION:
3026 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003027 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003028 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3029 {
3030 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3031 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3032 pAdapter->sessionId,
3033 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3034 else
3035 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3036 pAdapter->sessionId,
3037 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3038 //success implies disconnect command got queued up successfully
3039 if(halStatus == eHAL_STATUS_SUCCESS)
3040 {
3041 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3042 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3043 }
3044 memset(&wrqu, '\0', sizeof(wrqu));
3045 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3046 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3047 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3048 }
3049 else
3050 {
3051 hdd_abort_mac_scan(pHddCtx);
3052 }
3053
3054 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3055 {
3056 INIT_COMPLETION(pAdapter->session_close_comp_var);
3057 if (eHAL_STATUS_SUCCESS ==
3058 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3059 hdd_smeCloseSessionCallback, pAdapter))
3060 {
3061 //Block on a completion variable. Can't wait forever though.
3062 wait_for_completion_interruptible_timeout(
3063 &pAdapter->session_close_comp_var,
3064 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3065 }
3066 }
3067
3068 break;
3069
3070 case WLAN_HDD_SOFTAP:
3071 case WLAN_HDD_P2P_GO:
3072 //Any softap specific cleanup here...
3073 mutex_lock(&pHddCtx->sap_lock);
3074 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3075 {
3076 VOS_STATUS status;
3077 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3078
3079 //Stop Bss.
3080 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3081 if (VOS_IS_STATUS_SUCCESS(status))
3082 {
3083 hdd_hostapd_state_t *pHostapdState =
3084 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3085
3086 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3087
3088 if (!VOS_IS_STATUS_SUCCESS(status))
3089 {
3090 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003091 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003092 }
3093 }
3094 else
3095 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003096 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003097 }
3098 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3099
3100 if (eHAL_STATUS_FAILURE ==
3101 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3102 0, NULL, eANI_BOOLEAN_FALSE))
3103 {
3104 hddLog(LOGE,
3105 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003106 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003107 }
3108
3109 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3110 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3111 eANI_BOOLEAN_FALSE) )
3112 {
3113 hddLog(LOGE,
3114 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3115 }
3116
3117 // Reset WNI_CFG_PROBE_RSP Flags
3118 wlan_hdd_reset_prob_rspies(pAdapter);
3119 kfree(pAdapter->sessionCtx.ap.beacon);
3120 pAdapter->sessionCtx.ap.beacon = NULL;
3121 }
3122 mutex_unlock(&pHddCtx->sap_lock);
3123 break;
3124 case WLAN_HDD_MONITOR:
3125 break;
3126 default:
3127 break;
3128 }
3129
3130 EXIT();
3131 return VOS_STATUS_SUCCESS;
3132}
3133
3134VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3135{
3136 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3137 VOS_STATUS status;
3138 hdd_adapter_t *pAdapter;
3139
3140 ENTER();
3141
3142 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3143
3144 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3145 {
3146 pAdapter = pAdapterNode->pAdapter;
3147 netif_tx_disable(pAdapter->dev);
3148 netif_carrier_off(pAdapter->dev);
3149
3150 hdd_stop_adapter( pHddCtx, pAdapter );
3151
3152 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3153 pAdapterNode = pNext;
3154 }
3155
3156 EXIT();
3157
3158 return VOS_STATUS_SUCCESS;
3159}
3160
3161VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
3162{
3163 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3164 VOS_STATUS status;
3165 hdd_adapter_t *pAdapter;
3166
3167 ENTER();
3168
3169 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3170
3171 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3172 {
3173 pAdapter = pAdapterNode->pAdapter;
3174 netif_tx_disable(pAdapter->dev);
3175 netif_carrier_off(pAdapter->dev);
3176
3177 //Record whether STA is associated
3178 pAdapter->sessionCtx.station.bSendDisconnect =
3179 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
3180 VOS_TRUE : VOS_FALSE;
3181
3182 hdd_deinit_tx_rx(pAdapter);
3183 hdd_wmm_adapter_close(pAdapter);
3184
3185 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3186 pAdapterNode = pNext;
3187 }
3188
3189 EXIT();
3190
3191 return VOS_STATUS_SUCCESS;
3192}
3193
3194VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
3195{
3196 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3197 VOS_STATUS status;
3198 hdd_adapter_t *pAdapter;
3199 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
3200
3201 ENTER();
3202
3203 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3204
3205 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3206 {
3207 pAdapter = pAdapterNode->pAdapter;
3208
3209 switch(pAdapter->device_mode)
3210 {
3211 case WLAN_HDD_INFRA_STATION:
3212 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003213 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003214 hdd_init_station_mode(pAdapter);
3215 /* Open the gates for HDD to receive Wext commands */
3216 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003217 pHddCtx->scan_info.mScanPending = FALSE;
3218 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003219
3220 //Trigger the initial scan
3221 hdd_wlan_initial_scan(pAdapter);
3222
3223 //Indicate disconnect event to supplicant if associated previously
3224 if(pAdapter->sessionCtx.station.bSendDisconnect)
3225 {
3226 union iwreq_data wrqu;
3227 memset(&wrqu, '\0', sizeof(wrqu));
3228 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3229 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3230 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3231 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
3232
Jeff Johnson295189b2012-06-20 16:38:30 -07003233 /* indicate disconnected event to nl80211 */
3234 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
3235 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003236 }
3237 break;
3238
3239 case WLAN_HDD_SOFTAP:
3240 /* softAP can handle SSR */
3241 break;
3242
3243 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003244 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
3245 __func__);
3246 /* event supplicant to restart */
3247 cfg80211_del_sta(pAdapter->dev,
3248 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003249 break;
3250
3251 case WLAN_HDD_MONITOR:
3252 /* monitor interface start */
3253 break;
3254 default:
3255 break;
3256 }
3257
3258 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3259 pAdapterNode = pNext;
3260 }
3261
3262 EXIT();
3263
3264 return VOS_STATUS_SUCCESS;
3265}
3266
3267VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
3268{
3269 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3270 hdd_adapter_t *pAdapter;
3271 VOS_STATUS status;
3272 v_U32_t roamId;
3273
3274 ENTER();
3275
3276 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3277
3278 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3279 {
3280 pAdapter = pAdapterNode->pAdapter;
3281
3282 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3283 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
3284 {
3285 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3286 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3287
3288 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3289 init_completion(&pAdapter->disconnect_comp_var);
3290 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
3291 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3292
3293 wait_for_completion_interruptible_timeout(
3294 &pAdapter->disconnect_comp_var,
3295 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3296
3297 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
3298 pHddCtx->isAmpAllowed = VOS_FALSE;
3299 sme_RoamConnect(pHddCtx->hHal,
3300 pAdapter->sessionId, &(pWextState->roamProfile),
3301 &roamId);
3302 }
3303
3304 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3305 pAdapterNode = pNext;
3306 }
3307
3308 EXIT();
3309
3310 return VOS_STATUS_SUCCESS;
3311}
3312
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07003313void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
3314{
3315 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3316 VOS_STATUS status;
3317 hdd_adapter_t *pAdapter;
3318 hdd_station_ctx_t *pHddStaCtx;
3319 hdd_ap_ctx_t *pHddApCtx;
3320 hdd_hostapd_state_t * pHostapdState;
3321 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
3322 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
3323 const char *p2pMode = "DEV";
3324 const char *ccMode = "Standalone";
3325 int n;
3326
3327 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3328 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3329 {
3330 pAdapter = pAdapterNode->pAdapter;
3331 switch (pAdapter->device_mode) {
3332 case WLAN_HDD_INFRA_STATION:
3333 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3334 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3335 staChannel = pHddStaCtx->conn_info.operationChannel;
3336 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
3337 }
3338 break;
3339 case WLAN_HDD_P2P_CLIENT:
3340 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3341 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3342 p2pChannel = pHddStaCtx->conn_info.operationChannel;
3343 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
3344 p2pMode = "CLI";
3345 }
3346 break;
3347 case WLAN_HDD_P2P_GO:
3348 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3349 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3350 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3351 p2pChannel = pHddApCtx->operatingChannel;
3352 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
3353 }
3354 p2pMode = "GO";
3355 break;
3356 case WLAN_HDD_SOFTAP:
3357 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3358 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3359 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3360 apChannel = pHddApCtx->operatingChannel;
3361 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
3362 }
3363 break;
3364 default:
3365 break;
3366 }
3367 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3368 pAdapterNode = pNext;
3369 }
3370 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
3371 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
3372 }
3373 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
3374 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
3375 if (p2pChannel > 0) {
3376 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
3377 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
3378 }
3379 if (apChannel > 0) {
3380 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
3381 apChannel, MAC_ADDR_ARRAY(apBssid));
3382 }
3383
3384 if (p2pChannel > 0 && apChannel > 0) {
3385 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
3386 }
3387}
3388
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003389bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07003390{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003391 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07003392}
3393
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003394/* Once SSR is disabled then it cannot be set. */
3395void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07003396{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003397 if (HDD_SSR_DISABLED == isSsrRequired)
3398 return;
3399
Jeff Johnson295189b2012-06-20 16:38:30 -07003400 isSsrRequired = value;
3401}
3402
3403VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
3404 hdd_adapter_list_node_t** ppAdapterNode)
3405{
3406 VOS_STATUS status;
3407 spin_lock(&pHddCtx->hddAdapters.lock);
3408 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
3409 (hdd_list_node_t**) ppAdapterNode );
3410 spin_unlock(&pHddCtx->hddAdapters.lock);
3411 return status;
3412}
3413
3414VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
3415 hdd_adapter_list_node_t* pAdapterNode,
3416 hdd_adapter_list_node_t** pNextAdapterNode)
3417{
3418 VOS_STATUS status;
3419 spin_lock(&pHddCtx->hddAdapters.lock);
3420 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
3421 (hdd_list_node_t*) pAdapterNode,
3422 (hdd_list_node_t**)pNextAdapterNode );
3423
3424 spin_unlock(&pHddCtx->hddAdapters.lock);
3425 return status;
3426}
3427
3428VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
3429 hdd_adapter_list_node_t* pAdapterNode)
3430{
3431 VOS_STATUS status;
3432 spin_lock(&pHddCtx->hddAdapters.lock);
3433 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
3434 &pAdapterNode->node );
3435 spin_unlock(&pHddCtx->hddAdapters.lock);
3436 return status;
3437}
3438
3439VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
3440 hdd_adapter_list_node_t** ppAdapterNode)
3441{
3442 VOS_STATUS status;
3443 spin_lock(&pHddCtx->hddAdapters.lock);
3444 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
3445 (hdd_list_node_t**) ppAdapterNode );
3446 spin_unlock(&pHddCtx->hddAdapters.lock);
3447 return status;
3448}
3449
3450VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
3451 hdd_adapter_list_node_t* pAdapterNode)
3452{
3453 VOS_STATUS status;
3454 spin_lock(&pHddCtx->hddAdapters.lock);
3455 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
3456 (hdd_list_node_t*) pAdapterNode );
3457 spin_unlock(&pHddCtx->hddAdapters.lock);
3458 return status;
3459}
3460
3461VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
3462 hdd_adapter_list_node_t* pAdapterNode)
3463{
3464 VOS_STATUS status;
3465 spin_lock(&pHddCtx->hddAdapters.lock);
3466 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
3467 (hdd_list_node_t*) pAdapterNode );
3468 spin_unlock(&pHddCtx->hddAdapters.lock);
3469 return status;
3470}
3471
3472hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
3473 tSirMacAddr macAddr )
3474{
3475 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3476 hdd_adapter_t *pAdapter;
3477 VOS_STATUS status;
3478
3479 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3480
3481 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3482 {
3483 pAdapter = pAdapterNode->pAdapter;
3484
3485 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
3486 macAddr, sizeof(tSirMacAddr) ) )
3487 {
3488 return pAdapter;
3489 }
3490 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3491 pAdapterNode = pNext;
3492 }
3493
3494 return NULL;
3495
3496}
3497
3498hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
3499{
3500 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3501 hdd_adapter_t *pAdapter;
3502 VOS_STATUS status;
3503
3504 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3505
3506 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3507 {
3508 pAdapter = pAdapterNode->pAdapter;
3509
3510 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
3511 IFNAMSIZ ) )
3512 {
3513 return pAdapter;
3514 }
3515 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3516 pAdapterNode = pNext;
3517 }
3518
3519 return NULL;
3520
3521}
3522
3523hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
3524{
3525 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3526 hdd_adapter_t *pAdapter;
3527 VOS_STATUS status;
3528
3529 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3530
3531 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3532 {
3533 pAdapter = pAdapterNode->pAdapter;
3534
3535 if( pAdapter && (mode == pAdapter->device_mode) )
3536 {
3537 return pAdapter;
3538 }
3539 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3540 pAdapterNode = pNext;
3541 }
3542
3543 return NULL;
3544
3545}
3546
3547//Remove this function later
3548hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
3549{
3550 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3551 hdd_adapter_t *pAdapter;
3552 VOS_STATUS status;
3553
3554 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3555
3556 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3557 {
3558 pAdapter = pAdapterNode->pAdapter;
3559
3560 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
3561 {
3562 return pAdapter;
3563 }
3564
3565 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3566 pAdapterNode = pNext;
3567 }
3568
3569 return NULL;
3570
3571}
3572
Jeff Johnson295189b2012-06-20 16:38:30 -07003573/**---------------------------------------------------------------------------
3574
3575 \brief hdd_set_monitor_tx_adapter() -
3576
3577 This API initializes the adapter to be used while transmitting on monitor
3578 adapter.
3579
3580 \param - pHddCtx - Pointer to the HDD context.
3581 pAdapter - Adapter that will used for TX. This can be NULL.
3582 \return - None.
3583 --------------------------------------------------------------------------*/
3584void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3585{
3586 hdd_adapter_t *pMonAdapter;
3587
3588 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
3589
3590 if( NULL != pMonAdapter )
3591 {
3592 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
3593 }
3594}
Jeff Johnson295189b2012-06-20 16:38:30 -07003595/**---------------------------------------------------------------------------
3596
3597 \brief hdd_select_queue() -
3598
3599 This API returns the operating channel of the requested device mode
3600
3601 \param - pHddCtx - Pointer to the HDD context.
3602 - mode - Device mode for which operating channel is required
3603 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
3604 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
3605 \return - channel number. "0" id the requested device is not found OR it is not connected.
3606 --------------------------------------------------------------------------*/
3607v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
3608{
3609 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3610 VOS_STATUS status;
3611 hdd_adapter_t *pAdapter;
3612 v_U8_t operatingChannel = 0;
3613
3614 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3615
3616 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3617 {
3618 pAdapter = pAdapterNode->pAdapter;
3619
3620 if( mode == pAdapter->device_mode )
3621 {
3622 switch(pAdapter->device_mode)
3623 {
3624 case WLAN_HDD_INFRA_STATION:
3625 case WLAN_HDD_P2P_CLIENT:
3626 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3627 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
3628 break;
3629 case WLAN_HDD_SOFTAP:
3630 case WLAN_HDD_P2P_GO:
3631 /*softap connection info */
3632 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3633 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3634 break;
3635 default:
3636 break;
3637 }
3638
3639 break; //Found the device of interest. break the loop
3640 }
3641
3642 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3643 pAdapterNode = pNext;
3644 }
3645 return operatingChannel;
3646}
3647
3648#ifdef WLAN_FEATURE_PACKET_FILTERING
3649/**---------------------------------------------------------------------------
3650
3651 \brief hdd_set_multicast_list() -
3652
3653 This used to set the multicast address list.
3654
3655 \param - dev - Pointer to the WLAN device.
3656 - skb - Pointer to OS packet (sk_buff).
3657 \return - success/fail
3658
3659 --------------------------------------------------------------------------*/
3660static void hdd_set_multicast_list(struct net_device *dev)
3661{
3662 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003663 int mc_count;
3664 int i = 0;
3665 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303666
3667 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07003668 {
3669 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303670 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003671 return;
3672 }
3673
3674 if (dev->flags & IFF_ALLMULTI)
3675 {
3676 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003677 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303678 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003679 }
3680 else
3681 {
3682 mc_count = netdev_mc_count(dev);
3683 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003684 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07003685 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
3686 {
3687 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003688 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303689 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003690 return;
3691 }
3692
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303693 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07003694
3695 netdev_for_each_mc_addr(ha, dev) {
3696 if (i == mc_count)
3697 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303698 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
3699 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
3700 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003701 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303702 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07003703 i++;
3704 }
3705 }
3706 return;
3707}
3708#endif
3709
3710/**---------------------------------------------------------------------------
3711
3712 \brief hdd_select_queue() -
3713
3714 This function is registered with the Linux OS for network
3715 core to decide which queue to use first.
3716
3717 \param - dev - Pointer to the WLAN device.
3718 - skb - Pointer to OS packet (sk_buff).
3719 \return - ac, Queue Index/access category corresponding to UP in IP header
3720
3721 --------------------------------------------------------------------------*/
3722v_U16_t hdd_select_queue(struct net_device *dev,
3723 struct sk_buff *skb)
3724{
3725 return hdd_wmm_select_queue(dev, skb);
3726}
3727
3728
3729/**---------------------------------------------------------------------------
3730
3731 \brief hdd_wlan_initial_scan() -
3732
3733 This function triggers the initial scan
3734
3735 \param - pAdapter - Pointer to the HDD adapter.
3736
3737 --------------------------------------------------------------------------*/
3738void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
3739{
3740 tCsrScanRequest scanReq;
3741 tCsrChannelInfo channelInfo;
3742 eHalStatus halStatus;
3743 unsigned long scanId;
3744 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3745
3746 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
3747 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
3748 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
3749
3750 if(sme_Is11dSupported(pHddCtx->hHal))
3751 {
3752 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
3753 if ( HAL_STATUS_SUCCESS( halStatus ) )
3754 {
3755 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
3756 if( !scanReq.ChannelInfo.ChannelList )
3757 {
3758 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
3759 vos_mem_free(channelInfo.ChannelList);
3760 return;
3761 }
3762 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
3763 channelInfo.numOfChannels);
3764 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
3765 vos_mem_free(channelInfo.ChannelList);
3766 }
3767
3768 scanReq.scanType = eSIR_PASSIVE_SCAN;
3769 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
3770 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
3771 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
3772 }
3773 else
3774 {
3775 scanReq.scanType = eSIR_ACTIVE_SCAN;
3776 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3777 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
3778 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
3779 }
3780
3781 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
3782 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3783 {
3784 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
3785 __func__, halStatus );
3786 }
3787
3788 if(sme_Is11dSupported(pHddCtx->hHal))
3789 vos_mem_free(scanReq.ChannelInfo.ChannelList);
3790}
3791
3792struct fullPowerContext
3793{
3794 struct completion completion;
3795 unsigned int magic;
3796};
3797#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
3798
3799/**---------------------------------------------------------------------------
3800
3801 \brief hdd_full_power_callback() - HDD full power callback function
3802
3803 This is the function invoked by SME to inform the result of a full power
3804 request issued by HDD
3805
3806 \param - callbackcontext - Pointer to cookie
3807 \param - status - result of request
3808
3809 \return - None
3810
3811 --------------------------------------------------------------------------*/
3812static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
3813{
3814 struct fullPowerContext *pContext = callbackContext;
3815
3816 hddLog(VOS_TRACE_LEVEL_INFO,
3817 "%s: context = %p, status = %d", pContext, status);
3818
3819 if (NULL == callbackContext)
3820 {
3821 hddLog(VOS_TRACE_LEVEL_ERROR,
3822 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003823 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07003824 return;
3825 }
3826
3827 /* there is a race condition that exists between this callback function
3828 and the caller since the caller could time out either before or
3829 while this code is executing. we'll assume the timeout hasn't
3830 occurred, but we'll verify that right before we save our work */
3831
3832 if (POWER_CONTEXT_MAGIC != pContext->magic)
3833 {
3834 /* the caller presumably timed out so there is nothing we can do */
3835 hddLog(VOS_TRACE_LEVEL_WARN,
3836 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003837 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07003838 return;
3839 }
3840
3841 /* the race is on. caller could have timed out immediately after
3842 we verified the magic, but if so, caller will wait a short time
3843 for us to notify the caller, so the context will stay valid */
3844 complete(&pContext->completion);
3845}
3846
3847/**---------------------------------------------------------------------------
3848
3849 \brief hdd_wlan_exit() - HDD WLAN exit function
3850
3851 This is the driver exit point (invoked during rmmod)
3852
3853 \param - pHddCtx - Pointer to the HDD Context
3854
3855 \return - None
3856
3857 --------------------------------------------------------------------------*/
3858void hdd_wlan_exit(hdd_context_t *pHddCtx)
3859{
3860 eHalStatus halStatus;
3861 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
3862 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05303863 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003864 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003865 struct fullPowerContext powerContext;
3866 long lrc;
3867
3868 ENTER();
3869
Jeff Johnson88ba7742013-02-27 14:36:02 -08003870 if (VOS_FTM_MODE != hdd_get_conparam())
3871 {
3872 // Unloading, restart logic is no more required.
3873 wlan_hdd_restart_deinit(pHddCtx);
3874 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003875
Jeff Johnson295189b2012-06-20 16:38:30 -07003876 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003877 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003878 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003879 {
3880 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
3881 WLAN_HDD_INFRA_STATION);
3882 if (pAdapter == NULL)
3883 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3884
3885 if (pAdapter != NULL)
3886 {
3887 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
3888 hdd_UnregisterWext(pAdapter->dev);
3889 }
3890 }
3891 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003892
Jeff Johnson295189b2012-06-20 16:38:30 -07003893 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08003894 {
3895 wlan_hdd_ftm_close(pHddCtx);
3896 goto free_hdd_ctx;
3897 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003898 //Stop the Interface TX queue.
3899 //netif_tx_disable(pWlanDev);
3900 //netif_carrier_off(pWlanDev);
3901
Jeff Johnson295189b2012-06-20 16:38:30 -07003902 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3903 {
3904 pAdapter = hdd_get_adapter(pHddCtx,
3905 WLAN_HDD_SOFTAP);
3906 }
3907 else
3908 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003909 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003910 {
3911 pAdapter = hdd_get_adapter(pHddCtx,
3912 WLAN_HDD_INFRA_STATION);
3913 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003914 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003915 /* DeRegister with platform driver as client for Suspend/Resume */
3916 vosStatus = hddDeregisterPmOps(pHddCtx);
3917 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3918 {
3919 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
3920 VOS_ASSERT(0);
3921 }
3922
3923 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
3924 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3925 {
3926 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
3927 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003928
3929 // Cancel any outstanding scan requests. We are about to close all
3930 // of our adapters, but an adapter structure is what SME passes back
3931 // to our callback function. Hence if there are any outstanding scan
3932 // requests then there is a race condition between when the adapter
3933 // is closed and when the callback is invoked. We try to resolve that
3934 // race condition here by canceling any outstanding scans before we
3935 // close the adapters.
3936 // Note that the scans may be cancelled in an asynchronous manner, so
3937 // ideally there needs to be some kind of synchronization. Rather than
3938 // introduce a new synchronization here, we will utilize the fact that
3939 // we are about to Request Full Power, and since that is synchronized,
3940 // the expectation is that by the time Request Full Power has completed,
3941 // all scans will be cancelled.
3942 hdd_abort_mac_scan( pHddCtx );
3943
3944 //Disable IMPS/BMPS as we do not want the device to enter any power
3945 //save mode during shutdown
3946 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3947 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3948 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
3949
3950 //Ensure that device is in full power as we will touch H/W during vos_Stop
3951 init_completion(&powerContext.completion);
3952 powerContext.magic = POWER_CONTEXT_MAGIC;
3953
3954 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
3955 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
3956
3957 if (eHAL_STATUS_SUCCESS != halStatus)
3958 {
3959 if (eHAL_STATUS_PMC_PENDING == halStatus)
3960 {
3961 /* request was sent -- wait for the response */
3962 lrc = wait_for_completion_interruptible_timeout(
3963 &powerContext.completion,
3964 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
3965 /* either we have a response or we timed out
3966 either way, first invalidate our magic */
3967 powerContext.magic = 0;
3968 if (lrc <= 0)
3969 {
3970 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003971 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07003972 /* there is a race condition such that the callback
3973 function could be executing at the same time we are. of
3974 primary concern is if the callback function had already
3975 verified the "magic" but hasn't yet set the completion
3976 variable. Since the completion variable is on our
3977 stack, we'll delay just a bit to make sure the data is
3978 still valid if that is the case */
3979 msleep(50);
3980 }
3981 }
3982 else
3983 {
3984 hddLog(VOS_TRACE_LEVEL_ERROR,
3985 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003986 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07003987 VOS_ASSERT(0);
3988 /* continue -- need to clean up as much as possible */
3989 }
3990 }
3991
3992 // Unregister the Net Device Notifier
3993 unregister_netdevice_notifier(&hdd_netdev_notifier);
3994
Jeff Johnson295189b2012-06-20 16:38:30 -07003995 hdd_stop_all_adapters( pHddCtx );
3996
Jeff Johnson295189b2012-06-20 16:38:30 -07003997#ifdef WLAN_BTAMP_FEATURE
3998 vosStatus = WLANBAP_Stop(pVosContext);
3999 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4000 {
4001 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4002 "%s: Failed to stop BAP",__func__);
4003 }
4004#endif //WLAN_BTAMP_FEATURE
4005
4006 //Stop all the modules
4007 vosStatus = vos_stop( pVosContext );
4008 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4009 {
4010 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4011 "%s: Failed to stop VOSS",__func__);
4012 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4013 }
4014
Jeff Johnson295189b2012-06-20 16:38:30 -07004015 //Assert Deep sleep signal now to put Libra HW in lowest power state
4016 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4017 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4018
4019 //Vote off any PMIC voltage supplies
4020 vos_chipPowerDown(NULL, NULL, NULL);
4021
4022 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4023
4024 //Clean up HDD Nlink Service
4025 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4026 nl_srv_exit();
4027
4028 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004029 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004030
4031 //Close the scheduler before calling vos_close to make sure no thread is
4032 // scheduled after the each module close is called i.e after all the data
4033 // structures are freed.
4034 vosStatus = vos_sched_close( pVosContext );
4035 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4036 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4037 "%s: Failed to close VOSS Scheduler",__func__);
4038 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4039 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004040#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004041#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4042 /* Destroy the wake lock */
4043 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4044#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004045 /* Destroy the wake lock */
4046 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004047#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004048
4049 //Close VOSS
4050 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4051 vos_close(pVosContext);
4052
Jeff Johnson295189b2012-06-20 16:38:30 -07004053 //Close Watchdog
4054 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4055 vos_watchdog_close(pVosContext);
4056
4057 /* Cancel the vote for XO Core ON.
4058 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4059 * exited at this point
4060 */
4061 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4062 " when WLAN is turned OFF\n");
4063 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4064 {
4065 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4066 " Not returning failure."
4067 " Power consumed will be high\n");
4068 }
4069
4070 hdd_close_all_adapters( pHddCtx );
4071
4072
4073 //Free up dynamically allocated members inside HDD Adapter
4074 kfree(pHddCtx->cfg_ini);
4075 pHddCtx->cfg_ini= NULL;
4076
4077 /* free the power on lock from platform driver */
4078 if (free_riva_power_on_lock("wlan"))
4079 {
4080 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4081 __func__);
4082 }
4083
Jeff Johnson88ba7742013-02-27 14:36:02 -08004084free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004085 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004086 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004087 if (hdd_is_ssr_required())
4088 {
4089 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004090 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004091 msleep(5000);
4092 }
4093 hdd_set_ssr_required (VOS_FALSE);
4094}
4095
4096
4097/**---------------------------------------------------------------------------
4098
4099 \brief hdd_update_config_from_nv() - Function to update the contents of
4100 the running configuration with parameters taken from NV storage
4101
4102 \param - pHddCtx - Pointer to the HDD global context
4103
4104 \return - VOS_STATUS_SUCCESS if successful
4105
4106 --------------------------------------------------------------------------*/
4107static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4108{
Jeff Johnson295189b2012-06-20 16:38:30 -07004109 v_BOOL_t itemIsValid = VOS_FALSE;
4110 VOS_STATUS status;
4111 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4112 v_U8_t macLoop;
4113
4114 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4115 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4116 if(status != VOS_STATUS_SUCCESS)
4117 {
4118 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4119 return VOS_STATUS_E_FAILURE;
4120 }
4121
4122 if (itemIsValid == VOS_TRUE)
4123 {
4124 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4125 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4126 VOS_MAX_CONCURRENCY_PERSONA);
4127 if(status != VOS_STATUS_SUCCESS)
4128 {
4129 /* Get MAC from NV fail, not update CFG info
4130 * INI MAC value will be used for MAC setting */
4131 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4132 return VOS_STATUS_E_FAILURE;
4133 }
4134
4135 /* If first MAC is not valid, treat all others are not valid
4136 * Then all MACs will be got from ini file */
4137 if(vos_is_macaddr_zero(&macFromNV[0]))
4138 {
4139 /* MAC address in NV file is not configured yet */
4140 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4141 return VOS_STATUS_E_INVAL;
4142 }
4143
4144 /* Get MAC address from NV, update CFG info */
4145 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4146 {
4147 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
4148 {
4149 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
4150 /* This MAC is not valid, skip it
4151 * This MAC will be got from ini file */
4152 }
4153 else
4154 {
4155 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
4156 (v_U8_t *)&macFromNV[macLoop].bytes[0],
4157 VOS_MAC_ADDR_SIZE);
4158 }
4159 }
4160 }
4161 else
4162 {
4163 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
4164 return VOS_STATUS_E_FAILURE;
4165 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004166
Jeff Johnson295189b2012-06-20 16:38:30 -07004167
4168 return VOS_STATUS_SUCCESS;
4169}
4170
4171/**---------------------------------------------------------------------------
4172
4173 \brief hdd_post_voss_start_config() - HDD post voss start config helper
4174
4175 \param - pAdapter - Pointer to the HDD
4176
4177 \return - None
4178
4179 --------------------------------------------------------------------------*/
4180VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
4181{
4182 eHalStatus halStatus;
4183 v_U32_t listenInterval;
4184
Jeff Johnson295189b2012-06-20 16:38:30 -07004185
4186 // Send ready indication to the HDD. This will kick off the MAC
4187 // into a 'running' state and should kick off an initial scan.
4188 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
4189 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4190 {
4191 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
4192 "code %08d [x%08x]",__func__, halStatus, halStatus );
4193 return VOS_STATUS_E_FAILURE;
4194 }
4195
4196 // Set default LI into HDD context,
4197 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
4198 // And RIVA will crash
4199 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
4200 pHddCtx->hdd_actual_LI_value = listenInterval;
4201
4202 return VOS_STATUS_SUCCESS;
4203}
4204
Jeff Johnson295189b2012-06-20 16:38:30 -07004205/* wake lock APIs for HDD */
4206void hdd_prevent_suspend(void)
4207{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004208#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004209 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004210#else
4211 wcnss_prevent_suspend();
4212#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004213}
4214
4215void hdd_allow_suspend(void)
4216{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004217#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004218 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004219#else
4220 wcnss_allow_suspend();
4221#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004222}
4223
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004224void hdd_allow_suspend_timeout(v_U32_t timeout)
4225{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004226#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004227 wake_lock_timeout(&wlan_wake_lock, timeout);
4228#else
4229 /* Do nothing as there is no API in wcnss for timeout*/
4230#endif
4231}
4232
Jeff Johnson295189b2012-06-20 16:38:30 -07004233/**---------------------------------------------------------------------------
4234
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004235 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
4236 information between Host and Riva
4237
4238 This function gets reported version of FW
4239 It also finds the version of Riva headers used to compile the host
4240 It compares the above two and prints a warning if they are different
4241 It gets the SW and HW version string
4242 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
4243 indicating the features they support through a bitmap
4244
4245 \param - pHddCtx - Pointer to HDD context
4246
4247 \return - void
4248
4249 --------------------------------------------------------------------------*/
4250
4251void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
4252{
4253
4254 tSirVersionType versionCompiled;
4255 tSirVersionType versionReported;
4256 tSirVersionString versionString;
4257 tANI_U8 fwFeatCapsMsgSupported = 0;
4258 VOS_STATUS vstatus;
4259
4260 /* retrieve and display WCNSS version information */
4261 do {
4262
4263 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
4264 &versionCompiled);
4265 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4266 {
4267 hddLog(VOS_TRACE_LEVEL_FATAL,
4268 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004269 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004270 break;
4271 }
4272
4273 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
4274 &versionReported);
4275 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4276 {
4277 hddLog(VOS_TRACE_LEVEL_FATAL,
4278 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004279 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004280 break;
4281 }
4282
4283 if ((versionCompiled.major != versionReported.major) ||
4284 (versionCompiled.minor != versionReported.minor) ||
4285 (versionCompiled.version != versionReported.version) ||
4286 (versionCompiled.revision != versionReported.revision))
4287 {
4288 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4289 "Host expected %u.%u.%u.%u\n",
4290 WLAN_MODULE_NAME,
4291 (int)versionReported.major,
4292 (int)versionReported.minor,
4293 (int)versionReported.version,
4294 (int)versionReported.revision,
4295 (int)versionCompiled.major,
4296 (int)versionCompiled.minor,
4297 (int)versionCompiled.version,
4298 (int)versionCompiled.revision);
4299 }
4300 else
4301 {
4302 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4303 WLAN_MODULE_NAME,
4304 (int)versionReported.major,
4305 (int)versionReported.minor,
4306 (int)versionReported.version,
4307 (int)versionReported.revision);
4308 }
4309
4310 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
4311 versionString,
4312 sizeof(versionString));
4313 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4314 {
4315 hddLog(VOS_TRACE_LEVEL_FATAL,
4316 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004317 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004318 break;
4319 }
4320
4321 pr_info("%s: WCNSS software version %s\n",
4322 WLAN_MODULE_NAME, versionString);
4323
4324 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
4325 versionString,
4326 sizeof(versionString));
4327 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4328 {
4329 hddLog(VOS_TRACE_LEVEL_FATAL,
4330 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004331 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004332 break;
4333 }
4334
4335 pr_info("%s: WCNSS hardware version %s\n",
4336 WLAN_MODULE_NAME, versionString);
4337
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004338 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
4339 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004340 send the message only if it the riva is 1.1
4341 minor numbers for different riva branches:
4342 0 -> (1.0)Mainline Build
4343 1 -> (1.1)Mainline Build
4344 2->(1.04) Stability Build
4345 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004346 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004347 ((versionReported.minor>=1) && (versionReported.version>=1)))
4348 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
4349 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004350
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004351 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08004352 {
4353#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4354 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
4355 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
4356#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004357 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08004358 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004359
4360 } while (0);
4361
4362}
4363
4364/**---------------------------------------------------------------------------
4365
Jeff Johnson295189b2012-06-20 16:38:30 -07004366 \brief hdd_wlan_startup() - HDD init function
4367
4368 This is the driver startup code executed once a WLAN device has been detected
4369
4370 \param - dev - Pointer to the underlying device
4371
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004372 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07004373
4374 --------------------------------------------------------------------------*/
4375
4376int hdd_wlan_startup(struct device *dev )
4377{
4378 VOS_STATUS status;
4379 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004380 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004381 hdd_context_t *pHddCtx = NULL;
4382 v_CONTEXT_t pVosContext= NULL;
4383#ifdef WLAN_BTAMP_FEATURE
4384 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
4385 WLANBAP_ConfigType btAmpConfig;
4386 hdd_config_t *pConfig;
4387#endif
4388 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07004389 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004390
4391 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004392 /*
4393 * cfg80211: wiphy allocation
4394 */
4395 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
4396
4397 if(wiphy == NULL)
4398 {
4399 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004400 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004401 }
4402
4403 pHddCtx = wiphy_priv(wiphy);
4404
Jeff Johnson295189b2012-06-20 16:38:30 -07004405 //Initialize the adapter context to zeros.
4406 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4407
Jeff Johnson295189b2012-06-20 16:38:30 -07004408 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004409 hdd_prevent_suspend();
4410 pHddCtx->isLoadUnloadInProgress = TRUE;
4411
4412 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4413
4414 /*Get vos context here bcoz vos_open requires it*/
4415 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4416
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08004417 if(pVosContext == NULL)
4418 {
4419 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
4420 goto err_free_hdd_context;
4421 }
4422
Jeff Johnson295189b2012-06-20 16:38:30 -07004423 //Save the Global VOSS context in adapter context for future.
4424 pHddCtx->pvosContext = pVosContext;
4425
4426 //Save the adapter context in global context for future.
4427 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
4428
Jeff Johnson295189b2012-06-20 16:38:30 -07004429 pHddCtx->parent_dev = dev;
4430
4431 init_completion(&pHddCtx->full_pwr_comp_var);
4432 init_completion(&pHddCtx->standby_comp_var);
4433 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004434 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004435 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004436
4437 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
4438
4439 // Load all config first as TL config is needed during vos_open
4440 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
4441 if(pHddCtx->cfg_ini == NULL)
4442 {
4443 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
4444 goto err_free_hdd_context;
4445 }
4446
4447 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
4448
4449 // Read and parse the qcom_cfg.ini file
4450 status = hdd_parse_config_ini( pHddCtx );
4451 if ( VOS_STATUS_SUCCESS != status )
4452 {
4453 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
4454 __func__, WLAN_INI_FILE);
4455 goto err_config;
4456 }
4457
Jeff Johnson295189b2012-06-20 16:38:30 -07004458 /*
4459 * cfg80211: Initialization and registration ...
4460 */
4461 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
4462 {
4463 hddLog(VOS_TRACE_LEVEL_FATAL,
4464 "%s: wlan_hdd_cfg80211_register return failure", __func__);
4465 goto err_wiphy_reg;
4466 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004467
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004468 // Update VOS trace levels based upon the cfg.ini
4469 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
4470 pHddCtx->cfg_ini->vosTraceEnableBAP);
4471 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
4472 pHddCtx->cfg_ini->vosTraceEnableTL);
4473 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
4474 pHddCtx->cfg_ini->vosTraceEnableWDI);
4475 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
4476 pHddCtx->cfg_ini->vosTraceEnableHDD);
4477 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
4478 pHddCtx->cfg_ini->vosTraceEnableSME);
4479 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
4480 pHddCtx->cfg_ini->vosTraceEnablePE);
4481 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
4482 pHddCtx->cfg_ini->vosTraceEnableWDA);
4483 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
4484 pHddCtx->cfg_ini->vosTraceEnableSYS);
4485 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
4486 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004487 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
4488 pHddCtx->cfg_ini->vosTraceEnableSAP);
4489 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
4490 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004491
Jeff Johnson295189b2012-06-20 16:38:30 -07004492 // Update WDI trace levels based upon the cfg.ini
4493 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
4494 pHddCtx->cfg_ini->wdiTraceEnableDAL);
4495 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
4496 pHddCtx->cfg_ini->wdiTraceEnableCTL);
4497 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
4498 pHddCtx->cfg_ini->wdiTraceEnableDAT);
4499 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
4500 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004501
Jeff Johnson88ba7742013-02-27 14:36:02 -08004502 if (VOS_FTM_MODE == hdd_get_conparam())
4503 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004504 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
4505 {
4506 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
4507 goto err_free_hdd_context;
4508 }
4509 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
4510 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08004511 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004512
Jeff Johnson88ba7742013-02-27 14:36:02 -08004513 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07004514 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4515 {
4516 status = vos_watchdog_open(pVosContext,
4517 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4518
4519 if(!VOS_IS_STATUS_SUCCESS( status ))
4520 {
4521 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004522 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07004523 }
4524 }
4525
4526 pHddCtx->isLogpInProgress = FALSE;
4527 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4528
Jeff Johnson295189b2012-06-20 16:38:30 -07004529 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
4530 if(!VOS_IS_STATUS_SUCCESS(status))
4531 {
4532 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004533 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004534 }
4535
Jeff Johnson295189b2012-06-20 16:38:30 -07004536 status = vos_open( &pVosContext, 0);
4537 if ( !VOS_IS_STATUS_SUCCESS( status ))
4538 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004539 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
4540 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07004541 }
4542
Jeff Johnson295189b2012-06-20 16:38:30 -07004543 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
4544
4545 if ( NULL == pHddCtx->hHal )
4546 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004547 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004548 goto err_vosclose;
4549 }
4550
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004551 status = vos_preStart( pHddCtx->pvosContext );
4552 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4553 {
4554 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
4555 goto err_vosclose;
4556 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004557
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004558 /* Note that the vos_preStart() sequence triggers the cfg download.
4559 The cfg download must occur before we update the SME config
4560 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07004561 status = hdd_set_sme_config( pHddCtx );
4562
4563 if ( VOS_STATUS_SUCCESS != status )
4564 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004565 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
4566 goto err_vosclose;
4567 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004568
4569 //Initialize the WMM module
4570 status = hdd_wmm_init(pHddCtx);
4571 if (!VOS_IS_STATUS_SUCCESS(status))
4572 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004573 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004574 goto err_vosclose;
4575 }
4576
Jeff Johnson295189b2012-06-20 16:38:30 -07004577 /* In the integrated architecture we update the configuration from
4578 the INI file and from NV before vOSS has been started so that
4579 the final contents are available to send down to the cCPU */
4580
4581 // Apply the cfg.ini to cfg.dat
4582 if (FALSE == hdd_update_config_dat(pHddCtx))
4583 {
4584 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4585 goto err_vosclose;
4586 }
4587
4588 // Apply the NV to cfg.dat
4589 /* Prima Update MAC address only at here */
4590 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
4591 {
4592#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
4593 /* There was not a valid set of MAC Addresses in NV. See if the
4594 default addresses were modified by the cfg.ini settings. If so,
4595 we'll use them, but if not, we'll autogenerate a set of MAC
4596 addresses based upon the device serial number */
4597
4598 static const v_MACADDR_t default_address =
4599 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
4600 unsigned int serialno;
4601 int i;
4602
4603 serialno = wcnss_get_serial_number();
4604 if ((0 != serialno) &&
4605 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
4606 sizeof(default_address))))
4607 {
4608 /* cfg.ini has the default address, invoke autogen logic */
4609
4610 /* MAC address has 3 bytes of OUI so we have a maximum of 3
4611 bytes of the serial number that can be used to generate
4612 the other 3 bytes of the MAC address. Mask off all but
4613 the lower 3 bytes (this will also make sure we don't
4614 overflow in the next step) */
4615 serialno &= 0x00FFFFFF;
4616
4617 /* we need a unique address for each session */
4618 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
4619
4620 /* autogen all addresses */
4621 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4622 {
4623 /* start with the entire default address */
4624 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4625 /* then replace the lower 3 bytes */
4626 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
4627 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
4628 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4629
4630 serialno++;
4631 }
4632
4633 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4634 MAC_ADDRESS_STR,
4635 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4636 }
4637 else
4638#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4639 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004640 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004641 "%s: Invalid MAC address in NV, using MAC from ini file "
4642 MAC_ADDRESS_STR, __func__,
4643 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4644 }
4645 }
4646 {
4647 eHalStatus halStatus;
4648 // Set the MAC Address
4649 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4650 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4651 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
4652 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
4653
4654 if (!HAL_STATUS_SUCCESS( halStatus ))
4655 {
4656 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
4657 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08004658 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004659 }
4660 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004661
4662 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
4663 Note: Firmware image will be read and downloaded inside vos_start API */
4664 status = vos_start( pHddCtx->pvosContext );
4665 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4666 {
4667 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
4668 goto err_vosclose;
4669 }
4670
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004671 /* Exchange capability info between Host and FW and also get versioning info from FW */
4672 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004673
4674 status = hdd_post_voss_start_config( pHddCtx );
4675 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4676 {
4677 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
4678 __func__);
4679 goto err_vosstop;
4680 }
4681
Jeff Johnson295189b2012-06-20 16:38:30 -07004682 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4683 {
4684 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
4685 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4686 }
4687 else
4688 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004689 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
4690 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4691 if (pAdapter != NULL)
4692 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304693 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07004694 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304695 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
4696 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
4697 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07004698
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304699 /* Generate the P2P Device Address. This consists of the device's
4700 * primary MAC address with the locally administered bit set.
4701 */
4702 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07004703 }
4704 else
4705 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304706 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
4707 if (p2p_dev_addr != NULL)
4708 {
4709 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
4710 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
4711 }
4712 else
4713 {
4714 hddLog(VOS_TRACE_LEVEL_FATAL,
4715 "%s: Failed to allocate mac_address for p2p_device",
4716 __func__);
4717 goto err_close_adapter;
4718 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004719 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004720
4721 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
4722 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
4723 if ( NULL == pP2pAdapter )
4724 {
4725 hddLog(VOS_TRACE_LEVEL_FATAL,
4726 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004727 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004728 goto err_close_adapter;
4729 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004730 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004731 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004732
4733 if( pAdapter == NULL )
4734 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004735 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
4736 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004737 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004738
Jeff Johnson295189b2012-06-20 16:38:30 -07004739#ifdef WLAN_BTAMP_FEATURE
4740 vStatus = WLANBAP_Open(pVosContext);
4741 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4742 {
4743 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4744 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004745 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004746 }
4747
4748 vStatus = BSL_Init(pVosContext);
4749 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4750 {
4751 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4752 "%s: Failed to Init BSL",__func__);
4753 goto err_bap_close;
4754 }
4755 vStatus = WLANBAP_Start(pVosContext);
4756 if (!VOS_IS_STATUS_SUCCESS(vStatus))
4757 {
4758 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4759 "%s: Failed to start TL",__func__);
4760 goto err_bap_close;
4761 }
4762
4763 pConfig = pHddCtx->cfg_ini;
4764 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
4765 status = WLANBAP_SetConfig(&btAmpConfig);
4766
4767#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07004768
Jeff Johnson295189b2012-06-20 16:38:30 -07004769#ifdef FEATURE_WLAN_SCAN_PNO
4770 /*SME must send channel update configuration to RIVA*/
4771 sme_UpdateChannelConfig(pHddCtx->hHal);
4772#endif
4773
Jeff Johnson295189b2012-06-20 16:38:30 -07004774 /* Register with platform driver as client for Suspend/Resume */
4775 status = hddRegisterPmOps(pHddCtx);
4776 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4777 {
4778 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
4779#ifdef WLAN_BTAMP_FEATURE
4780 goto err_bap_stop;
4781#else
Jeff Johnsone7245742012-09-05 17:12:55 -07004782 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004783#endif //WLAN_BTAMP_FEATURE
4784 }
4785
4786 /* Register TM level change handler function to the platform */
4787 status = hddDevTmRegisterNotifyCallback(pHddCtx);
4788 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4789 {
4790 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
4791 goto err_unregister_pmops;
4792 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004793
4794 /* register for riva power on lock to platform driver */
4795 if (req_riva_power_on_lock("wlan"))
4796 {
4797 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
4798 __func__);
4799 goto err_unregister_pmops;
4800 }
4801
Jeff Johnson295189b2012-06-20 16:38:30 -07004802 // register net device notifier for device change notification
4803 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4804
4805 if(ret < 0)
4806 {
4807 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
4808 goto err_free_power_on_lock;
4809 }
4810
4811 //Initialize the nlink service
4812 if(nl_srv_init() != 0)
4813 {
4814 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
4815 goto err_reg_netdev;
4816 }
4817
4818 //Initialize the BTC service
4819 if(btc_activate_service(pHddCtx) != 0)
4820 {
4821 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
4822 goto err_nl_srv;
4823 }
4824
4825#ifdef PTT_SOCK_SVC_ENABLE
4826 //Initialize the PTT service
4827 if(ptt_sock_activate_svc(pHddCtx) != 0)
4828 {
4829 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
4830 goto err_nl_srv;
4831 }
4832#endif
4833
Jeff Johnson295189b2012-06-20 16:38:30 -07004834 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004835 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004836 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07004837 /* Action frame registered in one adapter which will
4838 * applicable to all interfaces
4839 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07004840 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004841 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004842
4843 mutex_init(&pHddCtx->sap_lock);
4844
4845 pHddCtx->isLoadUnloadInProgress = FALSE;
4846
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004847#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004848#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4849 /* Initialize the wake lcok */
4850 wake_lock_init(&pHddCtx->rx_wake_lock,
4851 WAKE_LOCK_SUSPEND,
4852 "qcom_rx_wakelock");
4853#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004854 /* Initialize the wake lcok */
4855 wake_lock_init(&pHddCtx->sap_wake_lock,
4856 WAKE_LOCK_SUSPEND,
4857 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004858#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004859
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004860 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
4861 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07004862
4863 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4864 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004865
4866 // Initialize the restart logic
4867 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304868
Jeff Johnson295189b2012-06-20 16:38:30 -07004869 goto success;
4870
4871err_nl_srv:
4872 nl_srv_exit();
4873
4874err_reg_netdev:
4875 unregister_netdevice_notifier(&hdd_netdev_notifier);
4876
4877err_free_power_on_lock:
4878 free_riva_power_on_lock("wlan");
4879
4880err_unregister_pmops:
4881 hddDevTmUnregisterNotifyCallback(pHddCtx);
4882 hddDeregisterPmOps(pHddCtx);
4883
4884#ifdef WLAN_BTAMP_FEATURE
4885err_bap_stop:
4886 WLANBAP_Stop(pVosContext);
4887#endif
4888
4889#ifdef WLAN_BTAMP_FEATURE
4890err_bap_close:
4891 WLANBAP_Close(pVosContext);
4892#endif
4893
Jeff Johnson295189b2012-06-20 16:38:30 -07004894err_close_adapter:
4895 hdd_close_all_adapters( pHddCtx );
4896
4897err_vosstop:
4898 vos_stop(pVosContext);
4899
4900err_vosclose:
4901 status = vos_sched_close( pVosContext );
4902 if (!VOS_IS_STATUS_SUCCESS(status)) {
4903 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4904 "%s: Failed to close VOSS Scheduler", __func__);
4905 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4906 }
4907 vos_close(pVosContext );
4908
Jeff Johnson295189b2012-06-20 16:38:30 -07004909err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004910 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004911
4912err_wdclose:
4913 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4914 vos_watchdog_close(pVosContext);
4915
Jeff Johnson295189b2012-06-20 16:38:30 -07004916err_wiphy_reg:
4917 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004918
4919err_config:
4920 kfree(pHddCtx->cfg_ini);
4921 pHddCtx->cfg_ini= NULL;
4922
4923err_free_hdd_context:
4924 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004925 wiphy_free(wiphy) ;
4926 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004927 VOS_BUG(1);
4928
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004929 if (hdd_is_ssr_required())
4930 {
4931 /* WDI timeout had happened during load, so SSR is needed here */
4932 subsystem_restart("wcnss");
4933 msleep(5000);
4934 }
4935 hdd_set_ssr_required (VOS_FALSE);
4936
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004937 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004938
4939success:
4940 EXIT();
4941 return 0;
4942}
4943
4944/**---------------------------------------------------------------------------
4945
Jeff Johnson32d95a32012-09-10 13:15:23 -07004946 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004947
Jeff Johnson32d95a32012-09-10 13:15:23 -07004948 This is the driver entry point - called in different timeline depending
4949 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004950
4951 \param - None
4952
4953 \return - 0 for success, non zero for failure
4954
4955 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004956static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004957{
4958 VOS_STATUS status;
4959 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004960 struct device *dev = NULL;
4961 int ret_status = 0;
4962
4963 ENTER();
4964
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004965#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004966 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004967#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004968
4969 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4970 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4971
4972 //Power Up Libra WLAN card first if not already powered up
4973 status = vos_chipPowerUp(NULL,NULL,NULL);
4974 if (!VOS_IS_STATUS_SUCCESS(status))
4975 {
4976 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4977 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004978 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004979 }
4980
Jeff Johnson295189b2012-06-20 16:38:30 -07004981#ifdef ANI_BUS_TYPE_PCI
4982
4983 dev = wcnss_wlan_get_device();
4984
4985#endif // ANI_BUS_TYPE_PCI
4986
4987#ifdef ANI_BUS_TYPE_PLATFORM
4988 dev = wcnss_wlan_get_device();
4989#endif // ANI_BUS_TYPE_PLATFORM
4990
4991
4992 do {
4993 if (NULL == dev) {
4994 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4995 ret_status = -1;
4996 break;
4997 }
4998
4999#ifdef MEMORY_DEBUG
5000 vos_mem_init();
5001#endif
5002
5003#ifdef TIMER_MANAGER
5004 vos_timer_manager_init();
5005#endif
5006
5007 /* Preopen VOSS so that it is ready to start at least SAL */
5008 status = vos_preOpen(&pVosContext);
5009
5010 if (!VOS_IS_STATUS_SUCCESS(status))
5011 {
5012 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5013 ret_status = -1;
5014 break;
5015 }
5016
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005017#ifndef MODULE
5018 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5019 */
5020 hdd_set_conparam((v_UINT_t)con_mode);
5021#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005022
5023 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005024 if (hdd_wlan_startup(dev))
5025 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005026 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005027 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005028 vos_preClose( &pVosContext );
5029 ret_status = -1;
5030 break;
5031 }
5032
5033 /* Cancel the vote for XO Core ON
5034 * This is done here for safety purposes in case we re-initialize without turning
5035 * it OFF in any error scenario.
5036 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005037 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005038 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005039 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005040 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5041 {
5042 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5043 " Power consumed will be high\n");
5044 }
5045 } while (0);
5046
5047 if (0 != ret_status)
5048 {
5049 //Assert Deep sleep signal now to put Libra HW in lowest power state
5050 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5051 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5052
5053 //Vote off any PMIC voltage supplies
5054 vos_chipPowerDown(NULL, NULL, NULL);
5055#ifdef TIMER_MANAGER
5056 vos_timer_exit();
5057#endif
5058#ifdef MEMORY_DEBUG
5059 vos_mem_exit();
5060#endif
5061
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005062#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005063 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005064#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005065 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5066 }
5067 else
5068 {
5069 //Send WLAN UP indication to Nlink Service
5070 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5071
5072 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5073
5074 }
5075
5076 EXIT();
5077
5078 return ret_status;
5079}
5080
Jeff Johnson32d95a32012-09-10 13:15:23 -07005081/**---------------------------------------------------------------------------
5082
5083 \brief hdd_module_init() - Init Function
5084
5085 This is the driver entry point (invoked when module is loaded using insmod)
5086
5087 \param - None
5088
5089 \return - 0 for success, non zero for failure
5090
5091 --------------------------------------------------------------------------*/
5092#ifdef MODULE
5093static int __init hdd_module_init ( void)
5094{
5095 return hdd_driver_init();
5096}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005097#else /* #ifdef MODULE */
5098static int __init hdd_module_init ( void)
5099{
5100 /* Driver initialization is delayed to fwpath_changed_handler */
5101 return 0;
5102}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005103#endif /* #ifdef MODULE */
5104
Jeff Johnson295189b2012-06-20 16:38:30 -07005105
5106/**---------------------------------------------------------------------------
5107
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005108 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005109
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005110 This is the driver exit point (invoked when module is unloaded using rmmod
5111 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005112
5113 \param - None
5114
5115 \return - None
5116
5117 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005118static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005119{
5120 hdd_context_t *pHddCtx = NULL;
5121 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005122
5123 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
5124
5125 //Get the global vos context
5126 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5127
5128 if(!pVosContext)
5129 {
5130 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
5131 goto done;
5132 }
5133
5134 //Get the HDD context.
5135 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
5136
5137 if(!pHddCtx)
5138 {
5139 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
5140 }
5141 else
5142 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005143 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005144 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07005145 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
5146 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07005147 }
5148
5149 pHddCtx->isLoadUnloadInProgress = TRUE;
5150 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5151
5152 //Do all the cleanup before deregistering the driver
5153 hdd_wlan_exit(pHddCtx);
5154 }
5155
Jeff Johnson295189b2012-06-20 16:38:30 -07005156 vos_preClose( &pVosContext );
5157
5158#ifdef TIMER_MANAGER
5159 vos_timer_exit();
5160#endif
5161#ifdef MEMORY_DEBUG
5162 vos_mem_exit();
5163#endif
5164
5165done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005166#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005167 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005168#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005169 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
5170}
5171
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005172/**---------------------------------------------------------------------------
5173
5174 \brief hdd_module_exit() - Exit function
5175
5176 This is the driver exit point (invoked when module is unloaded using rmmod)
5177
5178 \param - None
5179
5180 \return - None
5181
5182 --------------------------------------------------------------------------*/
5183static void __exit hdd_module_exit(void)
5184{
5185 hdd_driver_exit();
5186}
5187
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005188#ifdef MODULE
5189static int fwpath_changed_handler(const char *kmessage,
5190 struct kernel_param *kp)
5191{
5192 /* nothing to do when driver is DLKM */
5193 return 0;
5194}
5195
5196static int con_mode_handler(const char *kmessage,
5197 struct kernel_param *kp)
5198{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005199 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005200}
5201#else /* #ifdef MODULE */
5202/**---------------------------------------------------------------------------
5203
5204 \brief fwpath_changed_handler() - Handler Function
5205
5206 This is the driver entry point
5207 - delayed driver initialization when driver is statically linked
5208 - invoked when module parameter fwpath is modified from userpspace to signal
5209 initializing the WLAN driver
5210
5211 \return - 0 for success, non zero for failure
5212
5213 --------------------------------------------------------------------------*/
5214static int fwpath_changed_handler(const char *kmessage,
5215 struct kernel_param *kp)
5216{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005217 int ret_status;
5218
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005219 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005220 ret_status = hdd_driver_init();
5221 wlan_hdd_inited = ret_status ? 0 : 1;
5222 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005223 }
5224
5225 hdd_driver_exit();
5226
5227 msleep(200);
5228
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005229 ret_status = hdd_driver_init();
5230 wlan_hdd_inited = ret_status ? 0 : 1;
5231 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005232}
5233
Jeff Johnson295189b2012-06-20 16:38:30 -07005234/**---------------------------------------------------------------------------
5235
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005236 \brief con_mode_handler() -
5237
5238 Handler function for module param con_mode when it is changed by userspace
5239 Dynamically linked - do nothing
5240 Statically linked - exit and init driver, as in rmmod and insmod
5241
5242 \param -
5243
5244 \return -
5245
5246 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005247static int con_mode_handler(const char *kmessage,
5248 struct kernel_param *kp)
5249{
5250 int ret = param_set_int(kmessage, kp);
5251
5252 if (ret)
5253 return ret;
5254
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005255 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005256}
5257#endif /* #ifdef MODULE */
5258
5259/**---------------------------------------------------------------------------
5260
Jeff Johnson295189b2012-06-20 16:38:30 -07005261 \brief hdd_get_conparam() -
5262
5263 This is the driver exit point (invoked when module is unloaded using rmmod)
5264
5265 \param - None
5266
5267 \return - tVOS_CON_MODE
5268
5269 --------------------------------------------------------------------------*/
5270tVOS_CON_MODE hdd_get_conparam ( void )
5271{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005272#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005273 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005274#else
5275 return (tVOS_CON_MODE)curr_con_mode;
5276#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005277}
5278void hdd_set_conparam ( v_UINT_t newParam )
5279{
5280 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005281#ifndef MODULE
5282 curr_con_mode = con_mode;
5283#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005284}
5285/**---------------------------------------------------------------------------
5286
5287 \brief hdd_softap_sta_deauth() - function
5288
5289 This to take counter measure to handle deauth req from HDD
5290
5291 \param - pAdapter - Pointer to the HDD
5292
5293 \param - enable - boolean value
5294
5295 \return - None
5296
5297 --------------------------------------------------------------------------*/
5298
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005299VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005300{
Jeff Johnson295189b2012-06-20 16:38:30 -07005301 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005302 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005303
5304 ENTER();
5305
5306 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5307
5308 //Ignore request to deauth bcmc station
5309 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005310 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005311
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005312 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005313
5314 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005315 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005316}
5317
5318/**---------------------------------------------------------------------------
5319
5320 \brief hdd_softap_sta_disassoc() - function
5321
5322 This to take counter measure to handle deauth req from HDD
5323
5324 \param - pAdapter - Pointer to the HDD
5325
5326 \param - enable - boolean value
5327
5328 \return - None
5329
5330 --------------------------------------------------------------------------*/
5331
5332void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5333{
5334 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5335
5336 ENTER();
5337
5338 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5339
5340 //Ignore request to disassoc bcmc station
5341 if( pDestMacAddress[0] & 0x1 )
5342 return;
5343
5344 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5345}
5346
5347void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5348{
5349 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5350
5351 ENTER();
5352
5353 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5354
5355 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5356}
5357
Jeff Johnson295189b2012-06-20 16:38:30 -07005358/**---------------------------------------------------------------------------
5359 *
5360 * \brief hdd_get__concurrency_mode() -
5361 *
5362 *
5363 * \param - None
5364 *
5365 * \return - CONCURRENCY MODE
5366 *
5367 * --------------------------------------------------------------------------*/
5368tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
5369{
5370 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5371 hdd_context_t *pHddCtx;
5372
5373 if (NULL != pVosContext)
5374 {
5375 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5376 if (NULL != pHddCtx)
5377 {
5378 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
5379 }
5380 }
5381
5382 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005383 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005384 return VOS_STA;
5385}
5386
5387/* Decide whether to allow/not the apps power collapse.
5388 * Allow apps power collapse if we are in connected state.
5389 * if not, allow only if we are in IMPS */
5390v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
5391{
5392 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08005393 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005394 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005395 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5396 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5397 hdd_adapter_t *pAdapter = NULL;
5398 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08005399 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005400
Jeff Johnson295189b2012-06-20 16:38:30 -07005401 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5402 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005403
Yathish9f22e662012-12-10 14:21:35 -08005404 concurrent_state = hdd_get_concurrency_mode();
5405
5406#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5407 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
5408 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
5409 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
5410 return TRUE;
5411#endif
5412
Jeff Johnson295189b2012-06-20 16:38:30 -07005413 /*loop through all adapters. TBD fix for Concurrency */
5414 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5415 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5416 {
5417 pAdapter = pAdapterNode->pAdapter;
5418 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
5419 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5420 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005421 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07005422 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08005423 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005424 (eANI_BOOLEAN_TRUE == scanRspPending) ||
5425 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07005426 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005427 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005428 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
5429 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07005430 return FALSE;
5431 }
5432 }
5433 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5434 pAdapterNode = pNext;
5435 }
5436 return TRUE;
5437}
5438
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08005439/* Decides whether to send suspend notification to Riva
5440 * if any adapter is in BMPS; then it is required */
5441v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
5442{
5443 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
5444 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5445
5446 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
5447 {
5448 return TRUE;
5449 }
5450 return FALSE;
5451}
5452
Jeff Johnson295189b2012-06-20 16:38:30 -07005453void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5454{
5455 switch(mode)
5456 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005457 case VOS_STA_MODE:
5458 case VOS_P2P_CLIENT_MODE:
5459 case VOS_P2P_GO_MODE:
5460 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07005461 pHddCtx->concurrency_mode |= (1 << mode);
5462 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07005463 break;
5464 default:
5465 break;
5466
5467 }
5468 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5469 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5470}
5471
5472
5473void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5474{
5475 switch(mode)
5476 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005477 case VOS_STA_MODE:
5478 case VOS_P2P_CLIENT_MODE:
5479 case VOS_P2P_GO_MODE:
5480 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005481 pHddCtx->no_of_sessions[mode]--;
5482 if (!(pHddCtx->no_of_sessions[mode]))
5483 pHddCtx->concurrency_mode &= (~(1 << mode));
5484 break;
5485 default:
5486 break;
5487 }
5488 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5489 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5490}
5491
Jeff Johnsone7245742012-09-05 17:12:55 -07005492/**---------------------------------------------------------------------------
5493 *
5494 * \brief wlan_hdd_restart_init
5495 *
5496 * This function initalizes restart timer/flag. An internal function.
5497 *
5498 * \param - pHddCtx
5499 *
5500 * \return - None
5501 *
5502 * --------------------------------------------------------------------------*/
5503
5504static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
5505{
5506 /* Initialize */
5507 pHddCtx->hdd_restart_retries = 0;
5508 atomic_set(&pHddCtx->isRestartInProgress, 0);
5509 vos_timer_init(&pHddCtx->hdd_restart_timer,
5510 VOS_TIMER_TYPE_SW,
5511 wlan_hdd_restart_timer_cb,
5512 pHddCtx);
5513}
5514/**---------------------------------------------------------------------------
5515 *
5516 * \brief wlan_hdd_restart_deinit
5517 *
5518 * This function cleans up the resources used. An internal function.
5519 *
5520 * \param - pHddCtx
5521 *
5522 * \return - None
5523 *
5524 * --------------------------------------------------------------------------*/
5525
5526static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
5527{
5528
5529 VOS_STATUS vos_status;
5530 /* Block any further calls */
5531 atomic_set(&pHddCtx->isRestartInProgress, 1);
5532 /* Cleanup */
5533 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5534 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005535 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005536 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5537 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005538 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005539
5540}
5541
5542/**---------------------------------------------------------------------------
5543 *
5544 * \brief wlan_hdd_framework_restart
5545 *
5546 * This function uses a cfg80211 API to start a framework initiated WLAN
5547 * driver module unload/load.
5548 *
5549 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
5550 *
5551 *
5552 * \param - pHddCtx
5553 *
5554 * \return - VOS_STATUS_SUCCESS: Success
5555 * VOS_STATUS_E_EMPTY: Adapter is Empty
5556 * VOS_STATUS_E_NOMEM: No memory
5557
5558 * --------------------------------------------------------------------------*/
5559
5560static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
5561{
5562 VOS_STATUS status = VOS_STATUS_SUCCESS;
5563 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5564 int len = (sizeof (struct ieee80211_mgmt));
5565 struct ieee80211_mgmt *mgmt = NULL;
5566
5567 /* Prepare the DEAUTH managment frame with reason code */
5568 mgmt = kzalloc(len, GFP_KERNEL);
5569 if(mgmt == NULL)
5570 {
5571 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08005572 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07005573 return VOS_STATUS_E_NOMEM;
5574 }
5575 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
5576
5577 /* Iterate over all adapters/devices */
5578 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5579 do
5580 {
5581 if( (status == VOS_STATUS_SUCCESS) &&
5582 pAdapterNode &&
5583 pAdapterNode->pAdapter)
5584 {
5585 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5586 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
5587 pAdapterNode->pAdapter->dev->name,
5588 pAdapterNode->pAdapter->device_mode,
5589 pHddCtx->hdd_restart_retries + 1);
5590 /*
5591 * CFG80211 event to restart the driver
5592 *
5593 * 'cfg80211_send_unprot_deauth' sends a
5594 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
5595 * of SME(Linux Kernel) state machine.
5596 *
5597 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
5598 * the driver.
5599 *
5600 */
5601
5602 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
5603 }
5604 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5605 pAdapterNode = pNext;
5606 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
5607
5608
5609 /* Free the allocated management frame */
5610 kfree(mgmt);
5611
5612 /* Retry until we unload or reach max count */
5613 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
5614 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
5615
5616 return status;
5617
5618}
5619/**---------------------------------------------------------------------------
5620 *
5621 * \brief wlan_hdd_restart_timer_cb
5622 *
5623 * Restart timer callback. An internal function.
5624 *
5625 * \param - User data:
5626 *
5627 * \return - None
5628 *
5629 * --------------------------------------------------------------------------*/
5630
5631void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
5632{
5633 hdd_context_t *pHddCtx = usrDataForCallback;
5634 wlan_hdd_framework_restart(pHddCtx);
5635 return;
5636
5637}
5638
5639
5640/**---------------------------------------------------------------------------
5641 *
5642 * \brief wlan_hdd_restart_driver
5643 *
5644 * This function sends an event to supplicant to restart the WLAN driver.
5645 *
5646 * This function is called from vos_wlanRestart.
5647 *
5648 * \param - pHddCtx
5649 *
5650 * \return - VOS_STATUS_SUCCESS: Success
5651 * VOS_STATUS_E_EMPTY: Adapter is Empty
5652 * VOS_STATUS_E_ALREADY: Request already in progress
5653
5654 * --------------------------------------------------------------------------*/
5655VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
5656{
5657 VOS_STATUS status = VOS_STATUS_SUCCESS;
5658
5659 /* A tight check to make sure reentrancy */
5660 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
5661 {
5662 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
5663 "%s: WLAN restart is already in progress", __func__);
5664
5665 return VOS_STATUS_E_ALREADY;
5666 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07005667 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005668#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005669 wcnss_reset_intr();
5670#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005671
Jeff Johnsone7245742012-09-05 17:12:55 -07005672 return status;
5673}
5674
5675
Jeff Johnson295189b2012-06-20 16:38:30 -07005676//Register the module init/exit functions
5677module_init(hdd_module_init);
5678module_exit(hdd_module_exit);
5679
5680MODULE_LICENSE("Dual BSD/GPL");
5681MODULE_AUTHOR("Qualcomm Atheros, Inc.");
5682MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
5683
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005684module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
5685 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005686
5687module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
5688 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);