blob: eb3c584378efb97cdcbb581f3dfa9d677662d57e [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*/
1526 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1527
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);
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001537 if ((v < 0) || (tempInt <= 0)) return -EINVAL;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001538
1539 *pNumChannels = tempInt;
1540
1541 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1542 "Number of channels are: %d", *pNumChannels);
1543
1544 for (j = 0; j < (*pNumChannels); j++)
1545 {
1546 /*inPtr pointing to the beginning of first space after number of channels*/
1547 inPtr = strpbrk( inPtr, " " );
1548 /*no channel list after the number of channels argument*/
1549 if (NULL == inPtr)
1550 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001551 if (0 != j)
1552 {
1553 *pNumChannels = j;
1554 return VOS_STATUS_SUCCESS;
1555 }
1556 else
1557 {
1558 return -EINVAL;
1559 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001560 }
1561
1562 /*removing empty space*/
1563 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1564
1565 /*no channel list after the number of channels argument and spaces*/
1566 if ( '\0' == *inPtr )
1567 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001568 if (0 != j)
1569 {
1570 *pNumChannels = j;
1571 return VOS_STATUS_SUCCESS;
1572 }
1573 else
1574 {
1575 return -EINVAL;
1576 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001577 }
1578
1579 sscanf(inPtr, "%s ", buf);
1580 v = kstrtos32(buf, 10, &tempInt);
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07001581 if ((v < 0) || (tempInt <= 0)) return -EINVAL;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001582 pChannelList[j] = tempInt;
1583
1584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1585 "Channel %d added to preferred channel list",
1586 pChannelList[j] );
1587 }
1588
Srinivas Girigowdade697412013-02-14 16:31:48 -08001589 return VOS_STATUS_SUCCESS;
1590}
1591
1592#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001593/**---------------------------------------------------------------------------
1594
1595 \brief hdd_open() - HDD Open function
1596
1597 This is called in response to ifconfig up
1598
1599 \param - dev Pointer to net_device structure
1600
1601 \return - 0 for success non-zero for failure
1602
1603 --------------------------------------------------------------------------*/
1604int hdd_open (struct net_device *dev)
1605{
1606 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1607 hdd_context_t *pHddCtx;
1608 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1609 VOS_STATUS status;
1610 v_BOOL_t in_standby = TRUE;
1611
1612 if (NULL == pAdapter)
1613 {
1614 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001615 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001616 return -ENODEV;
1617 }
1618
1619 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1620 if (NULL == pHddCtx)
1621 {
1622 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001623 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001624 return -ENODEV;
1625 }
1626
1627 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1628 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1629 {
1630 if( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1631 {
1632 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of "
1633 "standby", __func__, pAdapter->device_mode);
1634 in_standby = FALSE;
1635 break;
1636 }
1637 else
1638 {
1639 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1640 pAdapterNode = pNext;
1641 }
1642 }
1643
1644 if (TRUE == in_standby)
1645 {
1646 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
1647 {
1648 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
1649 "wlan out of power save", __func__);
1650 return -EINVAL;
1651 }
1652 }
1653
1654 pAdapter->event_flags |= DEVICE_IFACE_OPENED;
1655 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1656 {
1657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001658 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001659 /* Enable TX queues only when we are connected */
1660 netif_tx_start_all_queues(dev);
1661 }
1662
1663 return 0;
1664}
1665
1666int hdd_mon_open (struct net_device *dev)
1667{
1668 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1669
1670 if(pAdapter == NULL) {
1671 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001672 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001673 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001674 }
1675
1676 netif_start_queue(dev);
1677
1678 return 0;
1679}
1680/**---------------------------------------------------------------------------
1681
1682 \brief hdd_stop() - HDD stop function
1683
1684 This is called in response to ifconfig down
1685
1686 \param - dev Pointer to net_device structure
1687
1688 \return - 0 for success non-zero for failure
1689
1690 --------------------------------------------------------------------------*/
1691
1692int hdd_stop (struct net_device *dev)
1693{
1694 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1695 hdd_context_t *pHddCtx;
1696 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1697 VOS_STATUS status;
1698 v_BOOL_t enter_standby = TRUE;
1699
1700 ENTER();
1701
1702 if (NULL == pAdapter)
1703 {
1704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001705 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001706 return -ENODEV;
1707 }
1708
1709 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1710 if (NULL == pHddCtx)
1711 {
1712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001713 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001714 return -ENODEV;
1715 }
1716
1717 pAdapter->event_flags &= ~(DEVICE_IFACE_OPENED);
1718 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
1719 netif_tx_disable(pAdapter->dev);
1720 netif_carrier_off(pAdapter->dev);
1721
1722
1723 /* SoftAP ifaces should never go in power save mode
1724 making sure same here. */
1725 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
1726 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001727 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001728 )
1729 {
1730 /* SoftAP mode, so return from here */
1731 EXIT();
1732 return 0;
1733 }
1734
1735 /* Find if any iface is up then
1736 if any iface is up then can't put device to sleep/ power save mode. */
1737 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1738 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1739 {
1740 if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1741 {
1742 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
1743 "put device to sleep", __func__, pAdapter->device_mode);
1744 enter_standby = FALSE;
1745 break;
1746 }
1747 else
1748 {
1749 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1750 pAdapterNode = pNext;
1751 }
1752 }
1753
1754 if (TRUE == enter_standby)
1755 {
1756 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
1757 "entering standby", __func__);
1758 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
1759 {
1760 /*log and return success*/
1761 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
1762 "wlan in power save", __func__);
1763 }
1764 }
1765
1766 EXIT();
1767 return 0;
1768}
1769
1770/**---------------------------------------------------------------------------
1771
1772 \brief hdd_uninit() - HDD uninit function
1773
1774 This is called during the netdev unregister to uninitialize all data
1775associated with the device
1776
1777 \param - dev Pointer to net_device structure
1778
1779 \return - void
1780
1781 --------------------------------------------------------------------------*/
1782static void hdd_uninit (struct net_device *dev)
1783{
1784 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1785
1786 ENTER();
1787
1788 do
1789 {
1790 if (NULL == pAdapter)
1791 {
1792 hddLog(VOS_TRACE_LEVEL_FATAL,
1793 "%s: NULL pAdapter", __func__);
1794 break;
1795 }
1796
1797 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1798 {
1799 hddLog(VOS_TRACE_LEVEL_FATAL,
1800 "%s: Invalid magic", __func__);
1801 break;
1802 }
1803
1804 if (NULL == pAdapter->pHddCtx)
1805 {
1806 hddLog(VOS_TRACE_LEVEL_FATAL,
1807 "%s: NULL pHddCtx", __func__);
1808 break;
1809 }
1810
1811 if (dev != pAdapter->dev)
1812 {
1813 hddLog(VOS_TRACE_LEVEL_FATAL,
1814 "%s: Invalid device reference", __func__);
1815 /* we haven't validated all cases so let this go for now */
1816 }
1817
1818 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
1819
1820 /* after uninit our adapter structure will no longer be valid */
1821 pAdapter->dev = NULL;
1822 pAdapter->magic = 0;
1823 } while (0);
1824
1825 EXIT();
1826}
1827
1828/**---------------------------------------------------------------------------
1829
1830 \brief hdd_release_firmware() -
1831
1832 This function calls the release firmware API to free the firmware buffer.
1833
1834 \param - pFileName Pointer to the File Name.
1835 pCtx - Pointer to the adapter .
1836
1837
1838 \return - 0 for success, non zero for failure
1839
1840 --------------------------------------------------------------------------*/
1841
1842VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
1843{
1844 VOS_STATUS status = VOS_STATUS_SUCCESS;
1845 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1846 ENTER();
1847
1848
1849 if (!strcmp(WLAN_FW_FILE, pFileName)) {
1850
1851 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
1852
1853 if(pHddCtx->fw) {
1854 release_firmware(pHddCtx->fw);
1855 pHddCtx->fw = NULL;
1856 }
1857 else
1858 status = VOS_STATUS_E_FAILURE;
1859 }
1860 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
1861 if(pHddCtx->nv) {
1862 release_firmware(pHddCtx->nv);
1863 pHddCtx->nv = NULL;
1864 }
1865 else
1866 status = VOS_STATUS_E_FAILURE;
1867
1868 }
1869
1870 EXIT();
1871 return status;
1872}
1873
1874/**---------------------------------------------------------------------------
1875
1876 \brief hdd_request_firmware() -
1877
1878 This function reads the firmware file using the request firmware
1879 API and returns the the firmware data and the firmware file size.
1880
1881 \param - pfileName - Pointer to the file name.
1882 - pCtx - Pointer to the adapter .
1883 - ppfw_data - Pointer to the pointer of the firmware data.
1884 - pSize - Pointer to the file size.
1885
1886 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
1887
1888 --------------------------------------------------------------------------*/
1889
1890
1891VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
1892{
1893 int status;
1894 VOS_STATUS retval = VOS_STATUS_SUCCESS;
1895 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1896 ENTER();
1897
1898 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
1899
1900 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
1901
1902 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1903 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
1904 __func__, pfileName);
1905 retval = VOS_STATUS_E_FAILURE;
1906 }
1907
1908 else {
1909 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
1910 *pSize = pHddCtx->fw->size;
1911 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
1912 __func__, *pSize);
1913 }
1914 }
1915 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
1916
1917 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
1918
1919 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
1920 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
1921 __func__, pfileName);
1922 retval = VOS_STATUS_E_FAILURE;
1923 }
1924
1925 else {
1926 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
1927 *pSize = pHddCtx->nv->size;
1928 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
1929 __func__, *pSize);
1930 }
1931 }
1932
1933 EXIT();
1934 return retval;
1935}
1936/**---------------------------------------------------------------------------
1937 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
1938
1939 This is the function invoked by SME to inform the result of a full power
1940 request issued by HDD
1941
1942 \param - callbackcontext - Pointer to cookie
1943 status - result of request
1944
1945 \return - None
1946
1947--------------------------------------------------------------------------*/
1948void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
1949{
1950 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
1951
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001952 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001953 if(&pHddCtx->full_pwr_comp_var)
1954 {
1955 complete(&pHddCtx->full_pwr_comp_var);
1956 }
1957}
1958
1959/**---------------------------------------------------------------------------
1960
1961 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
1962
1963 This is the function invoked by SME to inform the result of BMPS
1964 request issued by HDD
1965
1966 \param - callbackcontext - Pointer to cookie
1967 status - result of request
1968
1969 \return - None
1970
1971--------------------------------------------------------------------------*/
1972void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
1973{
1974
1975 struct completion *completion_var = (struct completion*) callbackContext;
1976
1977 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
1978 if(completion_var != NULL)
1979 {
1980 complete(completion_var);
1981 }
1982}
1983
1984/**---------------------------------------------------------------------------
1985
1986 \brief hdd_get_cfg_file_size() -
1987
1988 This function reads the configuration file using the request firmware
1989 API and returns the configuration file size.
1990
1991 \param - pCtx - Pointer to the adapter .
1992 - pFileName - Pointer to the file name.
1993 - pBufSize - Pointer to the buffer size.
1994
1995 \return - 0 for success, non zero for failure
1996
1997 --------------------------------------------------------------------------*/
1998
1999VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
2000{
2001 int status;
2002 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2003
2004 ENTER();
2005
2006 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2007
2008 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2009 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2010 status = VOS_STATUS_E_FAILURE;
2011 }
2012 else {
2013 *pBufSize = pHddCtx->fw->size;
2014 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
2015 release_firmware(pHddCtx->fw);
2016 pHddCtx->fw = NULL;
2017 }
2018
2019 EXIT();
2020 return VOS_STATUS_SUCCESS;
2021}
2022
2023/**---------------------------------------------------------------------------
2024
2025 \brief hdd_read_cfg_file() -
2026
2027 This function reads the configuration file using the request firmware
2028 API and returns the cfg data and the buffer size of the configuration file.
2029
2030 \param - pCtx - Pointer to the adapter .
2031 - pFileName - Pointer to the file name.
2032 - pBuffer - Pointer to the data buffer.
2033 - pBufSize - Pointer to the buffer size.
2034
2035 \return - 0 for success, non zero for failure
2036
2037 --------------------------------------------------------------------------*/
2038
2039VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
2040 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
2041{
2042 int status;
2043 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
2044
2045 ENTER();
2046
2047 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
2048
2049 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
2050 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
2051 return VOS_STATUS_E_FAILURE;
2052 }
2053 else {
2054 if(*pBufSize != pHddCtx->fw->size) {
2055 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
2056 "file size", __func__);
2057 release_firmware(pHddCtx->fw);
2058 pHddCtx->fw = NULL;
2059 return VOS_STATUS_E_FAILURE;
2060 }
2061 else {
2062 if(pBuffer) {
2063 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
2064 }
2065 release_firmware(pHddCtx->fw);
2066 pHddCtx->fw = NULL;
2067 }
2068 }
2069
2070 EXIT();
2071
2072 return VOS_STATUS_SUCCESS;
2073}
2074
2075/**---------------------------------------------------------------------------
2076
Jeff Johnson295189b2012-06-20 16:38:30 -07002077 \brief hdd_set_mac_address() -
2078
2079 This function sets the user specified mac address using
2080 the command ifconfig wlanX hw ether <mac adress>.
2081
2082 \param - dev - Pointer to the net device.
2083 - addr - Pointer to the sockaddr.
2084 \return - 0 for success, non zero for failure
2085
2086 --------------------------------------------------------------------------*/
2087
2088static int hdd_set_mac_address(struct net_device *dev, void *addr)
2089{
2090 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2091 struct sockaddr *psta_mac_addr = addr;
2092 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2093
2094 ENTER();
2095
2096 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2097
2098#ifdef HDD_SESSIONIZE
2099 // set the MAC address though the STA ID CFG.
2100 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
2101 (v_U8_t *)&pAdapter->macAddressCurrent,
2102 sizeof( pAdapter->macAddressCurrent ),
2103 hdd_set_mac_addr_cb, VOS_FALSE );
2104#endif
2105
2106 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2107
2108 EXIT();
2109 return halStatus;
2110}
2111
2112tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
2113{
2114 int i;
2115 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2116 {
2117 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
2118 break;
2119 }
2120
2121 if( VOS_MAX_CONCURRENCY_PERSONA == i)
2122 return NULL;
2123
2124 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
2125 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
2126}
2127
2128void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
2129{
2130 int i;
2131 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
2132 {
2133 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
2134 {
2135 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
2136 break;
2137 }
2138 }
2139 return;
2140}
2141
2142#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2143 static struct net_device_ops wlan_drv_ops = {
2144 .ndo_open = hdd_open,
2145 .ndo_stop = hdd_stop,
2146 .ndo_uninit = hdd_uninit,
2147 .ndo_start_xmit = hdd_hard_start_xmit,
2148 .ndo_tx_timeout = hdd_tx_timeout,
2149 .ndo_get_stats = hdd_stats,
2150 .ndo_do_ioctl = hdd_ioctl,
2151 .ndo_set_mac_address = hdd_set_mac_address,
2152 .ndo_select_queue = hdd_select_queue,
2153#ifdef WLAN_FEATURE_PACKET_FILTERING
2154#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
2155 .ndo_set_rx_mode = hdd_set_multicast_list,
2156#else
2157 .ndo_set_multicast_list = hdd_set_multicast_list,
2158#endif //LINUX_VERSION_CODE
2159#endif
2160 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002161 static struct net_device_ops wlan_mon_drv_ops = {
2162 .ndo_open = hdd_mon_open,
2163 .ndo_stop = hdd_stop,
2164 .ndo_uninit = hdd_uninit,
2165 .ndo_start_xmit = hdd_mon_hard_start_xmit,
2166 .ndo_tx_timeout = hdd_tx_timeout,
2167 .ndo_get_stats = hdd_stats,
2168 .ndo_do_ioctl = hdd_ioctl,
2169 .ndo_set_mac_address = hdd_set_mac_address,
2170 };
Jeff Johnson295189b2012-06-20 16:38:30 -07002171
2172#endif
2173
2174void hdd_set_station_ops( struct net_device *pWlanDev )
2175{
2176#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2177 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
2178 pWlanDev->netdev_ops = &wlan_drv_ops;
2179#else
2180 pWlanDev->open = hdd_open;
2181 pWlanDev->stop = hdd_stop;
2182 pWlanDev->uninit = hdd_uninit;
2183 pWlanDev->hard_start_xmit = NULL;
2184 pWlanDev->tx_timeout = hdd_tx_timeout;
2185 pWlanDev->get_stats = hdd_stats;
2186 pWlanDev->do_ioctl = hdd_ioctl;
2187 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
2188 pWlanDev->set_mac_address = hdd_set_mac_address;
2189#endif
2190}
2191
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002192static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07002193{
2194 struct net_device *pWlanDev = NULL;
2195 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002196 /*
2197 * cfg80211 initialization and registration....
2198 */
2199 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
2200
Jeff Johnson295189b2012-06-20 16:38:30 -07002201 if(pWlanDev != NULL)
2202 {
2203
2204 //Save the pointer to the net_device in the HDD adapter
2205 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
2206
Jeff Johnson295189b2012-06-20 16:38:30 -07002207 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
2208
2209 pAdapter->dev = pWlanDev;
2210 pAdapter->pHddCtx = pHddCtx;
2211 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2212
2213 init_completion(&pAdapter->session_open_comp_var);
2214 init_completion(&pAdapter->session_close_comp_var);
2215 init_completion(&pAdapter->disconnect_comp_var);
2216 init_completion(&pAdapter->linkup_event_var);
2217 init_completion(&pAdapter->cancel_rem_on_chan_var);
2218 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07002219#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2220 init_completion(&pAdapter->offchannel_tx_event);
2221#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002222 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002223#ifdef FEATURE_WLAN_TDLS
2224 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07002225 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002226 init_completion(&pAdapter->tdls_mgmt_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08002227#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002228 init_completion(&pHddCtx->mc_sus_event_var);
2229 init_completion(&pHddCtx->tx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07002230 init_completion(&pAdapter->ula_complete);
Jeff Johnson295189b2012-06-20 16:38:30 -07002231
Jeff Johnson295189b2012-06-20 16:38:30 -07002232 pAdapter->isLinkUpSvcNeeded = FALSE;
2233 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
2234 //Init the net_device structure
2235 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2236
2237 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
2238 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
2239 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
2240 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
2241
2242 hdd_set_station_ops( pAdapter->dev );
2243
2244 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002245 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
2246 pAdapter->wdev.wiphy = pHddCtx->wiphy;
2247 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07002248 /* set pWlanDev's parent to underlying device */
2249 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
2250 }
2251
2252 return pAdapter;
2253}
2254
2255VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
2256{
2257 struct net_device *pWlanDev = pAdapter->dev;
2258 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2259 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2260 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2261
2262 if( rtnl_lock_held )
2263 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08002264 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07002265 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
2266 {
2267 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
2268 return VOS_STATUS_E_FAILURE;
2269 }
2270 }
2271 if (register_netdevice(pWlanDev))
2272 {
2273 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
2274 return VOS_STATUS_E_FAILURE;
2275 }
2276 }
2277 else
2278 {
2279 if(register_netdev(pWlanDev))
2280 {
2281 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
2282 return VOS_STATUS_E_FAILURE;
2283 }
2284 }
2285 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
2286
2287 return VOS_STATUS_SUCCESS;
2288}
2289
2290eHalStatus hdd_smeCloseSessionCallback(void *pContext)
2291{
2292 if(pContext != NULL)
2293 {
2294 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
2295
2296 /* need to make sure all of our scheduled work has completed.
2297 * This callback is called from MC thread context, so it is safe to
2298 * to call below flush workqueue API from here.
2299 */
2300 flush_scheduled_work();
2301 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
2302 }
2303 return eHAL_STATUS_SUCCESS;
2304}
2305
2306VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
2307{
2308 struct net_device *pWlanDev = pAdapter->dev;
2309 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
2310 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
2311 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2312 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2313 int rc = 0;
2314
2315 INIT_COMPLETION(pAdapter->session_open_comp_var);
2316 //Open a SME session for future operation
2317 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
2318 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
2319 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2320 {
2321 hddLog(VOS_TRACE_LEVEL_FATAL,
2322 "sme_OpenSession() failed with status code %08d [x%08lx]",
2323 halStatus, halStatus );
2324 status = VOS_STATUS_E_FAILURE;
2325 goto error_sme_open;
2326 }
2327
2328 //Block on a completion variable. Can't wait forever though.
2329 rc = wait_for_completion_interruptible_timeout(
2330 &pAdapter->session_open_comp_var,
2331 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2332 if (!rc)
2333 {
2334 hddLog(VOS_TRACE_LEVEL_FATAL,
2335 "Session is not opened within timeout period code %08d", rc );
2336 status = VOS_STATUS_E_FAILURE;
2337 goto error_sme_open;
2338 }
2339
2340 // Register wireless extensions
2341 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
2342 {
2343 hddLog(VOS_TRACE_LEVEL_FATAL,
2344 "hdd_register_wext() failed with status code %08d [x%08lx]",
2345 halStatus, halStatus );
2346 status = VOS_STATUS_E_FAILURE;
2347 goto error_register_wext;
2348 }
2349 //Safe to register the hard_start_xmit function again
2350#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
2351 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
2352#else
2353 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
2354#endif
2355
2356 //Set the Connection State to Not Connected
2357 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2358
2359 //Set the default operation channel
2360 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
2361
2362 /* Make the default Auth Type as OPEN*/
2363 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2364
2365 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
2366 {
2367 hddLog(VOS_TRACE_LEVEL_FATAL,
2368 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
2369 status, status );
2370 goto error_init_txrx;
2371 }
2372
2373 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2374
2375 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
2376 {
2377 hddLog(VOS_TRACE_LEVEL_FATAL,
2378 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
2379 status, status );
2380 goto error_wmm_init;
2381 }
2382
2383 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2384
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002385#ifdef FEATURE_WLAN_TDLS
2386 if(0 != wlan_hdd_tdls_init(pAdapter))
2387 {
2388 status = VOS_STATUS_E_FAILURE;
2389 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
2390 goto error_tdls_init;
2391 }
2392 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2393#endif
2394
Jeff Johnson295189b2012-06-20 16:38:30 -07002395 return VOS_STATUS_SUCCESS;
2396
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002397#ifdef FEATURE_WLAN_TDLS
2398error_tdls_init:
2399 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2400 hdd_wmm_adapter_close(pAdapter);
2401#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002402error_wmm_init:
2403 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2404 hdd_deinit_tx_rx(pAdapter);
2405error_init_txrx:
2406 hdd_UnregisterWext(pWlanDev);
2407error_register_wext:
2408 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2409 {
2410 INIT_COMPLETION(pAdapter->session_close_comp_var);
2411 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
2412 pAdapter->sessionId,
2413 hdd_smeCloseSessionCallback, pAdapter ) )
2414 {
2415 //Block on a completion variable. Can't wait forever though.
2416 wait_for_completion_interruptible_timeout(
2417 &pAdapter->session_close_comp_var,
2418 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2419 }
2420}
2421error_sme_open:
2422 return status;
2423}
2424
Jeff Johnson295189b2012-06-20 16:38:30 -07002425void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2426{
2427 hdd_cfg80211_state_t *cfgState;
2428
2429 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
2430
2431 if( NULL != cfgState->buf )
2432 {
2433 int rc;
2434 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
2435 rc = wait_for_completion_interruptible_timeout(
2436 &pAdapter->tx_action_cnf_event,
2437 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2438 if(!rc)
2439 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08002440 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07002441 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
2442 }
2443 }
2444 return;
2445}
Jeff Johnson295189b2012-06-20 16:38:30 -07002446
2447void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2448{
2449 ENTER();
2450 switch ( pAdapter->device_mode )
2451 {
2452 case WLAN_HDD_INFRA_STATION:
2453 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002454 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002455 {
2456 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2457 {
2458 hdd_deinit_tx_rx( pAdapter );
2459 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2460 }
2461
2462 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
2463 {
2464 hdd_wmm_adapter_close( pAdapter );
2465 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
2466 }
2467
Jeff Johnson295189b2012-06-20 16:38:30 -07002468 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08002469#ifdef FEATURE_WLAN_TDLS
2470 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
2471 {
2472 wlan_hdd_tdls_exit(pAdapter);
2473 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
2474 }
2475#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002476
2477 break;
2478 }
2479
2480 case WLAN_HDD_SOFTAP:
2481 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002482 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002483 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07002484
2485 hdd_unregister_hostapd(pAdapter);
2486 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07002487 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07002488 break;
2489 }
2490
2491 case WLAN_HDD_MONITOR:
2492 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002493 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07002494 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2495 {
2496 hdd_deinit_tx_rx( pAdapter );
2497 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2498 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002499 if(NULL != pAdapterforTx)
2500 {
2501 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
2502 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002503 break;
2504 }
2505
2506
2507 default:
2508 break;
2509 }
2510
2511 EXIT();
2512}
2513
2514void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
2515{
2516 struct net_device *pWlanDev = pAdapter->dev;
2517
2518 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
2519 if( rtnl_held )
2520 {
2521 unregister_netdevice(pWlanDev);
2522 }
2523 else
2524 {
2525 unregister_netdev(pWlanDev);
2526 }
2527 // note that the pAdapter is no longer valid at this point
2528 // since the memory has been reclaimed
2529 }
2530
2531}
2532
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002533void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2534{
2535 tSirSetPowerParamsReq powerRequest = { 0 };
2536
2537 powerRequest.uIgnoreDTIM = 1;
2538
2539 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2540 {
2541 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2542 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2543 }
2544 else
2545 {
2546 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2547 }
2548
2549 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2550 *specified during Enter/Exit BMPS when LCD off*/
2551 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2552 NULL, eANI_BOOLEAN_FALSE);
2553 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2554 NULL, eANI_BOOLEAN_FALSE);
2555
2556 /* switch to the DTIM specified in cfg.ini */
2557 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2558 "Switch to DTIM%d", powerRequest.uListenInterval);
2559 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2560
2561}
2562
2563void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2564{
2565 /*Switch back to DTIM 1*/
2566 tSirSetPowerParamsReq powerRequest = { 0 };
2567
2568 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2569 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2570
2571 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2572 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2573 NULL, eANI_BOOLEAN_FALSE);
2574 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2575 NULL, eANI_BOOLEAN_FALSE);
2576
2577 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2578 "Switch to DTIM%d",powerRequest.uListenInterval);
2579 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2580
2581}
2582
Jeff Johnson295189b2012-06-20 16:38:30 -07002583VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2584{
2585 VOS_STATUS status = VOS_STATUS_SUCCESS;
2586
2587 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2588 {
2589 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2590 }
2591
2592 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2593 {
2594 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2595 }
2596
2597 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2598 {
2599 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2600 }
2601
2602 return status;
2603}
2604
2605VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2606{
2607 hdd_adapter_t *pAdapter = NULL;
2608 eHalStatus halStatus;
2609 VOS_STATUS status = VOS_STATUS_E_INVAL;
2610 v_BOOL_t disableBmps = FALSE;
2611 v_BOOL_t disableImps = FALSE;
2612
2613 switch(session_type)
2614 {
2615 case WLAN_HDD_INFRA_STATION:
2616 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07002617 case WLAN_HDD_P2P_CLIENT:
2618 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002619 //Exit BMPS -> Is Sta/P2P Client is already connected
2620 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2621 if((NULL != pAdapter)&&
2622 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2623 {
2624 disableBmps = TRUE;
2625 }
2626
2627 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2628 if((NULL != pAdapter)&&
2629 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2630 {
2631 disableBmps = TRUE;
2632 }
2633
2634 //Exit both Bmps and Imps incase of Go/SAP Mode
2635 if((WLAN_HDD_SOFTAP == session_type) ||
2636 (WLAN_HDD_P2P_GO == session_type))
2637 {
2638 disableBmps = TRUE;
2639 disableImps = TRUE;
2640 }
2641
2642 if(TRUE == disableImps)
2643 {
2644 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2645 {
2646 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2647 }
2648 }
2649
2650 if(TRUE == disableBmps)
2651 {
2652 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2653 {
2654 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2655
2656 if(eHAL_STATUS_SUCCESS != halStatus)
2657 {
2658 status = VOS_STATUS_E_FAILURE;
2659 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
2660 VOS_ASSERT(0);
2661 return status;
2662 }
2663 }
2664
2665 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2666 {
2667 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
2668
2669 if(eHAL_STATUS_SUCCESS != halStatus)
2670 {
2671 status = VOS_STATUS_E_FAILURE;
2672 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
2673 VOS_ASSERT(0);
2674 return status;
2675 }
2676 }
2677 }
2678
2679 if((TRUE == disableBmps) ||
2680 (TRUE == disableImps))
2681 {
2682 /* Now, get the chip into Full Power now */
2683 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
2684 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
2685 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
2686
2687 if(halStatus != eHAL_STATUS_SUCCESS)
2688 {
2689 if(halStatus == eHAL_STATUS_PMC_PENDING)
2690 {
2691 //Block on a completion variable. Can't wait forever though
2692 wait_for_completion_interruptible_timeout(
2693 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
2694 }
2695 else
2696 {
2697 status = VOS_STATUS_E_FAILURE;
2698 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
2699 VOS_ASSERT(0);
2700 return status;
2701 }
2702 }
2703
2704 status = VOS_STATUS_SUCCESS;
2705 }
2706
2707 break;
2708 }
2709 return status;
2710}
2711
2712hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002713 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07002714 tANI_U8 rtnl_held )
2715{
2716 hdd_adapter_t *pAdapter = NULL;
2717 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
2718 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2719 VOS_STATUS exitbmpsStatus;
2720
2721 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
2722
2723 //Disable BMPS incase of Concurrency
2724 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
2725
2726 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
2727 {
2728 //Fail to Exit BMPS
2729 VOS_ASSERT(0);
2730 return NULL;
2731 }
2732
2733 switch(session_type)
2734 {
2735 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07002736 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002737 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002738 {
2739 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2740
2741 if( NULL == pAdapter )
2742 return NULL;
2743
Jeff Johnsone7245742012-09-05 17:12:55 -07002744 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
2745 NL80211_IFTYPE_P2P_CLIENT:
2746 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07002747
Jeff Johnson295189b2012-06-20 16:38:30 -07002748 pAdapter->device_mode = session_type;
2749
2750 status = hdd_init_station_mode( pAdapter );
2751 if( VOS_STATUS_SUCCESS != status )
2752 goto err_free_netdev;
2753
2754 status = hdd_register_interface( pAdapter, rtnl_held );
2755 if( VOS_STATUS_SUCCESS != status )
2756 {
2757 hdd_deinit_adapter(pHddCtx, pAdapter);
2758 goto err_free_netdev;
2759 }
2760 //Stop the Interface TX queue.
2761 netif_tx_disable(pAdapter->dev);
2762 //netif_tx_disable(pWlanDev);
2763 netif_carrier_off(pAdapter->dev);
2764
2765 break;
2766 }
2767
Jeff Johnson295189b2012-06-20 16:38:30 -07002768 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07002769 case WLAN_HDD_SOFTAP:
2770 {
2771 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
2772 if( NULL == pAdapter )
2773 return NULL;
2774
Jeff Johnson295189b2012-06-20 16:38:30 -07002775 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
2776 NL80211_IFTYPE_AP:
2777 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07002778 pAdapter->device_mode = session_type;
2779
2780 status = hdd_init_ap_mode(pAdapter);
2781 if( VOS_STATUS_SUCCESS != status )
2782 goto err_free_netdev;
2783
2784 status = hdd_register_hostapd( pAdapter, rtnl_held );
2785 if( VOS_STATUS_SUCCESS != status )
2786 {
2787 hdd_deinit_adapter(pHddCtx, pAdapter);
2788 goto err_free_netdev;
2789 }
2790
2791 netif_tx_disable(pAdapter->dev);
2792 netif_carrier_off(pAdapter->dev);
2793
2794 hdd_set_conparam( 1 );
2795 break;
2796 }
2797 case WLAN_HDD_MONITOR:
2798 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002799 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2800 if( NULL == pAdapter )
2801 return NULL;
2802
2803 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
2804 pAdapter->device_mode = session_type;
2805 status = hdd_register_interface( pAdapter, rtnl_held );
2806#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2807 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
2808#else
2809 pAdapter->dev->open = hdd_mon_open;
2810 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
2811#endif
2812 hdd_init_tx_rx( pAdapter );
2813 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2814 //Set adapter to be used for data tx. It will use either GO or softap.
2815 pAdapter->sessionCtx.monitor.pAdapterForTx =
2816 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07002817 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
2818 {
2819 pAdapter->sessionCtx.monitor.pAdapterForTx =
2820 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
2821 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002822 /* This workqueue will be used to transmit management packet over
2823 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07002824 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
2825 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
2826 return NULL;
2827 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07002828
Jeff Johnson295189b2012-06-20 16:38:30 -07002829 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
2830 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07002831 }
2832 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002833 case WLAN_HDD_FTM:
2834 {
2835 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2836
2837 if( NULL == pAdapter )
2838 return NULL;
2839 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
2840 * message while loading driver in FTM mode. */
2841 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
2842 pAdapter->device_mode = session_type;
2843 status = hdd_register_interface( pAdapter, rtnl_held );
2844 }
2845 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07002846 default:
2847 {
2848 VOS_ASSERT(0);
2849 return NULL;
2850 }
2851 }
2852
2853
2854 if( VOS_STATUS_SUCCESS == status )
2855 {
2856 //Add it to the hdd's session list.
2857 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
2858 if( NULL == pHddAdapterNode )
2859 {
2860 status = VOS_STATUS_E_NOMEM;
2861 }
2862 else
2863 {
2864 pHddAdapterNode->pAdapter = pAdapter;
2865 status = hdd_add_adapter_back ( pHddCtx,
2866 pHddAdapterNode );
2867 }
2868 }
2869
2870 if( VOS_STATUS_SUCCESS != status )
2871 {
2872 if( NULL != pAdapter )
2873 {
2874 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
2875 pAdapter = NULL;
2876 }
2877 if( NULL != pHddAdapterNode )
2878 {
2879 vos_mem_free( pHddAdapterNode );
2880 }
2881
2882 goto resume_bmps;
2883 }
2884
2885 if(VOS_STATUS_SUCCESS == status)
2886 {
2887 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
2888
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002889 //Initialize the WoWL service
2890 if(!hdd_init_wowl(pAdapter))
2891 {
2892 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
2893 goto err_free_netdev;
2894 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002895 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002896 return pAdapter;
2897
2898err_free_netdev:
2899 free_netdev(pAdapter->dev);
2900 wlan_hdd_release_intf_addr( pHddCtx,
2901 pAdapter->macAddressCurrent.bytes );
2902
2903resume_bmps:
2904 //If bmps disabled enable it
2905 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
2906 {
2907 hdd_enable_bmps_imps(pHddCtx);
2908 }
2909 return NULL;
2910}
2911
2912VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
2913 tANI_U8 rtnl_held )
2914{
2915 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
2916 VOS_STATUS status;
2917
2918 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
2919 if( VOS_STATUS_SUCCESS != status )
2920 return status;
2921
2922 while ( pCurrent->pAdapter != pAdapter )
2923 {
2924 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
2925 if( VOS_STATUS_SUCCESS != status )
2926 break;
2927
2928 pCurrent = pNext;
2929 }
2930 pAdapterNode = pCurrent;
2931 if( VOS_STATUS_SUCCESS == status )
2932 {
2933 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2934 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
2935 hdd_remove_adapter( pHddCtx, pAdapterNode );
2936 vos_mem_free( pAdapterNode );
2937
Jeff Johnson295189b2012-06-20 16:38:30 -07002938
2939 /* If there is a single session of STA/P2P client, re-enable BMPS */
2940 if ((!vos_concurrent_sessions_running()) &&
2941 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
2942 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
2943 {
2944 hdd_enable_bmps_imps(pHddCtx);
2945 }
2946
2947 return VOS_STATUS_SUCCESS;
2948 }
2949
2950 return VOS_STATUS_E_FAILURE;
2951}
2952
2953VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
2954{
2955 hdd_adapter_list_node_t *pHddAdapterNode;
2956 VOS_STATUS status;
2957
2958 ENTER();
2959
2960 do
2961 {
2962 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
2963 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
2964 {
2965 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
2966 vos_mem_free( pHddAdapterNode );
2967 }
2968 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
2969
2970 EXIT();
2971
2972 return VOS_STATUS_SUCCESS;
2973}
2974
2975void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
2976{
2977 v_U8_t addIE[1] = {0};
2978
2979 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2980 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
2981 eANI_BOOLEAN_FALSE) )
2982 {
2983 hddLog(LOGE,
2984 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
2985 }
2986
2987 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2988 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
2989 eANI_BOOLEAN_FALSE) )
2990 {
2991 hddLog(LOGE,
2992 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
2993 }
2994
2995 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2996 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
2997 eANI_BOOLEAN_FALSE) )
2998 {
2999 hddLog(LOGE,
3000 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
3001 }
3002}
3003
3004VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3005{
3006 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
3007 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3008 union iwreq_data wrqu;
3009
3010 ENTER();
3011
3012 switch(pAdapter->device_mode)
3013 {
3014 case WLAN_HDD_INFRA_STATION:
3015 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003016 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003017 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3018 {
3019 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
3020 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3021 pAdapter->sessionId,
3022 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3023 else
3024 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
3025 pAdapter->sessionId,
3026 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3027 //success implies disconnect command got queued up successfully
3028 if(halStatus == eHAL_STATUS_SUCCESS)
3029 {
3030 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
3031 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3032 }
3033 memset(&wrqu, '\0', sizeof(wrqu));
3034 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3035 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3036 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3037 }
3038 else
3039 {
3040 hdd_abort_mac_scan(pHddCtx);
3041 }
3042
3043 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
3044 {
3045 INIT_COMPLETION(pAdapter->session_close_comp_var);
3046 if (eHAL_STATUS_SUCCESS ==
3047 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
3048 hdd_smeCloseSessionCallback, pAdapter))
3049 {
3050 //Block on a completion variable. Can't wait forever though.
3051 wait_for_completion_interruptible_timeout(
3052 &pAdapter->session_close_comp_var,
3053 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3054 }
3055 }
3056
3057 break;
3058
3059 case WLAN_HDD_SOFTAP:
3060 case WLAN_HDD_P2P_GO:
3061 //Any softap specific cleanup here...
3062 mutex_lock(&pHddCtx->sap_lock);
3063 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3064 {
3065 VOS_STATUS status;
3066 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3067
3068 //Stop Bss.
3069 status = WLANSAP_StopBss(pHddCtx->pvosContext);
3070 if (VOS_IS_STATUS_SUCCESS(status))
3071 {
3072 hdd_hostapd_state_t *pHostapdState =
3073 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3074
3075 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
3076
3077 if (!VOS_IS_STATUS_SUCCESS(status))
3078 {
3079 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003080 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003081 }
3082 }
3083 else
3084 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003085 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003086 }
3087 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
3088
3089 if (eHAL_STATUS_FAILURE ==
3090 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
3091 0, NULL, eANI_BOOLEAN_FALSE))
3092 {
3093 hddLog(LOGE,
3094 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003095 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003096 }
3097
3098 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
3099 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
3100 eANI_BOOLEAN_FALSE) )
3101 {
3102 hddLog(LOGE,
3103 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
3104 }
3105
3106 // Reset WNI_CFG_PROBE_RSP Flags
3107 wlan_hdd_reset_prob_rspies(pAdapter);
3108 kfree(pAdapter->sessionCtx.ap.beacon);
3109 pAdapter->sessionCtx.ap.beacon = NULL;
3110 }
3111 mutex_unlock(&pHddCtx->sap_lock);
3112 break;
3113 case WLAN_HDD_MONITOR:
3114 break;
3115 default:
3116 break;
3117 }
3118
3119 EXIT();
3120 return VOS_STATUS_SUCCESS;
3121}
3122
3123VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
3124{
3125 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3126 VOS_STATUS status;
3127 hdd_adapter_t *pAdapter;
3128
3129 ENTER();
3130
3131 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3132
3133 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3134 {
3135 pAdapter = pAdapterNode->pAdapter;
3136 netif_tx_disable(pAdapter->dev);
3137 netif_carrier_off(pAdapter->dev);
3138
3139 hdd_stop_adapter( pHddCtx, pAdapter );
3140
3141 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3142 pAdapterNode = pNext;
3143 }
3144
3145 EXIT();
3146
3147 return VOS_STATUS_SUCCESS;
3148}
3149
3150VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
3151{
3152 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3153 VOS_STATUS status;
3154 hdd_adapter_t *pAdapter;
3155
3156 ENTER();
3157
3158 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3159
3160 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3161 {
3162 pAdapter = pAdapterNode->pAdapter;
3163 netif_tx_disable(pAdapter->dev);
3164 netif_carrier_off(pAdapter->dev);
3165
3166 //Record whether STA is associated
3167 pAdapter->sessionCtx.station.bSendDisconnect =
3168 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
3169 VOS_TRUE : VOS_FALSE;
3170
3171 hdd_deinit_tx_rx(pAdapter);
3172 hdd_wmm_adapter_close(pAdapter);
3173
3174 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3175 pAdapterNode = pNext;
3176 }
3177
3178 EXIT();
3179
3180 return VOS_STATUS_SUCCESS;
3181}
3182
3183VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
3184{
3185 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3186 VOS_STATUS status;
3187 hdd_adapter_t *pAdapter;
3188 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
3189
3190 ENTER();
3191
3192 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3193
3194 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3195 {
3196 pAdapter = pAdapterNode->pAdapter;
3197
3198 switch(pAdapter->device_mode)
3199 {
3200 case WLAN_HDD_INFRA_STATION:
3201 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07003202 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07003203 hdd_init_station_mode(pAdapter);
3204 /* Open the gates for HDD to receive Wext commands */
3205 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003206 pHddCtx->scan_info.mScanPending = FALSE;
3207 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003208
3209 //Trigger the initial scan
3210 hdd_wlan_initial_scan(pAdapter);
3211
3212 //Indicate disconnect event to supplicant if associated previously
3213 if(pAdapter->sessionCtx.station.bSendDisconnect)
3214 {
3215 union iwreq_data wrqu;
3216 memset(&wrqu, '\0', sizeof(wrqu));
3217 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3218 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
3219 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
3220 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
3221
Jeff Johnson295189b2012-06-20 16:38:30 -07003222 /* indicate disconnected event to nl80211 */
3223 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
3224 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003225 }
3226 break;
3227
3228 case WLAN_HDD_SOFTAP:
3229 /* softAP can handle SSR */
3230 break;
3231
3232 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07003233 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
3234 __func__);
3235 /* event supplicant to restart */
3236 cfg80211_del_sta(pAdapter->dev,
3237 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003238 break;
3239
3240 case WLAN_HDD_MONITOR:
3241 /* monitor interface start */
3242 break;
3243 default:
3244 break;
3245 }
3246
3247 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3248 pAdapterNode = pNext;
3249 }
3250
3251 EXIT();
3252
3253 return VOS_STATUS_SUCCESS;
3254}
3255
3256VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
3257{
3258 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3259 hdd_adapter_t *pAdapter;
3260 VOS_STATUS status;
3261 v_U32_t roamId;
3262
3263 ENTER();
3264
3265 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3266
3267 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3268 {
3269 pAdapter = pAdapterNode->pAdapter;
3270
3271 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
3272 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
3273 {
3274 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3275 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
3276
3277 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3278 init_completion(&pAdapter->disconnect_comp_var);
3279 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
3280 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3281
3282 wait_for_completion_interruptible_timeout(
3283 &pAdapter->disconnect_comp_var,
3284 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
3285
3286 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
3287 pHddCtx->isAmpAllowed = VOS_FALSE;
3288 sme_RoamConnect(pHddCtx->hHal,
3289 pAdapter->sessionId, &(pWextState->roamProfile),
3290 &roamId);
3291 }
3292
3293 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3294 pAdapterNode = pNext;
3295 }
3296
3297 EXIT();
3298
3299 return VOS_STATUS_SUCCESS;
3300}
3301
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07003302void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
3303{
3304 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3305 VOS_STATUS status;
3306 hdd_adapter_t *pAdapter;
3307 hdd_station_ctx_t *pHddStaCtx;
3308 hdd_ap_ctx_t *pHddApCtx;
3309 hdd_hostapd_state_t * pHostapdState;
3310 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
3311 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
3312 const char *p2pMode = "DEV";
3313 const char *ccMode = "Standalone";
3314 int n;
3315
3316 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3317 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3318 {
3319 pAdapter = pAdapterNode->pAdapter;
3320 switch (pAdapter->device_mode) {
3321 case WLAN_HDD_INFRA_STATION:
3322 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3323 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3324 staChannel = pHddStaCtx->conn_info.operationChannel;
3325 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
3326 }
3327 break;
3328 case WLAN_HDD_P2P_CLIENT:
3329 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3330 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
3331 p2pChannel = pHddStaCtx->conn_info.operationChannel;
3332 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
3333 p2pMode = "CLI";
3334 }
3335 break;
3336 case WLAN_HDD_P2P_GO:
3337 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3338 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3339 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3340 p2pChannel = pHddApCtx->operatingChannel;
3341 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
3342 }
3343 p2pMode = "GO";
3344 break;
3345 case WLAN_HDD_SOFTAP:
3346 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
3347 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
3348 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
3349 apChannel = pHddApCtx->operatingChannel;
3350 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
3351 }
3352 break;
3353 default:
3354 break;
3355 }
3356 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3357 pAdapterNode = pNext;
3358 }
3359 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
3360 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
3361 }
3362 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
3363 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
3364 if (p2pChannel > 0) {
3365 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
3366 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
3367 }
3368 if (apChannel > 0) {
3369 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
3370 apChannel, MAC_ADDR_ARRAY(apBssid));
3371 }
3372
3373 if (p2pChannel > 0 && apChannel > 0) {
3374 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
3375 }
3376}
3377
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003378bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07003379{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003380 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07003381}
3382
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003383/* Once SSR is disabled then it cannot be set. */
3384void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07003385{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07003386 if (HDD_SSR_DISABLED == isSsrRequired)
3387 return;
3388
Jeff Johnson295189b2012-06-20 16:38:30 -07003389 isSsrRequired = value;
3390}
3391
3392VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
3393 hdd_adapter_list_node_t** ppAdapterNode)
3394{
3395 VOS_STATUS status;
3396 spin_lock(&pHddCtx->hddAdapters.lock);
3397 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
3398 (hdd_list_node_t**) ppAdapterNode );
3399 spin_unlock(&pHddCtx->hddAdapters.lock);
3400 return status;
3401}
3402
3403VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
3404 hdd_adapter_list_node_t* pAdapterNode,
3405 hdd_adapter_list_node_t** pNextAdapterNode)
3406{
3407 VOS_STATUS status;
3408 spin_lock(&pHddCtx->hddAdapters.lock);
3409 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
3410 (hdd_list_node_t*) pAdapterNode,
3411 (hdd_list_node_t**)pNextAdapterNode );
3412
3413 spin_unlock(&pHddCtx->hddAdapters.lock);
3414 return status;
3415}
3416
3417VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
3418 hdd_adapter_list_node_t* pAdapterNode)
3419{
3420 VOS_STATUS status;
3421 spin_lock(&pHddCtx->hddAdapters.lock);
3422 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
3423 &pAdapterNode->node );
3424 spin_unlock(&pHddCtx->hddAdapters.lock);
3425 return status;
3426}
3427
3428VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
3429 hdd_adapter_list_node_t** ppAdapterNode)
3430{
3431 VOS_STATUS status;
3432 spin_lock(&pHddCtx->hddAdapters.lock);
3433 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
3434 (hdd_list_node_t**) ppAdapterNode );
3435 spin_unlock(&pHddCtx->hddAdapters.lock);
3436 return status;
3437}
3438
3439VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
3440 hdd_adapter_list_node_t* pAdapterNode)
3441{
3442 VOS_STATUS status;
3443 spin_lock(&pHddCtx->hddAdapters.lock);
3444 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
3445 (hdd_list_node_t*) pAdapterNode );
3446 spin_unlock(&pHddCtx->hddAdapters.lock);
3447 return status;
3448}
3449
3450VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
3451 hdd_adapter_list_node_t* pAdapterNode)
3452{
3453 VOS_STATUS status;
3454 spin_lock(&pHddCtx->hddAdapters.lock);
3455 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
3456 (hdd_list_node_t*) pAdapterNode );
3457 spin_unlock(&pHddCtx->hddAdapters.lock);
3458 return status;
3459}
3460
3461hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
3462 tSirMacAddr macAddr )
3463{
3464 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3465 hdd_adapter_t *pAdapter;
3466 VOS_STATUS status;
3467
3468 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3469
3470 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3471 {
3472 pAdapter = pAdapterNode->pAdapter;
3473
3474 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
3475 macAddr, sizeof(tSirMacAddr) ) )
3476 {
3477 return pAdapter;
3478 }
3479 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3480 pAdapterNode = pNext;
3481 }
3482
3483 return NULL;
3484
3485}
3486
3487hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
3488{
3489 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3490 hdd_adapter_t *pAdapter;
3491 VOS_STATUS status;
3492
3493 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3494
3495 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3496 {
3497 pAdapter = pAdapterNode->pAdapter;
3498
3499 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
3500 IFNAMSIZ ) )
3501 {
3502 return pAdapter;
3503 }
3504 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3505 pAdapterNode = pNext;
3506 }
3507
3508 return NULL;
3509
3510}
3511
3512hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
3513{
3514 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3515 hdd_adapter_t *pAdapter;
3516 VOS_STATUS status;
3517
3518 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3519
3520 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3521 {
3522 pAdapter = pAdapterNode->pAdapter;
3523
3524 if( pAdapter && (mode == pAdapter->device_mode) )
3525 {
3526 return pAdapter;
3527 }
3528 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3529 pAdapterNode = pNext;
3530 }
3531
3532 return NULL;
3533
3534}
3535
3536//Remove this function later
3537hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
3538{
3539 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3540 hdd_adapter_t *pAdapter;
3541 VOS_STATUS status;
3542
3543 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3544
3545 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3546 {
3547 pAdapter = pAdapterNode->pAdapter;
3548
3549 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
3550 {
3551 return pAdapter;
3552 }
3553
3554 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3555 pAdapterNode = pNext;
3556 }
3557
3558 return NULL;
3559
3560}
3561
Jeff Johnson295189b2012-06-20 16:38:30 -07003562/**---------------------------------------------------------------------------
3563
3564 \brief hdd_set_monitor_tx_adapter() -
3565
3566 This API initializes the adapter to be used while transmitting on monitor
3567 adapter.
3568
3569 \param - pHddCtx - Pointer to the HDD context.
3570 pAdapter - Adapter that will used for TX. This can be NULL.
3571 \return - None.
3572 --------------------------------------------------------------------------*/
3573void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3574{
3575 hdd_adapter_t *pMonAdapter;
3576
3577 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
3578
3579 if( NULL != pMonAdapter )
3580 {
3581 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
3582 }
3583}
Jeff Johnson295189b2012-06-20 16:38:30 -07003584/**---------------------------------------------------------------------------
3585
3586 \brief hdd_select_queue() -
3587
3588 This API returns the operating channel of the requested device mode
3589
3590 \param - pHddCtx - Pointer to the HDD context.
3591 - mode - Device mode for which operating channel is required
3592 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
3593 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
3594 \return - channel number. "0" id the requested device is not found OR it is not connected.
3595 --------------------------------------------------------------------------*/
3596v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
3597{
3598 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3599 VOS_STATUS status;
3600 hdd_adapter_t *pAdapter;
3601 v_U8_t operatingChannel = 0;
3602
3603 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3604
3605 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3606 {
3607 pAdapter = pAdapterNode->pAdapter;
3608
3609 if( mode == pAdapter->device_mode )
3610 {
3611 switch(pAdapter->device_mode)
3612 {
3613 case WLAN_HDD_INFRA_STATION:
3614 case WLAN_HDD_P2P_CLIENT:
3615 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3616 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
3617 break;
3618 case WLAN_HDD_SOFTAP:
3619 case WLAN_HDD_P2P_GO:
3620 /*softap connection info */
3621 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3622 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3623 break;
3624 default:
3625 break;
3626 }
3627
3628 break; //Found the device of interest. break the loop
3629 }
3630
3631 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3632 pAdapterNode = pNext;
3633 }
3634 return operatingChannel;
3635}
3636
3637#ifdef WLAN_FEATURE_PACKET_FILTERING
3638/**---------------------------------------------------------------------------
3639
3640 \brief hdd_set_multicast_list() -
3641
3642 This used to set the multicast address list.
3643
3644 \param - dev - Pointer to the WLAN device.
3645 - skb - Pointer to OS packet (sk_buff).
3646 \return - success/fail
3647
3648 --------------------------------------------------------------------------*/
3649static void hdd_set_multicast_list(struct net_device *dev)
3650{
3651 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003652 int mc_count;
3653 int i = 0;
3654 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303655
3656 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07003657 {
3658 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303659 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003660 return;
3661 }
3662
3663 if (dev->flags & IFF_ALLMULTI)
3664 {
3665 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003666 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303667 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003668 }
3669 else
3670 {
3671 mc_count = netdev_mc_count(dev);
3672 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003673 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07003674 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
3675 {
3676 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003677 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303678 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003679 return;
3680 }
3681
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303682 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07003683
3684 netdev_for_each_mc_addr(ha, dev) {
3685 if (i == mc_count)
3686 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303687 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
3688 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
3689 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003690 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303691 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07003692 i++;
3693 }
3694 }
3695 return;
3696}
3697#endif
3698
3699/**---------------------------------------------------------------------------
3700
3701 \brief hdd_select_queue() -
3702
3703 This function is registered with the Linux OS for network
3704 core to decide which queue to use first.
3705
3706 \param - dev - Pointer to the WLAN device.
3707 - skb - Pointer to OS packet (sk_buff).
3708 \return - ac, Queue Index/access category corresponding to UP in IP header
3709
3710 --------------------------------------------------------------------------*/
3711v_U16_t hdd_select_queue(struct net_device *dev,
3712 struct sk_buff *skb)
3713{
3714 return hdd_wmm_select_queue(dev, skb);
3715}
3716
3717
3718/**---------------------------------------------------------------------------
3719
3720 \brief hdd_wlan_initial_scan() -
3721
3722 This function triggers the initial scan
3723
3724 \param - pAdapter - Pointer to the HDD adapter.
3725
3726 --------------------------------------------------------------------------*/
3727void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
3728{
3729 tCsrScanRequest scanReq;
3730 tCsrChannelInfo channelInfo;
3731 eHalStatus halStatus;
3732 unsigned long scanId;
3733 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3734
3735 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
3736 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
3737 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
3738
3739 if(sme_Is11dSupported(pHddCtx->hHal))
3740 {
3741 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
3742 if ( HAL_STATUS_SUCCESS( halStatus ) )
3743 {
3744 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
3745 if( !scanReq.ChannelInfo.ChannelList )
3746 {
3747 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
3748 vos_mem_free(channelInfo.ChannelList);
3749 return;
3750 }
3751 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
3752 channelInfo.numOfChannels);
3753 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
3754 vos_mem_free(channelInfo.ChannelList);
3755 }
3756
3757 scanReq.scanType = eSIR_PASSIVE_SCAN;
3758 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
3759 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
3760 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
3761 }
3762 else
3763 {
3764 scanReq.scanType = eSIR_ACTIVE_SCAN;
3765 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3766 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
3767 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
3768 }
3769
3770 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
3771 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3772 {
3773 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
3774 __func__, halStatus );
3775 }
3776
3777 if(sme_Is11dSupported(pHddCtx->hHal))
3778 vos_mem_free(scanReq.ChannelInfo.ChannelList);
3779}
3780
3781struct fullPowerContext
3782{
3783 struct completion completion;
3784 unsigned int magic;
3785};
3786#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
3787
3788/**---------------------------------------------------------------------------
3789
3790 \brief hdd_full_power_callback() - HDD full power callback function
3791
3792 This is the function invoked by SME to inform the result of a full power
3793 request issued by HDD
3794
3795 \param - callbackcontext - Pointer to cookie
3796 \param - status - result of request
3797
3798 \return - None
3799
3800 --------------------------------------------------------------------------*/
3801static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
3802{
3803 struct fullPowerContext *pContext = callbackContext;
3804
3805 hddLog(VOS_TRACE_LEVEL_INFO,
3806 "%s: context = %p, status = %d", pContext, status);
3807
3808 if (NULL == callbackContext)
3809 {
3810 hddLog(VOS_TRACE_LEVEL_ERROR,
3811 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003812 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07003813 return;
3814 }
3815
3816 /* there is a race condition that exists between this callback function
3817 and the caller since the caller could time out either before or
3818 while this code is executing. we'll assume the timeout hasn't
3819 occurred, but we'll verify that right before we save our work */
3820
3821 if (POWER_CONTEXT_MAGIC != pContext->magic)
3822 {
3823 /* the caller presumably timed out so there is nothing we can do */
3824 hddLog(VOS_TRACE_LEVEL_WARN,
3825 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003826 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07003827 return;
3828 }
3829
3830 /* the race is on. caller could have timed out immediately after
3831 we verified the magic, but if so, caller will wait a short time
3832 for us to notify the caller, so the context will stay valid */
3833 complete(&pContext->completion);
3834}
3835
3836/**---------------------------------------------------------------------------
3837
3838 \brief hdd_wlan_exit() - HDD WLAN exit function
3839
3840 This is the driver exit point (invoked during rmmod)
3841
3842 \param - pHddCtx - Pointer to the HDD Context
3843
3844 \return - None
3845
3846 --------------------------------------------------------------------------*/
3847void hdd_wlan_exit(hdd_context_t *pHddCtx)
3848{
3849 eHalStatus halStatus;
3850 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
3851 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05303852 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07003853 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003854 struct fullPowerContext powerContext;
3855 long lrc;
3856
3857 ENTER();
3858
Jeff Johnson88ba7742013-02-27 14:36:02 -08003859 if (VOS_FTM_MODE != hdd_get_conparam())
3860 {
3861 // Unloading, restart logic is no more required.
3862 wlan_hdd_restart_deinit(pHddCtx);
3863 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003864
Jeff Johnson295189b2012-06-20 16:38:30 -07003865 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003866 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003867 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003868 {
3869 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
3870 WLAN_HDD_INFRA_STATION);
3871 if (pAdapter == NULL)
3872 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3873
3874 if (pAdapter != NULL)
3875 {
3876 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
3877 hdd_UnregisterWext(pAdapter->dev);
3878 }
3879 }
3880 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003881
Jeff Johnson295189b2012-06-20 16:38:30 -07003882 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08003883 {
3884 wlan_hdd_ftm_close(pHddCtx);
3885 goto free_hdd_ctx;
3886 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003887 //Stop the Interface TX queue.
3888 //netif_tx_disable(pWlanDev);
3889 //netif_carrier_off(pWlanDev);
3890
Jeff Johnson295189b2012-06-20 16:38:30 -07003891 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3892 {
3893 pAdapter = hdd_get_adapter(pHddCtx,
3894 WLAN_HDD_SOFTAP);
3895 }
3896 else
3897 {
Jeff Johnson295189b2012-06-20 16:38:30 -07003898 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07003899 {
3900 pAdapter = hdd_get_adapter(pHddCtx,
3901 WLAN_HDD_INFRA_STATION);
3902 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003903 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003904 /* DeRegister with platform driver as client for Suspend/Resume */
3905 vosStatus = hddDeregisterPmOps(pHddCtx);
3906 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3907 {
3908 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
3909 VOS_ASSERT(0);
3910 }
3911
3912 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
3913 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3914 {
3915 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
3916 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003917
3918 // Cancel any outstanding scan requests. We are about to close all
3919 // of our adapters, but an adapter structure is what SME passes back
3920 // to our callback function. Hence if there are any outstanding scan
3921 // requests then there is a race condition between when the adapter
3922 // is closed and when the callback is invoked. We try to resolve that
3923 // race condition here by canceling any outstanding scans before we
3924 // close the adapters.
3925 // Note that the scans may be cancelled in an asynchronous manner, so
3926 // ideally there needs to be some kind of synchronization. Rather than
3927 // introduce a new synchronization here, we will utilize the fact that
3928 // we are about to Request Full Power, and since that is synchronized,
3929 // the expectation is that by the time Request Full Power has completed,
3930 // all scans will be cancelled.
3931 hdd_abort_mac_scan( pHddCtx );
3932
3933 //Disable IMPS/BMPS as we do not want the device to enter any power
3934 //save mode during shutdown
3935 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3936 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3937 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
3938
3939 //Ensure that device is in full power as we will touch H/W during vos_Stop
3940 init_completion(&powerContext.completion);
3941 powerContext.magic = POWER_CONTEXT_MAGIC;
3942
3943 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
3944 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
3945
3946 if (eHAL_STATUS_SUCCESS != halStatus)
3947 {
3948 if (eHAL_STATUS_PMC_PENDING == halStatus)
3949 {
3950 /* request was sent -- wait for the response */
3951 lrc = wait_for_completion_interruptible_timeout(
3952 &powerContext.completion,
3953 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
3954 /* either we have a response or we timed out
3955 either way, first invalidate our magic */
3956 powerContext.magic = 0;
3957 if (lrc <= 0)
3958 {
3959 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003960 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07003961 /* there is a race condition such that the callback
3962 function could be executing at the same time we are. of
3963 primary concern is if the callback function had already
3964 verified the "magic" but hasn't yet set the completion
3965 variable. Since the completion variable is on our
3966 stack, we'll delay just a bit to make sure the data is
3967 still valid if that is the case */
3968 msleep(50);
3969 }
3970 }
3971 else
3972 {
3973 hddLog(VOS_TRACE_LEVEL_ERROR,
3974 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003975 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07003976 VOS_ASSERT(0);
3977 /* continue -- need to clean up as much as possible */
3978 }
3979 }
3980
3981 // Unregister the Net Device Notifier
3982 unregister_netdevice_notifier(&hdd_netdev_notifier);
3983
Jeff Johnson295189b2012-06-20 16:38:30 -07003984 hdd_stop_all_adapters( pHddCtx );
3985
Jeff Johnson295189b2012-06-20 16:38:30 -07003986#ifdef WLAN_BTAMP_FEATURE
3987 vosStatus = WLANBAP_Stop(pVosContext);
3988 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3989 {
3990 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3991 "%s: Failed to stop BAP",__func__);
3992 }
3993#endif //WLAN_BTAMP_FEATURE
3994
3995 //Stop all the modules
3996 vosStatus = vos_stop( pVosContext );
3997 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3998 {
3999 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4000 "%s: Failed to stop VOSS",__func__);
4001 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4002 }
4003
Jeff Johnson295189b2012-06-20 16:38:30 -07004004 //Assert Deep sleep signal now to put Libra HW in lowest power state
4005 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4006 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4007
4008 //Vote off any PMIC voltage supplies
4009 vos_chipPowerDown(NULL, NULL, NULL);
4010
4011 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4012
4013 //Clean up HDD Nlink Service
4014 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
4015 nl_srv_exit();
4016
4017 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07004018 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004019
4020 //Close the scheduler before calling vos_close to make sure no thread is
4021 // scheduled after the each module close is called i.e after all the data
4022 // structures are freed.
4023 vosStatus = vos_sched_close( pVosContext );
4024 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
4025 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4026 "%s: Failed to close VOSS Scheduler",__func__);
4027 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
4028 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004029#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004030#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4031 /* Destroy the wake lock */
4032 wake_lock_destroy(&pHddCtx->rx_wake_lock);
4033#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004034 /* Destroy the wake lock */
4035 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004036#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004037
4038 //Close VOSS
4039 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
4040 vos_close(pVosContext);
4041
Jeff Johnson295189b2012-06-20 16:38:30 -07004042 //Close Watchdog
4043 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4044 vos_watchdog_close(pVosContext);
4045
4046 /* Cancel the vote for XO Core ON.
4047 * This is done here to ensure there is no race condition since MC, TX and WD threads have
4048 * exited at this point
4049 */
4050 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
4051 " when WLAN is turned OFF\n");
4052 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4053 {
4054 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
4055 " Not returning failure."
4056 " Power consumed will be high\n");
4057 }
4058
4059 hdd_close_all_adapters( pHddCtx );
4060
4061
4062 //Free up dynamically allocated members inside HDD Adapter
4063 kfree(pHddCtx->cfg_ini);
4064 pHddCtx->cfg_ini= NULL;
4065
4066 /* free the power on lock from platform driver */
4067 if (free_riva_power_on_lock("wlan"))
4068 {
4069 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
4070 __func__);
4071 }
4072
Jeff Johnson88ba7742013-02-27 14:36:02 -08004073free_hdd_ctx:
Jeff Johnson88ba7742013-02-27 14:36:02 -08004074 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004075 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004076 if (hdd_is_ssr_required())
4077 {
4078 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07004079 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07004080 msleep(5000);
4081 }
4082 hdd_set_ssr_required (VOS_FALSE);
4083}
4084
4085
4086/**---------------------------------------------------------------------------
4087
4088 \brief hdd_update_config_from_nv() - Function to update the contents of
4089 the running configuration with parameters taken from NV storage
4090
4091 \param - pHddCtx - Pointer to the HDD global context
4092
4093 \return - VOS_STATUS_SUCCESS if successful
4094
4095 --------------------------------------------------------------------------*/
4096static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
4097{
Jeff Johnson295189b2012-06-20 16:38:30 -07004098 v_BOOL_t itemIsValid = VOS_FALSE;
4099 VOS_STATUS status;
4100 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
4101 v_U8_t macLoop;
4102
4103 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
4104 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
4105 if(status != VOS_STATUS_SUCCESS)
4106 {
4107 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
4108 return VOS_STATUS_E_FAILURE;
4109 }
4110
4111 if (itemIsValid == VOS_TRUE)
4112 {
4113 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
4114 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
4115 VOS_MAX_CONCURRENCY_PERSONA);
4116 if(status != VOS_STATUS_SUCCESS)
4117 {
4118 /* Get MAC from NV fail, not update CFG info
4119 * INI MAC value will be used for MAC setting */
4120 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
4121 return VOS_STATUS_E_FAILURE;
4122 }
4123
4124 /* If first MAC is not valid, treat all others are not valid
4125 * Then all MACs will be got from ini file */
4126 if(vos_is_macaddr_zero(&macFromNV[0]))
4127 {
4128 /* MAC address in NV file is not configured yet */
4129 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
4130 return VOS_STATUS_E_INVAL;
4131 }
4132
4133 /* Get MAC address from NV, update CFG info */
4134 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
4135 {
4136 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
4137 {
4138 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
4139 /* This MAC is not valid, skip it
4140 * This MAC will be got from ini file */
4141 }
4142 else
4143 {
4144 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
4145 (v_U8_t *)&macFromNV[macLoop].bytes[0],
4146 VOS_MAC_ADDR_SIZE);
4147 }
4148 }
4149 }
4150 else
4151 {
4152 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
4153 return VOS_STATUS_E_FAILURE;
4154 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004155
Jeff Johnson295189b2012-06-20 16:38:30 -07004156
4157 return VOS_STATUS_SUCCESS;
4158}
4159
4160/**---------------------------------------------------------------------------
4161
4162 \brief hdd_post_voss_start_config() - HDD post voss start config helper
4163
4164 \param - pAdapter - Pointer to the HDD
4165
4166 \return - None
4167
4168 --------------------------------------------------------------------------*/
4169VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
4170{
4171 eHalStatus halStatus;
4172 v_U32_t listenInterval;
4173
Jeff Johnson295189b2012-06-20 16:38:30 -07004174
4175 // Send ready indication to the HDD. This will kick off the MAC
4176 // into a 'running' state and should kick off an initial scan.
4177 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
4178 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4179 {
4180 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
4181 "code %08d [x%08x]",__func__, halStatus, halStatus );
4182 return VOS_STATUS_E_FAILURE;
4183 }
4184
4185 // Set default LI into HDD context,
4186 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
4187 // And RIVA will crash
4188 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
4189 pHddCtx->hdd_actual_LI_value = listenInterval;
4190
4191 return VOS_STATUS_SUCCESS;
4192}
4193
Jeff Johnson295189b2012-06-20 16:38:30 -07004194/* wake lock APIs for HDD */
4195void hdd_prevent_suspend(void)
4196{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004197#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004198 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004199#else
4200 wcnss_prevent_suspend();
4201#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004202}
4203
4204void hdd_allow_suspend(void)
4205{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004206#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004207 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004208#else
4209 wcnss_allow_suspend();
4210#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004211}
4212
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004213void hdd_allow_suspend_timeout(v_U32_t timeout)
4214{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004215#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07004216 wake_lock_timeout(&wlan_wake_lock, timeout);
4217#else
4218 /* Do nothing as there is no API in wcnss for timeout*/
4219#endif
4220}
4221
Jeff Johnson295189b2012-06-20 16:38:30 -07004222/**---------------------------------------------------------------------------
4223
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004224 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
4225 information between Host and Riva
4226
4227 This function gets reported version of FW
4228 It also finds the version of Riva headers used to compile the host
4229 It compares the above two and prints a warning if they are different
4230 It gets the SW and HW version string
4231 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
4232 indicating the features they support through a bitmap
4233
4234 \param - pHddCtx - Pointer to HDD context
4235
4236 \return - void
4237
4238 --------------------------------------------------------------------------*/
4239
4240void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
4241{
4242
4243 tSirVersionType versionCompiled;
4244 tSirVersionType versionReported;
4245 tSirVersionString versionString;
4246 tANI_U8 fwFeatCapsMsgSupported = 0;
4247 VOS_STATUS vstatus;
4248
4249 /* retrieve and display WCNSS version information */
4250 do {
4251
4252 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
4253 &versionCompiled);
4254 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4255 {
4256 hddLog(VOS_TRACE_LEVEL_FATAL,
4257 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004258 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004259 break;
4260 }
4261
4262 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
4263 &versionReported);
4264 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4265 {
4266 hddLog(VOS_TRACE_LEVEL_FATAL,
4267 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004268 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004269 break;
4270 }
4271
4272 if ((versionCompiled.major != versionReported.major) ||
4273 (versionCompiled.minor != versionReported.minor) ||
4274 (versionCompiled.version != versionReported.version) ||
4275 (versionCompiled.revision != versionReported.revision))
4276 {
4277 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4278 "Host expected %u.%u.%u.%u\n",
4279 WLAN_MODULE_NAME,
4280 (int)versionReported.major,
4281 (int)versionReported.minor,
4282 (int)versionReported.version,
4283 (int)versionReported.revision,
4284 (int)versionCompiled.major,
4285 (int)versionCompiled.minor,
4286 (int)versionCompiled.version,
4287 (int)versionCompiled.revision);
4288 }
4289 else
4290 {
4291 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4292 WLAN_MODULE_NAME,
4293 (int)versionReported.major,
4294 (int)versionReported.minor,
4295 (int)versionReported.version,
4296 (int)versionReported.revision);
4297 }
4298
4299 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
4300 versionString,
4301 sizeof(versionString));
4302 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4303 {
4304 hddLog(VOS_TRACE_LEVEL_FATAL,
4305 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004306 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004307 break;
4308 }
4309
4310 pr_info("%s: WCNSS software version %s\n",
4311 WLAN_MODULE_NAME, versionString);
4312
4313 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
4314 versionString,
4315 sizeof(versionString));
4316 if (!VOS_IS_STATUS_SUCCESS(vstatus))
4317 {
4318 hddLog(VOS_TRACE_LEVEL_FATAL,
4319 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004320 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004321 break;
4322 }
4323
4324 pr_info("%s: WCNSS hardware version %s\n",
4325 WLAN_MODULE_NAME, versionString);
4326
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004327 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
4328 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004329 send the message only if it the riva is 1.1
4330 minor numbers for different riva branches:
4331 0 -> (1.0)Mainline Build
4332 1 -> (1.1)Mainline Build
4333 2->(1.04) Stability Build
4334 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004335 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004336 ((versionReported.minor>=1) && (versionReported.version>=1)))
4337 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
4338 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004339
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004340 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08004341 {
4342#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4343 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
4344 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
4345#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004346 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08004347 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004348
4349 } while (0);
4350
4351}
4352
4353/**---------------------------------------------------------------------------
4354
Jeff Johnson295189b2012-06-20 16:38:30 -07004355 \brief hdd_wlan_startup() - HDD init function
4356
4357 This is the driver startup code executed once a WLAN device has been detected
4358
4359 \param - dev - Pointer to the underlying device
4360
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004361 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07004362
4363 --------------------------------------------------------------------------*/
4364
4365int hdd_wlan_startup(struct device *dev )
4366{
4367 VOS_STATUS status;
4368 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004369 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004370 hdd_context_t *pHddCtx = NULL;
4371 v_CONTEXT_t pVosContext= NULL;
4372#ifdef WLAN_BTAMP_FEATURE
4373 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
4374 WLANBAP_ConfigType btAmpConfig;
4375 hdd_config_t *pConfig;
4376#endif
4377 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07004378 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004379
4380 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004381 /*
4382 * cfg80211: wiphy allocation
4383 */
4384 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
4385
4386 if(wiphy == NULL)
4387 {
4388 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004389 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004390 }
4391
4392 pHddCtx = wiphy_priv(wiphy);
4393
Jeff Johnson295189b2012-06-20 16:38:30 -07004394 //Initialize the adapter context to zeros.
4395 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4396
Jeff Johnson295189b2012-06-20 16:38:30 -07004397 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07004398 hdd_prevent_suspend();
4399 pHddCtx->isLoadUnloadInProgress = TRUE;
4400
4401 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4402
4403 /*Get vos context here bcoz vos_open requires it*/
4404 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4405
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08004406 if(pVosContext == NULL)
4407 {
4408 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
4409 goto err_free_hdd_context;
4410 }
4411
Jeff Johnson295189b2012-06-20 16:38:30 -07004412 //Save the Global VOSS context in adapter context for future.
4413 pHddCtx->pvosContext = pVosContext;
4414
4415 //Save the adapter context in global context for future.
4416 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
4417
Jeff Johnson295189b2012-06-20 16:38:30 -07004418 pHddCtx->parent_dev = dev;
4419
4420 init_completion(&pHddCtx->full_pwr_comp_var);
4421 init_completion(&pHddCtx->standby_comp_var);
4422 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004423 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004424 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004425
4426 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
4427
4428 // Load all config first as TL config is needed during vos_open
4429 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
4430 if(pHddCtx->cfg_ini == NULL)
4431 {
4432 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
4433 goto err_free_hdd_context;
4434 }
4435
4436 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
4437
4438 // Read and parse the qcom_cfg.ini file
4439 status = hdd_parse_config_ini( pHddCtx );
4440 if ( VOS_STATUS_SUCCESS != status )
4441 {
4442 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
4443 __func__, WLAN_INI_FILE);
4444 goto err_config;
4445 }
4446
Jeff Johnson295189b2012-06-20 16:38:30 -07004447 /*
4448 * cfg80211: Initialization and registration ...
4449 */
4450 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
4451 {
4452 hddLog(VOS_TRACE_LEVEL_FATAL,
4453 "%s: wlan_hdd_cfg80211_register return failure", __func__);
4454 goto err_wiphy_reg;
4455 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004456
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004457 // Update VOS trace levels based upon the cfg.ini
4458 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
4459 pHddCtx->cfg_ini->vosTraceEnableBAP);
4460 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
4461 pHddCtx->cfg_ini->vosTraceEnableTL);
4462 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
4463 pHddCtx->cfg_ini->vosTraceEnableWDI);
4464 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
4465 pHddCtx->cfg_ini->vosTraceEnableHDD);
4466 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
4467 pHddCtx->cfg_ini->vosTraceEnableSME);
4468 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
4469 pHddCtx->cfg_ini->vosTraceEnablePE);
4470 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
4471 pHddCtx->cfg_ini->vosTraceEnableWDA);
4472 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
4473 pHddCtx->cfg_ini->vosTraceEnableSYS);
4474 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
4475 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004476 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
4477 pHddCtx->cfg_ini->vosTraceEnableSAP);
4478 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
4479 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004480
Jeff Johnson295189b2012-06-20 16:38:30 -07004481 // Update WDI trace levels based upon the cfg.ini
4482 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
4483 pHddCtx->cfg_ini->wdiTraceEnableDAL);
4484 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
4485 pHddCtx->cfg_ini->wdiTraceEnableCTL);
4486 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
4487 pHddCtx->cfg_ini->wdiTraceEnableDAT);
4488 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
4489 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004490
Jeff Johnson88ba7742013-02-27 14:36:02 -08004491 if (VOS_FTM_MODE == hdd_get_conparam())
4492 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004493 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
4494 {
4495 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
4496 goto err_free_hdd_context;
4497 }
4498 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
4499 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08004500 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004501
Jeff Johnson88ba7742013-02-27 14:36:02 -08004502 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07004503 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4504 {
4505 status = vos_watchdog_open(pVosContext,
4506 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4507
4508 if(!VOS_IS_STATUS_SUCCESS( status ))
4509 {
4510 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004511 goto err_wiphy_reg;
Jeff Johnson295189b2012-06-20 16:38:30 -07004512 }
4513 }
4514
4515 pHddCtx->isLogpInProgress = FALSE;
4516 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4517
Jeff Johnson295189b2012-06-20 16:38:30 -07004518 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
4519 if(!VOS_IS_STATUS_SUCCESS(status))
4520 {
4521 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004522 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004523 }
4524
Jeff Johnson295189b2012-06-20 16:38:30 -07004525 status = vos_open( &pVosContext, 0);
4526 if ( !VOS_IS_STATUS_SUCCESS( status ))
4527 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004528 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
4529 goto err_clkvote;
Jeff Johnson295189b2012-06-20 16:38:30 -07004530 }
4531
Jeff Johnson295189b2012-06-20 16:38:30 -07004532 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
4533
4534 if ( NULL == pHddCtx->hHal )
4535 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004536 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004537 goto err_vosclose;
4538 }
4539
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004540 status = vos_preStart( pHddCtx->pvosContext );
4541 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4542 {
4543 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
4544 goto err_vosclose;
4545 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004546
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004547 /* Note that the vos_preStart() sequence triggers the cfg download.
4548 The cfg download must occur before we update the SME config
4549 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07004550 status = hdd_set_sme_config( pHddCtx );
4551
4552 if ( VOS_STATUS_SUCCESS != status )
4553 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004554 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
4555 goto err_vosclose;
4556 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004557
4558 //Initialize the WMM module
4559 status = hdd_wmm_init(pHddCtx);
4560 if (!VOS_IS_STATUS_SUCCESS(status))
4561 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004562 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004563 goto err_vosclose;
4564 }
4565
Jeff Johnson295189b2012-06-20 16:38:30 -07004566 /* In the integrated architecture we update the configuration from
4567 the INI file and from NV before vOSS has been started so that
4568 the final contents are available to send down to the cCPU */
4569
4570 // Apply the cfg.ini to cfg.dat
4571 if (FALSE == hdd_update_config_dat(pHddCtx))
4572 {
4573 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4574 goto err_vosclose;
4575 }
4576
4577 // Apply the NV to cfg.dat
4578 /* Prima Update MAC address only at here */
4579 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
4580 {
4581#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
4582 /* There was not a valid set of MAC Addresses in NV. See if the
4583 default addresses were modified by the cfg.ini settings. If so,
4584 we'll use them, but if not, we'll autogenerate a set of MAC
4585 addresses based upon the device serial number */
4586
4587 static const v_MACADDR_t default_address =
4588 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
4589 unsigned int serialno;
4590 int i;
4591
4592 serialno = wcnss_get_serial_number();
4593 if ((0 != serialno) &&
4594 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
4595 sizeof(default_address))))
4596 {
4597 /* cfg.ini has the default address, invoke autogen logic */
4598
4599 /* MAC address has 3 bytes of OUI so we have a maximum of 3
4600 bytes of the serial number that can be used to generate
4601 the other 3 bytes of the MAC address. Mask off all but
4602 the lower 3 bytes (this will also make sure we don't
4603 overflow in the next step) */
4604 serialno &= 0x00FFFFFF;
4605
4606 /* we need a unique address for each session */
4607 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
4608
4609 /* autogen all addresses */
4610 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4611 {
4612 /* start with the entire default address */
4613 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4614 /* then replace the lower 3 bytes */
4615 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
4616 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
4617 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4618
4619 serialno++;
4620 }
4621
4622 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4623 MAC_ADDRESS_STR,
4624 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4625 }
4626 else
4627#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4628 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004629 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004630 "%s: Invalid MAC address in NV, using MAC from ini file "
4631 MAC_ADDRESS_STR, __func__,
4632 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4633 }
4634 }
4635 {
4636 eHalStatus halStatus;
4637 // Set the MAC Address
4638 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4639 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4640 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
4641 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
4642
4643 if (!HAL_STATUS_SUCCESS( halStatus ))
4644 {
4645 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
4646 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08004647 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004648 }
4649 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004650
4651 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
4652 Note: Firmware image will be read and downloaded inside vos_start API */
4653 status = vos_start( pHddCtx->pvosContext );
4654 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4655 {
4656 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
4657 goto err_vosclose;
4658 }
4659
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004660 /* Exchange capability info between Host and FW and also get versioning info from FW */
4661 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004662
4663 status = hdd_post_voss_start_config( pHddCtx );
4664 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4665 {
4666 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
4667 __func__);
4668 goto err_vosstop;
4669 }
4670
Jeff Johnson295189b2012-06-20 16:38:30 -07004671 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4672 {
4673 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
4674 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4675 }
4676 else
4677 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004678 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
4679 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4680 if (pAdapter != NULL)
4681 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304682 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07004683 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304684 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
4685 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
4686 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07004687
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304688 /* Generate the P2P Device Address. This consists of the device's
4689 * primary MAC address with the locally administered bit set.
4690 */
4691 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07004692 }
4693 else
4694 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304695 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
4696 if (p2p_dev_addr != NULL)
4697 {
4698 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
4699 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
4700 }
4701 else
4702 {
4703 hddLog(VOS_TRACE_LEVEL_FATAL,
4704 "%s: Failed to allocate mac_address for p2p_device",
4705 __func__);
4706 goto err_close_adapter;
4707 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004708 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004709
4710 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
4711 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
4712 if ( NULL == pP2pAdapter )
4713 {
4714 hddLog(VOS_TRACE_LEVEL_FATAL,
4715 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004716 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004717 goto err_close_adapter;
4718 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004719 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004720 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004721
4722 if( pAdapter == NULL )
4723 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004724 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
4725 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004726 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004727
Jeff Johnson295189b2012-06-20 16:38:30 -07004728#ifdef WLAN_BTAMP_FEATURE
4729 vStatus = WLANBAP_Open(pVosContext);
4730 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4731 {
4732 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4733 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004734 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004735 }
4736
4737 vStatus = BSL_Init(pVosContext);
4738 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4739 {
4740 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4741 "%s: Failed to Init BSL",__func__);
4742 goto err_bap_close;
4743 }
4744 vStatus = WLANBAP_Start(pVosContext);
4745 if (!VOS_IS_STATUS_SUCCESS(vStatus))
4746 {
4747 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4748 "%s: Failed to start TL",__func__);
4749 goto err_bap_close;
4750 }
4751
4752 pConfig = pHddCtx->cfg_ini;
4753 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
4754 status = WLANBAP_SetConfig(&btAmpConfig);
4755
4756#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07004757
Jeff Johnson295189b2012-06-20 16:38:30 -07004758#ifdef FEATURE_WLAN_SCAN_PNO
4759 /*SME must send channel update configuration to RIVA*/
4760 sme_UpdateChannelConfig(pHddCtx->hHal);
4761#endif
4762
Jeff Johnson295189b2012-06-20 16:38:30 -07004763 /* Register with platform driver as client for Suspend/Resume */
4764 status = hddRegisterPmOps(pHddCtx);
4765 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4766 {
4767 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
4768#ifdef WLAN_BTAMP_FEATURE
4769 goto err_bap_stop;
4770#else
Jeff Johnsone7245742012-09-05 17:12:55 -07004771 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004772#endif //WLAN_BTAMP_FEATURE
4773 }
4774
4775 /* Register TM level change handler function to the platform */
4776 status = hddDevTmRegisterNotifyCallback(pHddCtx);
4777 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4778 {
4779 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
4780 goto err_unregister_pmops;
4781 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004782
4783 /* register for riva power on lock to platform driver */
4784 if (req_riva_power_on_lock("wlan"))
4785 {
4786 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
4787 __func__);
4788 goto err_unregister_pmops;
4789 }
4790
Jeff Johnson295189b2012-06-20 16:38:30 -07004791 // register net device notifier for device change notification
4792 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4793
4794 if(ret < 0)
4795 {
4796 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
4797 goto err_free_power_on_lock;
4798 }
4799
4800 //Initialize the nlink service
4801 if(nl_srv_init() != 0)
4802 {
4803 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
4804 goto err_reg_netdev;
4805 }
4806
4807 //Initialize the BTC service
4808 if(btc_activate_service(pHddCtx) != 0)
4809 {
4810 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
4811 goto err_nl_srv;
4812 }
4813
4814#ifdef PTT_SOCK_SVC_ENABLE
4815 //Initialize the PTT service
4816 if(ptt_sock_activate_svc(pHddCtx) != 0)
4817 {
4818 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
4819 goto err_nl_srv;
4820 }
4821#endif
4822
Jeff Johnson295189b2012-06-20 16:38:30 -07004823 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004824 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07004825 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07004826 /* Action frame registered in one adapter which will
4827 * applicable to all interfaces
4828 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07004829 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004830 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004831
4832 mutex_init(&pHddCtx->sap_lock);
4833
4834 pHddCtx->isLoadUnloadInProgress = FALSE;
4835
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004836#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004837#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4838 /* Initialize the wake lcok */
4839 wake_lock_init(&pHddCtx->rx_wake_lock,
4840 WAKE_LOCK_SUSPEND,
4841 "qcom_rx_wakelock");
4842#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004843 /* Initialize the wake lcok */
4844 wake_lock_init(&pHddCtx->sap_wake_lock,
4845 WAKE_LOCK_SUSPEND,
4846 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004847#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004848
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004849 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
4850 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07004851
4852 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4853 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004854
4855 // Initialize the restart logic
4856 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304857
Jeff Johnson295189b2012-06-20 16:38:30 -07004858 goto success;
4859
4860err_nl_srv:
4861 nl_srv_exit();
4862
4863err_reg_netdev:
4864 unregister_netdevice_notifier(&hdd_netdev_notifier);
4865
4866err_free_power_on_lock:
4867 free_riva_power_on_lock("wlan");
4868
4869err_unregister_pmops:
4870 hddDevTmUnregisterNotifyCallback(pHddCtx);
4871 hddDeregisterPmOps(pHddCtx);
4872
4873#ifdef WLAN_BTAMP_FEATURE
4874err_bap_stop:
4875 WLANBAP_Stop(pVosContext);
4876#endif
4877
4878#ifdef WLAN_BTAMP_FEATURE
4879err_bap_close:
4880 WLANBAP_Close(pVosContext);
4881#endif
4882
Jeff Johnson295189b2012-06-20 16:38:30 -07004883err_close_adapter:
4884 hdd_close_all_adapters( pHddCtx );
4885
4886err_vosstop:
4887 vos_stop(pVosContext);
4888
4889err_vosclose:
4890 status = vos_sched_close( pVosContext );
4891 if (!VOS_IS_STATUS_SUCCESS(status)) {
4892 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4893 "%s: Failed to close VOSS Scheduler", __func__);
4894 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4895 }
4896 vos_close(pVosContext );
4897
Jeff Johnson295189b2012-06-20 16:38:30 -07004898err_clkvote:
Jeff Johnsonbc676b42013-02-14 16:04:08 -08004899 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07004900
4901err_wdclose:
4902 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4903 vos_watchdog_close(pVosContext);
4904
Jeff Johnson295189b2012-06-20 16:38:30 -07004905err_wiphy_reg:
4906 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004907
4908err_config:
4909 kfree(pHddCtx->cfg_ini);
4910 pHddCtx->cfg_ini= NULL;
4911
4912err_free_hdd_context:
4913 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07004914 wiphy_free(wiphy) ;
4915 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07004916 VOS_BUG(1);
4917
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004918 if (hdd_is_ssr_required())
4919 {
4920 /* WDI timeout had happened during load, so SSR is needed here */
4921 subsystem_restart("wcnss");
4922 msleep(5000);
4923 }
4924 hdd_set_ssr_required (VOS_FALSE);
4925
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004926 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004927
4928success:
4929 EXIT();
4930 return 0;
4931}
4932
4933/**---------------------------------------------------------------------------
4934
Jeff Johnson32d95a32012-09-10 13:15:23 -07004935 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004936
Jeff Johnson32d95a32012-09-10 13:15:23 -07004937 This is the driver entry point - called in different timeline depending
4938 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004939
4940 \param - None
4941
4942 \return - 0 for success, non zero for failure
4943
4944 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004945static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004946{
4947 VOS_STATUS status;
4948 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004949 struct device *dev = NULL;
4950 int ret_status = 0;
4951
4952 ENTER();
4953
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004954#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004955 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004956#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004957
4958 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4959 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4960
4961 //Power Up Libra WLAN card first if not already powered up
4962 status = vos_chipPowerUp(NULL,NULL,NULL);
4963 if (!VOS_IS_STATUS_SUCCESS(status))
4964 {
4965 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4966 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004967 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004968 }
4969
Jeff Johnson295189b2012-06-20 16:38:30 -07004970#ifdef ANI_BUS_TYPE_PCI
4971
4972 dev = wcnss_wlan_get_device();
4973
4974#endif // ANI_BUS_TYPE_PCI
4975
4976#ifdef ANI_BUS_TYPE_PLATFORM
4977 dev = wcnss_wlan_get_device();
4978#endif // ANI_BUS_TYPE_PLATFORM
4979
4980
4981 do {
4982 if (NULL == dev) {
4983 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4984 ret_status = -1;
4985 break;
4986 }
4987
4988#ifdef MEMORY_DEBUG
4989 vos_mem_init();
4990#endif
4991
4992#ifdef TIMER_MANAGER
4993 vos_timer_manager_init();
4994#endif
4995
4996 /* Preopen VOSS so that it is ready to start at least SAL */
4997 status = vos_preOpen(&pVosContext);
4998
4999 if (!VOS_IS_STATUS_SUCCESS(status))
5000 {
5001 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
5002 ret_status = -1;
5003 break;
5004 }
5005
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005006#ifndef MODULE
5007 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
5008 */
5009 hdd_set_conparam((v_UINT_t)con_mode);
5010#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005011
5012 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005013 if (hdd_wlan_startup(dev))
5014 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005015 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08005016 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005017 vos_preClose( &pVosContext );
5018 ret_status = -1;
5019 break;
5020 }
5021
5022 /* Cancel the vote for XO Core ON
5023 * This is done here for safety purposes in case we re-initialize without turning
5024 * it OFF in any error scenario.
5025 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005026 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07005027 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005028 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07005029 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
5030 {
5031 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
5032 " Power consumed will be high\n");
5033 }
5034 } while (0);
5035
5036 if (0 != ret_status)
5037 {
5038 //Assert Deep sleep signal now to put Libra HW in lowest power state
5039 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
5040 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
5041
5042 //Vote off any PMIC voltage supplies
5043 vos_chipPowerDown(NULL, NULL, NULL);
5044#ifdef TIMER_MANAGER
5045 vos_timer_exit();
5046#endif
5047#ifdef MEMORY_DEBUG
5048 vos_mem_exit();
5049#endif
5050
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005051#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005052 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005053#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005054 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5055 }
5056 else
5057 {
5058 //Send WLAN UP indication to Nlink Service
5059 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
5060
5061 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5062
5063 }
5064
5065 EXIT();
5066
5067 return ret_status;
5068}
5069
Jeff Johnson32d95a32012-09-10 13:15:23 -07005070/**---------------------------------------------------------------------------
5071
5072 \brief hdd_module_init() - Init Function
5073
5074 This is the driver entry point (invoked when module is loaded using insmod)
5075
5076 \param - None
5077
5078 \return - 0 for success, non zero for failure
5079
5080 --------------------------------------------------------------------------*/
5081#ifdef MODULE
5082static int __init hdd_module_init ( void)
5083{
5084 return hdd_driver_init();
5085}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005086#else /* #ifdef MODULE */
5087static int __init hdd_module_init ( void)
5088{
5089 /* Driver initialization is delayed to fwpath_changed_handler */
5090 return 0;
5091}
Jeff Johnson32d95a32012-09-10 13:15:23 -07005092#endif /* #ifdef MODULE */
5093
Jeff Johnson295189b2012-06-20 16:38:30 -07005094
5095/**---------------------------------------------------------------------------
5096
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005097 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005098
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005099 This is the driver exit point (invoked when module is unloaded using rmmod
5100 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07005101
5102 \param - None
5103
5104 \return - None
5105
5106 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005107static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005108{
5109 hdd_context_t *pHddCtx = NULL;
5110 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005111
5112 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
5113
5114 //Get the global vos context
5115 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
5116
5117 if(!pVosContext)
5118 {
5119 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
5120 goto done;
5121 }
5122
5123 //Get the HDD context.
5124 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
5125
5126 if(!pHddCtx)
5127 {
5128 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
5129 }
5130 else
5131 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005132 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005133 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07005134 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
5135 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07005136 }
5137
5138 pHddCtx->isLoadUnloadInProgress = TRUE;
5139 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5140
5141 //Do all the cleanup before deregistering the driver
5142 hdd_wlan_exit(pHddCtx);
5143 }
5144
Jeff Johnson295189b2012-06-20 16:38:30 -07005145 vos_preClose( &pVosContext );
5146
5147#ifdef TIMER_MANAGER
5148 vos_timer_exit();
5149#endif
5150#ifdef MEMORY_DEBUG
5151 vos_mem_exit();
5152#endif
5153
5154done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005155#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005156 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005157#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005158 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
5159}
5160
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005161/**---------------------------------------------------------------------------
5162
5163 \brief hdd_module_exit() - Exit function
5164
5165 This is the driver exit point (invoked when module is unloaded using rmmod)
5166
5167 \param - None
5168
5169 \return - None
5170
5171 --------------------------------------------------------------------------*/
5172static void __exit hdd_module_exit(void)
5173{
5174 hdd_driver_exit();
5175}
5176
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005177#ifdef MODULE
5178static int fwpath_changed_handler(const char *kmessage,
5179 struct kernel_param *kp)
5180{
5181 /* nothing to do when driver is DLKM */
5182 return 0;
5183}
5184
5185static int con_mode_handler(const char *kmessage,
5186 struct kernel_param *kp)
5187{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005188 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005189}
5190#else /* #ifdef MODULE */
5191/**---------------------------------------------------------------------------
5192
5193 \brief fwpath_changed_handler() - Handler Function
5194
5195 This is the driver entry point
5196 - delayed driver initialization when driver is statically linked
5197 - invoked when module parameter fwpath is modified from userpspace to signal
5198 initializing the WLAN driver
5199
5200 \return - 0 for success, non zero for failure
5201
5202 --------------------------------------------------------------------------*/
5203static int fwpath_changed_handler(const char *kmessage,
5204 struct kernel_param *kp)
5205{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005206 int ret_status;
5207
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005208 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005209 ret_status = hdd_driver_init();
5210 wlan_hdd_inited = ret_status ? 0 : 1;
5211 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005212 }
5213
5214 hdd_driver_exit();
5215
5216 msleep(200);
5217
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005218 ret_status = hdd_driver_init();
5219 wlan_hdd_inited = ret_status ? 0 : 1;
5220 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005221}
5222
Jeff Johnson295189b2012-06-20 16:38:30 -07005223/**---------------------------------------------------------------------------
5224
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005225 \brief con_mode_handler() -
5226
5227 Handler function for module param con_mode when it is changed by userspace
5228 Dynamically linked - do nothing
5229 Statically linked - exit and init driver, as in rmmod and insmod
5230
5231 \param -
5232
5233 \return -
5234
5235 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005236static int con_mode_handler(const char *kmessage,
5237 struct kernel_param *kp)
5238{
5239 int ret = param_set_int(kmessage, kp);
5240
5241 if (ret)
5242 return ret;
5243
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005244 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005245}
5246#endif /* #ifdef MODULE */
5247
5248/**---------------------------------------------------------------------------
5249
Jeff Johnson295189b2012-06-20 16:38:30 -07005250 \brief hdd_get_conparam() -
5251
5252 This is the driver exit point (invoked when module is unloaded using rmmod)
5253
5254 \param - None
5255
5256 \return - tVOS_CON_MODE
5257
5258 --------------------------------------------------------------------------*/
5259tVOS_CON_MODE hdd_get_conparam ( void )
5260{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005261#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005262 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005263#else
5264 return (tVOS_CON_MODE)curr_con_mode;
5265#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005266}
5267void hdd_set_conparam ( v_UINT_t newParam )
5268{
5269 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005270#ifndef MODULE
5271 curr_con_mode = con_mode;
5272#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005273}
5274/**---------------------------------------------------------------------------
5275
5276 \brief hdd_softap_sta_deauth() - function
5277
5278 This to take counter measure to handle deauth req from HDD
5279
5280 \param - pAdapter - Pointer to the HDD
5281
5282 \param - enable - boolean value
5283
5284 \return - None
5285
5286 --------------------------------------------------------------------------*/
5287
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005288VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005289{
Jeff Johnson295189b2012-06-20 16:38:30 -07005290 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005291 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005292
5293 ENTER();
5294
5295 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5296
5297 //Ignore request to deauth bcmc station
5298 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005299 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005300
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005301 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005302
5303 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005304 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005305}
5306
5307/**---------------------------------------------------------------------------
5308
5309 \brief hdd_softap_sta_disassoc() - function
5310
5311 This to take counter measure to handle deauth req from HDD
5312
5313 \param - pAdapter - Pointer to the HDD
5314
5315 \param - enable - boolean value
5316
5317 \return - None
5318
5319 --------------------------------------------------------------------------*/
5320
5321void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5322{
5323 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5324
5325 ENTER();
5326
5327 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5328
5329 //Ignore request to disassoc bcmc station
5330 if( pDestMacAddress[0] & 0x1 )
5331 return;
5332
5333 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5334}
5335
5336void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5337{
5338 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5339
5340 ENTER();
5341
5342 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5343
5344 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5345}
5346
Jeff Johnson295189b2012-06-20 16:38:30 -07005347/**---------------------------------------------------------------------------
5348 *
5349 * \brief hdd_get__concurrency_mode() -
5350 *
5351 *
5352 * \param - None
5353 *
5354 * \return - CONCURRENCY MODE
5355 *
5356 * --------------------------------------------------------------------------*/
5357tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
5358{
5359 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5360 hdd_context_t *pHddCtx;
5361
5362 if (NULL != pVosContext)
5363 {
5364 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5365 if (NULL != pHddCtx)
5366 {
5367 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
5368 }
5369 }
5370
5371 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005372 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005373 return VOS_STA;
5374}
5375
5376/* Decide whether to allow/not the apps power collapse.
5377 * Allow apps power collapse if we are in connected state.
5378 * if not, allow only if we are in IMPS */
5379v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
5380{
5381 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08005382 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005383 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005384 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5385 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5386 hdd_adapter_t *pAdapter = NULL;
5387 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08005388 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005389
Jeff Johnson295189b2012-06-20 16:38:30 -07005390 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5391 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005392
Yathish9f22e662012-12-10 14:21:35 -08005393 concurrent_state = hdd_get_concurrency_mode();
5394
5395#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5396 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
5397 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
5398 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
5399 return TRUE;
5400#endif
5401
Jeff Johnson295189b2012-06-20 16:38:30 -07005402 /*loop through all adapters. TBD fix for Concurrency */
5403 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5404 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5405 {
5406 pAdapter = pAdapterNode->pAdapter;
5407 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
5408 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5409 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005410 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07005411 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08005412 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005413 (eANI_BOOLEAN_TRUE == scanRspPending) ||
5414 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07005415 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005416 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08005417 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
5418 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07005419 return FALSE;
5420 }
5421 }
5422 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5423 pAdapterNode = pNext;
5424 }
5425 return TRUE;
5426}
5427
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08005428/* Decides whether to send suspend notification to Riva
5429 * if any adapter is in BMPS; then it is required */
5430v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
5431{
5432 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
5433 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5434
5435 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
5436 {
5437 return TRUE;
5438 }
5439 return FALSE;
5440}
5441
Jeff Johnson295189b2012-06-20 16:38:30 -07005442void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5443{
5444 switch(mode)
5445 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005446 case VOS_STA_MODE:
5447 case VOS_P2P_CLIENT_MODE:
5448 case VOS_P2P_GO_MODE:
5449 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07005450 pHddCtx->concurrency_mode |= (1 << mode);
5451 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07005452 break;
5453 default:
5454 break;
5455
5456 }
5457 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5458 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5459}
5460
5461
5462void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5463{
5464 switch(mode)
5465 {
Chilam Ngc4244af2013-04-01 15:37:32 -07005466 case VOS_STA_MODE:
5467 case VOS_P2P_CLIENT_MODE:
5468 case VOS_P2P_GO_MODE:
5469 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005470 pHddCtx->no_of_sessions[mode]--;
5471 if (!(pHddCtx->no_of_sessions[mode]))
5472 pHddCtx->concurrency_mode &= (~(1 << mode));
5473 break;
5474 default:
5475 break;
5476 }
5477 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5478 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5479}
5480
Jeff Johnsone7245742012-09-05 17:12:55 -07005481/**---------------------------------------------------------------------------
5482 *
5483 * \brief wlan_hdd_restart_init
5484 *
5485 * This function initalizes restart timer/flag. An internal function.
5486 *
5487 * \param - pHddCtx
5488 *
5489 * \return - None
5490 *
5491 * --------------------------------------------------------------------------*/
5492
5493static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
5494{
5495 /* Initialize */
5496 pHddCtx->hdd_restart_retries = 0;
5497 atomic_set(&pHddCtx->isRestartInProgress, 0);
5498 vos_timer_init(&pHddCtx->hdd_restart_timer,
5499 VOS_TIMER_TYPE_SW,
5500 wlan_hdd_restart_timer_cb,
5501 pHddCtx);
5502}
5503/**---------------------------------------------------------------------------
5504 *
5505 * \brief wlan_hdd_restart_deinit
5506 *
5507 * This function cleans up the resources used. An internal function.
5508 *
5509 * \param - pHddCtx
5510 *
5511 * \return - None
5512 *
5513 * --------------------------------------------------------------------------*/
5514
5515static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
5516{
5517
5518 VOS_STATUS vos_status;
5519 /* Block any further calls */
5520 atomic_set(&pHddCtx->isRestartInProgress, 1);
5521 /* Cleanup */
5522 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5523 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005524 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005525 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5526 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005527 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005528
5529}
5530
5531/**---------------------------------------------------------------------------
5532 *
5533 * \brief wlan_hdd_framework_restart
5534 *
5535 * This function uses a cfg80211 API to start a framework initiated WLAN
5536 * driver module unload/load.
5537 *
5538 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
5539 *
5540 *
5541 * \param - pHddCtx
5542 *
5543 * \return - VOS_STATUS_SUCCESS: Success
5544 * VOS_STATUS_E_EMPTY: Adapter is Empty
5545 * VOS_STATUS_E_NOMEM: No memory
5546
5547 * --------------------------------------------------------------------------*/
5548
5549static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
5550{
5551 VOS_STATUS status = VOS_STATUS_SUCCESS;
5552 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5553 int len = (sizeof (struct ieee80211_mgmt));
5554 struct ieee80211_mgmt *mgmt = NULL;
5555
5556 /* Prepare the DEAUTH managment frame with reason code */
5557 mgmt = kzalloc(len, GFP_KERNEL);
5558 if(mgmt == NULL)
5559 {
5560 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08005561 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07005562 return VOS_STATUS_E_NOMEM;
5563 }
5564 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
5565
5566 /* Iterate over all adapters/devices */
5567 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5568 do
5569 {
5570 if( (status == VOS_STATUS_SUCCESS) &&
5571 pAdapterNode &&
5572 pAdapterNode->pAdapter)
5573 {
5574 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5575 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
5576 pAdapterNode->pAdapter->dev->name,
5577 pAdapterNode->pAdapter->device_mode,
5578 pHddCtx->hdd_restart_retries + 1);
5579 /*
5580 * CFG80211 event to restart the driver
5581 *
5582 * 'cfg80211_send_unprot_deauth' sends a
5583 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
5584 * of SME(Linux Kernel) state machine.
5585 *
5586 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
5587 * the driver.
5588 *
5589 */
5590
5591 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
5592 }
5593 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5594 pAdapterNode = pNext;
5595 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
5596
5597
5598 /* Free the allocated management frame */
5599 kfree(mgmt);
5600
5601 /* Retry until we unload or reach max count */
5602 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
5603 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
5604
5605 return status;
5606
5607}
5608/**---------------------------------------------------------------------------
5609 *
5610 * \brief wlan_hdd_restart_timer_cb
5611 *
5612 * Restart timer callback. An internal function.
5613 *
5614 * \param - User data:
5615 *
5616 * \return - None
5617 *
5618 * --------------------------------------------------------------------------*/
5619
5620void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
5621{
5622 hdd_context_t *pHddCtx = usrDataForCallback;
5623 wlan_hdd_framework_restart(pHddCtx);
5624 return;
5625
5626}
5627
5628
5629/**---------------------------------------------------------------------------
5630 *
5631 * \brief wlan_hdd_restart_driver
5632 *
5633 * This function sends an event to supplicant to restart the WLAN driver.
5634 *
5635 * This function is called from vos_wlanRestart.
5636 *
5637 * \param - pHddCtx
5638 *
5639 * \return - VOS_STATUS_SUCCESS: Success
5640 * VOS_STATUS_E_EMPTY: Adapter is Empty
5641 * VOS_STATUS_E_ALREADY: Request already in progress
5642
5643 * --------------------------------------------------------------------------*/
5644VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
5645{
5646 VOS_STATUS status = VOS_STATUS_SUCCESS;
5647
5648 /* A tight check to make sure reentrancy */
5649 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
5650 {
5651 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
5652 "%s: WLAN restart is already in progress", __func__);
5653
5654 return VOS_STATUS_E_ALREADY;
5655 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07005656 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005657#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005658 wcnss_reset_intr();
5659#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005660
Jeff Johnsone7245742012-09-05 17:12:55 -07005661 return status;
5662}
5663
5664
Jeff Johnson295189b2012-06-20 16:38:30 -07005665//Register the module init/exit functions
5666module_init(hdd_module_init);
5667module_exit(hdd_module_exit);
5668
5669MODULE_LICENSE("Dual BSD/GPL");
5670MODULE_AUTHOR("Qualcomm Atheros, Inc.");
5671MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
5672
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005673module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
5674 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005675
5676module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
5677 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);