blob: 83a17943de48cf5d4bbc91e23a3e3efee9096084 [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;
892 tANI_U8 len = 0, j = 0;
893 char extra[128] = {0};
894
895 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
896 ChannelList, &numChannels ))
897 {
898 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
899 "%s: failed to get roam scan channel list", __func__);
900 ret = -EFAULT;
901 goto exit;
902 }
903 /* output channel list is of the format
904 [Number of roam scan channels][Channel1][Channel2]... */
905 /* copy the number of channels in the 0th index */
906 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
907 for (j = 0; (j < numChannels); j++)
908 {
909 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
910 }
911
912 if (copy_to_user(priv_data.buf, &extra, len + 1))
913 {
914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
915 "%s: failed to copy data to user buffer", __func__);
916 ret = -EFAULT;
917 goto exit;
918 }
919 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -0700920 else if (strncmp(command, "GETCCXMODE", 10) == 0)
921 {
922 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
923 char extra[32];
924 tANI_U8 len = 0;
925
926 len = snprintf(extra, sizeof(extra), "%s %d", "GETCCXMODE", ccxMode);
927 if (copy_to_user(priv_data.buf, &extra, len + 1))
928 {
929 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
930 "%s: failed to copy data to user buffer", __func__);
931 ret = -EFAULT;
932 goto exit;
933 }
934 }
935 else if (strncmp(command, "GETOKCMODE", 10) == 0)
936 {
937 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
938 char extra[32];
939 tANI_U8 len = 0;
940
941 len = snprintf(extra, sizeof(extra), "%s %d", "GETOKCMODE", okcMode);
942 if (copy_to_user(priv_data.buf, &extra, len + 1))
943 {
944 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
945 "%s: failed to copy data to user buffer", __func__);
946 ret = -EFAULT;
947 goto exit;
948 }
949 }
950 else if (strncmp(command, "GETFASTROAM", 10) == 0)
951 {
952 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
953 char extra[32];
954 tANI_U8 len = 0;
955
956 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTROAM", lfrMode);
957 if (copy_to_user(priv_data.buf, &extra, len + 1))
958 {
959 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
960 "%s: failed to copy data to user buffer", __func__);
961 ret = -EFAULT;
962 goto exit;
963 }
964 }
965 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
966 {
967 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
968 char extra[32];
969 tANI_U8 len = 0;
970
971 len = snprintf(extra, sizeof(extra), "%s %d", "GETFASTTRANSITION", ft);
972 if (copy_to_user(priv_data.buf, &extra, len + 1))
973 {
974 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
975 "%s: failed to copy data to user buffer", __func__);
976 ret = -EFAULT;
977 goto exit;
978 }
979 }
980 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
981 {
982 tANI_U8 *value = command;
983 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
984
985 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
986 value = value + 26;
987 /* Convert the value from ascii to integer */
988 ret = kstrtou8(value, 10, &minTime);
989 if (ret < 0)
990 {
991 /* If the input value is greater than max value of datatype, then also
992 kstrtou8 fails */
993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
994 "%s: kstrtou8 failed range [%d - %d]", __func__,
995 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
996 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
997 ret = -EINVAL;
998 goto exit;
999 }
1000
1001 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
1002 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
1003 {
1004 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1005 "scan min channel time value %d is out of range"
1006 " (Min: %d Max: %d)", minTime,
1007 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
1008 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
1009 ret = -EINVAL;
1010 goto exit;
1011 }
1012
1013 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1014 "%s: Received Command to change channel min time = %d", __func__, minTime);
1015
1016 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
1017 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
1018 }
1019 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
1020 {
1021 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
1022 char extra[32];
1023 tANI_U8 len = 0;
1024
1025 /* value is interms of msec */
1026 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANCHANNELMINTIME", val);
1027 if (copy_to_user(priv_data.buf, &extra, len + 1))
1028 {
1029 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1030 "%s: failed to copy data to user buffer", __func__);
1031 ret = -EFAULT;
1032 goto exit;
1033 }
1034 }
1035 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
1036 {
1037 tANI_U8 *value = command;
1038 tANI_U8 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
1039
1040 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
1041 value = value + 19;
1042 /* Convert the value from ascii to integer */
1043 ret = kstrtou8(value, 10, &maxTime);
1044 if (ret < 0)
1045 {
1046 /* If the input value is greater than max value of datatype, then also
1047 kstrtou8 fails */
1048 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1049 "%s: kstrtou8 failed range [%d - %d]", __func__,
1050 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1051 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1052 ret = -EINVAL;
1053 goto exit;
1054 }
1055
1056 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
1057 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
1058 {
1059 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1060 "lfr mode value %d is out of range"
1061 " (Min: %d Max: %d)", maxTime,
1062 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
1063 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
1064 ret = -EINVAL;
1065 goto exit;
1066 }
1067
1068 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1069 "%s: Received Command to change channel max time = %d", __func__, maxTime);
1070
1071 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
1072 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
1073 }
1074 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
1075 {
1076 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
1077 char extra[32];
1078 tANI_U8 len = 0;
1079
1080 /* value is interms of msec */
1081 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANCHANNELTIME", val);
1082 if (copy_to_user(priv_data.buf, &extra, len + 1))
1083 {
1084 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1085 "%s: failed to copy data to user buffer", __func__);
1086 ret = -EFAULT;
1087 goto exit;
1088 }
1089 }
1090 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
1091 {
1092 tANI_U8 *value = command;
1093 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
1094
1095 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
1096 value = value + 16;
1097 /* Convert the value from ascii to integer */
1098 ret = kstrtou16(value, 10, &val);
1099 if (ret < 0)
1100 {
1101 /* If the input value is greater than max value of datatype, then also
1102 kstrtou16 fails */
1103 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1104 "%s: kstrtou16 failed range [%d - %d]", __func__,
1105 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1106 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1107 ret = -EINVAL;
1108 goto exit;
1109 }
1110
1111 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
1112 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
1113 {
1114 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1115 "scan home time value %d is out of range"
1116 " (Min: %d Max: %d)", val,
1117 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
1118 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
1119 ret = -EINVAL;
1120 goto exit;
1121 }
1122
1123 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1124 "%s: Received Command to change scan home time = %d", __func__, val);
1125
1126 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
1127 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
1128 }
1129 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
1130 {
1131 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
1132 char extra[32];
1133 tANI_U8 len = 0;
1134
1135 /* value is interms of msec */
1136 len = snprintf(extra, sizeof(extra), "%s %d", "GETSCANHOMETIME", val);
1137 if (copy_to_user(priv_data.buf, &extra, len + 1))
1138 {
1139 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1140 "%s: failed to copy data to user buffer", __func__);
1141 ret = -EFAULT;
1142 goto exit;
1143 }
1144 }
1145 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
1146 {
1147 tANI_U8 *value = command;
1148 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
1149
1150 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
1151 value = value + 17;
1152 /* Convert the value from ascii to integer */
1153 ret = kstrtou8(value, 10, &val);
1154 if (ret < 0)
1155 {
1156 /* If the input value is greater than max value of datatype, then also
1157 kstrtou8 fails */
1158 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1159 "%s: kstrtou8 failed range [%d - %d]", __func__,
1160 CFG_ROAM_INTRA_BAND_MIN,
1161 CFG_ROAM_INTRA_BAND_MAX);
1162 ret = -EINVAL;
1163 goto exit;
1164 }
1165
1166 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
1167 (val > CFG_ROAM_INTRA_BAND_MAX))
1168 {
1169 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1170 "intra band mode value %d is out of range"
1171 " (Min: %d Max: %d)", val,
1172 CFG_ROAM_INTRA_BAND_MIN,
1173 CFG_ROAM_INTRA_BAND_MAX);
1174 ret = -EINVAL;
1175 goto exit;
1176 }
1177
1178 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1179 "%s: Received Command to change intra band = %d", __func__, val);
1180
1181 pHddCtx->cfg_ini->nRoamIntraBand = val;
1182 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
1183 }
1184 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
1185 {
1186 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
1187 char extra[32];
1188 tANI_U8 len = 0;
1189
1190 /* value is interms of msec */
1191 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMINTRABAND", val);
1192 if (copy_to_user(priv_data.buf, &extra, len + 1))
1193 {
1194 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1195 "%s: failed to copy data to user buffer", __func__);
1196 ret = -EFAULT;
1197 goto exit;
1198 }
1199 }
1200
1201#endif
1202#ifdef FEATURE_WLAN_LFR
1203 else if (strncmp(command, "SETFASTROAM", 11) == 0)
1204 {
1205 tANI_U8 *value = command;
1206 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1207
1208 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1209 value = value + 12;
1210 /* Convert the value from ascii to integer */
1211 ret = kstrtou8(value, 10, &lfrMode);
1212 if (ret < 0)
1213 {
1214 /* If the input value is greater than max value of datatype, then also
1215 kstrtou8 fails */
1216 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1217 "%s: kstrtou8 failed range [%d - %d]", __func__,
1218 CFG_LFR_FEATURE_ENABLED_MIN,
1219 CFG_LFR_FEATURE_ENABLED_MAX);
1220 ret = -EINVAL;
1221 goto exit;
1222 }
1223
1224 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1225 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
1226 {
1227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1228 "lfr mode value %d is out of range"
1229 " (Min: %d Max: %d)", lfrMode,
1230 CFG_LFR_FEATURE_ENABLED_MIN,
1231 CFG_LFR_FEATURE_ENABLED_MAX);
1232 ret = -EINVAL;
1233 goto exit;
1234 }
1235
1236 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1237 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
1238
1239 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
1240 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
1241 }
1242#endif
1243#ifdef WLAN_FEATURE_VOWIFI_11R
1244 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
1245 {
1246 tANI_U8 *value = command;
1247 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
1248
1249 /* Move pointer to ahead of SETFASTROAM<delimiter> */
1250 value = value + 18;
1251 /* Convert the value from ascii to integer */
1252 ret = kstrtou8(value, 10, &ft);
1253 if (ret < 0)
1254 {
1255 /* If the input value is greater than max value of datatype, then also
1256 kstrtou8 fails */
1257 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1258 "%s: kstrtou8 failed range [%d - %d]", __func__,
1259 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1260 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1261 ret = -EINVAL;
1262 goto exit;
1263 }
1264
1265 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
1266 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
1267 {
1268 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1269 "ft mode value %d is out of range"
1270 " (Min: %d Max: %d)", ft,
1271 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
1272 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
1273 ret = -EINVAL;
1274 goto exit;
1275 }
1276
1277 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1278 "%s: Received Command to change ft mode = %d", __func__, ft);
1279
1280 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
1281 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
1282 }
1283#endif
1284#ifdef FEATURE_WLAN_CCX
1285 else if (strncmp(command, "SETCCXMODE", 10) == 0)
1286 {
1287 tANI_U8 *value = command;
1288 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
1289
1290 /* Move pointer to ahead of SETCCXMODE<delimiter> */
1291 value = value + 11;
1292 /* Convert the value from ascii to integer */
1293 ret = kstrtou8(value, 10, &ccxMode);
1294 if (ret < 0)
1295 {
1296 /* If the input value is greater than max value of datatype, then also
1297 kstrtou8 fails */
1298 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1299 "%s: kstrtou8 failed range [%d - %d]", __func__,
1300 CFG_CCX_FEATURE_ENABLED_MIN,
1301 CFG_CCX_FEATURE_ENABLED_MAX);
1302 ret = -EINVAL;
1303 goto exit;
1304 }
1305
1306 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
1307 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
1308 {
1309 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1310 "Ccx mode value %d is out of range"
1311 " (Min: %d Max: %d)", ccxMode,
1312 CFG_CCX_FEATURE_ENABLED_MIN,
1313 CFG_CCX_FEATURE_ENABLED_MAX);
1314 ret = -EINVAL;
1315 goto exit;
1316 }
1317
1318 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1319 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
1320
1321 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
1322 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
1323 }
1324#endif
1325#ifdef FEATURE_WLAN_OKC
1326 else if (strncmp(command, "SETOKCMODE", 10) == 0)
1327 {
1328 tANI_U8 *value = command;
1329 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
1330
1331 /* Move pointer to ahead of SETOKCMODE<delimiter> */
1332 value = value + 11;
1333 /* Convert the value from ascii to integer */
1334 ret = kstrtou8(value, 10, &okcMode);
1335 if (ret < 0)
1336 {
1337 /* If the input value is greater than max value of datatype, then also
1338 kstrtou8 fails */
1339 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1340 "%s: kstrtou8 failed range [%d - %d]", __func__,
1341 CFG_OKC_FEATURE_ENABLED_MIN,
1342 CFG_OKC_FEATURE_ENABLED_MAX);
1343 ret = -EINVAL;
1344 goto exit;
1345 }
1346
1347 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
1348 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
1349 {
1350 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1351 "Okc mode value %d is out of range"
1352 " (Min: %d Max: %d)", okcMode,
1353 CFG_OKC_FEATURE_ENABLED_MIN,
1354 CFG_OKC_FEATURE_ENABLED_MAX);
1355 ret = -EINVAL;
1356 goto exit;
1357 }
1358
1359 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1360 "%s: Received Command to change okc mode = %d", __func__, okcMode);
1361
1362 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
1363 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001364#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001365 else {
1366 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
1367 __func__, command);
1368 }
1369
Jeff Johnson295189b2012-06-20 16:38:30 -07001370 }
1371exit:
1372 if (command)
1373 {
1374 kfree(command);
1375 }
1376 return ret;
1377}
1378
Srinivas Girigowdade697412013-02-14 16:31:48 -08001379#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1380void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
1381{
1382 eCsrBand band = -1;
1383 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
1384 switch (band)
1385 {
1386 case eCSR_BAND_ALL:
1387 *pBand = WLAN_HDD_UI_BAND_AUTO;
1388 break;
1389
1390 case eCSR_BAND_24:
1391 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
1392 break;
1393
1394 case eCSR_BAND_5G:
1395 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
1396 break;
1397
1398 default:
1399 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
1400 *pBand = -1;
1401 break;
1402 }
1403}
1404
1405/**---------------------------------------------------------------------------
1406
1407 \brief hdd_parse_countryrev() - HDD Parse country code revision
1408
1409 This function parses the country code revision passed in the format
1410 SETCOUNTRYREV<space><Country code><space>revision
1411
1412 \param - pValue Pointer to input country code revision
1413 \param - pCountryCode Pointer to local output array to record country code
1414 \param - pRevision Pointer to store revision integer number
1415
1416 \return - 0 for success non-zero for failure
1417
1418 --------------------------------------------------------------------------*/
1419VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
1420{
1421 tANI_U8 *inPtr = pValue;
1422 int tempInt;
1423
1424 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1425 /*no argument after the command*/
1426 if (NULL == inPtr)
1427 {
1428 return -EINVAL;
1429 }
1430
1431 /*no space after the command*/
1432 else if (SPACE_ASCII_VALUE != *inPtr)
1433 {
1434 return -EINVAL;
1435 }
1436
1437 /*removing empty spaces*/
1438 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1439
1440 /*no argument followed by spaces*/
1441 if ('\0' == *inPtr)
1442 {
1443 return -EINVAL;
1444 }
1445
1446 /*getting the first argument ie the country code */
Chilam Ngc4244af2013-04-01 15:37:32 -07001447 sscanf(inPtr, "%3s ", pCountryCode);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001448
1449 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1450 "Country code is : %s", pCountryCode);
1451
1452 /*inPtr pointing to the beginning of first space after country code */
1453 inPtr = strpbrk( inPtr, " " );
1454 /*no revision number after the country code argument */
1455 if (NULL == inPtr)
1456 {
1457 return -EINVAL;
1458 }
1459
1460 inPtr++;
1461
1462 /*removing empty space*/
1463 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1464
1465 /*no channel list after the number of channels argument and spaces*/
1466 if (0 == strncmp(pCountryCode, "KR", 2))
1467 {
1468 if ('\0' == *inPtr)
1469 {
1470 return -EINVAL;
1471 }
1472
1473 sscanf(inPtr, "%d", &tempInt);
1474 *pRevision = tempInt;
1475 }
1476 else
1477 {
1478 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1479 "Revision input is required only for Country KR");
1480 return -EINVAL;
1481 }
1482 return VOS_STATUS_SUCCESS;
1483}
1484
1485/**---------------------------------------------------------------------------
1486
1487 \brief hdd_parse_channellist() - HDD Parse channel list
1488
1489 This function parses the channel list passed in the format
1490 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001491 if the Number of channels (N) does not match with the actual number of channels passed
1492 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
1493 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
1494 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
1495 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08001496
1497 \param - pValue Pointer to input channel list
1498 \param - ChannelList Pointer to local output array to record channel list
1499 \param - pNumChannels Pointer to number of roam scan channels
1500
1501 \return - 0 for success non-zero for failure
1502
1503 --------------------------------------------------------------------------*/
1504VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
1505{
1506 tANI_U8 *inPtr = pValue;
1507 int tempInt;
1508 int j = 0;
1509 int v = 0;
1510 char buf[32];
1511
1512 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1513 /*no argument after the command*/
1514 if (NULL == inPtr)
1515 {
1516 return -EINVAL;
1517 }
1518
1519 /*no space after the command*/
1520 else if (SPACE_ASCII_VALUE != *inPtr)
1521 {
1522 return -EINVAL;
1523 }
1524
1525 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001526 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001527
1528 /*no argument followed by spaces*/
1529 if ('\0' == *inPtr)
1530 {
1531 return -EINVAL;
1532 }
1533
1534 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07001535 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001536 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001537 if ((v < 0) ||
1538 (tempInt <= 0) ||
1539 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
1540 {
1541 return -EINVAL;
1542 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001543
1544 *pNumChannels = tempInt;
1545
1546 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1547 "Number of channels are: %d", *pNumChannels);
1548
1549 for (j = 0; j < (*pNumChannels); j++)
1550 {
1551 /*inPtr pointing to the beginning of first space after number of channels*/
1552 inPtr = strpbrk( inPtr, " " );
1553 /*no channel list after the number of channels argument*/
1554 if (NULL == inPtr)
1555 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001556 if (0 != j)
1557 {
1558 *pNumChannels = j;
1559 return VOS_STATUS_SUCCESS;
1560 }
1561 else
1562 {
1563 return -EINVAL;
1564 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001565 }
1566
1567 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001568 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001569
1570 /*no channel list after the number of channels argument and spaces*/
1571 if ( '\0' == *inPtr )
1572 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001573 if (0 != j)
1574 {
1575 *pNumChannels = j;
1576 return VOS_STATUS_SUCCESS;
1577 }
1578 else
1579 {
1580 return -EINVAL;
1581 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001582 }
1583
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001584 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001585 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07001586 if ((v < 0) ||
1587 (tempInt <= 0) ||
1588 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
1589 {
1590 return -EINVAL;
1591 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001592 pChannelList[j] = tempInt;
1593
1594 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1595 "Channel %d added to preferred channel list",
1596 pChannelList[j] );
1597 }
1598
Srinivas Girigowdade697412013-02-14 16:31:48 -08001599 return VOS_STATUS_SUCCESS;
1600}
1601
1602#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001603/**---------------------------------------------------------------------------
1604
1605 \brief hdd_open() - HDD Open function
1606
1607 This is called in response to ifconfig up
1608
1609 \param - dev Pointer to net_device structure
1610
1611 \return - 0 for success non-zero for failure
1612
1613 --------------------------------------------------------------------------*/
1614int hdd_open (struct net_device *dev)
1615{
1616 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1617 hdd_context_t *pHddCtx;
1618 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1619 VOS_STATUS status;
1620 v_BOOL_t in_standby = TRUE;
1621
1622 if (NULL == pAdapter)
1623 {
1624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001625 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001626 return -ENODEV;
1627 }
1628
1629 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1630 if (NULL == pHddCtx)
1631 {
1632 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001633 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001634 return -ENODEV;
1635 }
1636
1637 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1638 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1639 {
1640 if( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1641 {
1642 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of "
1643 "standby", __func__, pAdapter->device_mode);
1644 in_standby = FALSE;
1645 break;
1646 }
1647 else
1648 {
1649 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1650 pAdapterNode = pNext;
1651 }
1652 }
1653
1654 if (TRUE == in_standby)
1655 {
1656 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
1657 {
1658 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
1659 "wlan out of power save", __func__);
1660 return -EINVAL;
1661 }
1662 }
1663
1664 pAdapter->event_flags |= DEVICE_IFACE_OPENED;
1665 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1666 {
1667 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001668 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001669 /* Enable TX queues only when we are connected */
1670 netif_tx_start_all_queues(dev);
1671 }
1672
1673 return 0;
1674}
1675
1676int hdd_mon_open (struct net_device *dev)
1677{
1678 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1679
1680 if(pAdapter == NULL) {
1681 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001682 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001683 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001684 }
1685
1686 netif_start_queue(dev);
1687
1688 return 0;
1689}
1690/**---------------------------------------------------------------------------
1691
1692 \brief hdd_stop() - HDD stop function
1693
1694 This is called in response to ifconfig down
1695
1696 \param - dev Pointer to net_device structure
1697
1698 \return - 0 for success non-zero for failure
1699
1700 --------------------------------------------------------------------------*/
1701
1702int hdd_stop (struct net_device *dev)
1703{
1704 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1705 hdd_context_t *pHddCtx;
1706 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1707 VOS_STATUS status;
1708 v_BOOL_t enter_standby = TRUE;
1709
1710 ENTER();
1711
1712 if (NULL == pAdapter)
1713 {
1714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001715 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001716 return -ENODEV;
1717 }
1718
1719 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1720 if (NULL == pHddCtx)
1721 {
1722 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001723 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001724 return -ENODEV;
1725 }
1726
1727 pAdapter->event_flags &= ~(DEVICE_IFACE_OPENED);
1728 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
1729 netif_tx_disable(pAdapter->dev);
1730 netif_carrier_off(pAdapter->dev);
1731
1732
1733 /* SoftAP ifaces should never go in power save mode
1734 making sure same here. */
1735 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
1736 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001737 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001738 )
1739 {
1740 /* SoftAP mode, so return from here */
1741 EXIT();
1742 return 0;
1743 }
1744
1745 /* Find if any iface is up then
1746 if any iface is up then can't put device to sleep/ power save mode. */
1747 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1748 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1749 {
1750 if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1751 {
1752 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
1753 "put device to sleep", __func__, pAdapter->device_mode);
1754 enter_standby = FALSE;
1755 break;
1756 }
1757 else
1758 {
1759 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1760 pAdapterNode = pNext;
1761 }
1762 }
1763
1764 if (TRUE == enter_standby)
1765 {
1766 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
1767 "entering standby", __func__);
1768 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
1769 {
1770 /*log and return success*/
1771 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
1772 "wlan in power save", __func__);
1773 }
1774 }
1775
1776 EXIT();
1777 return 0;
1778}
1779
1780/**---------------------------------------------------------------------------
1781
1782 \brief hdd_uninit() - HDD uninit function
1783
1784 This is called during the netdev unregister to uninitialize all data
1785associated with the device
1786
1787 \param - dev Pointer to net_device structure
1788
1789 \return - void
1790
1791 --------------------------------------------------------------------------*/
1792static void hdd_uninit (struct net_device *dev)
1793{
1794 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1795
1796 ENTER();
1797
1798 do
1799 {
1800 if (NULL == pAdapter)
1801 {
1802 hddLog(VOS_TRACE_LEVEL_FATAL,
1803 "%s: NULL pAdapter", __func__);
1804 break;
1805 }
1806
1807 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1808 {
1809 hddLog(VOS_TRACE_LEVEL_FATAL,
1810 "%s: Invalid magic", __func__);
1811 break;
1812 }
1813
1814 if (NULL == pAdapter->pHddCtx)
1815 {
1816 hddLog(VOS_TRACE_LEVEL_FATAL,
1817 "%s: NULL pHddCtx", __func__);
1818 break;
1819 }
1820
1821 if (dev != pAdapter->dev)
1822 {
1823 hddLog(VOS_TRACE_LEVEL_FATAL,
1824 "%s: Invalid device reference", __func__);
1825 /* we haven't validated all cases so let this go for now */
1826 }
1827
1828 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
1829
1830 /* after uninit our adapter structure will no longer be valid */
1831 pAdapter->dev = NULL;
1832 pAdapter->magic = 0;
1833 } while (0);
1834
1835 EXIT();
1836}
1837
1838/**---------------------------------------------------------------------------
1839
1840 \brief hdd_release_firmware() -
1841
1842 This function calls the release firmware API to free the firmware buffer.
1843
1844 \param - pFileName Pointer to the File Name.
1845 pCtx - Pointer to the adapter .
1846
1847
1848 \return - 0 for success, non zero for failure
1849
1850 --------------------------------------------------------------------------*/
1851
1852VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
1853{
1854 VOS_STATUS status = VOS_STATUS_SUCCESS;
1855 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1856 ENTER();
1857
1858
1859 if (!strcmp(WLAN_FW_FILE, pFileName)) {
1860
1861 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
1862
1863 if(pHddCtx->fw) {
1864 release_firmware(pHddCtx->fw);
1865 pHddCtx->fw = NULL;
1866 }
1867 else
1868 status = VOS_STATUS_E_FAILURE;
1869 }
1870 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
1871 if(pHddCtx->nv) {
1872 release_firmware(pHddCtx->nv);
1873 pHddCtx->nv = NULL;
1874 }
1875 else
1876 status = VOS_STATUS_E_FAILURE;
1877
1878 }
1879
1880 EXIT();
1881 return status;
1882}
1883
1884/**---------------------------------------------------------------------------
1885
1886 \brief hdd_request_firmware() -
1887
1888 This function reads the firmware file using the request firmware
1889 API and returns the the firmware data and the firmware file size.
1890
1891 \param - pfileName - Pointer to the file name.
1892 - pCtx - Pointer to the adapter .
1893 - ppfw_data - Pointer to the pointer of the firmware data.
1894 - pSize - Pointer to the file size.
1895
1896 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
1897
1898 --------------------------------------------------------------------------*/
1899
1900
1901VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
1902{
1903 int status;
1904 VOS_STATUS retval = VOS_STATUS_SUCCESS;
1905 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1906 ENTER();
1907
1908 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
1909
1910 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
1911
1912 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1913 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
1914 __func__, pfileName);
1915 retval = VOS_STATUS_E_FAILURE;
1916 }
1917
1918 else {
1919 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
1920 *pSize = pHddCtx->fw->size;
1921 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
1922 __func__, *pSize);
1923 }
1924 }
1925 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
1926
1927 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
1928
1929 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
1930 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
1931 __func__, pfileName);
1932 retval = VOS_STATUS_E_FAILURE;
1933 }
1934
1935 else {
1936 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
1937 *pSize = pHddCtx->nv->size;
1938 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
1939 __func__, *pSize);
1940 }
1941 }
1942
1943 EXIT();
1944 return retval;
1945}
1946/**---------------------------------------------------------------------------
1947 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
1948
1949 This is the function invoked by SME to inform the result of a full power
1950 request issued by HDD
1951
1952 \param - callbackcontext - Pointer to cookie
1953 status - result of request
1954
1955 \return - None
1956
1957--------------------------------------------------------------------------*/
1958void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
1959{
1960 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
1961
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001962 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001963 if(&pHddCtx->full_pwr_comp_var)
1964 {
1965 complete(&pHddCtx->full_pwr_comp_var);
1966 }
1967}
1968
1969/**---------------------------------------------------------------------------
1970
1971 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
1972
1973 This is the function invoked by SME to inform the result of BMPS
1974 request issued by HDD
1975
1976 \param - callbackcontext - Pointer to cookie
1977 status - result of request
1978
1979 \return - None
1980
1981--------------------------------------------------------------------------*/
1982void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
1983{
1984
1985 struct completion *completion_var = (struct completion*) callbackContext;
1986
1987 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
1988 if(completion_var != NULL)
1989 {
1990 complete(completion_var);
1991 }
1992}
1993
1994/**---------------------------------------------------------------------------
1995
1996 \brief hdd_get_cfg_file_size() -
1997
1998 This function reads the configuration file using the request firmware
1999 API and returns the configuration file size.
2000
2001 \param - pCtx - Pointer to the adapter .
2002 - pFileName - Pointer to the file name.
2003 - pBufSize - Pointer to the buffer size.
2004
2005 \return - 0 for success, non zero for failure
2006
2007 --------------------------------------------------------------------------*/
2008
2009VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2010{
2011 int status;
2012 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2013
2014 ENTER();
2015
2016 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2017
2018 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2019 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2020 status = VOS_STATUS_E_FAILURE;
2021 }
2022 else {
2023 *pBufSize = pHddCtx->fw->size;
2024 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2025 release_firmware(pHddCtx->fw);
2026 pHddCtx->fw = NULL;
2027 }
2028
2029 EXIT();
2030 return VOS_STATUS_SUCCESS;
2031}
2032
2033/**---------------------------------------------------------------------------
2034
2035 \brief hdd_read_cfg_file() -
2036
2037 This function reads the configuration file using the request firmware
2038 API and returns the cfg data and the buffer size of the configuration file.
2039
2040 \param - pCtx - Pointer to the adapter .
2041 - pFileName - Pointer to the file name.
2042 - pBuffer - Pointer to the data buffer.
2043 - pBufSize - Pointer to the buffer size.
2044
2045 \return - 0 for success, non zero for failure
2046
2047 --------------------------------------------------------------------------*/
2048
2049VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2050 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2051{
2052 int status;
2053 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2054
2055 ENTER();
2056
2057 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2058
2059 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2060 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2061 return VOS_STATUS_E_FAILURE;
2062 }
2063 else {
2064 if(*pBufSize != pHddCtx->fw->size) {
2065 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2066 "file size", __func__);
2067 release_firmware(pHddCtx->fw);
2068 pHddCtx->fw = NULL;
2069 return VOS_STATUS_E_FAILURE;
2070 }
2071 else {
2072 if(pBuffer) {
2073 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2074 }
2075 release_firmware(pHddCtx->fw);
2076 pHddCtx->fw = NULL;
2077 }
2078 }
2079
2080 EXIT();
2081
2082 return VOS_STATUS_SUCCESS;
2083}
2084
2085/**---------------------------------------------------------------------------
2086
Jeff Johnson295189b2012-06-20 16:38:30 -07002087 \brief hdd_set_mac_address() -
2088
2089 This function sets the user specified mac address using
2090 the command ifconfig wlanX hw ether <mac adress>.
2091
2092 \param - dev - Pointer to the net device.
2093 - addr - Pointer to the sockaddr.
2094 \return - 0 for success, non zero for failure
2095
2096 --------------------------------------------------------------------------*/
2097
2098static int hdd_set_mac_address(struct net_device *dev, void *addr)
2099{
2100 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2101 struct sockaddr *psta_mac_addr = addr;
2102 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2103
2104 ENTER();
2105
2106 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2107
2108#ifdef HDD_SESSIONIZE
2109 // set the MAC address though the STA ID CFG.
2110 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2111 (v_U8_t *)&pAdapter->macAddressCurrent,
2112 sizeof( pAdapter->macAddressCurrent ),
2113 hdd_set_mac_addr_cb, VOS_FALSE );
2114#endif
2115
2116 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2117
2118 EXIT();
2119 return halStatus;
2120}
2121
2122tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2123{
2124 int i;
2125 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2126 {
2127 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2128 break;
2129 }
2130
2131 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2132 return NULL;
2133
2134 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2135 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2136}
2137
2138void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2139{
2140 int i;
2141 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2142 {
2143 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2144 {
2145 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2146 break;
2147 }
2148 }
2149 return;
2150}
2151
2152#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2153 static struct net_device_ops wlan_drv_ops = {
2154 .ndo_open = hdd_open,
2155 .ndo_stop = hdd_stop,
2156 .ndo_uninit = hdd_uninit,
2157 .ndo_start_xmit = hdd_hard_start_xmit,
2158 .ndo_tx_timeout = hdd_tx_timeout,
2159 .ndo_get_stats = hdd_stats,
2160 .ndo_do_ioctl = hdd_ioctl,
2161 .ndo_set_mac_address = hdd_set_mac_address,
2162 .ndo_select_queue = hdd_select_queue,
2163#ifdef WLAN_FEATURE_PACKET_FILTERING
2164#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2165 .ndo_set_rx_mode = hdd_set_multicast_list,
2166#else
2167 .ndo_set_multicast_list = hdd_set_multicast_list,
2168#endif //LINUX_VERSION_CODE
2169#endif
2170 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002171 static struct net_device_ops wlan_mon_drv_ops = {
2172 .ndo_open = hdd_mon_open,
2173 .ndo_stop = hdd_stop,
2174 .ndo_uninit = hdd_uninit,
2175 .ndo_start_xmit = hdd_mon_hard_start_xmit,
2176 .ndo_tx_timeout = hdd_tx_timeout,
2177 .ndo_get_stats = hdd_stats,
2178 .ndo_do_ioctl = hdd_ioctl,
2179 .ndo_set_mac_address = hdd_set_mac_address,
2180 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002181
2182#endif
2183
2184void hdd_set_station_ops( struct net_device *pWlanDev )
2185{
2186#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2187 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
2188 pWlanDev->netdev_ops = &wlan_drv_ops;
2189#else
2190 pWlanDev->open = hdd_open;
2191 pWlanDev->stop = hdd_stop;
2192 pWlanDev->uninit = hdd_uninit;
2193 pWlanDev->hard_start_xmit = NULL;
2194 pWlanDev->tx_timeout = hdd_tx_timeout;
2195 pWlanDev->get_stats = hdd_stats;
2196 pWlanDev->do_ioctl = hdd_ioctl;
2197 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
2198 pWlanDev->set_mac_address = hdd_set_mac_address;
2199#endif
2200}
2201
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002202static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07002203{
2204 struct net_device *pWlanDev = NULL;
2205 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002206 /*
2207 * cfg80211 initialization and registration....
2208 */
2209 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
2210
Jeff Johnson295189b2012-06-20 16:38:30 -07002211 if(pWlanDev != NULL)
2212 {
2213
2214 //Save the pointer to the net_device in the HDD adapter
2215 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
2216
Jeff Johnson295189b2012-06-20 16:38:30 -07002217 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
2218
2219 pAdapter->dev = pWlanDev;
2220 pAdapter->pHddCtx = pHddCtx;
2221 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2222
2223 init_completion(&pAdapter->session_open_comp_var);
2224 init_completion(&pAdapter->session_close_comp_var);
2225 init_completion(&pAdapter->disconnect_comp_var);
2226 init_completion(&pAdapter->linkup_event_var);
2227 init_completion(&pAdapter->cancel_rem_on_chan_var);
2228 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07002229#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2230 init_completion(&pAdapter->offchannel_tx_event);
2231#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002232 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002233#ifdef FEATURE_WLAN_TDLS
2234 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002235 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002236 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002237#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002238 init_completion(&pHddCtx->mc_sus_event_var);
2239 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07002240 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07002241
Jeff Johnson295189b2012-06-20 16:38:30 -07002242 pAdapter->isLinkUpSvcNeeded = FALSE;
2243 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
2244 //Init the net_device structure
2245 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2246
2247 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
2248 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
2249 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
2250 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
2251
2252 hdd_set_station_ops( pAdapter->dev );
2253
2254 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002255 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
2256 pAdapter->wdev.wiphy = pHddCtx->wiphy;
2257 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002258 /* set pWlanDev's parent to underlying device */
2259 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
2260 }
2261
2262 return pAdapter;
2263}
2264
2265VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
2266{
2267 struct net_device *pWlanDev = pAdapter->dev;
2268 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2269 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2270 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2271
2272 if( rtnl_lock_held )
2273 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08002274 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07002275 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
2276 {
2277 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
2278 return VOS_STATUS_E_FAILURE;
2279 }
2280 }
2281 if (register_netdevice(pWlanDev))
2282 {
2283 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
2284 return VOS_STATUS_E_FAILURE;
2285 }
2286 }
2287 else
2288 {
2289 if(register_netdev(pWlanDev))
2290 {
2291 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
2292 return VOS_STATUS_E_FAILURE;
2293 }
2294 }
2295 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
2296
2297 return VOS_STATUS_SUCCESS;
2298}
2299
2300eHalStatus hdd_smeCloseSessionCallback(void *pContext)
2301{
2302 if(pContext != NULL)
2303 {
2304 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
2305
2306 /* need to make sure all of our scheduled work has completed.
2307 * This callback is called from MC thread context, so it is safe to
2308 * to call below flush workqueue API from here.
2309 */
2310 flush_scheduled_work();
2311 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
2312 }
2313 return eHAL_STATUS_SUCCESS;
2314}
2315
2316VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
2317{
2318 struct net_device *pWlanDev = pAdapter->dev;
2319 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2320 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2321 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2322 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2323 int rc = 0;
2324
2325 INIT_COMPLETION(pAdapter->session_open_comp_var);
2326 //Open a SME session for future operation
2327 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
2328 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
2329 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2330 {
2331 hddLog(VOS_TRACE_LEVEL_FATAL,
2332 "sme_OpenSession() failed with status code %08d [x%08lx]",
2333 halStatus, halStatus );
2334 status = VOS_STATUS_E_FAILURE;
2335 goto error_sme_open;
2336 }
2337
2338 //Block on a completion variable. Can't wait forever though.
2339 rc = wait_for_completion_interruptible_timeout(
2340 &pAdapter->session_open_comp_var,
2341 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2342 if (!rc)
2343 {
2344 hddLog(VOS_TRACE_LEVEL_FATAL,
2345 "Session is not opened within timeout period code %08d", rc );
2346 status = VOS_STATUS_E_FAILURE;
2347 goto error_sme_open;
2348 }
2349
2350 // Register wireless extensions
2351 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
2352 {
2353 hddLog(VOS_TRACE_LEVEL_FATAL,
2354 "hdd_register_wext() failed with status code %08d [x%08lx]",
2355 halStatus, halStatus );
2356 status = VOS_STATUS_E_FAILURE;
2357 goto error_register_wext;
2358 }
2359 //Safe to register the hard_start_xmit function again
2360#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2361 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
2362#else
2363 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
2364#endif
2365
2366 //Set the Connection State to Not Connected
2367 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2368
2369 //Set the default operation channel
2370 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
2371
2372 /* Make the default Auth Type as OPEN*/
2373 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2374
2375 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
2376 {
2377 hddLog(VOS_TRACE_LEVEL_FATAL,
2378 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
2379 status, status );
2380 goto error_init_txrx;
2381 }
2382
2383 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2384
2385 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
2386 {
2387 hddLog(VOS_TRACE_LEVEL_FATAL,
2388 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
2389 status, status );
2390 goto error_wmm_init;
2391 }
2392
2393 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2394
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002395#ifdef FEATURE_WLAN_TDLS
2396 if(0 != wlan_hdd_tdls_init(pAdapter))
2397 {
2398 status = VOS_STATUS_E_FAILURE;
2399 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
2400 goto error_tdls_init;
2401 }
2402 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2403#endif
2404
Jeff Johnson295189b2012-06-20 16:38:30 -07002405 return VOS_STATUS_SUCCESS;
2406
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002407#ifdef FEATURE_WLAN_TDLS
2408error_tdls_init:
2409 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2410 hdd_wmm_adapter_close(pAdapter);
2411#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002412error_wmm_init:
2413 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2414 hdd_deinit_tx_rx(pAdapter);
2415error_init_txrx:
2416 hdd_UnregisterWext(pWlanDev);
2417error_register_wext:
2418 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2419 {
2420 INIT_COMPLETION(pAdapter->session_close_comp_var);
2421 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
2422 pAdapter->sessionId,
2423 hdd_smeCloseSessionCallback, pAdapter ) )
2424 {
2425 //Block on a completion variable. Can't wait forever though.
2426 wait_for_completion_interruptible_timeout(
2427 &pAdapter->session_close_comp_var,
2428 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2429 }
2430}
2431error_sme_open:
2432 return status;
2433}
2434
Jeff Johnson295189b2012-06-20 16:38:30 -07002435void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2436{
2437 hdd_cfg80211_state_t *cfgState;
2438
2439 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
2440
2441 if( NULL != cfgState->buf )
2442 {
2443 int rc;
2444 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
2445 rc = wait_for_completion_interruptible_timeout(
2446 &pAdapter->tx_action_cnf_event,
2447 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2448 if(!rc)
2449 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08002450 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002451 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
2452 }
2453 }
2454 return;
2455}
Jeff Johnson295189b2012-06-20 16:38:30 -07002456
2457void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2458{
2459 ENTER();
2460 switch ( pAdapter->device_mode )
2461 {
2462 case WLAN_HDD_INFRA_STATION:
2463 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002464 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002465 {
2466 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2467 {
2468 hdd_deinit_tx_rx( pAdapter );
2469 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2470 }
2471
2472 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
2473 {
2474 hdd_wmm_adapter_close( pAdapter );
2475 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2476 }
2477
Jeff Johnson295189b2012-06-20 16:38:30 -07002478 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002479#ifdef FEATURE_WLAN_TDLS
2480 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
2481 {
2482 wlan_hdd_tdls_exit(pAdapter);
2483 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2484 }
2485#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002486
2487 break;
2488 }
2489
2490 case WLAN_HDD_SOFTAP:
2491 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002492 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002493 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002494
2495 hdd_unregister_hostapd(pAdapter);
2496 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07002497 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07002498 break;
2499 }
2500
2501 case WLAN_HDD_MONITOR:
2502 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002503 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07002504 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2505 {
2506 hdd_deinit_tx_rx( pAdapter );
2507 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2508 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002509 if(NULL != pAdapterforTx)
2510 {
2511 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
2512 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002513 break;
2514 }
2515
2516
2517 default:
2518 break;
2519 }
2520
2521 EXIT();
2522}
2523
2524void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
2525{
2526 struct net_device *pWlanDev = pAdapter->dev;
2527
2528 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
2529 if( rtnl_held )
2530 {
2531 unregister_netdevice(pWlanDev);
2532 }
2533 else
2534 {
2535 unregister_netdev(pWlanDev);
2536 }
2537 // note that the pAdapter is no longer valid at this point
2538 // since the memory has been reclaimed
2539 }
2540
2541}
2542
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002543void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2544{
2545 tSirSetPowerParamsReq powerRequest = { 0 };
2546
2547 powerRequest.uIgnoreDTIM = 1;
2548
2549 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2550 {
2551 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2552 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2553 }
2554 else
2555 {
2556 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2557 }
2558
2559 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2560 *specified during Enter/Exit BMPS when LCD off*/
2561 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2562 NULL, eANI_BOOLEAN_FALSE);
2563 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2564 NULL, eANI_BOOLEAN_FALSE);
2565
2566 /* switch to the DTIM specified in cfg.ini */
2567 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2568 "Switch to DTIM%d", powerRequest.uListenInterval);
2569 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2570
2571}
2572
2573void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2574{
2575 /*Switch back to DTIM 1*/
2576 tSirSetPowerParamsReq powerRequest = { 0 };
2577
2578 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2579 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2580
2581 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2582 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2583 NULL, eANI_BOOLEAN_FALSE);
2584 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2585 NULL, eANI_BOOLEAN_FALSE);
2586
2587 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2588 "Switch to DTIM%d",powerRequest.uListenInterval);
2589 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2590
2591}
2592
Jeff Johnson295189b2012-06-20 16:38:30 -07002593VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2594{
2595 VOS_STATUS status = VOS_STATUS_SUCCESS;
2596
2597 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2598 {
2599 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2600 }
2601
2602 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2603 {
2604 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2605 }
2606
2607 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2608 {
2609 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2610 }
2611
2612 return status;
2613}
2614
2615VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2616{
2617 hdd_adapter_t *pAdapter = NULL;
2618 eHalStatus halStatus;
2619 VOS_STATUS status = VOS_STATUS_E_INVAL;
2620 v_BOOL_t disableBmps = FALSE;
2621 v_BOOL_t disableImps = FALSE;
2622
2623 switch(session_type)
2624 {
2625 case WLAN_HDD_INFRA_STATION:
2626 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002627 case WLAN_HDD_P2P_CLIENT:
2628 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002629 //Exit BMPS -> Is Sta/P2P Client is already connected
2630 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2631 if((NULL != pAdapter)&&
2632 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2633 {
2634 disableBmps = TRUE;
2635 }
2636
2637 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2638 if((NULL != pAdapter)&&
2639 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2640 {
2641 disableBmps = TRUE;
2642 }
2643
2644 //Exit both Bmps and Imps incase of Go/SAP Mode
2645 if((WLAN_HDD_SOFTAP == session_type) ||
2646 (WLAN_HDD_P2P_GO == session_type))
2647 {
2648 disableBmps = TRUE;
2649 disableImps = TRUE;
2650 }
2651
2652 if(TRUE == disableImps)
2653 {
2654 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2655 {
2656 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2657 }
2658 }
2659
2660 if(TRUE == disableBmps)
2661 {
2662 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2663 {
2664 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2665
2666 if(eHAL_STATUS_SUCCESS != halStatus)
2667 {
2668 status = VOS_STATUS_E_FAILURE;
2669 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
2670 VOS_ASSERT(0);
2671 return status;
2672 }
2673 }
2674
2675 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2676 {
2677 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
2678
2679 if(eHAL_STATUS_SUCCESS != halStatus)
2680 {
2681 status = VOS_STATUS_E_FAILURE;
2682 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
2683 VOS_ASSERT(0);
2684 return status;
2685 }
2686 }
2687 }
2688
2689 if((TRUE == disableBmps) ||
2690 (TRUE == disableImps))
2691 {
2692 /* Now, get the chip into Full Power now */
2693 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
2694 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
2695 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
2696
2697 if(halStatus != eHAL_STATUS_SUCCESS)
2698 {
2699 if(halStatus == eHAL_STATUS_PMC_PENDING)
2700 {
2701 //Block on a completion variable. Can't wait forever though
2702 wait_for_completion_interruptible_timeout(
2703 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
2704 }
2705 else
2706 {
2707 status = VOS_STATUS_E_FAILURE;
2708 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
2709 VOS_ASSERT(0);
2710 return status;
2711 }
2712 }
2713
2714 status = VOS_STATUS_SUCCESS;
2715 }
2716
2717 break;
2718 }
2719 return status;
2720}
2721
2722hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002723 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07002724 tANI_U8 rtnl_held )
2725{
2726 hdd_adapter_t *pAdapter = NULL;
2727 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
2728 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2729 VOS_STATUS exitbmpsStatus;
2730
2731 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
2732
2733 //Disable BMPS incase of Concurrency
2734 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
2735
2736 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
2737 {
2738 //Fail to Exit BMPS
2739 VOS_ASSERT(0);
2740 return NULL;
2741 }
2742
2743 switch(session_type)
2744 {
2745 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002746 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002747 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002748 {
2749 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2750
2751 if( NULL == pAdapter )
2752 return NULL;
2753
Jeff Johnsone7245742012-09-05 17:12:55 -07002754 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
2755 NL80211_IFTYPE_P2P_CLIENT:
2756 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07002757
Jeff Johnson295189b2012-06-20 16:38:30 -07002758 pAdapter->device_mode = session_type;
2759
2760 status = hdd_init_station_mode( pAdapter );
2761 if( VOS_STATUS_SUCCESS != status )
2762 goto err_free_netdev;
2763
2764 status = hdd_register_interface( pAdapter, rtnl_held );
2765 if( VOS_STATUS_SUCCESS != status )
2766 {
2767 hdd_deinit_adapter(pHddCtx, pAdapter);
2768 goto err_free_netdev;
2769 }
2770 //Stop the Interface TX queue.
2771 netif_tx_disable(pAdapter->dev);
2772 //netif_tx_disable(pWlanDev);
2773 netif_carrier_off(pAdapter->dev);
2774
2775 break;
2776 }
2777
Jeff Johnson295189b2012-06-20 16:38:30 -07002778 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002779 case WLAN_HDD_SOFTAP:
2780 {
2781 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
2782 if( NULL == pAdapter )
2783 return NULL;
2784
Jeff Johnson295189b2012-06-20 16:38:30 -07002785 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
2786 NL80211_IFTYPE_AP:
2787 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002788 pAdapter->device_mode = session_type;
2789
2790 status = hdd_init_ap_mode(pAdapter);
2791 if( VOS_STATUS_SUCCESS != status )
2792 goto err_free_netdev;
2793
2794 status = hdd_register_hostapd( pAdapter, rtnl_held );
2795 if( VOS_STATUS_SUCCESS != status )
2796 {
2797 hdd_deinit_adapter(pHddCtx, pAdapter);
2798 goto err_free_netdev;
2799 }
2800
2801 netif_tx_disable(pAdapter->dev);
2802 netif_carrier_off(pAdapter->dev);
2803
2804 hdd_set_conparam( 1 );
2805 break;
2806 }
2807 case WLAN_HDD_MONITOR:
2808 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002809 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2810 if( NULL == pAdapter )
2811 return NULL;
2812
2813 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
2814 pAdapter->device_mode = session_type;
2815 status = hdd_register_interface( pAdapter, rtnl_held );
2816#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2817 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
2818#else
2819 pAdapter->dev->open = hdd_mon_open;
2820 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
2821#endif
2822 hdd_init_tx_rx( pAdapter );
2823 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2824 //Set adapter to be used for data tx. It will use either GO or softap.
2825 pAdapter->sessionCtx.monitor.pAdapterForTx =
2826 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07002827 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
2828 {
2829 pAdapter->sessionCtx.monitor.pAdapterForTx =
2830 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
2831 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002832 /* This workqueue will be used to transmit management packet over
2833 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07002834 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
2835 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
2836 return NULL;
2837 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07002838
Jeff Johnson295189b2012-06-20 16:38:30 -07002839 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
2840 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07002841 }
2842 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002843 case WLAN_HDD_FTM:
2844 {
2845 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2846
2847 if( NULL == pAdapter )
2848 return NULL;
2849 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
2850 * message while loading driver in FTM mode. */
2851 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
2852 pAdapter->device_mode = session_type;
2853 status = hdd_register_interface( pAdapter, rtnl_held );
2854 }
2855 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002856 default:
2857 {
2858 VOS_ASSERT(0);
2859 return NULL;
2860 }
2861 }
2862
2863
2864 if( VOS_STATUS_SUCCESS == status )
2865 {
2866 //Add it to the hdd's session list.
2867 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
2868 if( NULL == pHddAdapterNode )
2869 {
2870 status = VOS_STATUS_E_NOMEM;
2871 }
2872 else
2873 {
2874 pHddAdapterNode->pAdapter = pAdapter;
2875 status = hdd_add_adapter_back ( pHddCtx,
2876 pHddAdapterNode );
2877 }
2878 }
2879
2880 if( VOS_STATUS_SUCCESS != status )
2881 {
2882 if( NULL != pAdapter )
2883 {
2884 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
2885 pAdapter = NULL;
2886 }
2887 if( NULL != pHddAdapterNode )
2888 {
2889 vos_mem_free( pHddAdapterNode );
2890 }
2891
2892 goto resume_bmps;
2893 }
2894
2895 if(VOS_STATUS_SUCCESS == status)
2896 {
2897 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
2898
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002899 //Initialize the WoWL service
2900 if(!hdd_init_wowl(pAdapter))
2901 {
2902 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
2903 goto err_free_netdev;
2904 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002905 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002906 return pAdapter;
2907
2908err_free_netdev:
2909 free_netdev(pAdapter->dev);
2910 wlan_hdd_release_intf_addr( pHddCtx,
2911 pAdapter->macAddressCurrent.bytes );
2912
2913resume_bmps:
2914 //If bmps disabled enable it
2915 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
2916 {
2917 hdd_enable_bmps_imps(pHddCtx);
2918 }
2919 return NULL;
2920}
2921
2922VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
2923 tANI_U8 rtnl_held )
2924{
2925 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
2926 VOS_STATUS status;
2927
2928 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
2929 if( VOS_STATUS_SUCCESS != status )
2930 return status;
2931
2932 while ( pCurrent->pAdapter != pAdapter )
2933 {
2934 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
2935 if( VOS_STATUS_SUCCESS != status )
2936 break;
2937
2938 pCurrent = pNext;
2939 }
2940 pAdapterNode = pCurrent;
2941 if( VOS_STATUS_SUCCESS == status )
2942 {
2943 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2944 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
2945 hdd_remove_adapter( pHddCtx, pAdapterNode );
2946 vos_mem_free( pAdapterNode );
2947
Jeff Johnson295189b2012-06-20 16:38:30 -07002948
2949 /* If there is a single session of STA/P2P client, re-enable BMPS */
2950 if ((!vos_concurrent_sessions_running()) &&
2951 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
2952 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
2953 {
2954 hdd_enable_bmps_imps(pHddCtx);
2955 }
2956
2957 return VOS_STATUS_SUCCESS;
2958 }
2959
2960 return VOS_STATUS_E_FAILURE;
2961}
2962
2963VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
2964{
2965 hdd_adapter_list_node_t *pHddAdapterNode;
2966 VOS_STATUS status;
2967
2968 ENTER();
2969
2970 do
2971 {
2972 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
2973 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
2974 {
2975 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
2976 vos_mem_free( pHddAdapterNode );
2977 }
2978 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
2979
2980 EXIT();
2981
2982 return VOS_STATUS_SUCCESS;
2983}
2984
2985void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
2986{
2987 v_U8_t addIE[1] = {0};
2988
2989 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2990 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
2991 eANI_BOOLEAN_FALSE) )
2992 {
2993 hddLog(LOGE,
2994 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
2995 }
2996
2997 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2998 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
2999 eANI_BOOLEAN_FALSE) )
3000 {
3001 hddLog(LOGE,
3002 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
3003 }
3004
3005 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
3006 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
3007 eANI_BOOLEAN_FALSE) )
3008 {
3009 hddLog(LOGE,
3010 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3011 }
3012}
3013
3014VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3015{
3016 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3017 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3018 union iwreq_data wrqu;
3019
3020 ENTER();
3021
3022 switch(pAdapter->device_mode)
3023 {
3024 case WLAN_HDD_INFRA_STATION:
3025 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003026 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003027 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3028 {
3029 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3030 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3031 pAdapter->sessionId,
3032 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3033 else
3034 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3035 pAdapter->sessionId,
3036 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3037 //success implies disconnect command got queued up successfully
3038 if(halStatus == eHAL_STATUS_SUCCESS)
3039 {
3040 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3041 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3042 }
3043 memset(&wrqu, '\0', sizeof(wrqu));
3044 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3045 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3046 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3047 }
3048 else
3049 {
3050 hdd_abort_mac_scan(pHddCtx);
3051 }
3052
3053 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3054 {
3055 INIT_COMPLETION(pAdapter->session_close_comp_var);
3056 if (eHAL_STATUS_SUCCESS ==
3057 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3058 hdd_smeCloseSessionCallback, pAdapter))
3059 {
3060 //Block on a completion variable. Can't wait forever though.
3061 wait_for_completion_interruptible_timeout(
3062 &pAdapter->session_close_comp_var,
3063 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3064 }
3065 }
3066
3067 break;
3068
3069 case WLAN_HDD_SOFTAP:
3070 case WLAN_HDD_P2P_GO:
3071 //Any softap specific cleanup here...
3072 mutex_lock(&pHddCtx->sap_lock);
3073 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3074 {
3075 VOS_STATUS status;
3076 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3077
3078 //Stop Bss.
3079 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3080 if (VOS_IS_STATUS_SUCCESS(status))
3081 {
3082 hdd_hostapd_state_t *pHostapdState =
3083 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3084
3085 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3086
3087 if (!VOS_IS_STATUS_SUCCESS(status))
3088 {
3089 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003090 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003091 }
3092 }
3093 else
3094 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003095 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003096 }
3097 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3098
3099 if (eHAL_STATUS_FAILURE ==
3100 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3101 0, NULL, eANI_BOOLEAN_FALSE))
3102 {
3103 hddLog(LOGE,
3104 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003105 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003106 }
3107
3108 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3109 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3110 eANI_BOOLEAN_FALSE) )
3111 {
3112 hddLog(LOGE,
3113 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3114 }
3115
3116 // Reset WNI_CFG_PROBE_RSP Flags
3117 wlan_hdd_reset_prob_rspies(pAdapter);
3118 kfree(pAdapter->sessionCtx.ap.beacon);
3119 pAdapter->sessionCtx.ap.beacon = NULL;
3120 }
3121 mutex_unlock(&pHddCtx->sap_lock);
3122 break;
3123 case WLAN_HDD_MONITOR:
3124 break;
3125 default:
3126 break;
3127 }
3128
3129 EXIT();
3130 return VOS_STATUS_SUCCESS;
3131}
3132
3133VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3134{
3135 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3136 VOS_STATUS status;
3137 hdd_adapter_t *pAdapter;
3138
3139 ENTER();
3140
3141 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3142
3143 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3144 {
3145 pAdapter = pAdapterNode->pAdapter;
3146 netif_tx_disable(pAdapter->dev);
3147 netif_carrier_off(pAdapter->dev);
3148
3149 hdd_stop_adapter( pHddCtx, pAdapter );
3150
3151 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3152 pAdapterNode = pNext;
3153 }
3154
3155 EXIT();
3156
3157 return VOS_STATUS_SUCCESS;
3158}
3159
3160VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
3161{
3162 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3163 VOS_STATUS status;
3164 hdd_adapter_t *pAdapter;
3165
3166 ENTER();
3167
3168 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3169
3170 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3171 {
3172 pAdapter = pAdapterNode->pAdapter;
3173 netif_tx_disable(pAdapter->dev);
3174 netif_carrier_off(pAdapter->dev);
3175
3176 //Record whether STA is associated
3177 pAdapter->sessionCtx.station.bSendDisconnect =
3178 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
3179 VOS_TRUE : VOS_FALSE;
3180
3181 hdd_deinit_tx_rx(pAdapter);
3182 hdd_wmm_adapter_close(pAdapter);
3183
3184 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3185 pAdapterNode = pNext;
3186 }
3187
3188 EXIT();
3189
3190 return VOS_STATUS_SUCCESS;
3191}
3192
3193VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
3194{
3195 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3196 VOS_STATUS status;
3197 hdd_adapter_t *pAdapter;
3198 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
3199
3200 ENTER();
3201
3202 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3203
3204 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3205 {
3206 pAdapter = pAdapterNode->pAdapter;
3207
3208 switch(pAdapter->device_mode)
3209 {
3210 case WLAN_HDD_INFRA_STATION:
3211 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003212 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003213 hdd_init_station_mode(pAdapter);
3214 /* Open the gates for HDD to receive Wext commands */
3215 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003216 pHddCtx->scan_info.mScanPending = FALSE;
3217 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003218
3219 //Trigger the initial scan
3220 hdd_wlan_initial_scan(pAdapter);
3221
3222 //Indicate disconnect event to supplicant if associated previously
3223 if(pAdapter->sessionCtx.station.bSendDisconnect)
3224 {
3225 union iwreq_data wrqu;
3226 memset(&wrqu, '\0', sizeof(wrqu));
3227 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3228 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3229 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3230 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
3231
Jeff Johnson295189b2012-06-20 16:38:30 -07003232 /* indicate disconnected event to nl80211 */
3233 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
3234 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003235 }
3236 break;
3237
3238 case WLAN_HDD_SOFTAP:
3239 /* softAP can handle SSR */
3240 break;
3241
3242 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003243 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
3244 __func__);
3245 /* event supplicant to restart */
3246 cfg80211_del_sta(pAdapter->dev,
3247 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003248 break;
3249
3250 case WLAN_HDD_MONITOR:
3251 /* monitor interface start */
3252 break;
3253 default:
3254 break;
3255 }
3256
3257 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3258 pAdapterNode = pNext;
3259 }
3260
3261 EXIT();
3262
3263 return VOS_STATUS_SUCCESS;
3264}
3265
3266VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
3267{
3268 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3269 hdd_adapter_t *pAdapter;
3270 VOS_STATUS status;
3271 v_U32_t roamId;
3272
3273 ENTER();
3274
3275 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3276
3277 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3278 {
3279 pAdapter = pAdapterNode->pAdapter;
3280
3281 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3282 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
3283 {
3284 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3285 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3286
3287 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3288 init_completion(&pAdapter->disconnect_comp_var);
3289 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
3290 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3291
3292 wait_for_completion_interruptible_timeout(
3293 &pAdapter->disconnect_comp_var,
3294 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3295
3296 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
3297 pHddCtx->isAmpAllowed = VOS_FALSE;
3298 sme_RoamConnect(pHddCtx->hHal,
3299 pAdapter->sessionId, &(pWextState->roamProfile),
3300 &roamId);
3301 }
3302
3303 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3304 pAdapterNode = pNext;
3305 }
3306
3307 EXIT();
3308
3309 return VOS_STATUS_SUCCESS;
3310}
3311
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07003312void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
3313{
3314 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3315 VOS_STATUS status;
3316 hdd_adapter_t *pAdapter;
3317 hdd_station_ctx_t *pHddStaCtx;
3318 hdd_ap_ctx_t *pHddApCtx;
3319 hdd_hostapd_state_t * pHostapdState;
3320 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
3321 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
3322 const char *p2pMode = "DEV";
3323 const char *ccMode = "Standalone";
3324 int n;
3325
3326 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3327 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3328 {
3329 pAdapter = pAdapterNode->pAdapter;
3330 switch (pAdapter->device_mode) {
3331 case WLAN_HDD_INFRA_STATION:
3332 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3333 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3334 staChannel = pHddStaCtx->conn_info.operationChannel;
3335 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
3336 }
3337 break;
3338 case WLAN_HDD_P2P_CLIENT:
3339 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3340 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3341 p2pChannel = pHddStaCtx->conn_info.operationChannel;
3342 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
3343 p2pMode = "CLI";
3344 }
3345 break;
3346 case WLAN_HDD_P2P_GO:
3347 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3348 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3349 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3350 p2pChannel = pHddApCtx->operatingChannel;
3351 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
3352 }
3353 p2pMode = "GO";
3354 break;
3355 case WLAN_HDD_SOFTAP:
3356 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3357 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3358 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3359 apChannel = pHddApCtx->operatingChannel;
3360 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
3361 }
3362 break;
3363 default:
3364 break;
3365 }
3366 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3367 pAdapterNode = pNext;
3368 }
3369 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
3370 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
3371 }
3372 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
3373 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
3374 if (p2pChannel > 0) {
3375 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
3376 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
3377 }
3378 if (apChannel > 0) {
3379 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
3380 apChannel, MAC_ADDR_ARRAY(apBssid));
3381 }
3382
3383 if (p2pChannel > 0 && apChannel > 0) {
3384 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
3385 }
3386}
3387
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003388bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07003389{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003390 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07003391}
3392
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003393/* Once SSR is disabled then it cannot be set. */
3394void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07003395{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003396 if (HDD_SSR_DISABLED == isSsrRequired)
3397 return;
3398
Jeff Johnson295189b2012-06-20 16:38:30 -07003399 isSsrRequired = value;
3400}
3401
3402VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
3403 hdd_adapter_list_node_t** ppAdapterNode)
3404{
3405 VOS_STATUS status;
3406 spin_lock(&pHddCtx->hddAdapters.lock);
3407 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
3408 (hdd_list_node_t**) ppAdapterNode );
3409 spin_unlock(&pHddCtx->hddAdapters.lock);
3410 return status;
3411}
3412
3413VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
3414 hdd_adapter_list_node_t* pAdapterNode,
3415 hdd_adapter_list_node_t** pNextAdapterNode)
3416{
3417 VOS_STATUS status;
3418 spin_lock(&pHddCtx->hddAdapters.lock);
3419 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
3420 (hdd_list_node_t*) pAdapterNode,
3421 (hdd_list_node_t**)pNextAdapterNode );
3422
3423 spin_unlock(&pHddCtx->hddAdapters.lock);
3424 return status;
3425}
3426
3427VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
3428 hdd_adapter_list_node_t* pAdapterNode)
3429{
3430 VOS_STATUS status;
3431 spin_lock(&pHddCtx->hddAdapters.lock);
3432 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
3433 &pAdapterNode->node );
3434 spin_unlock(&pHddCtx->hddAdapters.lock);
3435 return status;
3436}
3437
3438VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
3439 hdd_adapter_list_node_t** ppAdapterNode)
3440{
3441 VOS_STATUS status;
3442 spin_lock(&pHddCtx->hddAdapters.lock);
3443 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
3444 (hdd_list_node_t**) ppAdapterNode );
3445 spin_unlock(&pHddCtx->hddAdapters.lock);
3446 return status;
3447}
3448
3449VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
3450 hdd_adapter_list_node_t* pAdapterNode)
3451{
3452 VOS_STATUS status;
3453 spin_lock(&pHddCtx->hddAdapters.lock);
3454 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
3455 (hdd_list_node_t*) pAdapterNode );
3456 spin_unlock(&pHddCtx->hddAdapters.lock);
3457 return status;
3458}
3459
3460VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
3461 hdd_adapter_list_node_t* pAdapterNode)
3462{
3463 VOS_STATUS status;
3464 spin_lock(&pHddCtx->hddAdapters.lock);
3465 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
3466 (hdd_list_node_t*) pAdapterNode );
3467 spin_unlock(&pHddCtx->hddAdapters.lock);
3468 return status;
3469}
3470
3471hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
3472 tSirMacAddr macAddr )
3473{
3474 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3475 hdd_adapter_t *pAdapter;
3476 VOS_STATUS status;
3477
3478 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3479
3480 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3481 {
3482 pAdapter = pAdapterNode->pAdapter;
3483
3484 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
3485 macAddr, sizeof(tSirMacAddr) ) )
3486 {
3487 return pAdapter;
3488 }
3489 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3490 pAdapterNode = pNext;
3491 }
3492
3493 return NULL;
3494
3495}
3496
3497hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
3498{
3499 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3500 hdd_adapter_t *pAdapter;
3501 VOS_STATUS status;
3502
3503 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3504
3505 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3506 {
3507 pAdapter = pAdapterNode->pAdapter;
3508
3509 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
3510 IFNAMSIZ ) )
3511 {
3512 return pAdapter;
3513 }
3514 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3515 pAdapterNode = pNext;
3516 }
3517
3518 return NULL;
3519
3520}
3521
3522hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
3523{
3524 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3525 hdd_adapter_t *pAdapter;
3526 VOS_STATUS status;
3527
3528 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3529
3530 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3531 {
3532 pAdapter = pAdapterNode->pAdapter;
3533
3534 if( pAdapter && (mode == pAdapter->device_mode) )
3535 {
3536 return pAdapter;
3537 }
3538 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3539 pAdapterNode = pNext;
3540 }
3541
3542 return NULL;
3543
3544}
3545
3546//Remove this function later
3547hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
3548{
3549 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3550 hdd_adapter_t *pAdapter;
3551 VOS_STATUS status;
3552
3553 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3554
3555 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3556 {
3557 pAdapter = pAdapterNode->pAdapter;
3558
3559 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
3560 {
3561 return pAdapter;
3562 }
3563
3564 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3565 pAdapterNode = pNext;
3566 }
3567
3568 return NULL;
3569
3570}
3571
Jeff Johnson295189b2012-06-20 16:38:30 -07003572/**---------------------------------------------------------------------------
3573
3574 \brief hdd_set_monitor_tx_adapter() -
3575
3576 This API initializes the adapter to be used while transmitting on monitor
3577 adapter.
3578
3579 \param - pHddCtx - Pointer to the HDD context.
3580 pAdapter - Adapter that will used for TX. This can be NULL.
3581 \return - None.
3582 --------------------------------------------------------------------------*/
3583void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3584{
3585 hdd_adapter_t *pMonAdapter;
3586
3587 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
3588
3589 if( NULL != pMonAdapter )
3590 {
3591 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
3592 }
3593}
Jeff Johnson295189b2012-06-20 16:38:30 -07003594/**---------------------------------------------------------------------------
3595
3596 \brief hdd_select_queue() -
3597
3598 This API returns the operating channel of the requested device mode
3599
3600 \param - pHddCtx - Pointer to the HDD context.
3601 - mode - Device mode for which operating channel is required
3602 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
3603 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
3604 \return - channel number. "0" id the requested device is not found OR it is not connected.
3605 --------------------------------------------------------------------------*/
3606v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
3607{
3608 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3609 VOS_STATUS status;
3610 hdd_adapter_t *pAdapter;
3611 v_U8_t operatingChannel = 0;
3612
3613 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3614
3615 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3616 {
3617 pAdapter = pAdapterNode->pAdapter;
3618
3619 if( mode == pAdapter->device_mode )
3620 {
3621 switch(pAdapter->device_mode)
3622 {
3623 case WLAN_HDD_INFRA_STATION:
3624 case WLAN_HDD_P2P_CLIENT:
3625 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3626 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
3627 break;
3628 case WLAN_HDD_SOFTAP:
3629 case WLAN_HDD_P2P_GO:
3630 /*softap connection info */
3631 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3632 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3633 break;
3634 default:
3635 break;
3636 }
3637
3638 break; //Found the device of interest. break the loop
3639 }
3640
3641 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3642 pAdapterNode = pNext;
3643 }
3644 return operatingChannel;
3645}
3646
3647#ifdef WLAN_FEATURE_PACKET_FILTERING
3648/**---------------------------------------------------------------------------
3649
3650 \brief hdd_set_multicast_list() -
3651
3652 This used to set the multicast address list.
3653
3654 \param - dev - Pointer to the WLAN device.
3655 - skb - Pointer to OS packet (sk_buff).
3656 \return - success/fail
3657
3658 --------------------------------------------------------------------------*/
3659static void hdd_set_multicast_list(struct net_device *dev)
3660{
3661 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003662 int mc_count;
3663 int i = 0;
3664 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303665
3666 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07003667 {
3668 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303669 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003670 return;
3671 }
3672
3673 if (dev->flags & IFF_ALLMULTI)
3674 {
3675 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003676 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303677 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003678 }
3679 else
3680 {
3681 mc_count = netdev_mc_count(dev);
3682 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003683 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07003684 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
3685 {
3686 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003687 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303688 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003689 return;
3690 }
3691
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303692 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07003693
3694 netdev_for_each_mc_addr(ha, dev) {
3695 if (i == mc_count)
3696 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303697 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
3698 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
3699 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003700 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303701 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07003702 i++;
3703 }
3704 }
3705 return;
3706}
3707#endif
3708
3709/**---------------------------------------------------------------------------
3710
3711 \brief hdd_select_queue() -
3712
3713 This function is registered with the Linux OS for network
3714 core to decide which queue to use first.
3715
3716 \param - dev - Pointer to the WLAN device.
3717 - skb - Pointer to OS packet (sk_buff).
3718 \return - ac, Queue Index/access category corresponding to UP in IP header
3719
3720 --------------------------------------------------------------------------*/
3721v_U16_t hdd_select_queue(struct net_device *dev,
3722 struct sk_buff *skb)
3723{
3724 return hdd_wmm_select_queue(dev, skb);
3725}
3726
3727
3728/**---------------------------------------------------------------------------
3729
3730 \brief hdd_wlan_initial_scan() -
3731
3732 This function triggers the initial scan
3733
3734 \param - pAdapter - Pointer to the HDD adapter.
3735
3736 --------------------------------------------------------------------------*/
3737void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
3738{
3739 tCsrScanRequest scanReq;
3740 tCsrChannelInfo channelInfo;
3741 eHalStatus halStatus;
3742 unsigned long scanId;
3743 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3744
3745 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
3746 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
3747 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
3748
3749 if(sme_Is11dSupported(pHddCtx->hHal))
3750 {
3751 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
3752 if ( HAL_STATUS_SUCCESS( halStatus ) )
3753 {
3754 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
3755 if( !scanReq.ChannelInfo.ChannelList )
3756 {
3757 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
3758 vos_mem_free(channelInfo.ChannelList);
3759 return;
3760 }
3761 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
3762 channelInfo.numOfChannels);
3763 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
3764 vos_mem_free(channelInfo.ChannelList);
3765 }
3766
3767 scanReq.scanType = eSIR_PASSIVE_SCAN;
3768 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
3769 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
3770 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
3771 }
3772 else
3773 {
3774 scanReq.scanType = eSIR_ACTIVE_SCAN;
3775 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3776 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
3777 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
3778 }
3779
3780 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
3781 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3782 {
3783 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
3784 __func__, halStatus );
3785 }
3786
3787 if(sme_Is11dSupported(pHddCtx->hHal))
3788 vos_mem_free(scanReq.ChannelInfo.ChannelList);
3789}
3790
3791struct fullPowerContext
3792{
3793 struct completion completion;
3794 unsigned int magic;
3795};
3796#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
3797
3798/**---------------------------------------------------------------------------
3799
3800 \brief hdd_full_power_callback() - HDD full power callback function
3801
3802 This is the function invoked by SME to inform the result of a full power
3803 request issued by HDD
3804
3805 \param - callbackcontext - Pointer to cookie
3806 \param - status - result of request
3807
3808 \return - None
3809
3810 --------------------------------------------------------------------------*/
3811static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
3812{
3813 struct fullPowerContext *pContext = callbackContext;
3814
3815 hddLog(VOS_TRACE_LEVEL_INFO,
3816 "%s: context = %p, status = %d", pContext, status);
3817
3818 if (NULL == callbackContext)
3819 {
3820 hddLog(VOS_TRACE_LEVEL_ERROR,
3821 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003822 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07003823 return;
3824 }
3825
3826 /* there is a race condition that exists between this callback function
3827 and the caller since the caller could time out either before or
3828 while this code is executing. we'll assume the timeout hasn't
3829 occurred, but we'll verify that right before we save our work */
3830
3831 if (POWER_CONTEXT_MAGIC != pContext->magic)
3832 {
3833 /* the caller presumably timed out so there is nothing we can do */
3834 hddLog(VOS_TRACE_LEVEL_WARN,
3835 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003836 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07003837 return;
3838 }
3839
3840 /* the race is on. caller could have timed out immediately after
3841 we verified the magic, but if so, caller will wait a short time
3842 for us to notify the caller, so the context will stay valid */
3843 complete(&pContext->completion);
3844}
3845
3846/**---------------------------------------------------------------------------
3847
3848 \brief hdd_wlan_exit() - HDD WLAN exit function
3849
3850 This is the driver exit point (invoked during rmmod)
3851
3852 \param - pHddCtx - Pointer to the HDD Context
3853
3854 \return - None
3855
3856 --------------------------------------------------------------------------*/
3857void hdd_wlan_exit(hdd_context_t *pHddCtx)
3858{
3859 eHalStatus halStatus;
3860 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
3861 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05303862 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003863 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003864 struct fullPowerContext powerContext;
3865 long lrc;
3866
3867 ENTER();
3868
Jeff Johnson88ba7742013-02-27 14:36:02 -08003869 if (VOS_FTM_MODE != hdd_get_conparam())
3870 {
3871 // Unloading, restart logic is no more required.
3872 wlan_hdd_restart_deinit(pHddCtx);
3873 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003874
Jeff Johnson295189b2012-06-20 16:38:30 -07003875 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003876 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003877 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003878 {
3879 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
3880 WLAN_HDD_INFRA_STATION);
3881 if (pAdapter == NULL)
3882 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3883
3884 if (pAdapter != NULL)
3885 {
3886 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
3887 hdd_UnregisterWext(pAdapter->dev);
3888 }
3889 }
3890 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003891
Jeff Johnson295189b2012-06-20 16:38:30 -07003892 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08003893 {
3894 wlan_hdd_ftm_close(pHddCtx);
3895 goto free_hdd_ctx;
3896 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003897 //Stop the Interface TX queue.
3898 //netif_tx_disable(pWlanDev);
3899 //netif_carrier_off(pWlanDev);
3900
Jeff Johnson295189b2012-06-20 16:38:30 -07003901 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3902 {
3903 pAdapter = hdd_get_adapter(pHddCtx,
3904 WLAN_HDD_SOFTAP);
3905 }
3906 else
3907 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003908 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003909 {
3910 pAdapter = hdd_get_adapter(pHddCtx,
3911 WLAN_HDD_INFRA_STATION);
3912 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003913 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003914 /* DeRegister with platform driver as client for Suspend/Resume */
3915 vosStatus = hddDeregisterPmOps(pHddCtx);
3916 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3917 {
3918 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
3919 VOS_ASSERT(0);
3920 }
3921
3922 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
3923 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3924 {
3925 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
3926 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003927
3928 // Cancel any outstanding scan requests. We are about to close all
3929 // of our adapters, but an adapter structure is what SME passes back
3930 // to our callback function. Hence if there are any outstanding scan
3931 // requests then there is a race condition between when the adapter
3932 // is closed and when the callback is invoked. We try to resolve that
3933 // race condition here by canceling any outstanding scans before we
3934 // close the adapters.
3935 // Note that the scans may be cancelled in an asynchronous manner, so
3936 // ideally there needs to be some kind of synchronization. Rather than
3937 // introduce a new synchronization here, we will utilize the fact that
3938 // we are about to Request Full Power, and since that is synchronized,
3939 // the expectation is that by the time Request Full Power has completed,
3940 // all scans will be cancelled.
3941 hdd_abort_mac_scan( pHddCtx );
3942
3943 //Disable IMPS/BMPS as we do not want the device to enter any power
3944 //save mode during shutdown
3945 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3946 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3947 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
3948
3949 //Ensure that device is in full power as we will touch H/W during vos_Stop
3950 init_completion(&powerContext.completion);
3951 powerContext.magic = POWER_CONTEXT_MAGIC;
3952
3953 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
3954 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
3955
3956 if (eHAL_STATUS_SUCCESS != halStatus)
3957 {
3958 if (eHAL_STATUS_PMC_PENDING == halStatus)
3959 {
3960 /* request was sent -- wait for the response */
3961 lrc = wait_for_completion_interruptible_timeout(
3962 &powerContext.completion,
3963 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
3964 /* either we have a response or we timed out
3965 either way, first invalidate our magic */
3966 powerContext.magic = 0;
3967 if (lrc <= 0)
3968 {
3969 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003970 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07003971 /* there is a race condition such that the callback
3972 function could be executing at the same time we are. of
3973 primary concern is if the callback function had already
3974 verified the "magic" but hasn't yet set the completion
3975 variable. Since the completion variable is on our
3976 stack, we'll delay just a bit to make sure the data is
3977 still valid if that is the case */
3978 msleep(50);
3979 }
3980 }
3981 else
3982 {
3983 hddLog(VOS_TRACE_LEVEL_ERROR,
3984 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003985 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07003986 VOS_ASSERT(0);
3987 /* continue -- need to clean up as much as possible */
3988 }
3989 }
3990
3991 // Unregister the Net Device Notifier
3992 unregister_netdevice_notifier(&hdd_netdev_notifier);
3993
Jeff Johnson295189b2012-06-20 16:38:30 -07003994 hdd_stop_all_adapters( pHddCtx );
3995
Jeff Johnson295189b2012-06-20 16:38:30 -07003996#ifdef WLAN_BTAMP_FEATURE
3997 vosStatus = WLANBAP_Stop(pVosContext);
3998 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3999 {
4000 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4001 "%s: Failed to stop BAP",__func__);
4002 }
4003#endif //WLAN_BTAMP_FEATURE
4004
4005 //Stop all the modules
4006 vosStatus = vos_stop( pVosContext );
4007 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
4008 {
4009 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4010 "%s: Failed to stop VOSS",__func__);
4011 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4012 }
4013
Jeff Johnson295189b2012-06-20 16:38:30 -07004014 //Assert Deep sleep signal now to put Libra HW in lowest power state
4015 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4016 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4017
4018 //Vote off any PMIC voltage supplies
4019 vos_chipPowerDown(NULL, NULL, NULL);
4020
4021 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4022
4023 //Clean up HDD Nlink Service
4024 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4025 nl_srv_exit();
4026
4027 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004028 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004029
4030 //Close the scheduler before calling vos_close to make sure no thread is
4031 // scheduled after the each module close is called i.e after all the data
4032 // structures are freed.
4033 vosStatus = vos_sched_close( pVosContext );
4034 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4035 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4036 "%s: Failed to close VOSS Scheduler",__func__);
4037 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4038 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004039#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004040#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4041 /* Destroy the wake lock */
4042 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4043#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004044 /* Destroy the wake lock */
4045 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004046#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004047
4048 //Close VOSS
4049 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4050 vos_close(pVosContext);
4051
Jeff Johnson295189b2012-06-20 16:38:30 -07004052 //Close Watchdog
4053 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4054 vos_watchdog_close(pVosContext);
4055
4056 /* Cancel the vote for XO Core ON.
4057 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4058 * exited at this point
4059 */
4060 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4061 " when WLAN is turned OFF\n");
4062 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4063 {
4064 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4065 " Not returning failure."
4066 " Power consumed will be high\n");
4067 }
4068
4069 hdd_close_all_adapters( pHddCtx );
4070
4071
4072 //Free up dynamically allocated members inside HDD Adapter
4073 kfree(pHddCtx->cfg_ini);
4074 pHddCtx->cfg_ini= NULL;
4075
4076 /* free the power on lock from platform driver */
4077 if (free_riva_power_on_lock("wlan"))
4078 {
4079 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4080 __func__);
4081 }
4082
Jeff Johnson88ba7742013-02-27 14:36:02 -08004083free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004084 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004085 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004086 if (hdd_is_ssr_required())
4087 {
4088 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004089 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004090 msleep(5000);
4091 }
4092 hdd_set_ssr_required (VOS_FALSE);
4093}
4094
4095
4096/**---------------------------------------------------------------------------
4097
4098 \brief hdd_update_config_from_nv() - Function to update the contents of
4099 the running configuration with parameters taken from NV storage
4100
4101 \param - pHddCtx - Pointer to the HDD global context
4102
4103 \return - VOS_STATUS_SUCCESS if successful
4104
4105 --------------------------------------------------------------------------*/
4106static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4107{
Jeff Johnson295189b2012-06-20 16:38:30 -07004108 v_BOOL_t itemIsValid = VOS_FALSE;
4109 VOS_STATUS status;
4110 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4111 v_U8_t macLoop;
4112
4113 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4114 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4115 if(status != VOS_STATUS_SUCCESS)
4116 {
4117 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4118 return VOS_STATUS_E_FAILURE;
4119 }
4120
4121 if (itemIsValid == VOS_TRUE)
4122 {
4123 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4124 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4125 VOS_MAX_CONCURRENCY_PERSONA);
4126 if(status != VOS_STATUS_SUCCESS)
4127 {
4128 /* Get MAC from NV fail, not update CFG info
4129 * INI MAC value will be used for MAC setting */
4130 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4131 return VOS_STATUS_E_FAILURE;
4132 }
4133
4134 /* If first MAC is not valid, treat all others are not valid
4135 * Then all MACs will be got from ini file */
4136 if(vos_is_macaddr_zero(&macFromNV[0]))
4137 {
4138 /* MAC address in NV file is not configured yet */
4139 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4140 return VOS_STATUS_E_INVAL;
4141 }
4142
4143 /* Get MAC address from NV, update CFG info */
4144 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4145 {
4146 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
4147 {
4148 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
4149 /* This MAC is not valid, skip it
4150 * This MAC will be got from ini file */
4151 }
4152 else
4153 {
4154 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
4155 (v_U8_t *)&macFromNV[macLoop].bytes[0],
4156 VOS_MAC_ADDR_SIZE);
4157 }
4158 }
4159 }
4160 else
4161 {
4162 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
4163 return VOS_STATUS_E_FAILURE;
4164 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004165
Jeff Johnson295189b2012-06-20 16:38:30 -07004166
4167 return VOS_STATUS_SUCCESS;
4168}
4169
4170/**---------------------------------------------------------------------------
4171
4172 \brief hdd_post_voss_start_config() - HDD post voss start config helper
4173
4174 \param - pAdapter - Pointer to the HDD
4175
4176 \return - None
4177
4178 --------------------------------------------------------------------------*/
4179VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
4180{
4181 eHalStatus halStatus;
4182 v_U32_t listenInterval;
4183
Jeff Johnson295189b2012-06-20 16:38:30 -07004184
4185 // Send ready indication to the HDD. This will kick off the MAC
4186 // into a 'running' state and should kick off an initial scan.
4187 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
4188 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4189 {
4190 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
4191 "code %08d [x%08x]",__func__, halStatus, halStatus );
4192 return VOS_STATUS_E_FAILURE;
4193 }
4194
4195 // Set default LI into HDD context,
4196 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
4197 // And RIVA will crash
4198 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
4199 pHddCtx->hdd_actual_LI_value = listenInterval;
4200
4201 return VOS_STATUS_SUCCESS;
4202}
4203
Jeff Johnson295189b2012-06-20 16:38:30 -07004204/* wake lock APIs for HDD */
4205void hdd_prevent_suspend(void)
4206{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004207#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004208 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004209#else
4210 wcnss_prevent_suspend();
4211#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004212}
4213
4214void hdd_allow_suspend(void)
4215{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004216#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004217 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004218#else
4219 wcnss_allow_suspend();
4220#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004221}
4222
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004223void hdd_allow_suspend_timeout(v_U32_t timeout)
4224{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004225#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004226 wake_lock_timeout(&wlan_wake_lock, timeout);
4227#else
4228 /* Do nothing as there is no API in wcnss for timeout*/
4229#endif
4230}
4231
Jeff Johnson295189b2012-06-20 16:38:30 -07004232/**---------------------------------------------------------------------------
4233
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004234 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
4235 information between Host and Riva
4236
4237 This function gets reported version of FW
4238 It also finds the version of Riva headers used to compile the host
4239 It compares the above two and prints a warning if they are different
4240 It gets the SW and HW version string
4241 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
4242 indicating the features they support through a bitmap
4243
4244 \param - pHddCtx - Pointer to HDD context
4245
4246 \return - void
4247
4248 --------------------------------------------------------------------------*/
4249
4250void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
4251{
4252
4253 tSirVersionType versionCompiled;
4254 tSirVersionType versionReported;
4255 tSirVersionString versionString;
4256 tANI_U8 fwFeatCapsMsgSupported = 0;
4257 VOS_STATUS vstatus;
4258
4259 /* retrieve and display WCNSS version information */
4260 do {
4261
4262 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
4263 &versionCompiled);
4264 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4265 {
4266 hddLog(VOS_TRACE_LEVEL_FATAL,
4267 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004268 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004269 break;
4270 }
4271
4272 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
4273 &versionReported);
4274 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4275 {
4276 hddLog(VOS_TRACE_LEVEL_FATAL,
4277 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004278 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004279 break;
4280 }
4281
4282 if ((versionCompiled.major != versionReported.major) ||
4283 (versionCompiled.minor != versionReported.minor) ||
4284 (versionCompiled.version != versionReported.version) ||
4285 (versionCompiled.revision != versionReported.revision))
4286 {
4287 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4288 "Host expected %u.%u.%u.%u\n",
4289 WLAN_MODULE_NAME,
4290 (int)versionReported.major,
4291 (int)versionReported.minor,
4292 (int)versionReported.version,
4293 (int)versionReported.revision,
4294 (int)versionCompiled.major,
4295 (int)versionCompiled.minor,
4296 (int)versionCompiled.version,
4297 (int)versionCompiled.revision);
4298 }
4299 else
4300 {
4301 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4302 WLAN_MODULE_NAME,
4303 (int)versionReported.major,
4304 (int)versionReported.minor,
4305 (int)versionReported.version,
4306 (int)versionReported.revision);
4307 }
4308
4309 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
4310 versionString,
4311 sizeof(versionString));
4312 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4313 {
4314 hddLog(VOS_TRACE_LEVEL_FATAL,
4315 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004316 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004317 break;
4318 }
4319
4320 pr_info("%s: WCNSS software version %s\n",
4321 WLAN_MODULE_NAME, versionString);
4322
4323 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
4324 versionString,
4325 sizeof(versionString));
4326 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4327 {
4328 hddLog(VOS_TRACE_LEVEL_FATAL,
4329 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004330 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004331 break;
4332 }
4333
4334 pr_info("%s: WCNSS hardware version %s\n",
4335 WLAN_MODULE_NAME, versionString);
4336
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004337 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
4338 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004339 send the message only if it the riva is 1.1
4340 minor numbers for different riva branches:
4341 0 -> (1.0)Mainline Build
4342 1 -> (1.1)Mainline Build
4343 2->(1.04) Stability Build
4344 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004345 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004346 ((versionReported.minor>=1) && (versionReported.version>=1)))
4347 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
4348 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004349
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004350 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08004351 {
4352#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4353 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
4354 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
4355#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004356 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08004357 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004358
4359 } while (0);
4360
4361}
4362
4363/**---------------------------------------------------------------------------
4364
Jeff Johnson295189b2012-06-20 16:38:30 -07004365 \brief hdd_wlan_startup() - HDD init function
4366
4367 This is the driver startup code executed once a WLAN device has been detected
4368
4369 \param - dev - Pointer to the underlying device
4370
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004371 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07004372
4373 --------------------------------------------------------------------------*/
4374
4375int hdd_wlan_startup(struct device *dev )
4376{
4377 VOS_STATUS status;
4378 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004379 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004380 hdd_context_t *pHddCtx = NULL;
4381 v_CONTEXT_t pVosContext= NULL;
4382#ifdef WLAN_BTAMP_FEATURE
4383 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
4384 WLANBAP_ConfigType btAmpConfig;
4385 hdd_config_t *pConfig;
4386#endif
4387 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07004388 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004389
4390 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004391 /*
4392 * cfg80211: wiphy allocation
4393 */
4394 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
4395
4396 if(wiphy == NULL)
4397 {
4398 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004399 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004400 }
4401
4402 pHddCtx = wiphy_priv(wiphy);
4403
Jeff Johnson295189b2012-06-20 16:38:30 -07004404 //Initialize the adapter context to zeros.
4405 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4406
Jeff Johnson295189b2012-06-20 16:38:30 -07004407 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004408 hdd_prevent_suspend();
4409 pHddCtx->isLoadUnloadInProgress = TRUE;
4410
4411 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4412
4413 /*Get vos context here bcoz vos_open requires it*/
4414 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4415
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08004416 if(pVosContext == NULL)
4417 {
4418 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
4419 goto err_free_hdd_context;
4420 }
4421
Jeff Johnson295189b2012-06-20 16:38:30 -07004422 //Save the Global VOSS context in adapter context for future.
4423 pHddCtx->pvosContext = pVosContext;
4424
4425 //Save the adapter context in global context for future.
4426 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
4427
Jeff Johnson295189b2012-06-20 16:38:30 -07004428 pHddCtx->parent_dev = dev;
4429
4430 init_completion(&pHddCtx->full_pwr_comp_var);
4431 init_completion(&pHddCtx->standby_comp_var);
4432 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004433 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004434 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004435
4436 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
4437
4438 // Load all config first as TL config is needed during vos_open
4439 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
4440 if(pHddCtx->cfg_ini == NULL)
4441 {
4442 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
4443 goto err_free_hdd_context;
4444 }
4445
4446 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
4447
4448 // Read and parse the qcom_cfg.ini file
4449 status = hdd_parse_config_ini( pHddCtx );
4450 if ( VOS_STATUS_SUCCESS != status )
4451 {
4452 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
4453 __func__, WLAN_INI_FILE);
4454 goto err_config;
4455 }
4456
Jeff Johnson295189b2012-06-20 16:38:30 -07004457 /*
4458 * cfg80211: Initialization and registration ...
4459 */
4460 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
4461 {
4462 hddLog(VOS_TRACE_LEVEL_FATAL,
4463 "%s: wlan_hdd_cfg80211_register return failure", __func__);
4464 goto err_wiphy_reg;
4465 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004466
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004467 // Update VOS trace levels based upon the cfg.ini
4468 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
4469 pHddCtx->cfg_ini->vosTraceEnableBAP);
4470 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
4471 pHddCtx->cfg_ini->vosTraceEnableTL);
4472 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
4473 pHddCtx->cfg_ini->vosTraceEnableWDI);
4474 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
4475 pHddCtx->cfg_ini->vosTraceEnableHDD);
4476 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
4477 pHddCtx->cfg_ini->vosTraceEnableSME);
4478 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
4479 pHddCtx->cfg_ini->vosTraceEnablePE);
4480 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
4481 pHddCtx->cfg_ini->vosTraceEnableWDA);
4482 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
4483 pHddCtx->cfg_ini->vosTraceEnableSYS);
4484 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
4485 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004486 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
4487 pHddCtx->cfg_ini->vosTraceEnableSAP);
4488 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
4489 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004490
Jeff Johnson295189b2012-06-20 16:38:30 -07004491 // Update WDI trace levels based upon the cfg.ini
4492 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
4493 pHddCtx->cfg_ini->wdiTraceEnableDAL);
4494 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
4495 pHddCtx->cfg_ini->wdiTraceEnableCTL);
4496 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
4497 pHddCtx->cfg_ini->wdiTraceEnableDAT);
4498 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
4499 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004500
Jeff Johnson88ba7742013-02-27 14:36:02 -08004501 if (VOS_FTM_MODE == hdd_get_conparam())
4502 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004503 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
4504 {
4505 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
4506 goto err_free_hdd_context;
4507 }
4508 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
4509 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08004510 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004511
Jeff Johnson88ba7742013-02-27 14:36:02 -08004512 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07004513 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4514 {
4515 status = vos_watchdog_open(pVosContext,
4516 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4517
4518 if(!VOS_IS_STATUS_SUCCESS( status ))
4519 {
4520 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004521 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07004522 }
4523 }
4524
4525 pHddCtx->isLogpInProgress = FALSE;
4526 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4527
Jeff Johnson295189b2012-06-20 16:38:30 -07004528 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
4529 if(!VOS_IS_STATUS_SUCCESS(status))
4530 {
4531 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004532 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004533 }
4534
Jeff Johnson295189b2012-06-20 16:38:30 -07004535 status = vos_open( &pVosContext, 0);
4536 if ( !VOS_IS_STATUS_SUCCESS( status ))
4537 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004538 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
4539 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07004540 }
4541
Jeff Johnson295189b2012-06-20 16:38:30 -07004542 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
4543
4544 if ( NULL == pHddCtx->hHal )
4545 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004546 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004547 goto err_vosclose;
4548 }
4549
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004550 status = vos_preStart( pHddCtx->pvosContext );
4551 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4552 {
4553 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
4554 goto err_vosclose;
4555 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004556
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004557 /* Note that the vos_preStart() sequence triggers the cfg download.
4558 The cfg download must occur before we update the SME config
4559 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07004560 status = hdd_set_sme_config( pHddCtx );
4561
4562 if ( VOS_STATUS_SUCCESS != status )
4563 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004564 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
4565 goto err_vosclose;
4566 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004567
4568 //Initialize the WMM module
4569 status = hdd_wmm_init(pHddCtx);
4570 if (!VOS_IS_STATUS_SUCCESS(status))
4571 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004572 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004573 goto err_vosclose;
4574 }
4575
Jeff Johnson295189b2012-06-20 16:38:30 -07004576 /* In the integrated architecture we update the configuration from
4577 the INI file and from NV before vOSS has been started so that
4578 the final contents are available to send down to the cCPU */
4579
4580 // Apply the cfg.ini to cfg.dat
4581 if (FALSE == hdd_update_config_dat(pHddCtx))
4582 {
4583 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4584 goto err_vosclose;
4585 }
4586
4587 // Apply the NV to cfg.dat
4588 /* Prima Update MAC address only at here */
4589 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
4590 {
4591#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
4592 /* There was not a valid set of MAC Addresses in NV. See if the
4593 default addresses were modified by the cfg.ini settings. If so,
4594 we'll use them, but if not, we'll autogenerate a set of MAC
4595 addresses based upon the device serial number */
4596
4597 static const v_MACADDR_t default_address =
4598 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
4599 unsigned int serialno;
4600 int i;
4601
4602 serialno = wcnss_get_serial_number();
4603 if ((0 != serialno) &&
4604 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
4605 sizeof(default_address))))
4606 {
4607 /* cfg.ini has the default address, invoke autogen logic */
4608
4609 /* MAC address has 3 bytes of OUI so we have a maximum of 3
4610 bytes of the serial number that can be used to generate
4611 the other 3 bytes of the MAC address. Mask off all but
4612 the lower 3 bytes (this will also make sure we don't
4613 overflow in the next step) */
4614 serialno &= 0x00FFFFFF;
4615
4616 /* we need a unique address for each session */
4617 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
4618
4619 /* autogen all addresses */
4620 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4621 {
4622 /* start with the entire default address */
4623 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4624 /* then replace the lower 3 bytes */
4625 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
4626 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
4627 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4628
4629 serialno++;
4630 }
4631
4632 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4633 MAC_ADDRESS_STR,
4634 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4635 }
4636 else
4637#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4638 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004639 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004640 "%s: Invalid MAC address in NV, using MAC from ini file "
4641 MAC_ADDRESS_STR, __func__,
4642 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4643 }
4644 }
4645 {
4646 eHalStatus halStatus;
4647 // Set the MAC Address
4648 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4649 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4650 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
4651 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
4652
4653 if (!HAL_STATUS_SUCCESS( halStatus ))
4654 {
4655 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
4656 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08004657 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004658 }
4659 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004660
4661 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
4662 Note: Firmware image will be read and downloaded inside vos_start API */
4663 status = vos_start( pHddCtx->pvosContext );
4664 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4665 {
4666 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
4667 goto err_vosclose;
4668 }
4669
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004670 /* Exchange capability info between Host and FW and also get versioning info from FW */
4671 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004672
4673 status = hdd_post_voss_start_config( pHddCtx );
4674 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4675 {
4676 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
4677 __func__);
4678 goto err_vosstop;
4679 }
4680
Jeff Johnson295189b2012-06-20 16:38:30 -07004681 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4682 {
4683 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
4684 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4685 }
4686 else
4687 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004688 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
4689 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4690 if (pAdapter != NULL)
4691 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304692 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07004693 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304694 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
4695 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
4696 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07004697
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304698 /* Generate the P2P Device Address. This consists of the device's
4699 * primary MAC address with the locally administered bit set.
4700 */
4701 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07004702 }
4703 else
4704 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304705 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
4706 if (p2p_dev_addr != NULL)
4707 {
4708 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
4709 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
4710 }
4711 else
4712 {
4713 hddLog(VOS_TRACE_LEVEL_FATAL,
4714 "%s: Failed to allocate mac_address for p2p_device",
4715 __func__);
4716 goto err_close_adapter;
4717 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004718 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004719
4720 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
4721 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
4722 if ( NULL == pP2pAdapter )
4723 {
4724 hddLog(VOS_TRACE_LEVEL_FATAL,
4725 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004726 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004727 goto err_close_adapter;
4728 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004729 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004730 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004731
4732 if( pAdapter == NULL )
4733 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004734 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
4735 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004736 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004737
Jeff Johnson295189b2012-06-20 16:38:30 -07004738#ifdef WLAN_BTAMP_FEATURE
4739 vStatus = WLANBAP_Open(pVosContext);
4740 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4741 {
4742 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4743 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004744 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004745 }
4746
4747 vStatus = BSL_Init(pVosContext);
4748 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4749 {
4750 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4751 "%s: Failed to Init BSL",__func__);
4752 goto err_bap_close;
4753 }
4754 vStatus = WLANBAP_Start(pVosContext);
4755 if (!VOS_IS_STATUS_SUCCESS(vStatus))
4756 {
4757 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4758 "%s: Failed to start TL",__func__);
4759 goto err_bap_close;
4760 }
4761
4762 pConfig = pHddCtx->cfg_ini;
4763 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
4764 status = WLANBAP_SetConfig(&btAmpConfig);
4765
4766#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07004767
Jeff Johnson295189b2012-06-20 16:38:30 -07004768#ifdef FEATURE_WLAN_SCAN_PNO
4769 /*SME must send channel update configuration to RIVA*/
4770 sme_UpdateChannelConfig(pHddCtx->hHal);
4771#endif
4772
Jeff Johnson295189b2012-06-20 16:38:30 -07004773 /* Register with platform driver as client for Suspend/Resume */
4774 status = hddRegisterPmOps(pHddCtx);
4775 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4776 {
4777 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
4778#ifdef WLAN_BTAMP_FEATURE
4779 goto err_bap_stop;
4780#else
Jeff Johnsone7245742012-09-05 17:12:55 -07004781 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004782#endif //WLAN_BTAMP_FEATURE
4783 }
4784
4785 /* Register TM level change handler function to the platform */
4786 status = hddDevTmRegisterNotifyCallback(pHddCtx);
4787 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4788 {
4789 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
4790 goto err_unregister_pmops;
4791 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004792
4793 /* register for riva power on lock to platform driver */
4794 if (req_riva_power_on_lock("wlan"))
4795 {
4796 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
4797 __func__);
4798 goto err_unregister_pmops;
4799 }
4800
Jeff Johnson295189b2012-06-20 16:38:30 -07004801 // register net device notifier for device change notification
4802 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4803
4804 if(ret < 0)
4805 {
4806 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
4807 goto err_free_power_on_lock;
4808 }
4809
4810 //Initialize the nlink service
4811 if(nl_srv_init() != 0)
4812 {
4813 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
4814 goto err_reg_netdev;
4815 }
4816
4817 //Initialize the BTC service
4818 if(btc_activate_service(pHddCtx) != 0)
4819 {
4820 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
4821 goto err_nl_srv;
4822 }
4823
4824#ifdef PTT_SOCK_SVC_ENABLE
4825 //Initialize the PTT service
4826 if(ptt_sock_activate_svc(pHddCtx) != 0)
4827 {
4828 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
4829 goto err_nl_srv;
4830 }
4831#endif
4832
Jeff Johnson295189b2012-06-20 16:38:30 -07004833 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004834 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004835 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07004836 /* Action frame registered in one adapter which will
4837 * applicable to all interfaces
4838 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07004839 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004840 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004841
4842 mutex_init(&pHddCtx->sap_lock);
4843
4844 pHddCtx->isLoadUnloadInProgress = FALSE;
4845
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004846#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004847#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4848 /* Initialize the wake lcok */
4849 wake_lock_init(&pHddCtx->rx_wake_lock,
4850 WAKE_LOCK_SUSPEND,
4851 "qcom_rx_wakelock");
4852#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004853 /* Initialize the wake lcok */
4854 wake_lock_init(&pHddCtx->sap_wake_lock,
4855 WAKE_LOCK_SUSPEND,
4856 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004857#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004858
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004859 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
4860 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07004861
4862 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4863 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004864
4865 // Initialize the restart logic
4866 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304867
Jeff Johnson295189b2012-06-20 16:38:30 -07004868 goto success;
4869
4870err_nl_srv:
4871 nl_srv_exit();
4872
4873err_reg_netdev:
4874 unregister_netdevice_notifier(&hdd_netdev_notifier);
4875
4876err_free_power_on_lock:
4877 free_riva_power_on_lock("wlan");
4878
4879err_unregister_pmops:
4880 hddDevTmUnregisterNotifyCallback(pHddCtx);
4881 hddDeregisterPmOps(pHddCtx);
4882
4883#ifdef WLAN_BTAMP_FEATURE
4884err_bap_stop:
4885 WLANBAP_Stop(pVosContext);
4886#endif
4887
4888#ifdef WLAN_BTAMP_FEATURE
4889err_bap_close:
4890 WLANBAP_Close(pVosContext);
4891#endif
4892
Jeff Johnson295189b2012-06-20 16:38:30 -07004893err_close_adapter:
4894 hdd_close_all_adapters( pHddCtx );
4895
4896err_vosstop:
4897 vos_stop(pVosContext);
4898
4899err_vosclose:
4900 status = vos_sched_close( pVosContext );
4901 if (!VOS_IS_STATUS_SUCCESS(status)) {
4902 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4903 "%s: Failed to close VOSS Scheduler", __func__);
4904 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4905 }
4906 vos_close(pVosContext );
4907
Jeff Johnson295189b2012-06-20 16:38:30 -07004908err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004909 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004910
4911err_wdclose:
4912 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4913 vos_watchdog_close(pVosContext);
4914
Jeff Johnson295189b2012-06-20 16:38:30 -07004915err_wiphy_reg:
4916 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004917
4918err_config:
4919 kfree(pHddCtx->cfg_ini);
4920 pHddCtx->cfg_ini= NULL;
4921
4922err_free_hdd_context:
4923 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004924 wiphy_free(wiphy) ;
4925 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004926 VOS_BUG(1);
4927
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004928 if (hdd_is_ssr_required())
4929 {
4930 /* WDI timeout had happened during load, so SSR is needed here */
4931 subsystem_restart("wcnss");
4932 msleep(5000);
4933 }
4934 hdd_set_ssr_required (VOS_FALSE);
4935
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004936 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004937
4938success:
4939 EXIT();
4940 return 0;
4941}
4942
4943/**---------------------------------------------------------------------------
4944
Jeff Johnson32d95a32012-09-10 13:15:23 -07004945 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004946
Jeff Johnson32d95a32012-09-10 13:15:23 -07004947 This is the driver entry point - called in different timeline depending
4948 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004949
4950 \param - None
4951
4952 \return - 0 for success, non zero for failure
4953
4954 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004955static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004956{
4957 VOS_STATUS status;
4958 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004959 struct device *dev = NULL;
4960 int ret_status = 0;
4961
4962 ENTER();
4963
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004964#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004965 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004966#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004967
4968 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4969 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4970
4971 //Power Up Libra WLAN card first if not already powered up
4972 status = vos_chipPowerUp(NULL,NULL,NULL);
4973 if (!VOS_IS_STATUS_SUCCESS(status))
4974 {
4975 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4976 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004977 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004978 }
4979
Jeff Johnson295189b2012-06-20 16:38:30 -07004980#ifdef ANI_BUS_TYPE_PCI
4981
4982 dev = wcnss_wlan_get_device();
4983
4984#endif // ANI_BUS_TYPE_PCI
4985
4986#ifdef ANI_BUS_TYPE_PLATFORM
4987 dev = wcnss_wlan_get_device();
4988#endif // ANI_BUS_TYPE_PLATFORM
4989
4990
4991 do {
4992 if (NULL == dev) {
4993 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4994 ret_status = -1;
4995 break;
4996 }
4997
4998#ifdef MEMORY_DEBUG
4999 vos_mem_init();
5000#endif
5001
5002#ifdef TIMER_MANAGER
5003 vos_timer_manager_init();
5004#endif
5005
5006 /* Preopen VOSS so that it is ready to start at least SAL */
5007 status = vos_preOpen(&pVosContext);
5008
5009 if (!VOS_IS_STATUS_SUCCESS(status))
5010 {
5011 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5012 ret_status = -1;
5013 break;
5014 }
5015
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005016#ifndef MODULE
5017 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5018 */
5019 hdd_set_conparam((v_UINT_t)con_mode);
5020#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005021
5022 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005023 if (hdd_wlan_startup(dev))
5024 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005025 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005026 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005027 vos_preClose( &pVosContext );
5028 ret_status = -1;
5029 break;
5030 }
5031
5032 /* Cancel the vote for XO Core ON
5033 * This is done here for safety purposes in case we re-initialize without turning
5034 * it OFF in any error scenario.
5035 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005036 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005037 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005038 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005039 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5040 {
5041 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5042 " Power consumed will be high\n");
5043 }
5044 } while (0);
5045
5046 if (0 != ret_status)
5047 {
5048 //Assert Deep sleep signal now to put Libra HW in lowest power state
5049 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5050 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5051
5052 //Vote off any PMIC voltage supplies
5053 vos_chipPowerDown(NULL, NULL, NULL);
5054#ifdef TIMER_MANAGER
5055 vos_timer_exit();
5056#endif
5057#ifdef MEMORY_DEBUG
5058 vos_mem_exit();
5059#endif
5060
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005061#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005062 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005063#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005064 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5065 }
5066 else
5067 {
5068 //Send WLAN UP indication to Nlink Service
5069 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5070
5071 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5072
5073 }
5074
5075 EXIT();
5076
5077 return ret_status;
5078}
5079
Jeff Johnson32d95a32012-09-10 13:15:23 -07005080/**---------------------------------------------------------------------------
5081
5082 \brief hdd_module_init() - Init Function
5083
5084 This is the driver entry point (invoked when module is loaded using insmod)
5085
5086 \param - None
5087
5088 \return - 0 for success, non zero for failure
5089
5090 --------------------------------------------------------------------------*/
5091#ifdef MODULE
5092static int __init hdd_module_init ( void)
5093{
5094 return hdd_driver_init();
5095}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005096#else /* #ifdef MODULE */
5097static int __init hdd_module_init ( void)
5098{
5099 /* Driver initialization is delayed to fwpath_changed_handler */
5100 return 0;
5101}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005102#endif /* #ifdef MODULE */
5103
Jeff Johnson295189b2012-06-20 16:38:30 -07005104
5105/**---------------------------------------------------------------------------
5106
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005107 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005108
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005109 This is the driver exit point (invoked when module is unloaded using rmmod
5110 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005111
5112 \param - None
5113
5114 \return - None
5115
5116 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005117static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005118{
5119 hdd_context_t *pHddCtx = NULL;
5120 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005121
5122 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
5123
5124 //Get the global vos context
5125 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5126
5127 if(!pVosContext)
5128 {
5129 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
5130 goto done;
5131 }
5132
5133 //Get the HDD context.
5134 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
5135
5136 if(!pHddCtx)
5137 {
5138 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
5139 }
5140 else
5141 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005142 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005143 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07005144 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
5145 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07005146 }
5147
5148 pHddCtx->isLoadUnloadInProgress = TRUE;
5149 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5150
5151 //Do all the cleanup before deregistering the driver
5152 hdd_wlan_exit(pHddCtx);
5153 }
5154
Jeff Johnson295189b2012-06-20 16:38:30 -07005155 vos_preClose( &pVosContext );
5156
5157#ifdef TIMER_MANAGER
5158 vos_timer_exit();
5159#endif
5160#ifdef MEMORY_DEBUG
5161 vos_mem_exit();
5162#endif
5163
5164done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005165#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005166 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005167#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005168 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
5169}
5170
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005171/**---------------------------------------------------------------------------
5172
5173 \brief hdd_module_exit() - Exit function
5174
5175 This is the driver exit point (invoked when module is unloaded using rmmod)
5176
5177 \param - None
5178
5179 \return - None
5180
5181 --------------------------------------------------------------------------*/
5182static void __exit hdd_module_exit(void)
5183{
5184 hdd_driver_exit();
5185}
5186
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005187#ifdef MODULE
5188static int fwpath_changed_handler(const char *kmessage,
5189 struct kernel_param *kp)
5190{
5191 /* nothing to do when driver is DLKM */
5192 return 0;
5193}
5194
5195static int con_mode_handler(const char *kmessage,
5196 struct kernel_param *kp)
5197{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005198 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005199}
5200#else /* #ifdef MODULE */
5201/**---------------------------------------------------------------------------
5202
5203 \brief fwpath_changed_handler() - Handler Function
5204
5205 This is the driver entry point
5206 - delayed driver initialization when driver is statically linked
5207 - invoked when module parameter fwpath is modified from userpspace to signal
5208 initializing the WLAN driver
5209
5210 \return - 0 for success, non zero for failure
5211
5212 --------------------------------------------------------------------------*/
5213static int fwpath_changed_handler(const char *kmessage,
5214 struct kernel_param *kp)
5215{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005216 int ret_status;
5217
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005218 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005219 ret_status = hdd_driver_init();
5220 wlan_hdd_inited = ret_status ? 0 : 1;
5221 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005222 }
5223
5224 hdd_driver_exit();
5225
5226 msleep(200);
5227
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005228 ret_status = hdd_driver_init();
5229 wlan_hdd_inited = ret_status ? 0 : 1;
5230 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005231}
5232
Jeff Johnson295189b2012-06-20 16:38:30 -07005233/**---------------------------------------------------------------------------
5234
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005235 \brief con_mode_handler() -
5236
5237 Handler function for module param con_mode when it is changed by userspace
5238 Dynamically linked - do nothing
5239 Statically linked - exit and init driver, as in rmmod and insmod
5240
5241 \param -
5242
5243 \return -
5244
5245 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005246static int con_mode_handler(const char *kmessage,
5247 struct kernel_param *kp)
5248{
5249 int ret = param_set_int(kmessage, kp);
5250
5251 if (ret)
5252 return ret;
5253
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005254 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005255}
5256#endif /* #ifdef MODULE */
5257
5258/**---------------------------------------------------------------------------
5259
Jeff Johnson295189b2012-06-20 16:38:30 -07005260 \brief hdd_get_conparam() -
5261
5262 This is the driver exit point (invoked when module is unloaded using rmmod)
5263
5264 \param - None
5265
5266 \return - tVOS_CON_MODE
5267
5268 --------------------------------------------------------------------------*/
5269tVOS_CON_MODE hdd_get_conparam ( void )
5270{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005271#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005272 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005273#else
5274 return (tVOS_CON_MODE)curr_con_mode;
5275#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005276}
5277void hdd_set_conparam ( v_UINT_t newParam )
5278{
5279 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005280#ifndef MODULE
5281 curr_con_mode = con_mode;
5282#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005283}
5284/**---------------------------------------------------------------------------
5285
5286 \brief hdd_softap_sta_deauth() - function
5287
5288 This to take counter measure to handle deauth req from HDD
5289
5290 \param - pAdapter - Pointer to the HDD
5291
5292 \param - enable - boolean value
5293
5294 \return - None
5295
5296 --------------------------------------------------------------------------*/
5297
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005298VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005299{
Jeff Johnson295189b2012-06-20 16:38:30 -07005300 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005301 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005302
5303 ENTER();
5304
5305 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5306
5307 //Ignore request to deauth bcmc station
5308 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005309 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005310
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005311 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005312
5313 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005314 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005315}
5316
5317/**---------------------------------------------------------------------------
5318
5319 \brief hdd_softap_sta_disassoc() - function
5320
5321 This to take counter measure to handle deauth req from HDD
5322
5323 \param - pAdapter - Pointer to the HDD
5324
5325 \param - enable - boolean value
5326
5327 \return - None
5328
5329 --------------------------------------------------------------------------*/
5330
5331void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5332{
5333 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5334
5335 ENTER();
5336
5337 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5338
5339 //Ignore request to disassoc bcmc station
5340 if( pDestMacAddress[0] & 0x1 )
5341 return;
5342
5343 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5344}
5345
5346void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5347{
5348 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5349
5350 ENTER();
5351
5352 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5353
5354 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5355}
5356
Jeff Johnson295189b2012-06-20 16:38:30 -07005357/**---------------------------------------------------------------------------
5358 *
5359 * \brief hdd_get__concurrency_mode() -
5360 *
5361 *
5362 * \param - None
5363 *
5364 * \return - CONCURRENCY MODE
5365 *
5366 * --------------------------------------------------------------------------*/
5367tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
5368{
5369 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5370 hdd_context_t *pHddCtx;
5371
5372 if (NULL != pVosContext)
5373 {
5374 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5375 if (NULL != pHddCtx)
5376 {
5377 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
5378 }
5379 }
5380
5381 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005382 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005383 return VOS_STA;
5384}
5385
5386/* Decide whether to allow/not the apps power collapse.
5387 * Allow apps power collapse if we are in connected state.
5388 * if not, allow only if we are in IMPS */
5389v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
5390{
5391 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08005392 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005393 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005394 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5395 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5396 hdd_adapter_t *pAdapter = NULL;
5397 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08005398 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005399
Jeff Johnson295189b2012-06-20 16:38:30 -07005400 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5401 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005402
Yathish9f22e662012-12-10 14:21:35 -08005403 concurrent_state = hdd_get_concurrency_mode();
5404
5405#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5406 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
5407 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
5408 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
5409 return TRUE;
5410#endif
5411
Jeff Johnson295189b2012-06-20 16:38:30 -07005412 /*loop through all adapters. TBD fix for Concurrency */
5413 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5414 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5415 {
5416 pAdapter = pAdapterNode->pAdapter;
5417 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
5418 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5419 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005420 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07005421 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08005422 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005423 (eANI_BOOLEAN_TRUE == scanRspPending) ||
5424 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07005425 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005426 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005427 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
5428 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07005429 return FALSE;
5430 }
5431 }
5432 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5433 pAdapterNode = pNext;
5434 }
5435 return TRUE;
5436}
5437
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08005438/* Decides whether to send suspend notification to Riva
5439 * if any adapter is in BMPS; then it is required */
5440v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
5441{
5442 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
5443 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5444
5445 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
5446 {
5447 return TRUE;
5448 }
5449 return FALSE;
5450}
5451
Jeff Johnson295189b2012-06-20 16:38:30 -07005452void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5453{
5454 switch(mode)
5455 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005456 case VOS_STA_MODE:
5457 case VOS_P2P_CLIENT_MODE:
5458 case VOS_P2P_GO_MODE:
5459 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07005460 pHddCtx->concurrency_mode |= (1 << mode);
5461 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07005462 break;
5463 default:
5464 break;
5465
5466 }
5467 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5468 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5469}
5470
5471
5472void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5473{
5474 switch(mode)
5475 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005476 case VOS_STA_MODE:
5477 case VOS_P2P_CLIENT_MODE:
5478 case VOS_P2P_GO_MODE:
5479 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005480 pHddCtx->no_of_sessions[mode]--;
5481 if (!(pHddCtx->no_of_sessions[mode]))
5482 pHddCtx->concurrency_mode &= (~(1 << mode));
5483 break;
5484 default:
5485 break;
5486 }
5487 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5488 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5489}
5490
Jeff Johnsone7245742012-09-05 17:12:55 -07005491/**---------------------------------------------------------------------------
5492 *
5493 * \brief wlan_hdd_restart_init
5494 *
5495 * This function initalizes restart timer/flag. An internal function.
5496 *
5497 * \param - pHddCtx
5498 *
5499 * \return - None
5500 *
5501 * --------------------------------------------------------------------------*/
5502
5503static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
5504{
5505 /* Initialize */
5506 pHddCtx->hdd_restart_retries = 0;
5507 atomic_set(&pHddCtx->isRestartInProgress, 0);
5508 vos_timer_init(&pHddCtx->hdd_restart_timer,
5509 VOS_TIMER_TYPE_SW,
5510 wlan_hdd_restart_timer_cb,
5511 pHddCtx);
5512}
5513/**---------------------------------------------------------------------------
5514 *
5515 * \brief wlan_hdd_restart_deinit
5516 *
5517 * This function cleans up the resources used. An internal function.
5518 *
5519 * \param - pHddCtx
5520 *
5521 * \return - None
5522 *
5523 * --------------------------------------------------------------------------*/
5524
5525static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
5526{
5527
5528 VOS_STATUS vos_status;
5529 /* Block any further calls */
5530 atomic_set(&pHddCtx->isRestartInProgress, 1);
5531 /* Cleanup */
5532 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5533 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005534 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005535 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5536 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005537 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005538
5539}
5540
5541/**---------------------------------------------------------------------------
5542 *
5543 * \brief wlan_hdd_framework_restart
5544 *
5545 * This function uses a cfg80211 API to start a framework initiated WLAN
5546 * driver module unload/load.
5547 *
5548 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
5549 *
5550 *
5551 * \param - pHddCtx
5552 *
5553 * \return - VOS_STATUS_SUCCESS: Success
5554 * VOS_STATUS_E_EMPTY: Adapter is Empty
5555 * VOS_STATUS_E_NOMEM: No memory
5556
5557 * --------------------------------------------------------------------------*/
5558
5559static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
5560{
5561 VOS_STATUS status = VOS_STATUS_SUCCESS;
5562 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5563 int len = (sizeof (struct ieee80211_mgmt));
5564 struct ieee80211_mgmt *mgmt = NULL;
5565
5566 /* Prepare the DEAUTH managment frame with reason code */
5567 mgmt = kzalloc(len, GFP_KERNEL);
5568 if(mgmt == NULL)
5569 {
5570 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08005571 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07005572 return VOS_STATUS_E_NOMEM;
5573 }
5574 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
5575
5576 /* Iterate over all adapters/devices */
5577 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5578 do
5579 {
5580 if( (status == VOS_STATUS_SUCCESS) &&
5581 pAdapterNode &&
5582 pAdapterNode->pAdapter)
5583 {
5584 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5585 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
5586 pAdapterNode->pAdapter->dev->name,
5587 pAdapterNode->pAdapter->device_mode,
5588 pHddCtx->hdd_restart_retries + 1);
5589 /*
5590 * CFG80211 event to restart the driver
5591 *
5592 * 'cfg80211_send_unprot_deauth' sends a
5593 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
5594 * of SME(Linux Kernel) state machine.
5595 *
5596 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
5597 * the driver.
5598 *
5599 */
5600
5601 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
5602 }
5603 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5604 pAdapterNode = pNext;
5605 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
5606
5607
5608 /* Free the allocated management frame */
5609 kfree(mgmt);
5610
5611 /* Retry until we unload or reach max count */
5612 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
5613 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
5614
5615 return status;
5616
5617}
5618/**---------------------------------------------------------------------------
5619 *
5620 * \brief wlan_hdd_restart_timer_cb
5621 *
5622 * Restart timer callback. An internal function.
5623 *
5624 * \param - User data:
5625 *
5626 * \return - None
5627 *
5628 * --------------------------------------------------------------------------*/
5629
5630void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
5631{
5632 hdd_context_t *pHddCtx = usrDataForCallback;
5633 wlan_hdd_framework_restart(pHddCtx);
5634 return;
5635
5636}
5637
5638
5639/**---------------------------------------------------------------------------
5640 *
5641 * \brief wlan_hdd_restart_driver
5642 *
5643 * This function sends an event to supplicant to restart the WLAN driver.
5644 *
5645 * This function is called from vos_wlanRestart.
5646 *
5647 * \param - pHddCtx
5648 *
5649 * \return - VOS_STATUS_SUCCESS: Success
5650 * VOS_STATUS_E_EMPTY: Adapter is Empty
5651 * VOS_STATUS_E_ALREADY: Request already in progress
5652
5653 * --------------------------------------------------------------------------*/
5654VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
5655{
5656 VOS_STATUS status = VOS_STATUS_SUCCESS;
5657
5658 /* A tight check to make sure reentrancy */
5659 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
5660 {
5661 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
5662 "%s: WLAN restart is already in progress", __func__);
5663
5664 return VOS_STATUS_E_ALREADY;
5665 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07005666 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005667#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005668 wcnss_reset_intr();
5669#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005670
Jeff Johnsone7245742012-09-05 17:12:55 -07005671 return status;
5672}
5673
5674
Jeff Johnson295189b2012-06-20 16:38:30 -07005675//Register the module init/exit functions
5676module_init(hdd_module_init);
5677module_exit(hdd_module_exit);
5678
5679MODULE_LICENSE("Dual BSD/GPL");
5680MODULE_AUTHOR("Qualcomm Atheros, Inc.");
5681MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
5682
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005683module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
5684 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005685
5686module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
5687 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);