blob: 64adfc1758aa323bfa25a6f4de820845af2a6ae0 [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>
78#ifdef ANI_BUS_TYPE_SDIO
79#include <wlan_sal_misc.h>
80#endif // ANI_BUS_TYPE_SDIO
81#include <vos_api.h>
82#include <vos_sched.h>
83#include <vos_power.h>
84#include <linux/etherdevice.h>
85#include <linux/firmware.h>
86#ifdef ANI_BUS_TYPE_SDIO
87#include <linux/mmc/sdio_func.h>
88#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32))
89// added in 2.6.32, need to define locally if using an earlier kernel
90#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev)
91#endif
92#endif // ANI_BUS_TYPE_SDIO
93#ifdef ANI_BUS_TYPE_PLATFORM
94#include <linux/wcnss_wlan.h>
95#endif //ANI_BUS_TYPE_PLATFORM
96#ifdef ANI_BUS_TYPE_PCI
97#include "wcnss_wlan.h"
98#endif /* ANI_BUS_TYPE_PCI */
99#include <wlan_hdd_tx_rx.h>
100#include <palTimer.h>
101#include <wniApi.h>
102#include <wlan_nlink_srv.h>
103#include <wlan_btc_svc.h>
104#include <wlan_hdd_cfg.h>
105#include <wlan_ptt_sock_svc.h>
106#include <wlan_hdd_wowl.h>
107#include <wlan_hdd_misc.h>
108#include <wlan_hdd_wext.h>
109#ifdef WLAN_BTAMP_FEATURE
110#include <bap_hdd_main.h>
111#include <bapInternal.h>
112#endif // WLAN_BTAMP_FEATURE
113
114#ifdef CONFIG_CFG80211
115#include <linux/wireless.h>
116#include <net/cfg80211.h>
117#include "wlan_hdd_cfg80211.h"
118#include "wlan_hdd_p2p.h"
119#endif
120#include <linux/rtnetlink.h>
121#ifdef ANI_MANF_DIAG
122int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
123#endif
124#ifdef WLAN_SOFTAP_FEATURE
125#include "sapApi.h"
126#include <linux/semaphore.h>
127#include <mach/subsystem_restart.h>
128#include <wlan_hdd_hostapd.h>
129#include <wlan_hdd_softap_tx_rx.h>
130#endif
131#ifdef FEATURE_WLAN_INTEGRATED_SOC
132#include "cfgApi.h"
133#endif
134#include "wlan_hdd_dev_pwr.h"
135#ifdef WLAN_BTAMP_FEATURE
136#include "bap_hdd_misc.h"
137#endif
138#ifdef FEATURE_WLAN_INTEGRATED_SOC
139#include "wlan_qct_pal_trace.h"
140#endif /* FEATURE_WLAN_INTEGRATED_SOC */
141#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800142#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530143#ifdef FEATURE_WLAN_TDLS
144#include "wlan_hdd_tdls.h"
145#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700146
147#ifdef MODULE
148#define WLAN_MODULE_NAME module_name(THIS_MODULE)
149#else
150#define WLAN_MODULE_NAME "wlan"
151#endif
152
153#ifdef TIMER_MANAGER
154#define TIMER_MANAGER_STR " +TIMER_MANAGER"
155#else
156#define TIMER_MANAGER_STR ""
157#endif
158
159#ifdef MEMORY_DEBUG
160#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
161#else
162#define MEMORY_DEBUG_STR ""
163#endif
164
165/* the Android framework expects this param even though we don't use it */
166#define BUF_LEN 20
167static char fwpath[BUF_LEN];
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700168#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700169static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700170#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700171
Jeff Johnsone7245742012-09-05 17:12:55 -0700172/*
173 * The rate at which the driver sends RESTART event to supplicant
174 * once the function 'vos_wlanRestart()' is called
175 *
176 */
177#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
178#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800179#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700180static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700181#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700182/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700183static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700184
185//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700186static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
187static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
188static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
189void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800190void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700191
Jeff Johnson295189b2012-06-20 16:38:30 -0700192v_U16_t hdd_select_queue(struct net_device *dev,
193 struct sk_buff *skb);
194
195#ifdef WLAN_FEATURE_PACKET_FILTERING
196static void hdd_set_multicast_list(struct net_device *dev);
197#endif
198
199void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
200
201extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
202
203static int hdd_netdev_notifier_call(struct notifier_block * nb,
204 unsigned long state,
205 void *ndev)
206{
207 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700208 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
209 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -0700210#ifdef WLAN_BTAMP_FEATURE
211 VOS_STATUS status;
212 hdd_context_t *pHddCtx;
213#endif
214
215 //Make sure that this callback corresponds to our device.
216 if((strncmp( dev->name, "wlan", 4 )) &&
Jeff Johnsone7245742012-09-05 17:12:55 -0700217 (strncmp( dev->name, "p2p", 3))
Jeff Johnson295189b2012-06-20 16:38:30 -0700218 )
219 return NOTIFY_DONE;
220
221#ifdef CONFIG_CFG80211
222 if (!dev->ieee80211_ptr)
223 return NOTIFY_DONE;
224#endif
225
Jeff Johnson295189b2012-06-20 16:38:30 -0700226
227 if(NULL == pAdapter)
228 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800229 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700230 VOS_ASSERT(0);
231 return NOTIFY_DONE;
232 }
233
234 hddLog(VOS_TRACE_LEVEL_INFO,"%s: New Net Device State = %lu", __func__, state);
235
236 switch (state) {
237 case NETDEV_REGISTER:
238 break;
239
240 case NETDEV_UNREGISTER:
241 break;
242
243 case NETDEV_UP:
244 break;
245
246 case NETDEV_DOWN:
247 break;
248
249 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700250 if(TRUE == pAdapter->isLinkUpSvcNeeded)
251 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700252 break;
253
254 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700255 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700256 {
257 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800258 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700259 hdd_abort_mac_scan(pAdapter->pHddCtx);
260 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800261 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700262 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
263 if(!result)
264 {
265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800266 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700267 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700268 }
269 }
270 else
271 {
272 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700273 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700274 }
275#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700276 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700277 status = WLANBAP_StopAmp();
278 if(VOS_STATUS_SUCCESS != status )
279 {
280 pHddCtx->isAmpAllowed = VOS_TRUE;
281 hddLog(VOS_TRACE_LEVEL_FATAL,
282 "%s: Failed to stop AMP", __func__);
283 }
284 else
285 {
286 //a state m/c implementation in PAL is TBD to avoid this delay
287 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700288 if ( pHddCtx->isAmpAllowed )
289 {
290 WLANBAP_DeregisterFromHCI();
291 pHddCtx->isAmpAllowed = VOS_FALSE;
292 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700293 }
294#endif //WLAN_BTAMP_FEATURE
295 break;
296
297 default:
298 break;
299 }
300
301 return NOTIFY_DONE;
302}
303
304struct notifier_block hdd_netdev_notifier = {
305 .notifier_call = hdd_netdev_notifier_call,
306};
307
308/*---------------------------------------------------------------------------
309 * Function definitions
310 *-------------------------------------------------------------------------*/
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800311int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700312void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
313void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700314//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700315static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700316#ifndef MODULE
317/* current con_mode - used only for statically linked driver
318 * con_mode is changed by userspace to indicate a mode change which will
319 * result in calling the module exit and init functions. The module
320 * exit function will clean up based on the value of con_mode prior to it
321 * being changed by userspace. So curr_con_mode records the current con_mode
322 * for exit when con_mode becomes the next mode for init
323 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700324static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700325#endif
326
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800327/**---------------------------------------------------------------------------
328
329 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
330
331 Called immediately after the cfg.ini is read in order to configure
332 the desired trace levels.
333
334 \param - moduleId - module whose trace level is being configured
335 \param - bitmask - bitmask of log levels to be enabled
336
337 \return - void
338
339 --------------------------------------------------------------------------*/
340static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
341{
342 wpt_tracelevel level;
343
344 /* if the bitmask is the default value, then a bitmask was not
345 specified in cfg.ini, so leave the logging level alone (it
346 will remain at the "compiled in" default value) */
347 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
348 {
349 return;
350 }
351
352 /* a mask was specified. start by disabling all logging */
353 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
354
355 /* now cycle through the bitmask until all "set" bits are serviced */
356 level = VOS_TRACE_LEVEL_FATAL;
357 while (0 != bitmask)
358 {
359 if (bitmask & 1)
360 {
361 vos_trace_setValue(moduleId, level, 1);
362 }
363 level++;
364 bitmask >>= 1;
365 }
366}
367
368
Jeff Johnson295189b2012-06-20 16:38:30 -0700369#ifdef FEATURE_WLAN_INTEGRATED_SOC
370/**---------------------------------------------------------------------------
371
372 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
373
374 Called immediately after the cfg.ini is read in order to configure
375 the desired trace levels in the WDI.
376
377 \param - moduleId - module whose trace level is being configured
378 \param - bitmask - bitmask of log levels to be enabled
379
380 \return - void
381
382 --------------------------------------------------------------------------*/
383static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
384{
385 wpt_tracelevel level;
386
387 /* if the bitmask is the default value, then a bitmask was not
388 specified in cfg.ini, so leave the logging level alone (it
389 will remain at the "compiled in" default value) */
390 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
391 {
392 return;
393 }
394
395 /* a mask was specified. start by disabling all logging */
396 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
397
398 /* now cycle through the bitmask until all "set" bits are serviced */
399 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
400 while (0 != bitmask)
401 {
402 if (bitmask & 1)
403 {
404 wpalTraceSetLevel(moduleId, level, 1);
405 }
406 level++;
407 bitmask >>= 1;
408 }
409}
410#endif /* FEATURE_WLAN_INTEGRATED_SOC */
411
412int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
413{
414 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
415 hdd_priv_data_t priv_data;
416 tANI_U8 *command = NULL;
417 int ret = 0;
418
419 if (NULL == pAdapter)
420 {
421 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700422 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700423 ret = -ENODEV;
424 goto exit;
425 }
426
Jeff Johnsone7245742012-09-05 17:12:55 -0700427 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700428 {
429 ret = -EINVAL;
430 goto exit;
431 }
432
433 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
434 {
435 ret = -EFAULT;
436 goto exit;
437 }
438
439 command = kmalloc(priv_data.total_len, GFP_KERNEL);
440 if (!command)
441 {
442 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700443 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700444 ret = -ENOMEM;
445 goto exit;
446 }
447
448 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
449 {
450 ret = -EFAULT;
451 goto exit;
452 }
453
454 if ((SIOCDEVPRIVATE + 1) == cmd)
455 {
456 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
457
458 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700459 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700460
461 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
462 {
463 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
464 sizeof(tSirMacAddr)))
465 {
466 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700467 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700468 ret = -EFAULT;
469 }
470 }
Amar Singhal0974e402013-02-12 14:27:46 -0800471 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700472 {
Amar Singhal0974e402013-02-12 14:27:46 -0800473 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700474 int ret = 0 ;
475
476 /* Change band request received */
477
478 /* First 8 bytes will have "SETBAND " and
479 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700480 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800481 "%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 -0700482
483 /* Change band request received */
484 ret = hdd_setBand_helper(dev, ptr);
485 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700486 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
487 {
488 char *country_code;
489
490 country_code = command + 8;
491 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
492 pAdapter, pHddCtx->pvosContext);
493 if( 0 != ret )
494 {
495 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
496 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
497
498 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700499 }
500 /*
501 command should be a string having format
502 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
503 */
Amar Singhal0974e402013-02-12 14:27:46 -0800504 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700505 {
Amar Singhal0974e402013-02-12 14:27:46 -0800506 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700507
508 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700509 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700510
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800511 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700512 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800513 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
514 {
515 int suspend = 0;
516 tANI_U8 *ptr = (tANI_U8*)command + 15;
517
518 suspend = *ptr - '0';
519 hdd_set_wlan_suspend_mode(suspend);
520 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700521 else {
522 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
523 __func__, command);
524 }
525
Jeff Johnson295189b2012-06-20 16:38:30 -0700526 }
527exit:
528 if (command)
529 {
530 kfree(command);
531 }
532 return ret;
533}
534
535/**---------------------------------------------------------------------------
536
537 \brief hdd_open() - HDD Open function
538
539 This is called in response to ifconfig up
540
541 \param - dev Pointer to net_device structure
542
543 \return - 0 for success non-zero for failure
544
545 --------------------------------------------------------------------------*/
546int hdd_open (struct net_device *dev)
547{
548 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
549 hdd_context_t *pHddCtx;
550 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
551 VOS_STATUS status;
552 v_BOOL_t in_standby = TRUE;
553
554 if (NULL == pAdapter)
555 {
556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700557 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700558 return -ENODEV;
559 }
560
561 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
562 if (NULL == pHddCtx)
563 {
564 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700565 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700566 return -ENODEV;
567 }
568
569 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
570 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
571 {
572 if( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
573 {
574 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of "
575 "standby", __func__, pAdapter->device_mode);
576 in_standby = FALSE;
577 break;
578 }
579 else
580 {
581 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
582 pAdapterNode = pNext;
583 }
584 }
585
586 if (TRUE == in_standby)
587 {
588 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
589 {
590 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
591 "wlan out of power save", __func__);
592 return -EINVAL;
593 }
594 }
595
596 pAdapter->event_flags |= DEVICE_IFACE_OPENED;
597 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
598 {
599 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700600 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700601 /* Enable TX queues only when we are connected */
602 netif_tx_start_all_queues(dev);
603 }
604
605 return 0;
606}
607
608int hdd_mon_open (struct net_device *dev)
609{
610 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
611
612 if(pAdapter == NULL) {
613 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700614 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800615 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700616 }
617
618 netif_start_queue(dev);
619
620 return 0;
621}
622/**---------------------------------------------------------------------------
623
624 \brief hdd_stop() - HDD stop function
625
626 This is called in response to ifconfig down
627
628 \param - dev Pointer to net_device structure
629
630 \return - 0 for success non-zero for failure
631
632 --------------------------------------------------------------------------*/
633
634int hdd_stop (struct net_device *dev)
635{
636 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
637 hdd_context_t *pHddCtx;
638 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
639 VOS_STATUS status;
640 v_BOOL_t enter_standby = TRUE;
641
642 ENTER();
643
644 if (NULL == pAdapter)
645 {
646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700647 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700648 return -ENODEV;
649 }
650
651 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
652 if (NULL == pHddCtx)
653 {
654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700655 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700656 return -ENODEV;
657 }
658
659 pAdapter->event_flags &= ~(DEVICE_IFACE_OPENED);
660 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
661 netif_tx_disable(pAdapter->dev);
662 netif_carrier_off(pAdapter->dev);
663
664
665 /* SoftAP ifaces should never go in power save mode
666 making sure same here. */
667 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
668 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
669#ifdef WLAN_FEATURE_P2P
670 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
671#endif
672 )
673 {
674 /* SoftAP mode, so return from here */
675 EXIT();
676 return 0;
677 }
678
679 /* Find if any iface is up then
680 if any iface is up then can't put device to sleep/ power save mode. */
681 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
682 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
683 {
684 if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
685 {
686 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
687 "put device to sleep", __func__, pAdapter->device_mode);
688 enter_standby = FALSE;
689 break;
690 }
691 else
692 {
693 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
694 pAdapterNode = pNext;
695 }
696 }
697
698 if (TRUE == enter_standby)
699 {
700 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
701 "entering standby", __func__);
702 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
703 {
704 /*log and return success*/
705 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
706 "wlan in power save", __func__);
707 }
708 }
709
710 EXIT();
711 return 0;
712}
713
714/**---------------------------------------------------------------------------
715
716 \brief hdd_uninit() - HDD uninit function
717
718 This is called during the netdev unregister to uninitialize all data
719associated with the device
720
721 \param - dev Pointer to net_device structure
722
723 \return - void
724
725 --------------------------------------------------------------------------*/
726static void hdd_uninit (struct net_device *dev)
727{
728 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
729
730 ENTER();
731
732 do
733 {
734 if (NULL == pAdapter)
735 {
736 hddLog(VOS_TRACE_LEVEL_FATAL,
737 "%s: NULL pAdapter", __func__);
738 break;
739 }
740
741 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
742 {
743 hddLog(VOS_TRACE_LEVEL_FATAL,
744 "%s: Invalid magic", __func__);
745 break;
746 }
747
748 if (NULL == pAdapter->pHddCtx)
749 {
750 hddLog(VOS_TRACE_LEVEL_FATAL,
751 "%s: NULL pHddCtx", __func__);
752 break;
753 }
754
755 if (dev != pAdapter->dev)
756 {
757 hddLog(VOS_TRACE_LEVEL_FATAL,
758 "%s: Invalid device reference", __func__);
759 /* we haven't validated all cases so let this go for now */
760 }
761
762 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
763
764 /* after uninit our adapter structure will no longer be valid */
765 pAdapter->dev = NULL;
766 pAdapter->magic = 0;
767 } while (0);
768
769 EXIT();
770}
771
772/**---------------------------------------------------------------------------
773
774 \brief hdd_release_firmware() -
775
776 This function calls the release firmware API to free the firmware buffer.
777
778 \param - pFileName Pointer to the File Name.
779 pCtx - Pointer to the adapter .
780
781
782 \return - 0 for success, non zero for failure
783
784 --------------------------------------------------------------------------*/
785
786VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
787{
788 VOS_STATUS status = VOS_STATUS_SUCCESS;
789 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
790 ENTER();
791
792
793 if (!strcmp(WLAN_FW_FILE, pFileName)) {
794
795 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
796
797 if(pHddCtx->fw) {
798 release_firmware(pHddCtx->fw);
799 pHddCtx->fw = NULL;
800 }
801 else
802 status = VOS_STATUS_E_FAILURE;
803 }
804 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
805 if(pHddCtx->nv) {
806 release_firmware(pHddCtx->nv);
807 pHddCtx->nv = NULL;
808 }
809 else
810 status = VOS_STATUS_E_FAILURE;
811
812 }
813
814 EXIT();
815 return status;
816}
817
818/**---------------------------------------------------------------------------
819
820 \brief hdd_request_firmware() -
821
822 This function reads the firmware file using the request firmware
823 API and returns the the firmware data and the firmware file size.
824
825 \param - pfileName - Pointer to the file name.
826 - pCtx - Pointer to the adapter .
827 - ppfw_data - Pointer to the pointer of the firmware data.
828 - pSize - Pointer to the file size.
829
830 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
831
832 --------------------------------------------------------------------------*/
833
834
835VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
836{
837 int status;
838 VOS_STATUS retval = VOS_STATUS_SUCCESS;
839 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
840 ENTER();
841
842 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
843
844 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
845
846 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
847 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
848 __func__, pfileName);
849 retval = VOS_STATUS_E_FAILURE;
850 }
851
852 else {
853 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
854 *pSize = pHddCtx->fw->size;
855 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
856 __func__, *pSize);
857 }
858 }
859 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
860
861 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
862
863 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
864 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
865 __func__, pfileName);
866 retval = VOS_STATUS_E_FAILURE;
867 }
868
869 else {
870 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
871 *pSize = pHddCtx->nv->size;
872 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
873 __func__, *pSize);
874 }
875 }
876
877 EXIT();
878 return retval;
879}
880/**---------------------------------------------------------------------------
881 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
882
883 This is the function invoked by SME to inform the result of a full power
884 request issued by HDD
885
886 \param - callbackcontext - Pointer to cookie
887 status - result of request
888
889 \return - None
890
891--------------------------------------------------------------------------*/
892void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
893{
894 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
895
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700896 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -0700897 if(&pHddCtx->full_pwr_comp_var)
898 {
899 complete(&pHddCtx->full_pwr_comp_var);
900 }
901}
902
903/**---------------------------------------------------------------------------
904
905 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
906
907 This is the function invoked by SME to inform the result of BMPS
908 request issued by HDD
909
910 \param - callbackcontext - Pointer to cookie
911 status - result of request
912
913 \return - None
914
915--------------------------------------------------------------------------*/
916void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
917{
918
919 struct completion *completion_var = (struct completion*) callbackContext;
920
921 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
922 if(completion_var != NULL)
923 {
924 complete(completion_var);
925 }
926}
927
928/**---------------------------------------------------------------------------
929
930 \brief hdd_get_cfg_file_size() -
931
932 This function reads the configuration file using the request firmware
933 API and returns the configuration file size.
934
935 \param - pCtx - Pointer to the adapter .
936 - pFileName - Pointer to the file name.
937 - pBufSize - Pointer to the buffer size.
938
939 \return - 0 for success, non zero for failure
940
941 --------------------------------------------------------------------------*/
942
943VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
944{
945 int status;
946 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
947
948 ENTER();
949
950 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
951
952 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
953 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
954 status = VOS_STATUS_E_FAILURE;
955 }
956 else {
957 *pBufSize = pHddCtx->fw->size;
958 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
959 release_firmware(pHddCtx->fw);
960 pHddCtx->fw = NULL;
961 }
962
963 EXIT();
964 return VOS_STATUS_SUCCESS;
965}
966
967/**---------------------------------------------------------------------------
968
969 \brief hdd_read_cfg_file() -
970
971 This function reads the configuration file using the request firmware
972 API and returns the cfg data and the buffer size of the configuration file.
973
974 \param - pCtx - Pointer to the adapter .
975 - pFileName - Pointer to the file name.
976 - pBuffer - Pointer to the data buffer.
977 - pBufSize - Pointer to the buffer size.
978
979 \return - 0 for success, non zero for failure
980
981 --------------------------------------------------------------------------*/
982
983VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
984 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
985{
986 int status;
987 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
988
989 ENTER();
990
991 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
992
993 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
994 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
995 return VOS_STATUS_E_FAILURE;
996 }
997 else {
998 if(*pBufSize != pHddCtx->fw->size) {
999 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
1000 "file size", __func__);
1001 release_firmware(pHddCtx->fw);
1002 pHddCtx->fw = NULL;
1003 return VOS_STATUS_E_FAILURE;
1004 }
1005 else {
1006 if(pBuffer) {
1007 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
1008 }
1009 release_firmware(pHddCtx->fw);
1010 pHddCtx->fw = NULL;
1011 }
1012 }
1013
1014 EXIT();
1015
1016 return VOS_STATUS_SUCCESS;
1017}
1018
1019/**---------------------------------------------------------------------------
1020
1021 \brief hdd_set_mac_addr_cb() -
1022
1023 This function is the call back function for setting the station
1024 mac adrress called by ccm module to indicate the
1025 success/failure result.
1026
1027 \param - hHal - Pointer to the hal module.
1028 - result - returns the result of the set mac address.
1029
1030 \return - void
1031
1032 --------------------------------------------------------------------------*/
1033#ifndef FEATURE_WLAN_INTEGRATED_SOC
1034static void hdd_set_mac_addr_cb( tHalHandle hHal, tANI_S32 result )
1035{
1036 // ignore the STA_ID response for now.
1037
1038 VOS_ASSERT( CCM_IS_RESULT_SUCCESS( result ) );
1039}
1040#endif
1041
1042
1043/**---------------------------------------------------------------------------
1044
1045 \brief hdd_set_mac_address() -
1046
1047 This function sets the user specified mac address using
1048 the command ifconfig wlanX hw ether <mac adress>.
1049
1050 \param - dev - Pointer to the net device.
1051 - addr - Pointer to the sockaddr.
1052 \return - 0 for success, non zero for failure
1053
1054 --------------------------------------------------------------------------*/
1055
1056static int hdd_set_mac_address(struct net_device *dev, void *addr)
1057{
1058 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1059 struct sockaddr *psta_mac_addr = addr;
1060 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1061
1062 ENTER();
1063
1064 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1065
1066#ifdef HDD_SESSIONIZE
1067 // set the MAC address though the STA ID CFG.
1068 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
1069 (v_U8_t *)&pAdapter->macAddressCurrent,
1070 sizeof( pAdapter->macAddressCurrent ),
1071 hdd_set_mac_addr_cb, VOS_FALSE );
1072#endif
1073
1074 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1075
1076 EXIT();
1077 return halStatus;
1078}
1079
1080tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
1081{
1082 int i;
1083 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1084 {
1085 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
1086 break;
1087 }
1088
1089 if( VOS_MAX_CONCURRENCY_PERSONA == i)
1090 return NULL;
1091
1092 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
1093 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
1094}
1095
1096void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
1097{
1098 int i;
1099 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1100 {
1101 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
1102 {
1103 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
1104 break;
1105 }
1106 }
1107 return;
1108}
1109
1110#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1111 static struct net_device_ops wlan_drv_ops = {
1112 .ndo_open = hdd_open,
1113 .ndo_stop = hdd_stop,
1114 .ndo_uninit = hdd_uninit,
1115 .ndo_start_xmit = hdd_hard_start_xmit,
1116 .ndo_tx_timeout = hdd_tx_timeout,
1117 .ndo_get_stats = hdd_stats,
1118 .ndo_do_ioctl = hdd_ioctl,
1119 .ndo_set_mac_address = hdd_set_mac_address,
1120 .ndo_select_queue = hdd_select_queue,
1121#ifdef WLAN_FEATURE_PACKET_FILTERING
1122#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
1123 .ndo_set_rx_mode = hdd_set_multicast_list,
1124#else
1125 .ndo_set_multicast_list = hdd_set_multicast_list,
1126#endif //LINUX_VERSION_CODE
1127#endif
1128 };
1129#ifdef CONFIG_CFG80211
1130 static struct net_device_ops wlan_mon_drv_ops = {
1131 .ndo_open = hdd_mon_open,
1132 .ndo_stop = hdd_stop,
1133 .ndo_uninit = hdd_uninit,
1134 .ndo_start_xmit = hdd_mon_hard_start_xmit,
1135 .ndo_tx_timeout = hdd_tx_timeout,
1136 .ndo_get_stats = hdd_stats,
1137 .ndo_do_ioctl = hdd_ioctl,
1138 .ndo_set_mac_address = hdd_set_mac_address,
1139 };
1140#endif
1141
1142#endif
1143
1144void hdd_set_station_ops( struct net_device *pWlanDev )
1145{
1146#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1147 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
1148 pWlanDev->netdev_ops = &wlan_drv_ops;
1149#else
1150 pWlanDev->open = hdd_open;
1151 pWlanDev->stop = hdd_stop;
1152 pWlanDev->uninit = hdd_uninit;
1153 pWlanDev->hard_start_xmit = NULL;
1154 pWlanDev->tx_timeout = hdd_tx_timeout;
1155 pWlanDev->get_stats = hdd_stats;
1156 pWlanDev->do_ioctl = hdd_ioctl;
1157 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
1158 pWlanDev->set_mac_address = hdd_set_mac_address;
1159#endif
1160}
1161
Jeff Johnsoneed415b2013-01-18 16:11:20 -08001162static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07001163{
1164 struct net_device *pWlanDev = NULL;
1165 hdd_adapter_t *pAdapter = NULL;
1166#ifdef CONFIG_CFG80211
1167 /*
1168 * cfg80211 initialization and registration....
1169 */
1170 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
1171
1172#else
1173 //Allocate the net_device and private data (station ctx)
1174 pWlanDev = alloc_etherdev_mq(sizeof( hdd_adapter_t ), NUM_TX_QUEUES);
1175
1176#endif
1177
1178 if(pWlanDev != NULL)
1179 {
1180
1181 //Save the pointer to the net_device in the HDD adapter
1182 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
1183
1184#ifndef CONFIG_CFG80211
1185 //Init the net_device structure
1186 ether_setup(pWlanDev);
1187#endif
1188
1189 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
1190
1191 pAdapter->dev = pWlanDev;
1192 pAdapter->pHddCtx = pHddCtx;
1193 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
1194
1195 init_completion(&pAdapter->session_open_comp_var);
1196 init_completion(&pAdapter->session_close_comp_var);
1197 init_completion(&pAdapter->disconnect_comp_var);
1198 init_completion(&pAdapter->linkup_event_var);
1199 init_completion(&pAdapter->cancel_rem_on_chan_var);
1200 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001201#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1202 init_completion(&pAdapter->offchannel_tx_event);
1203#endif
1204#ifdef CONFIG_CFG80211
1205 init_completion(&pAdapter->tx_action_cnf_event);
1206#endif
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001207#ifdef FEATURE_WLAN_TDLS
1208 init_completion(&pAdapter->tdls_add_station_comp);
1209#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001210 init_completion(&pHddCtx->mc_sus_event_var);
1211 init_completion(&pHddCtx->tx_sus_event_var);
1212
Jeff Johnson295189b2012-06-20 16:38:30 -07001213 pAdapter->isLinkUpSvcNeeded = FALSE;
1214 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
1215 //Init the net_device structure
1216 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1217
1218 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
1219 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
1220 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
1221 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
1222
1223 hdd_set_station_ops( pAdapter->dev );
1224
1225 pWlanDev->destructor = free_netdev;
1226#ifdef CONFIG_CFG80211
1227 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
1228 pAdapter->wdev.wiphy = pHddCtx->wiphy;
1229 pAdapter->wdev.netdev = pWlanDev;
1230#endif
1231 /* set pWlanDev's parent to underlying device */
1232 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
1233 }
1234
1235 return pAdapter;
1236}
1237
1238VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
1239{
1240 struct net_device *pWlanDev = pAdapter->dev;
1241 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1242 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1243 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1244
1245 if( rtnl_lock_held )
1246 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001247 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001248 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
1249 {
1250 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
1251 return VOS_STATUS_E_FAILURE;
1252 }
1253 }
1254 if (register_netdevice(pWlanDev))
1255 {
1256 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
1257 return VOS_STATUS_E_FAILURE;
1258 }
1259 }
1260 else
1261 {
1262 if(register_netdev(pWlanDev))
1263 {
1264 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
1265 return VOS_STATUS_E_FAILURE;
1266 }
1267 }
1268 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
1269
1270 return VOS_STATUS_SUCCESS;
1271}
1272
1273eHalStatus hdd_smeCloseSessionCallback(void *pContext)
1274{
1275 if(pContext != NULL)
1276 {
1277 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
1278
1279 /* need to make sure all of our scheduled work has completed.
1280 * This callback is called from MC thread context, so it is safe to
1281 * to call below flush workqueue API from here.
1282 */
1283 flush_scheduled_work();
1284 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
1285 }
1286 return eHAL_STATUS_SUCCESS;
1287}
1288
1289VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
1290{
1291 struct net_device *pWlanDev = pAdapter->dev;
1292 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1293 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1294 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1295 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1296 int rc = 0;
1297
1298 INIT_COMPLETION(pAdapter->session_open_comp_var);
1299 //Open a SME session for future operation
1300 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
1301 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
1302 if ( !HAL_STATUS_SUCCESS( halStatus ) )
1303 {
1304 hddLog(VOS_TRACE_LEVEL_FATAL,
1305 "sme_OpenSession() failed with status code %08d [x%08lx]",
1306 halStatus, halStatus );
1307 status = VOS_STATUS_E_FAILURE;
1308 goto error_sme_open;
1309 }
1310
1311 //Block on a completion variable. Can't wait forever though.
1312 rc = wait_for_completion_interruptible_timeout(
1313 &pAdapter->session_open_comp_var,
1314 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1315 if (!rc)
1316 {
1317 hddLog(VOS_TRACE_LEVEL_FATAL,
1318 "Session is not opened within timeout period code %08d", rc );
1319 status = VOS_STATUS_E_FAILURE;
1320 goto error_sme_open;
1321 }
1322
1323 // Register wireless extensions
1324 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
1325 {
1326 hddLog(VOS_TRACE_LEVEL_FATAL,
1327 "hdd_register_wext() failed with status code %08d [x%08lx]",
1328 halStatus, halStatus );
1329 status = VOS_STATUS_E_FAILURE;
1330 goto error_register_wext;
1331 }
1332 //Safe to register the hard_start_xmit function again
1333#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1334 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
1335#else
1336 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
1337#endif
1338
1339 //Set the Connection State to Not Connected
1340 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
1341
1342 //Set the default operation channel
1343 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
1344
1345 /* Make the default Auth Type as OPEN*/
1346 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
1347
1348 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
1349 {
1350 hddLog(VOS_TRACE_LEVEL_FATAL,
1351 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
1352 status, status );
1353 goto error_init_txrx;
1354 }
1355
1356 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1357
1358 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
1359 {
1360 hddLog(VOS_TRACE_LEVEL_FATAL,
1361 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
1362 status, status );
1363 goto error_wmm_init;
1364 }
1365
1366 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1367
1368 return VOS_STATUS_SUCCESS;
1369
1370error_wmm_init:
1371 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1372 hdd_deinit_tx_rx(pAdapter);
1373error_init_txrx:
1374 hdd_UnregisterWext(pWlanDev);
1375error_register_wext:
1376 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
1377 {
1378 INIT_COMPLETION(pAdapter->session_close_comp_var);
1379 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
1380 pAdapter->sessionId,
1381 hdd_smeCloseSessionCallback, pAdapter ) )
1382 {
1383 //Block on a completion variable. Can't wait forever though.
1384 wait_for_completion_interruptible_timeout(
1385 &pAdapter->session_close_comp_var,
1386 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1387 }
1388}
1389error_sme_open:
1390 return status;
1391}
1392
Jeff Johnson295189b2012-06-20 16:38:30 -07001393#ifdef CONFIG_CFG80211
1394void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1395{
1396 hdd_cfg80211_state_t *cfgState;
1397
1398 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1399
1400 if( NULL != cfgState->buf )
1401 {
1402 int rc;
1403 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
1404 rc = wait_for_completion_interruptible_timeout(
1405 &pAdapter->tx_action_cnf_event,
1406 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
1407 if(!rc)
1408 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001409 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001410 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
1411 }
1412 }
1413 return;
1414}
1415#endif
1416
1417void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1418{
1419 ENTER();
1420 switch ( pAdapter->device_mode )
1421 {
1422 case WLAN_HDD_INFRA_STATION:
1423 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001424 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001425 {
1426 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1427 {
1428 hdd_deinit_tx_rx( pAdapter );
1429 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1430 }
1431
1432 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
1433 {
1434 hdd_wmm_adapter_close( pAdapter );
1435 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1436 }
1437
1438#ifdef CONFIG_CFG80211
1439 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1440#endif
1441
1442 break;
1443 }
1444
1445 case WLAN_HDD_SOFTAP:
1446 case WLAN_HDD_P2P_GO:
1447#ifdef WLAN_SOFTAP_FEATURE
1448 {
1449#ifdef CONFIG_CFG80211
1450 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1451#endif
1452
1453 hdd_unregister_hostapd(pAdapter);
1454 hdd_set_conparam( 0 );
1455#ifdef CONFIG_CFG80211
1456 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
1457#endif
1458 break;
1459 }
1460
1461 case WLAN_HDD_MONITOR:
1462 {
1463#ifdef CONFIG_CFG80211
1464 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
1465#endif
1466 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1467 {
1468 hdd_deinit_tx_rx( pAdapter );
1469 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1470 }
1471#ifdef CONFIG_CFG80211
1472 if(NULL != pAdapterforTx)
1473 {
1474 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
1475 }
1476#endif
1477#endif //WLAN_SOFTAP_FEATURE
1478 break;
1479 }
1480
1481
1482 default:
1483 break;
1484 }
1485
1486 EXIT();
1487}
1488
1489void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
1490{
1491 struct net_device *pWlanDev = pAdapter->dev;
1492
1493 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
1494 if( rtnl_held )
1495 {
1496 unregister_netdevice(pWlanDev);
1497 }
1498 else
1499 {
1500 unregister_netdev(pWlanDev);
1501 }
1502 // note that the pAdapter is no longer valid at this point
1503 // since the memory has been reclaimed
1504 }
1505
1506}
1507
1508VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
1509{
1510 VOS_STATUS status = VOS_STATUS_SUCCESS;
1511
1512 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
1513 {
1514 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1515 }
1516
1517 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
1518 {
1519 sme_StartAutoBmpsTimer(pHddCtx->hHal);
1520 }
1521
1522 if (pHddCtx->cfg_ini->fIsImpsEnabled)
1523 {
1524 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1525 }
1526
1527 return status;
1528}
1529
1530VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
1531{
1532 hdd_adapter_t *pAdapter = NULL;
1533 eHalStatus halStatus;
1534 VOS_STATUS status = VOS_STATUS_E_INVAL;
1535 v_BOOL_t disableBmps = FALSE;
1536 v_BOOL_t disableImps = FALSE;
1537
1538 switch(session_type)
1539 {
1540 case WLAN_HDD_INFRA_STATION:
1541 case WLAN_HDD_SOFTAP:
1542#ifdef WLAN_FEATURE_P2P
1543 case WLAN_HDD_P2P_CLIENT:
1544 case WLAN_HDD_P2P_GO:
1545#endif
1546 //Exit BMPS -> Is Sta/P2P Client is already connected
1547 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
1548 if((NULL != pAdapter)&&
1549 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1550 {
1551 disableBmps = TRUE;
1552 }
1553
1554 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
1555 if((NULL != pAdapter)&&
1556 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1557 {
1558 disableBmps = TRUE;
1559 }
1560
1561 //Exit both Bmps and Imps incase of Go/SAP Mode
1562 if((WLAN_HDD_SOFTAP == session_type) ||
1563 (WLAN_HDD_P2P_GO == session_type))
1564 {
1565 disableBmps = TRUE;
1566 disableImps = TRUE;
1567 }
1568
1569 if(TRUE == disableImps)
1570 {
1571 if (pHddCtx->cfg_ini->fIsImpsEnabled)
1572 {
1573 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1574 }
1575 }
1576
1577 if(TRUE == disableBmps)
1578 {
1579 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
1580 {
1581 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1582
1583 if(eHAL_STATUS_SUCCESS != halStatus)
1584 {
1585 status = VOS_STATUS_E_FAILURE;
1586 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
1587 VOS_ASSERT(0);
1588 return status;
1589 }
1590 }
1591
1592 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
1593 {
1594 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
1595
1596 if(eHAL_STATUS_SUCCESS != halStatus)
1597 {
1598 status = VOS_STATUS_E_FAILURE;
1599 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
1600 VOS_ASSERT(0);
1601 return status;
1602 }
1603 }
1604 }
1605
1606 if((TRUE == disableBmps) ||
1607 (TRUE == disableImps))
1608 {
1609 /* Now, get the chip into Full Power now */
1610 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
1611 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
1612 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
1613
1614 if(halStatus != eHAL_STATUS_SUCCESS)
1615 {
1616 if(halStatus == eHAL_STATUS_PMC_PENDING)
1617 {
1618 //Block on a completion variable. Can't wait forever though
1619 wait_for_completion_interruptible_timeout(
1620 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
1621 }
1622 else
1623 {
1624 status = VOS_STATUS_E_FAILURE;
1625 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
1626 VOS_ASSERT(0);
1627 return status;
1628 }
1629 }
1630
1631 status = VOS_STATUS_SUCCESS;
1632 }
1633
1634 break;
1635 }
1636 return status;
1637}
1638
1639hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08001640 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07001641 tANI_U8 rtnl_held )
1642{
1643 hdd_adapter_t *pAdapter = NULL;
1644 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
1645 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1646 VOS_STATUS exitbmpsStatus;
1647
1648 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
1649
1650 //Disable BMPS incase of Concurrency
1651 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
1652
1653 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
1654 {
1655 //Fail to Exit BMPS
1656 VOS_ASSERT(0);
1657 return NULL;
1658 }
1659
1660 switch(session_type)
1661 {
1662 case WLAN_HDD_INFRA_STATION:
1663#ifdef WLAN_FEATURE_P2P
1664 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001665 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001666#endif
1667 {
1668 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
1669
1670 if( NULL == pAdapter )
1671 return NULL;
1672
1673#ifdef CONFIG_CFG80211
Jeff Johnsone7245742012-09-05 17:12:55 -07001674 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
1675 NL80211_IFTYPE_P2P_CLIENT:
1676 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07001677#endif
1678
Jeff Johnson295189b2012-06-20 16:38:30 -07001679 pAdapter->device_mode = session_type;
1680
1681 status = hdd_init_station_mode( pAdapter );
1682 if( VOS_STATUS_SUCCESS != status )
1683 goto err_free_netdev;
1684
1685 status = hdd_register_interface( pAdapter, rtnl_held );
1686 if( VOS_STATUS_SUCCESS != status )
1687 {
1688 hdd_deinit_adapter(pHddCtx, pAdapter);
1689 goto err_free_netdev;
1690 }
1691 //Stop the Interface TX queue.
1692 netif_tx_disable(pAdapter->dev);
1693 //netif_tx_disable(pWlanDev);
1694 netif_carrier_off(pAdapter->dev);
1695
1696 break;
1697 }
1698
1699#ifdef WLAN_FEATURE_P2P
1700 case WLAN_HDD_P2P_GO:
1701#endif
1702 case WLAN_HDD_SOFTAP:
1703 {
1704 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
1705 if( NULL == pAdapter )
1706 return NULL;
1707
1708#ifdef CONFIG_CFG80211
1709 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
1710 NL80211_IFTYPE_AP:
1711 NL80211_IFTYPE_P2P_GO;
1712#endif
1713 pAdapter->device_mode = session_type;
1714
1715 status = hdd_init_ap_mode(pAdapter);
1716 if( VOS_STATUS_SUCCESS != status )
1717 goto err_free_netdev;
1718
1719 status = hdd_register_hostapd( pAdapter, rtnl_held );
1720 if( VOS_STATUS_SUCCESS != status )
1721 {
1722 hdd_deinit_adapter(pHddCtx, pAdapter);
1723 goto err_free_netdev;
1724 }
1725
1726 netif_tx_disable(pAdapter->dev);
1727 netif_carrier_off(pAdapter->dev);
1728
1729 hdd_set_conparam( 1 );
1730 break;
1731 }
1732 case WLAN_HDD_MONITOR:
1733 {
1734#ifdef CONFIG_CFG80211
1735 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
1736 if( NULL == pAdapter )
1737 return NULL;
1738
1739 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
1740 pAdapter->device_mode = session_type;
1741 status = hdd_register_interface( pAdapter, rtnl_held );
1742#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
1743 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
1744#else
1745 pAdapter->dev->open = hdd_mon_open;
1746 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
1747#endif
1748 hdd_init_tx_rx( pAdapter );
1749 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1750 //Set adapter to be used for data tx. It will use either GO or softap.
1751 pAdapter->sessionCtx.monitor.pAdapterForTx =
1752 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
1753#ifdef WLAN_FEATURE_P2P
1754 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
1755 {
1756 pAdapter->sessionCtx.monitor.pAdapterForTx =
1757 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
1758 }
1759#endif
1760 /* This workqueue will be used to transmit management packet over
1761 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07001762 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
1763 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
1764 return NULL;
1765 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07001766
Jeff Johnson295189b2012-06-20 16:38:30 -07001767 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
1768 hdd_mon_tx_work_queue);
1769#endif
1770 }
1771 break;
1772#ifdef ANI_MANF_DIAG
1773 case WLAN_HDD_FTM:
1774 {
1775 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
1776
1777 if( NULL == pAdapter )
1778 return NULL;
1779 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
1780 * message while loading driver in FTM mode. */
1781 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
1782 pAdapter->device_mode = session_type;
1783 status = hdd_register_interface( pAdapter, rtnl_held );
1784 }
1785 break;
1786#endif
1787 default:
1788 {
1789 VOS_ASSERT(0);
1790 return NULL;
1791 }
1792 }
1793
1794
1795 if( VOS_STATUS_SUCCESS == status )
1796 {
1797 //Add it to the hdd's session list.
1798 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
1799 if( NULL == pHddAdapterNode )
1800 {
1801 status = VOS_STATUS_E_NOMEM;
1802 }
1803 else
1804 {
1805 pHddAdapterNode->pAdapter = pAdapter;
1806 status = hdd_add_adapter_back ( pHddCtx,
1807 pHddAdapterNode );
1808 }
1809 }
1810
1811 if( VOS_STATUS_SUCCESS != status )
1812 {
1813 if( NULL != pAdapter )
1814 {
1815 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
1816 pAdapter = NULL;
1817 }
1818 if( NULL != pHddAdapterNode )
1819 {
1820 vos_mem_free( pHddAdapterNode );
1821 }
1822
1823 goto resume_bmps;
1824 }
1825
1826 if(VOS_STATUS_SUCCESS == status)
1827 {
1828 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
1829
1830#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1831 /* If there are concurrent session enable SW frame translation
1832 * for all registered STA
1833 * This is not required in case of PRIMA as HW frame translation
1834 * is disabled in PRIMA*/
1835 if (vos_concurrent_sessions_running())
1836 {
1837 WLANTL_ConfigureSwFrameTXXlationForAll(pHddCtx->pvosContext, TRUE);
1838 }
1839#endif
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07001840 //Initialize the WoWL service
1841 if(!hdd_init_wowl(pAdapter))
1842 {
1843 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
1844 goto err_free_netdev;
1845 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001846 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001847 return pAdapter;
1848
1849err_free_netdev:
1850 free_netdev(pAdapter->dev);
1851 wlan_hdd_release_intf_addr( pHddCtx,
1852 pAdapter->macAddressCurrent.bytes );
1853
1854resume_bmps:
1855 //If bmps disabled enable it
1856 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
1857 {
1858 hdd_enable_bmps_imps(pHddCtx);
1859 }
1860 return NULL;
1861}
1862
1863VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
1864 tANI_U8 rtnl_held )
1865{
1866 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
1867 VOS_STATUS status;
1868
1869 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
1870 if( VOS_STATUS_SUCCESS != status )
1871 return status;
1872
1873 while ( pCurrent->pAdapter != pAdapter )
1874 {
1875 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
1876 if( VOS_STATUS_SUCCESS != status )
1877 break;
1878
1879 pCurrent = pNext;
1880 }
1881 pAdapterNode = pCurrent;
1882 if( VOS_STATUS_SUCCESS == status )
1883 {
1884 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
1885 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
1886 hdd_remove_adapter( pHddCtx, pAdapterNode );
1887 vos_mem_free( pAdapterNode );
1888
1889#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1890 /* If there is no concurrent session disable SW frame translation
1891 * for all registered STA */
1892 /* This is not required in case of PRIMA as HW frame translation
1893 * is disabled in PRIMA*/
1894 if (!vos_concurrent_sessions_running())
1895 {
1896 WLANTL_ConfigureSwFrameTXXlationForAll(pHddCtx->pvosContext, FALSE);
1897 }
1898#endif
1899
1900 /* If there is a single session of STA/P2P client, re-enable BMPS */
1901 if ((!vos_concurrent_sessions_running()) &&
1902 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
1903 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
1904 {
1905 hdd_enable_bmps_imps(pHddCtx);
1906 }
1907
1908 return VOS_STATUS_SUCCESS;
1909 }
1910
1911 return VOS_STATUS_E_FAILURE;
1912}
1913
1914VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
1915{
1916 hdd_adapter_list_node_t *pHddAdapterNode;
1917 VOS_STATUS status;
1918
1919 ENTER();
1920
1921 do
1922 {
1923 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
1924 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
1925 {
1926 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
1927 vos_mem_free( pHddAdapterNode );
1928 }
1929 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
1930
1931 EXIT();
1932
1933 return VOS_STATUS_SUCCESS;
1934}
1935
1936void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
1937{
1938 v_U8_t addIE[1] = {0};
1939
1940 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1941 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
1942 eANI_BOOLEAN_FALSE) )
1943 {
1944 hddLog(LOGE,
1945 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
1946 }
1947
1948 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1949 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1950 eANI_BOOLEAN_FALSE) )
1951 {
1952 hddLog(LOGE,
1953 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1954 }
1955
1956 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1957 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1958 eANI_BOOLEAN_FALSE) )
1959 {
1960 hddLog(LOGE,
1961 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1962 }
1963}
1964
1965VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1966{
1967 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1968 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1969 union iwreq_data wrqu;
1970
1971 ENTER();
1972
1973 switch(pAdapter->device_mode)
1974 {
1975 case WLAN_HDD_INFRA_STATION:
1976 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001977 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001978 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
1979 {
1980 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
1981 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
1982 pAdapter->sessionId,
1983 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
1984 else
1985 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
1986 pAdapter->sessionId,
1987 eCSR_DISCONNECT_REASON_UNSPECIFIED);
1988 //success implies disconnect command got queued up successfully
1989 if(halStatus == eHAL_STATUS_SUCCESS)
1990 {
1991 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
1992 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
1993 }
1994 memset(&wrqu, '\0', sizeof(wrqu));
1995 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1996 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
1997 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
1998 }
1999 else
2000 {
2001 hdd_abort_mac_scan(pHddCtx);
2002 }
2003
2004 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2005 {
2006 INIT_COMPLETION(pAdapter->session_close_comp_var);
2007 if (eHAL_STATUS_SUCCESS ==
2008 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
2009 hdd_smeCloseSessionCallback, pAdapter))
2010 {
2011 //Block on a completion variable. Can't wait forever though.
2012 wait_for_completion_interruptible_timeout(
2013 &pAdapter->session_close_comp_var,
2014 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2015 }
2016 }
2017
2018 break;
2019
2020 case WLAN_HDD_SOFTAP:
2021 case WLAN_HDD_P2P_GO:
2022 //Any softap specific cleanup here...
2023 mutex_lock(&pHddCtx->sap_lock);
2024 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2025 {
2026 VOS_STATUS status;
2027 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2028
2029 //Stop Bss.
2030 status = WLANSAP_StopBss(pHddCtx->pvosContext);
2031 if (VOS_IS_STATUS_SUCCESS(status))
2032 {
2033 hdd_hostapd_state_t *pHostapdState =
2034 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2035
2036 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2037
2038 if (!VOS_IS_STATUS_SUCCESS(status))
2039 {
2040 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002041 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002042 }
2043 }
2044 else
2045 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002046 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002047 }
2048 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2049
2050 if (eHAL_STATUS_FAILURE ==
2051 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
2052 0, NULL, eANI_BOOLEAN_FALSE))
2053 {
2054 hddLog(LOGE,
2055 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002056 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002057 }
2058
2059 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2060 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2061 eANI_BOOLEAN_FALSE) )
2062 {
2063 hddLog(LOGE,
2064 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
2065 }
2066
2067 // Reset WNI_CFG_PROBE_RSP Flags
2068 wlan_hdd_reset_prob_rspies(pAdapter);
2069 kfree(pAdapter->sessionCtx.ap.beacon);
2070 pAdapter->sessionCtx.ap.beacon = NULL;
2071 }
2072 mutex_unlock(&pHddCtx->sap_lock);
2073 break;
2074 case WLAN_HDD_MONITOR:
2075 break;
2076 default:
2077 break;
2078 }
2079
2080 EXIT();
2081 return VOS_STATUS_SUCCESS;
2082}
2083
2084VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
2085{
2086 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2087 VOS_STATUS status;
2088 hdd_adapter_t *pAdapter;
2089
2090 ENTER();
2091
2092 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2093
2094 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2095 {
2096 pAdapter = pAdapterNode->pAdapter;
2097 netif_tx_disable(pAdapter->dev);
2098 netif_carrier_off(pAdapter->dev);
2099
2100 hdd_stop_adapter( pHddCtx, pAdapter );
2101
2102 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2103 pAdapterNode = pNext;
2104 }
2105
2106 EXIT();
2107
2108 return VOS_STATUS_SUCCESS;
2109}
2110
2111VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
2112{
2113 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2114 VOS_STATUS status;
2115 hdd_adapter_t *pAdapter;
2116
2117 ENTER();
2118
2119 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2120
2121 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2122 {
2123 pAdapter = pAdapterNode->pAdapter;
2124 netif_tx_disable(pAdapter->dev);
2125 netif_carrier_off(pAdapter->dev);
2126
2127 //Record whether STA is associated
2128 pAdapter->sessionCtx.station.bSendDisconnect =
2129 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
2130 VOS_TRUE : VOS_FALSE;
2131
2132 hdd_deinit_tx_rx(pAdapter);
2133 hdd_wmm_adapter_close(pAdapter);
2134
2135 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2136 pAdapterNode = pNext;
2137 }
2138
2139 EXIT();
2140
2141 return VOS_STATUS_SUCCESS;
2142}
2143
2144VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
2145{
2146 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2147 VOS_STATUS status;
2148 hdd_adapter_t *pAdapter;
2149 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
2150
2151 ENTER();
2152
2153 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2154
2155 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2156 {
2157 pAdapter = pAdapterNode->pAdapter;
2158
2159 switch(pAdapter->device_mode)
2160 {
2161 case WLAN_HDD_INFRA_STATION:
2162 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002163 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002164 hdd_init_station_mode(pAdapter);
2165 /* Open the gates for HDD to receive Wext commands */
2166 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002167 pHddCtx->scan_info.mScanPending = FALSE;
2168 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002169
2170 //Trigger the initial scan
2171 hdd_wlan_initial_scan(pAdapter);
2172
2173 //Indicate disconnect event to supplicant if associated previously
2174 if(pAdapter->sessionCtx.station.bSendDisconnect)
2175 {
2176 union iwreq_data wrqu;
2177 memset(&wrqu, '\0', sizeof(wrqu));
2178 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2179 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2180 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2181 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
2182
2183#ifdef CONFIG_CFG80211
2184 /* indicate disconnected event to nl80211 */
2185 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
2186 NULL, 0, GFP_KERNEL);
2187#endif
2188 }
2189 break;
2190
2191 case WLAN_HDD_SOFTAP:
2192 /* softAP can handle SSR */
2193 break;
2194
2195 case WLAN_HDD_P2P_GO:
2196#ifdef CONFIG_CFG80211
2197 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
2198 __func__);
2199 /* event supplicant to restart */
2200 cfg80211_del_sta(pAdapter->dev,
2201 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
2202#endif
2203 break;
2204
2205 case WLAN_HDD_MONITOR:
2206 /* monitor interface start */
2207 break;
2208 default:
2209 break;
2210 }
2211
2212 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2213 pAdapterNode = pNext;
2214 }
2215
2216 EXIT();
2217
2218 return VOS_STATUS_SUCCESS;
2219}
2220
2221VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
2222{
2223 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2224 hdd_adapter_t *pAdapter;
2225 VOS_STATUS status;
2226 v_U32_t roamId;
2227
2228 ENTER();
2229
2230 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2231
2232 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2233 {
2234 pAdapter = pAdapterNode->pAdapter;
2235
2236 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2237 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
2238 {
2239 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2240 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2241
2242 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2243 init_completion(&pAdapter->disconnect_comp_var);
2244 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
2245 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2246
2247 wait_for_completion_interruptible_timeout(
2248 &pAdapter->disconnect_comp_var,
2249 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2250
2251 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
2252 pHddCtx->isAmpAllowed = VOS_FALSE;
2253 sme_RoamConnect(pHddCtx->hHal,
2254 pAdapter->sessionId, &(pWextState->roamProfile),
2255 &roamId);
2256 }
2257
2258 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2259 pAdapterNode = pNext;
2260 }
2261
2262 EXIT();
2263
2264 return VOS_STATUS_SUCCESS;
2265}
2266
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002267bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07002268{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002269 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07002270}
2271
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002272/* Once SSR is disabled then it cannot be set. */
2273void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07002274{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002275 if (HDD_SSR_DISABLED == isSsrRequired)
2276 return;
2277
Jeff Johnson295189b2012-06-20 16:38:30 -07002278 isSsrRequired = value;
2279}
2280
2281VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
2282 hdd_adapter_list_node_t** ppAdapterNode)
2283{
2284 VOS_STATUS status;
2285 spin_lock(&pHddCtx->hddAdapters.lock);
2286 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
2287 (hdd_list_node_t**) ppAdapterNode );
2288 spin_unlock(&pHddCtx->hddAdapters.lock);
2289 return status;
2290}
2291
2292VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
2293 hdd_adapter_list_node_t* pAdapterNode,
2294 hdd_adapter_list_node_t** pNextAdapterNode)
2295{
2296 VOS_STATUS status;
2297 spin_lock(&pHddCtx->hddAdapters.lock);
2298 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
2299 (hdd_list_node_t*) pAdapterNode,
2300 (hdd_list_node_t**)pNextAdapterNode );
2301
2302 spin_unlock(&pHddCtx->hddAdapters.lock);
2303 return status;
2304}
2305
2306VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
2307 hdd_adapter_list_node_t* pAdapterNode)
2308{
2309 VOS_STATUS status;
2310 spin_lock(&pHddCtx->hddAdapters.lock);
2311 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
2312 &pAdapterNode->node );
2313 spin_unlock(&pHddCtx->hddAdapters.lock);
2314 return status;
2315}
2316
2317VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
2318 hdd_adapter_list_node_t** ppAdapterNode)
2319{
2320 VOS_STATUS status;
2321 spin_lock(&pHddCtx->hddAdapters.lock);
2322 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
2323 (hdd_list_node_t**) ppAdapterNode );
2324 spin_unlock(&pHddCtx->hddAdapters.lock);
2325 return status;
2326}
2327
2328VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
2329 hdd_adapter_list_node_t* pAdapterNode)
2330{
2331 VOS_STATUS status;
2332 spin_lock(&pHddCtx->hddAdapters.lock);
2333 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
2334 (hdd_list_node_t*) pAdapterNode );
2335 spin_unlock(&pHddCtx->hddAdapters.lock);
2336 return status;
2337}
2338
2339VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
2340 hdd_adapter_list_node_t* pAdapterNode)
2341{
2342 VOS_STATUS status;
2343 spin_lock(&pHddCtx->hddAdapters.lock);
2344 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
2345 (hdd_list_node_t*) pAdapterNode );
2346 spin_unlock(&pHddCtx->hddAdapters.lock);
2347 return status;
2348}
2349
2350hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
2351 tSirMacAddr macAddr )
2352{
2353 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2354 hdd_adapter_t *pAdapter;
2355 VOS_STATUS status;
2356
2357 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2358
2359 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2360 {
2361 pAdapter = pAdapterNode->pAdapter;
2362
2363 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
2364 macAddr, sizeof(tSirMacAddr) ) )
2365 {
2366 return pAdapter;
2367 }
2368 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2369 pAdapterNode = pNext;
2370 }
2371
2372 return NULL;
2373
2374}
2375
2376hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
2377{
2378 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2379 hdd_adapter_t *pAdapter;
2380 VOS_STATUS status;
2381
2382 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2383
2384 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2385 {
2386 pAdapter = pAdapterNode->pAdapter;
2387
2388 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
2389 IFNAMSIZ ) )
2390 {
2391 return pAdapter;
2392 }
2393 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2394 pAdapterNode = pNext;
2395 }
2396
2397 return NULL;
2398
2399}
2400
2401hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
2402{
2403 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2404 hdd_adapter_t *pAdapter;
2405 VOS_STATUS status;
2406
2407 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2408
2409 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2410 {
2411 pAdapter = pAdapterNode->pAdapter;
2412
2413 if( pAdapter && (mode == pAdapter->device_mode) )
2414 {
2415 return pAdapter;
2416 }
2417 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2418 pAdapterNode = pNext;
2419 }
2420
2421 return NULL;
2422
2423}
2424
2425//Remove this function later
2426hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
2427{
2428 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2429 hdd_adapter_t *pAdapter;
2430 VOS_STATUS status;
2431
2432 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2433
2434 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2435 {
2436 pAdapter = pAdapterNode->pAdapter;
2437
2438 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
2439 {
2440 return pAdapter;
2441 }
2442
2443 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2444 pAdapterNode = pNext;
2445 }
2446
2447 return NULL;
2448
2449}
2450
2451#ifdef CONFIG_CFG80211
2452/**---------------------------------------------------------------------------
2453
2454 \brief hdd_set_monitor_tx_adapter() -
2455
2456 This API initializes the adapter to be used while transmitting on monitor
2457 adapter.
2458
2459 \param - pHddCtx - Pointer to the HDD context.
2460 pAdapter - Adapter that will used for TX. This can be NULL.
2461 \return - None.
2462 --------------------------------------------------------------------------*/
2463void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2464{
2465 hdd_adapter_t *pMonAdapter;
2466
2467 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
2468
2469 if( NULL != pMonAdapter )
2470 {
2471 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
2472 }
2473}
2474#endif
2475/**---------------------------------------------------------------------------
2476
2477 \brief hdd_select_queue() -
2478
2479 This API returns the operating channel of the requested device mode
2480
2481 \param - pHddCtx - Pointer to the HDD context.
2482 - mode - Device mode for which operating channel is required
2483 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
2484 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
2485 \return - channel number. "0" id the requested device is not found OR it is not connected.
2486 --------------------------------------------------------------------------*/
2487v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
2488{
2489 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2490 VOS_STATUS status;
2491 hdd_adapter_t *pAdapter;
2492 v_U8_t operatingChannel = 0;
2493
2494 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2495
2496 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2497 {
2498 pAdapter = pAdapterNode->pAdapter;
2499
2500 if( mode == pAdapter->device_mode )
2501 {
2502 switch(pAdapter->device_mode)
2503 {
2504 case WLAN_HDD_INFRA_STATION:
2505 case WLAN_HDD_P2P_CLIENT:
2506 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
2507 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
2508 break;
2509 case WLAN_HDD_SOFTAP:
2510 case WLAN_HDD_P2P_GO:
2511 /*softap connection info */
2512 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2513 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
2514 break;
2515 default:
2516 break;
2517 }
2518
2519 break; //Found the device of interest. break the loop
2520 }
2521
2522 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2523 pAdapterNode = pNext;
2524 }
2525 return operatingChannel;
2526}
2527
2528#ifdef WLAN_FEATURE_PACKET_FILTERING
2529/**---------------------------------------------------------------------------
2530
2531 \brief hdd_set_multicast_list() -
2532
2533 This used to set the multicast address list.
2534
2535 \param - dev - Pointer to the WLAN device.
2536 - skb - Pointer to OS packet (sk_buff).
2537 \return - success/fail
2538
2539 --------------------------------------------------------------------------*/
2540static void hdd_set_multicast_list(struct net_device *dev)
2541{
2542 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2543 hdd_context_t *pHddCtx;
2544 int mc_count;
2545 int i = 0;
2546 struct netdev_hw_addr *ha;
2547 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2548 if (NULL == pHddCtx)
2549 {
2550 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002551 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002552 return;
2553 }
2554
2555 if (dev->flags & IFF_ALLMULTI)
2556 {
2557 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002558 "%s: allow all multicast frames", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002559 pHddCtx->mc_addr_list.mc_cnt = 0;
2560 }
2561 else
2562 {
2563 mc_count = netdev_mc_count(dev);
2564 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002565 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07002566 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
2567 {
2568 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002569 "%s: No free filter available; allow all multicast frames", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002570 pHddCtx->mc_addr_list.mc_cnt = 0;
2571 return;
2572 }
2573
2574 pHddCtx->mc_addr_list.mc_cnt = mc_count;
2575
2576 netdev_for_each_mc_addr(ha, dev) {
2577 if (i == mc_count)
2578 break;
2579 memset(&(pHddCtx->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
2580 memcpy(&(pHddCtx->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
2581 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = %02x:%02x:%02x:%02x:%02x:%02x",
2582 __func__, i,
2583 pHddCtx->mc_addr_list.addr[i][0], pHddCtx->mc_addr_list.addr[i][1],
2584 pHddCtx->mc_addr_list.addr[i][2], pHddCtx->mc_addr_list.addr[i][3],
2585 pHddCtx->mc_addr_list.addr[i][4], pHddCtx->mc_addr_list.addr[i][5]);
2586 i++;
2587 }
2588 }
2589 return;
2590}
2591#endif
2592
2593/**---------------------------------------------------------------------------
2594
2595 \brief hdd_select_queue() -
2596
2597 This function is registered with the Linux OS for network
2598 core to decide which queue to use first.
2599
2600 \param - dev - Pointer to the WLAN device.
2601 - skb - Pointer to OS packet (sk_buff).
2602 \return - ac, Queue Index/access category corresponding to UP in IP header
2603
2604 --------------------------------------------------------------------------*/
2605v_U16_t hdd_select_queue(struct net_device *dev,
2606 struct sk_buff *skb)
2607{
2608 return hdd_wmm_select_queue(dev, skb);
2609}
2610
2611
2612/**---------------------------------------------------------------------------
2613
2614 \brief hdd_wlan_initial_scan() -
2615
2616 This function triggers the initial scan
2617
2618 \param - pAdapter - Pointer to the HDD adapter.
2619
2620 --------------------------------------------------------------------------*/
2621void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
2622{
2623 tCsrScanRequest scanReq;
2624 tCsrChannelInfo channelInfo;
2625 eHalStatus halStatus;
2626 unsigned long scanId;
2627 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2628
2629 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
2630 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
2631 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
2632
2633 if(sme_Is11dSupported(pHddCtx->hHal))
2634 {
2635 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
2636 if ( HAL_STATUS_SUCCESS( halStatus ) )
2637 {
2638 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
2639 if( !scanReq.ChannelInfo.ChannelList )
2640 {
2641 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
2642 vos_mem_free(channelInfo.ChannelList);
2643 return;
2644 }
2645 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
2646 channelInfo.numOfChannels);
2647 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
2648 vos_mem_free(channelInfo.ChannelList);
2649 }
2650
2651 scanReq.scanType = eSIR_PASSIVE_SCAN;
2652 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
2653 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
2654 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
2655 }
2656 else
2657 {
2658 scanReq.scanType = eSIR_ACTIVE_SCAN;
2659 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
2660 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
2661 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
2662 }
2663
2664 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
2665 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2666 {
2667 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
2668 __func__, halStatus );
2669 }
2670
2671 if(sme_Is11dSupported(pHddCtx->hHal))
2672 vos_mem_free(scanReq.ChannelInfo.ChannelList);
2673}
2674
2675struct fullPowerContext
2676{
2677 struct completion completion;
2678 unsigned int magic;
2679};
2680#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
2681
2682/**---------------------------------------------------------------------------
2683
2684 \brief hdd_full_power_callback() - HDD full power callback function
2685
2686 This is the function invoked by SME to inform the result of a full power
2687 request issued by HDD
2688
2689 \param - callbackcontext - Pointer to cookie
2690 \param - status - result of request
2691
2692 \return - None
2693
2694 --------------------------------------------------------------------------*/
2695static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
2696{
2697 struct fullPowerContext *pContext = callbackContext;
2698
2699 hddLog(VOS_TRACE_LEVEL_INFO,
2700 "%s: context = %p, status = %d", pContext, status);
2701
2702 if (NULL == callbackContext)
2703 {
2704 hddLog(VOS_TRACE_LEVEL_ERROR,
2705 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002706 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07002707 return;
2708 }
2709
2710 /* there is a race condition that exists between this callback function
2711 and the caller since the caller could time out either before or
2712 while this code is executing. we'll assume the timeout hasn't
2713 occurred, but we'll verify that right before we save our work */
2714
2715 if (POWER_CONTEXT_MAGIC != pContext->magic)
2716 {
2717 /* the caller presumably timed out so there is nothing we can do */
2718 hddLog(VOS_TRACE_LEVEL_WARN,
2719 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002720 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07002721 return;
2722 }
2723
2724 /* the race is on. caller could have timed out immediately after
2725 we verified the magic, but if so, caller will wait a short time
2726 for us to notify the caller, so the context will stay valid */
2727 complete(&pContext->completion);
2728}
2729
2730/**---------------------------------------------------------------------------
2731
2732 \brief hdd_wlan_exit() - HDD WLAN exit function
2733
2734 This is the driver exit point (invoked during rmmod)
2735
2736 \param - pHddCtx - Pointer to the HDD Context
2737
2738 \return - None
2739
2740 --------------------------------------------------------------------------*/
2741void hdd_wlan_exit(hdd_context_t *pHddCtx)
2742{
2743 eHalStatus halStatus;
2744 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
2745 VOS_STATUS vosStatus;
2746#ifdef ANI_BUS_TYPE_SDIO
2747 struct sdio_func *sdio_func_dev = NULL;
2748#endif // ANI_BUS_TYPE_SDIO
2749#ifdef CONFIG_CFG80211
2750 struct wiphy *wiphy = pHddCtx->wiphy;
2751#endif
2752#ifdef FEATURE_WLAN_INTEGRATED_SOC
2753 hdd_adapter_t* pAdapter;
2754#endif
2755 struct fullPowerContext powerContext;
2756 long lrc;
2757
2758 ENTER();
2759
Ng Chilam1322ea32012-12-27 17:33:08 -08002760#ifdef ANI_MANF_DIAG
2761 if (VOS_FTM_MODE != hdd_get_conparam())
2762#endif /* ANI_MANF_DIAG */
2763 {
2764 // Unloading, restart logic is no more required.
2765 wlan_hdd_restart_deinit(pHddCtx);
2766 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002767
Jeff Johnson295189b2012-06-20 16:38:30 -07002768#ifdef CONFIG_CFG80211
2769#ifdef WLAN_SOFTAP_FEATURE
2770 if (VOS_STA_SAP_MODE != hdd_get_conparam())
2771#endif
2772 {
2773#ifdef ANI_MANF_DIAG
2774 if (VOS_FTM_MODE != hdd_get_conparam())
2775#endif /* ANI_MANF_DIAG */
2776 {
2777 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
2778 WLAN_HDD_INFRA_STATION);
2779 if (pAdapter == NULL)
2780 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2781
2782 if (pAdapter != NULL)
2783 {
2784 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
2785 hdd_UnregisterWext(pAdapter->dev);
2786 }
2787 }
2788 }
2789#endif
2790
2791#ifdef ANI_MANF_DIAG
2792 if (VOS_FTM_MODE == hdd_get_conparam())
2793 {
2794 wlan_hdd_ftm_close(pHddCtx);
2795 goto free_hdd_ctx;
2796 }
2797#endif
2798 //Stop the Interface TX queue.
2799 //netif_tx_disable(pWlanDev);
2800 //netif_carrier_off(pWlanDev);
2801
Jeff Johnson295189b2012-06-20 16:38:30 -07002802#ifdef FEATURE_WLAN_INTEGRATED_SOC
2803#ifdef WLAN_SOFTAP_FEATURE
2804 if (VOS_STA_SAP_MODE == hdd_get_conparam())
2805 {
2806 pAdapter = hdd_get_adapter(pHddCtx,
2807 WLAN_HDD_SOFTAP);
2808 }
2809 else
2810 {
2811#endif
2812#ifdef ANI_MANF_DIAG
2813 if (VOS_FTM_MODE != hdd_get_conparam())
2814#endif /* ANI_MANF_DIAG */
2815 {
2816 pAdapter = hdd_get_adapter(pHddCtx,
2817 WLAN_HDD_INFRA_STATION);
2818 }
2819#ifdef WLAN_SOFTAP_FEATURE
2820 }
2821#endif
2822 /* DeRegister with platform driver as client for Suspend/Resume */
2823 vosStatus = hddDeregisterPmOps(pHddCtx);
2824 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2825 {
2826 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
2827 VOS_ASSERT(0);
2828 }
2829
2830 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
2831 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2832 {
2833 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
2834 }
2835#endif //FEATURE_WLAN_INTEGRATED_SOC
2836
Chilam NG571c65a2013-01-19 12:27:36 +05302837#ifdef FEATURE_WLAN_TDLS
2838 wlan_hdd_tdls_exit();
2839#endif
2840
Jeff Johnson295189b2012-06-20 16:38:30 -07002841 // Cancel any outstanding scan requests. We are about to close all
2842 // of our adapters, but an adapter structure is what SME passes back
2843 // to our callback function. Hence if there are any outstanding scan
2844 // requests then there is a race condition between when the adapter
2845 // is closed and when the callback is invoked. We try to resolve that
2846 // race condition here by canceling any outstanding scans before we
2847 // close the adapters.
2848 // Note that the scans may be cancelled in an asynchronous manner, so
2849 // ideally there needs to be some kind of synchronization. Rather than
2850 // introduce a new synchronization here, we will utilize the fact that
2851 // we are about to Request Full Power, and since that is synchronized,
2852 // the expectation is that by the time Request Full Power has completed,
2853 // all scans will be cancelled.
2854 hdd_abort_mac_scan( pHddCtx );
2855
2856 //Disable IMPS/BMPS as we do not want the device to enter any power
2857 //save mode during shutdown
2858 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2859 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2860 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
2861
2862 //Ensure that device is in full power as we will touch H/W during vos_Stop
2863 init_completion(&powerContext.completion);
2864 powerContext.magic = POWER_CONTEXT_MAGIC;
2865
2866 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
2867 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
2868
2869 if (eHAL_STATUS_SUCCESS != halStatus)
2870 {
2871 if (eHAL_STATUS_PMC_PENDING == halStatus)
2872 {
2873 /* request was sent -- wait for the response */
2874 lrc = wait_for_completion_interruptible_timeout(
2875 &powerContext.completion,
2876 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
2877 /* either we have a response or we timed out
2878 either way, first invalidate our magic */
2879 powerContext.magic = 0;
2880 if (lrc <= 0)
2881 {
2882 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002883 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07002884 /* there is a race condition such that the callback
2885 function could be executing at the same time we are. of
2886 primary concern is if the callback function had already
2887 verified the "magic" but hasn't yet set the completion
2888 variable. Since the completion variable is on our
2889 stack, we'll delay just a bit to make sure the data is
2890 still valid if that is the case */
2891 msleep(50);
2892 }
2893 }
2894 else
2895 {
2896 hddLog(VOS_TRACE_LEVEL_ERROR,
2897 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002898 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07002899 VOS_ASSERT(0);
2900 /* continue -- need to clean up as much as possible */
2901 }
2902 }
2903
2904 // Unregister the Net Device Notifier
2905 unregister_netdevice_notifier(&hdd_netdev_notifier);
2906
Jeff Johnson295189b2012-06-20 16:38:30 -07002907 hdd_stop_all_adapters( pHddCtx );
2908
2909#ifdef ANI_BUS_TYPE_SDIO
2910 sdio_func_dev = libra_getsdio_funcdev();
2911
2912 if(sdio_func_dev == NULL)
2913 {
2914 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
2915 VOS_ASSERT(0);
2916 return;
2917 }
2918
2919 sd_claim_host(sdio_func_dev);
2920
2921 /* Disable SDIO IRQ since we are exiting */
2922 libra_enable_sdio_irq(sdio_func_dev, 0);
2923
2924 sd_release_host(sdio_func_dev);
2925#endif // ANI_BUS_TYPE_SDIO
2926
2927#ifdef WLAN_BTAMP_FEATURE
2928 vosStatus = WLANBAP_Stop(pVosContext);
2929 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2930 {
2931 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2932 "%s: Failed to stop BAP",__func__);
2933 }
2934#endif //WLAN_BTAMP_FEATURE
2935
2936 //Stop all the modules
2937 vosStatus = vos_stop( pVosContext );
2938 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2939 {
2940 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2941 "%s: Failed to stop VOSS",__func__);
2942 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2943 }
2944
2945#ifdef ANI_BUS_TYPE_SDIO
2946 vosStatus = WLANBAL_Stop( pVosContext );
2947
2948 hddLog(VOS_TRACE_LEVEL_ERROR,"WLAN BAL STOP\n");
2949 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2950 {
2951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2952 "%s: Failed to stop BAL",__func__);
2953 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2954 }
2955
2956 msleep(50);
2957 //Put the chip is standby before asserting deep sleep
2958 vosStatus = WLANBAL_SuspendChip( pVosContext );
2959
2960 hddLog(VOS_TRACE_LEVEL_ERROR,"WLAN Suspend Chip\n");
2961
2962 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2963 {
2964 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2965 "%s: Failed to suspend chip ",__func__);
2966 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2967 }
2968 //Invoke SAL stop
2969 vosStatus = WLANSAL_Stop( pVosContext );
2970 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2971 {
2972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2973 "%s: Failed to stop SAL",__func__);
2974 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2975 }
2976
2977#endif // ANI_BUS_TYPE_SDIO
2978
2979 //Assert Deep sleep signal now to put Libra HW in lowest power state
2980 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
2981 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2982
2983 //Vote off any PMIC voltage supplies
2984 vos_chipPowerDown(NULL, NULL, NULL);
2985
2986 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
2987
2988 //Clean up HDD Nlink Service
2989 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2990 nl_srv_exit();
2991
2992 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07002993 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002994
2995 //Close the scheduler before calling vos_close to make sure no thread is
2996 // scheduled after the each module close is called i.e after all the data
2997 // structures are freed.
2998 vosStatus = vos_sched_close( pVosContext );
2999 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
3000 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3001 "%s: Failed to close VOSS Scheduler",__func__);
3002 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3003 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003004#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003005#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3006 /* Destroy the wake lock */
3007 wake_lock_destroy(&pHddCtx->rx_wake_lock);
3008#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003009 /* Destroy the wake lock */
3010 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003011#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003012
3013 //Close VOSS
3014 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
3015 vos_close(pVosContext);
3016
3017#ifdef ANI_BUS_TYPE_SDIO
3018 vosStatus = WLANBAL_Close(pVosContext);
3019 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3020 {
3021 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3022 "%s: Failed to close BAL",__func__);
3023 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3024 }
3025 hddLog(VOS_TRACE_LEVEL_ERROR,"Returned WLAN BAL CLOSE\n\n\n\n");
3026#endif // ANI_BUS_TYPE_SDIO
3027
3028 //Close Watchdog
3029 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3030 vos_watchdog_close(pVosContext);
3031
3032 /* Cancel the vote for XO Core ON.
3033 * This is done here to ensure there is no race condition since MC, TX and WD threads have
3034 * exited at this point
3035 */
3036 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
3037 " when WLAN is turned OFF\n");
3038 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
3039 {
3040 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
3041 " Not returning failure."
3042 " Power consumed will be high\n");
3043 }
3044
3045 hdd_close_all_adapters( pHddCtx );
3046
3047
3048 //Free up dynamically allocated members inside HDD Adapter
3049 kfree(pHddCtx->cfg_ini);
3050 pHddCtx->cfg_ini= NULL;
3051
3052 /* free the power on lock from platform driver */
3053 if (free_riva_power_on_lock("wlan"))
3054 {
3055 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
3056 __func__);
3057 }
3058
3059#ifdef ANI_MANF_DIAG
3060free_hdd_ctx:
3061#endif
3062#ifdef CONFIG_CFG80211
3063 wiphy_unregister(wiphy) ;
3064 wiphy_free(wiphy) ;
3065#else
3066 vos_mem_free( pHddCtx );
3067#endif
3068 if (hdd_is_ssr_required())
3069 {
3070 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07003071 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07003072 msleep(5000);
3073 }
3074 hdd_set_ssr_required (VOS_FALSE);
3075}
3076
3077
3078/**---------------------------------------------------------------------------
3079
3080 \brief hdd_update_config_from_nv() - Function to update the contents of
3081 the running configuration with parameters taken from NV storage
3082
3083 \param - pHddCtx - Pointer to the HDD global context
3084
3085 \return - VOS_STATUS_SUCCESS if successful
3086
3087 --------------------------------------------------------------------------*/
3088static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
3089{
3090#ifndef FEATURE_WLAN_INTEGRATED_SOC
3091 eHalStatus halStatus;
3092#endif
3093
3094#ifdef FEATURE_WLAN_INTEGRATED_SOC
3095 v_BOOL_t itemIsValid = VOS_FALSE;
3096 VOS_STATUS status;
3097 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
3098 v_U8_t macLoop;
3099
3100 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
3101 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
3102 if(status != VOS_STATUS_SUCCESS)
3103 {
3104 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
3105 return VOS_STATUS_E_FAILURE;
3106 }
3107
3108 if (itemIsValid == VOS_TRUE)
3109 {
3110 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
3111 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
3112 VOS_MAX_CONCURRENCY_PERSONA);
3113 if(status != VOS_STATUS_SUCCESS)
3114 {
3115 /* Get MAC from NV fail, not update CFG info
3116 * INI MAC value will be used for MAC setting */
3117 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
3118 return VOS_STATUS_E_FAILURE;
3119 }
3120
3121 /* If first MAC is not valid, treat all others are not valid
3122 * Then all MACs will be got from ini file */
3123 if(vos_is_macaddr_zero(&macFromNV[0]))
3124 {
3125 /* MAC address in NV file is not configured yet */
3126 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
3127 return VOS_STATUS_E_INVAL;
3128 }
3129
3130 /* Get MAC address from NV, update CFG info */
3131 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
3132 {
3133 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
3134 {
3135 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
3136 /* This MAC is not valid, skip it
3137 * This MAC will be got from ini file */
3138 }
3139 else
3140 {
3141 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
3142 (v_U8_t *)&macFromNV[macLoop].bytes[0],
3143 VOS_MAC_ADDR_SIZE);
3144 }
3145 }
3146 }
3147 else
3148 {
3149 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
3150 return VOS_STATUS_E_FAILURE;
3151 }
3152#endif /* FEATURE_WLAN_INTEGRATED_SOC */
3153
3154#ifndef FEATURE_WLAN_INTEGRATED_SOC
3155#if 1 /* need to fix for concurrency */
3156 // Set the MAC Address
3157 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
3158 halStatus = ccmCfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
3159 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
3160 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]),
3161 hdd_set_mac_addr_cb, VOS_FALSE );
3162
3163 if (!HAL_STATUS_SUCCESS( halStatus ))
3164 {
3165 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
3166 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
3167 return VOS_STATUS_E_FAILURE;
3168 }
3169#endif
3170#endif
3171
3172 return VOS_STATUS_SUCCESS;
3173}
3174
3175/**---------------------------------------------------------------------------
3176
3177 \brief hdd_post_voss_start_config() - HDD post voss start config helper
3178
3179 \param - pAdapter - Pointer to the HDD
3180
3181 \return - None
3182
3183 --------------------------------------------------------------------------*/
3184VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
3185{
3186 eHalStatus halStatus;
3187 v_U32_t listenInterval;
3188
3189#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
3190 /* In the non-integrated architecture we update the configuration from
3191 the INI file and from NV after vOSS has been started
3192 */
3193
3194 // Apply the cfg.ini to cfg.dat
3195 if (FALSE == hdd_update_config_dat(pHddCtx))
3196 {
3197 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
3198 return VOS_STATUS_E_FAILURE;
3199 }
3200
3201 // Apply the NV to cfg.dat
3202 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
3203 {
3204 hddLog(VOS_TRACE_LEVEL_FATAL,
3205 "%s: config update from NV failed", __func__ );
3206 return VOS_STATUS_E_FAILURE;
3207 }
3208#endif // FEATURE_WLAN_NON_INTEGRATED_SOC
3209
3210 // Send ready indication to the HDD. This will kick off the MAC
3211 // into a 'running' state and should kick off an initial scan.
3212 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
3213 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3214 {
3215 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
3216 "code %08d [x%08x]",__func__, halStatus, halStatus );
3217 return VOS_STATUS_E_FAILURE;
3218 }
3219
3220 // Set default LI into HDD context,
3221 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
3222 // And RIVA will crash
3223 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
3224 pHddCtx->hdd_actual_LI_value = listenInterval;
3225
3226 return VOS_STATUS_SUCCESS;
3227}
3228
3229#ifdef ANI_BUS_TYPE_SDIO
3230
3231#ifndef ANI_MANF_DIAG
3232// Routine to initialize the PMU
3233void wlan_hdd_enable_deepsleep(v_VOID_t * pVosContext)
3234{
3235/*-------------- Need to fix this correctly while doing Deepsleep testing
3236 tANI_U32 regValue = 0;
3237
3238 regValue = QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_DEEP_SLEEP_EN_MASK |
3239 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_1P23_LPM_AON_MASK_MASK |
3240 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_1P23_LPM_SW_MASK_MASK |
3241 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_2P3_LPM_MASK_MASK;
3242
3243 WLANBAL_WriteRegister(pVosContext, QWLAN_PMU_LDO_CTRL_REG_REG, regValue);
3244---------------------*/
3245
3246 return;
3247}
3248#endif
3249#endif
3250
3251/* wake lock APIs for HDD */
3252void hdd_prevent_suspend(void)
3253{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003254#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003255 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003256#else
3257 wcnss_prevent_suspend();
3258#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003259}
3260
3261void hdd_allow_suspend(void)
3262{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003263#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003264 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003265#else
3266 wcnss_allow_suspend();
3267#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003268}
3269
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003270void hdd_allow_suspend_timeout(v_U32_t timeout)
3271{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003272#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003273 wake_lock_timeout(&wlan_wake_lock, timeout);
3274#else
3275 /* Do nothing as there is no API in wcnss for timeout*/
3276#endif
3277}
3278
Jeff Johnson295189b2012-06-20 16:38:30 -07003279/**---------------------------------------------------------------------------
3280
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003281 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
3282 information between Host and Riva
3283
3284 This function gets reported version of FW
3285 It also finds the version of Riva headers used to compile the host
3286 It compares the above two and prints a warning if they are different
3287 It gets the SW and HW version string
3288 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
3289 indicating the features they support through a bitmap
3290
3291 \param - pHddCtx - Pointer to HDD context
3292
3293 \return - void
3294
3295 --------------------------------------------------------------------------*/
3296
3297void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
3298{
3299
3300 tSirVersionType versionCompiled;
3301 tSirVersionType versionReported;
3302 tSirVersionString versionString;
3303 tANI_U8 fwFeatCapsMsgSupported = 0;
3304 VOS_STATUS vstatus;
3305
3306 /* retrieve and display WCNSS version information */
3307 do {
3308
3309 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
3310 &versionCompiled);
3311 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3312 {
3313 hddLog(VOS_TRACE_LEVEL_FATAL,
3314 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003315 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003316 break;
3317 }
3318
3319 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
3320 &versionReported);
3321 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3322 {
3323 hddLog(VOS_TRACE_LEVEL_FATAL,
3324 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003325 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003326 break;
3327 }
3328
3329 if ((versionCompiled.major != versionReported.major) ||
3330 (versionCompiled.minor != versionReported.minor) ||
3331 (versionCompiled.version != versionReported.version) ||
3332 (versionCompiled.revision != versionReported.revision))
3333 {
3334 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
3335 "Host expected %u.%u.%u.%u\n",
3336 WLAN_MODULE_NAME,
3337 (int)versionReported.major,
3338 (int)versionReported.minor,
3339 (int)versionReported.version,
3340 (int)versionReported.revision,
3341 (int)versionCompiled.major,
3342 (int)versionCompiled.minor,
3343 (int)versionCompiled.version,
3344 (int)versionCompiled.revision);
3345 }
3346 else
3347 {
3348 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
3349 WLAN_MODULE_NAME,
3350 (int)versionReported.major,
3351 (int)versionReported.minor,
3352 (int)versionReported.version,
3353 (int)versionReported.revision);
3354 }
3355
3356 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
3357 versionString,
3358 sizeof(versionString));
3359 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3360 {
3361 hddLog(VOS_TRACE_LEVEL_FATAL,
3362 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003363 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003364 break;
3365 }
3366
3367 pr_info("%s: WCNSS software version %s\n",
3368 WLAN_MODULE_NAME, versionString);
3369
3370 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
3371 versionString,
3372 sizeof(versionString));
3373 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3374 {
3375 hddLog(VOS_TRACE_LEVEL_FATAL,
3376 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003377 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003378 break;
3379 }
3380
3381 pr_info("%s: WCNSS hardware version %s\n",
3382 WLAN_MODULE_NAME, versionString);
3383
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003384 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
3385 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003386 send the message only if it the riva is 1.1
3387 minor numbers for different riva branches:
3388 0 -> (1.0)Mainline Build
3389 1 -> (1.1)Mainline Build
3390 2->(1.04) Stability Build
3391 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003392 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003393 ((versionReported.minor>=1) && (versionReported.version>=1)))
3394 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
3395 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003396
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003397 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08003398 {
3399#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
3400 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
3401 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
3402#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003403 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08003404 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003405
3406 } while (0);
3407
3408}
3409
3410/**---------------------------------------------------------------------------
3411
Jeff Johnson295189b2012-06-20 16:38:30 -07003412 \brief hdd_wlan_startup() - HDD init function
3413
3414 This is the driver startup code executed once a WLAN device has been detected
3415
3416 \param - dev - Pointer to the underlying device
3417
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003418 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07003419
3420 --------------------------------------------------------------------------*/
3421
3422int hdd_wlan_startup(struct device *dev )
3423{
3424 VOS_STATUS status;
3425 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003426 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003427 hdd_context_t *pHddCtx = NULL;
3428 v_CONTEXT_t pVosContext= NULL;
3429#ifdef WLAN_BTAMP_FEATURE
3430 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
3431 WLANBAP_ConfigType btAmpConfig;
3432 hdd_config_t *pConfig;
3433#endif
3434 int ret;
3435#ifdef CONFIG_CFG80211
3436 struct wiphy *wiphy;
3437#endif
3438#ifdef ANI_BUS_TYPE_SDIO
3439 struct sdio_func *sdio_func_dev = dev_to_sdio_func(dev);
3440#endif //ANI_BUS_TYPE_SDIO
3441
3442 ENTER();
3443#ifdef CONFIG_CFG80211
3444 /*
3445 * cfg80211: wiphy allocation
3446 */
3447 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
3448
3449 if(wiphy == NULL)
3450 {
3451 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003452 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003453 }
3454
3455 pHddCtx = wiphy_priv(wiphy);
3456
3457#else
3458
3459 pHddCtx = vos_mem_malloc ( sizeof( hdd_context_t ) );
3460 if(pHddCtx == NULL)
3461 {
3462 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003463 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07003464 }
3465
3466#endif
3467 //Initialize the adapter context to zeros.
3468 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
3469
3470#ifdef CONFIG_CFG80211
3471 pHddCtx->wiphy = wiphy;
3472#endif
3473 hdd_prevent_suspend();
3474 pHddCtx->isLoadUnloadInProgress = TRUE;
3475
3476 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
3477
3478 /*Get vos context here bcoz vos_open requires it*/
3479 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
3480
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08003481 if(pVosContext == NULL)
3482 {
3483 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
3484 goto err_free_hdd_context;
3485 }
3486
Jeff Johnson295189b2012-06-20 16:38:30 -07003487 //Save the Global VOSS context in adapter context for future.
3488 pHddCtx->pvosContext = pVosContext;
3489
3490 //Save the adapter context in global context for future.
3491 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
3492
3493#ifdef ANI_BUS_TYPE_SDIO
3494 // Set the private data for the device to our adapter.
3495 libra_sdio_setprivdata (sdio_func_dev, pHddCtx);
3496 atomic_set(&pHddCtx->sdio_claim_count, 0);
3497#endif // ANI_BUS_TYPE_SDIO
3498
3499 pHddCtx->parent_dev = dev;
3500
3501 init_completion(&pHddCtx->full_pwr_comp_var);
3502 init_completion(&pHddCtx->standby_comp_var);
3503 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003504 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003505 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003506
3507 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
3508
3509 // Load all config first as TL config is needed during vos_open
3510 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
3511 if(pHddCtx->cfg_ini == NULL)
3512 {
3513 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
3514 goto err_free_hdd_context;
3515 }
3516
3517 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
3518
3519 // Read and parse the qcom_cfg.ini file
3520 status = hdd_parse_config_ini( pHddCtx );
3521 if ( VOS_STATUS_SUCCESS != status )
3522 {
3523 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
3524 __func__, WLAN_INI_FILE);
3525 goto err_config;
3526 }
3527
3528#ifdef CONFIG_CFG80211
3529 /*
3530 * cfg80211: Initialization and registration ...
3531 */
3532 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
3533 {
3534 hddLog(VOS_TRACE_LEVEL_FATAL,
3535 "%s: wlan_hdd_cfg80211_register return failure", __func__);
3536 goto err_wiphy_reg;
3537 }
3538#endif
3539
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003540 // Update VOS trace levels based upon the cfg.ini
3541 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
3542 pHddCtx->cfg_ini->vosTraceEnableBAP);
3543 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
3544 pHddCtx->cfg_ini->vosTraceEnableTL);
3545 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
3546 pHddCtx->cfg_ini->vosTraceEnableWDI);
3547 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
3548 pHddCtx->cfg_ini->vosTraceEnableHDD);
3549 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
3550 pHddCtx->cfg_ini->vosTraceEnableSME);
3551 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
3552 pHddCtx->cfg_ini->vosTraceEnablePE);
3553 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
3554 pHddCtx->cfg_ini->vosTraceEnableWDA);
3555 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
3556 pHddCtx->cfg_ini->vosTraceEnableSYS);
3557 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
3558 pHddCtx->cfg_ini->vosTraceEnableVOSS);
3559#ifdef WLAN_SOFTAP_FEATURE
3560 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
3561 pHddCtx->cfg_ini->vosTraceEnableSAP);
3562 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
3563 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
3564#endif
3565
Jeff Johnson295189b2012-06-20 16:38:30 -07003566#ifdef FEATURE_WLAN_INTEGRATED_SOC
3567 // Update WDI trace levels based upon the cfg.ini
3568 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
3569 pHddCtx->cfg_ini->wdiTraceEnableDAL);
3570 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
3571 pHddCtx->cfg_ini->wdiTraceEnableCTL);
3572 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
3573 pHddCtx->cfg_ini->wdiTraceEnableDAT);
3574 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
3575 pHddCtx->cfg_ini->wdiTraceEnablePAL);
3576#endif /* FEATURE_WLAN_INTEGRATED_SOC */
3577
3578#ifdef ANI_MANF_DIAG
3579 if(VOS_FTM_MODE == hdd_get_conparam())
3580 {
3581 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
3582 {
3583 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
3584 goto err_free_hdd_context;
3585 }
3586 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
3587 return VOS_STATUS_SUCCESS;
3588 }
3589#endif
3590
3591 //Open watchdog module
3592 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3593 {
3594 status = vos_watchdog_open(pVosContext,
3595 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
3596
3597 if(!VOS_IS_STATUS_SUCCESS( status ))
3598 {
3599 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
3600#ifdef CONFIG_CFG80211
3601 goto err_wiphy_reg;
3602#else
3603 goto err_config;
3604#endif
3605 }
3606 }
3607
3608 pHddCtx->isLogpInProgress = FALSE;
3609 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
3610
3611#ifdef ANI_BUS_TYPE_SDIO
3612 status = WLANBAL_Open(pHddCtx->pvosContext);
3613 if(!VOS_IS_STATUS_SUCCESS(status))
3614 {
3615 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3616 "%s: Failed to open BAL",__func__);
3617 goto err_wdclose;
3618 }
3619#endif // ANI_BUS_TYPE_SDIO
3620
3621 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
3622 if(!VOS_IS_STATUS_SUCCESS(status))
3623 {
3624 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
3625#ifdef ANI_BUS_TYPE_SDIO
3626 goto err_balclose;
3627#else
3628 goto err_wdclose;
3629#endif
3630 }
3631
3632
3633#ifdef ANI_BUS_TYPE_SDIO
3634 status = WLANSAL_Start(pHddCtx->pvosContext);
3635 if (!VOS_IS_STATUS_SUCCESS(status))
3636 {
3637 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to start SAL",__func__);
3638 goto err_clkvote;
3639 }
3640
3641 /* Start BAL */
3642 status = WLANBAL_Start(pHddCtx->pvosContext);
3643
3644 if (!VOS_IS_STATUS_SUCCESS(status))
3645 {
3646 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3647 "%s: Failed to start BAL",__func__);
3648 goto err_salstop;
3649 }
3650#endif // ANI_BUS_TYPE_SDIO
3651
3652#ifdef MSM_PLATFORM_7x30
3653 /* FIXME: Volans 2.0 configuration. Reconfigure 1.3v SW supply to 1.3v. It will be configured to
3654 * 1.4v in vos_ChipPowerup() routine above
3655 */
3656#endif
3657
3658 status = vos_open( &pVosContext, 0);
3659 if ( !VOS_IS_STATUS_SUCCESS( status ))
3660 {
3661 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
3662 goto err_balstop;
3663 }
3664
3665 /* Save the hal context in Adapter */
3666 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
3667
3668 if ( NULL == pHddCtx->hHal )
3669 {
3670 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
3671 goto err_vosclose;
3672 }
3673
Jeff Johnsone7245742012-09-05 17:12:55 -07003674#ifdef FEATURE_WLAN_INTEGRATED_SOC
3675 /* Vos preStart is calling */
3676 /* vos preStart which does cfg download should be called before set sme config which accesses/sets some cfgs */
3677 status = vos_preStart( pHddCtx->pvosContext );
3678 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3679 {
3680 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
3681 goto err_vosclose;
3682 }
3683#endif
3684
Jeff Johnson295189b2012-06-20 16:38:30 -07003685 // Set the SME configuration parameters...
3686 status = hdd_set_sme_config( pHddCtx );
3687
3688 if ( VOS_STATUS_SUCCESS != status )
3689 {
3690 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
3691 goto err_vosclose;
3692 }
3693
3694 //Initialize the WMM module
3695 status = hdd_wmm_init(pHddCtx);
3696 if (!VOS_IS_STATUS_SUCCESS(status))
3697 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003698 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003699 goto err_vosclose;
3700 }
3701
3702#ifdef FEATURE_WLAN_INTEGRATED_SOC
Jeff Johnson295189b2012-06-20 16:38:30 -07003703 /* In the integrated architecture we update the configuration from
3704 the INI file and from NV before vOSS has been started so that
3705 the final contents are available to send down to the cCPU */
3706
3707 // Apply the cfg.ini to cfg.dat
3708 if (FALSE == hdd_update_config_dat(pHddCtx))
3709 {
3710 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
3711 goto err_vosclose;
3712 }
3713
3714 // Apply the NV to cfg.dat
3715 /* Prima Update MAC address only at here */
3716 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
3717 {
3718#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
3719 /* There was not a valid set of MAC Addresses in NV. See if the
3720 default addresses were modified by the cfg.ini settings. If so,
3721 we'll use them, but if not, we'll autogenerate a set of MAC
3722 addresses based upon the device serial number */
3723
3724 static const v_MACADDR_t default_address =
3725 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
3726 unsigned int serialno;
3727 int i;
3728
3729 serialno = wcnss_get_serial_number();
3730 if ((0 != serialno) &&
3731 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
3732 sizeof(default_address))))
3733 {
3734 /* cfg.ini has the default address, invoke autogen logic */
3735
3736 /* MAC address has 3 bytes of OUI so we have a maximum of 3
3737 bytes of the serial number that can be used to generate
3738 the other 3 bytes of the MAC address. Mask off all but
3739 the lower 3 bytes (this will also make sure we don't
3740 overflow in the next step) */
3741 serialno &= 0x00FFFFFF;
3742
3743 /* we need a unique address for each session */
3744 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
3745
3746 /* autogen all addresses */
3747 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3748 {
3749 /* start with the entire default address */
3750 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
3751 /* then replace the lower 3 bytes */
3752 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
3753 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
3754 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
3755
3756 serialno++;
3757 }
3758
3759 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
3760 MAC_ADDRESS_STR,
3761 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
3762 }
3763 else
3764#endif //WLAN_AUTOGEN_MACADDR_FEATURE
3765 {
3766 hddLog(VOS_TRACE_LEVEL_ERROR,
3767 "%s: Invalid MAC address in NV, using MAC from ini file "
3768 MAC_ADDRESS_STR, __func__,
3769 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
3770 }
3771 }
3772 {
3773 eHalStatus halStatus;
3774 // Set the MAC Address
3775 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
3776 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
3777 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
3778 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
3779
3780 if (!HAL_STATUS_SUCCESS( halStatus ))
3781 {
3782 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
3783 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08003784 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07003785 }
3786 }
3787#endif // FEATURE_WLAN_INTEGRATED_SOC
3788
3789 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
3790 Note: Firmware image will be read and downloaded inside vos_start API */
3791 status = vos_start( pHddCtx->pvosContext );
3792 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3793 {
3794 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
3795 goto err_vosclose;
3796 }
3797
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003798 /* Exchange capability info between Host and FW and also get versioning info from FW */
3799 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003800
3801 status = hdd_post_voss_start_config( pHddCtx );
3802 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3803 {
3804 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
3805 __func__);
3806 goto err_vosstop;
3807 }
3808
3809#ifdef WLAN_SOFTAP_FEATURE
3810 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3811 {
3812 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
3813 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
3814 }
3815 else
3816 {
3817#endif
3818 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
3819 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
3820 if (pAdapter != NULL)
3821 {
3822#ifdef WLAN_FEATURE_P2P
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05303823 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07003824 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05303825 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
3826 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
3827 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07003828
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05303829 /* Generate the P2P Device Address. This consists of the device's
3830 * primary MAC address with the locally administered bit set.
3831 */
3832 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07003833 }
3834 else
3835 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05303836 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
3837 if (p2p_dev_addr != NULL)
3838 {
3839 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
3840 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
3841 }
3842 else
3843 {
3844 hddLog(VOS_TRACE_LEVEL_FATAL,
3845 "%s: Failed to allocate mac_address for p2p_device",
3846 __func__);
3847 goto err_close_adapter;
3848 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003849 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003850
3851 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
3852 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
3853 if ( NULL == pP2pAdapter )
3854 {
3855 hddLog(VOS_TRACE_LEVEL_FATAL,
3856 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003857 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07003858 goto err_close_adapter;
3859 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003860#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003861 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003862#ifdef WLAN_SOFTAP_FEATURE
3863 }
3864#endif
3865
3866 if( pAdapter == NULL )
3867 {
3868 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
3869#ifdef ANI_BUS_TYPE_SDIO
3870 goto err_balstop;
3871#else
Jeff Johnson546a5c12013-02-15 10:11:20 -08003872 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003873#endif
3874 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003875
Jeff Johnson295189b2012-06-20 16:38:30 -07003876#ifdef WLAN_BTAMP_FEATURE
3877 vStatus = WLANBAP_Open(pVosContext);
3878 if(!VOS_IS_STATUS_SUCCESS(vStatus))
3879 {
3880 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3881 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07003882 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003883 }
3884
3885 vStatus = BSL_Init(pVosContext);
3886 if(!VOS_IS_STATUS_SUCCESS(vStatus))
3887 {
3888 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3889 "%s: Failed to Init BSL",__func__);
3890 goto err_bap_close;
3891 }
3892 vStatus = WLANBAP_Start(pVosContext);
3893 if (!VOS_IS_STATUS_SUCCESS(vStatus))
3894 {
3895 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3896 "%s: Failed to start TL",__func__);
3897 goto err_bap_close;
3898 }
3899
3900 pConfig = pHddCtx->cfg_ini;
3901 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
3902 status = WLANBAP_SetConfig(&btAmpConfig);
3903
3904#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07003905
Jeff Johnson295189b2012-06-20 16:38:30 -07003906#ifdef FEATURE_WLAN_SCAN_PNO
3907 /*SME must send channel update configuration to RIVA*/
3908 sme_UpdateChannelConfig(pHddCtx->hHal);
3909#endif
3910
3911#ifdef FEATURE_WLAN_INTEGRATED_SOC
3912 /* Register with platform driver as client for Suspend/Resume */
3913 status = hddRegisterPmOps(pHddCtx);
3914 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3915 {
3916 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
3917#ifdef WLAN_BTAMP_FEATURE
3918 goto err_bap_stop;
3919#else
Jeff Johnsone7245742012-09-05 17:12:55 -07003920 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003921#endif //WLAN_BTAMP_FEATURE
3922 }
3923
3924 /* Register TM level change handler function to the platform */
3925 status = hddDevTmRegisterNotifyCallback(pHddCtx);
3926 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3927 {
3928 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
3929 goto err_unregister_pmops;
3930 }
3931#endif
3932
3933 /* register for riva power on lock to platform driver */
3934 if (req_riva_power_on_lock("wlan"))
3935 {
3936 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
3937 __func__);
3938 goto err_unregister_pmops;
3939 }
3940
Jeff Johnson295189b2012-06-20 16:38:30 -07003941 // register net device notifier for device change notification
3942 ret = register_netdevice_notifier(&hdd_netdev_notifier);
3943
3944 if(ret < 0)
3945 {
3946 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
3947 goto err_free_power_on_lock;
3948 }
3949
3950 //Initialize the nlink service
3951 if(nl_srv_init() != 0)
3952 {
3953 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
3954 goto err_reg_netdev;
3955 }
3956
3957 //Initialize the BTC service
3958 if(btc_activate_service(pHddCtx) != 0)
3959 {
3960 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
3961 goto err_nl_srv;
3962 }
3963
3964#ifdef PTT_SOCK_SVC_ENABLE
3965 //Initialize the PTT service
3966 if(ptt_sock_activate_svc(pHddCtx) != 0)
3967 {
3968 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
3969 goto err_nl_srv;
3970 }
3971#endif
3972
Jeff Johnson295189b2012-06-20 16:38:30 -07003973 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003974#ifdef CONFIG_CFG80211
3975#ifdef WLAN_SOFTAP_FEATURE
3976 if (VOS_STA_SAP_MODE != hdd_get_conparam())
3977#endif
3978 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07003979 /* Action frame registered in one adapter which will
3980 * applicable to all interfaces
3981 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07003982 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003983 }
3984#endif
3985
3986 mutex_init(&pHddCtx->sap_lock);
3987
3988 pHddCtx->isLoadUnloadInProgress = FALSE;
3989
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003990#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003991#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3992 /* Initialize the wake lcok */
3993 wake_lock_init(&pHddCtx->rx_wake_lock,
3994 WAKE_LOCK_SUSPEND,
3995 "qcom_rx_wakelock");
3996#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003997 /* Initialize the wake lcok */
3998 wake_lock_init(&pHddCtx->sap_wake_lock,
3999 WAKE_LOCK_SUSPEND,
4000 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004001#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004002
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004003 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
4004 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07004005
4006 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4007 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004008
4009 // Initialize the restart logic
4010 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304011
4012#ifdef FEATURE_WLAN_TDLS
Hoonki Lee387663d2013-02-05 18:08:43 -08004013 if(0 != wlan_hdd_tdls_init(pAdapter->dev))
4014 {
4015 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_tdls_init failed",__func__);
4016 goto err_nl_srv;
4017 }
Chilam NG571c65a2013-01-19 12:27:36 +05304018#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004019
4020 goto success;
4021
4022err_nl_srv:
4023 nl_srv_exit();
4024
4025err_reg_netdev:
4026 unregister_netdevice_notifier(&hdd_netdev_notifier);
4027
4028err_free_power_on_lock:
4029 free_riva_power_on_lock("wlan");
4030
4031err_unregister_pmops:
4032 hddDevTmUnregisterNotifyCallback(pHddCtx);
4033 hddDeregisterPmOps(pHddCtx);
4034
4035#ifdef WLAN_BTAMP_FEATURE
4036err_bap_stop:
4037 WLANBAP_Stop(pVosContext);
4038#endif
4039
4040#ifdef WLAN_BTAMP_FEATURE
4041err_bap_close:
4042 WLANBAP_Close(pVosContext);
4043#endif
4044
Jeff Johnson295189b2012-06-20 16:38:30 -07004045err_close_adapter:
4046 hdd_close_all_adapters( pHddCtx );
4047
4048err_vosstop:
4049 vos_stop(pVosContext);
4050
4051err_vosclose:
4052 status = vos_sched_close( pVosContext );
4053 if (!VOS_IS_STATUS_SUCCESS(status)) {
4054 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4055 "%s: Failed to close VOSS Scheduler", __func__);
4056 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4057 }
4058 vos_close(pVosContext );
4059
4060err_balstop:
4061#ifdef ANI_BUS_TYPE_SDIO
4062#ifndef ANI_MANF_DIAG
4063 wlan_hdd_enable_deepsleep(pHddCtx->pvosContext);
4064#endif
4065
4066 WLANBAL_Stop(pHddCtx->pvosContext);
4067 WLANBAL_SuspendChip(pHddCtx->pvosContext);
4068#endif
4069
4070#ifdef ANI_BUS_TYPE_SDIO
4071err_salstop:
4072 WLANSAL_Stop(pHddCtx->pvosContext);
4073
Jeff Johnson295189b2012-06-20 16:38:30 -07004074err_clkvote:
Jeff Johnson546a5c12013-02-15 10:11:20 -08004075#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004076 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4077
4078#ifdef ANI_BUS_TYPE_SDIO
4079err_balclose:
4080 WLANBAL_Close(pHddCtx->pvosContext);
4081#endif // ANI_BUS_TYPE_SDIO
4082
4083err_wdclose:
4084 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4085 vos_watchdog_close(pVosContext);
4086
4087#ifdef CONFIG_CFG80211
4088err_wiphy_reg:
4089 wiphy_unregister(wiphy) ;
4090#endif
4091
4092err_config:
4093 kfree(pHddCtx->cfg_ini);
4094 pHddCtx->cfg_ini= NULL;
4095
4096err_free_hdd_context:
4097 hdd_allow_suspend();
4098#ifdef CONFIG_CFG80211
4099 wiphy_free(wiphy) ;
4100 //kfree(wdev) ;
4101#else
4102 vos_mem_free( pHddCtx );
4103#endif
4104 VOS_BUG(1);
4105
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004106 if (hdd_is_ssr_required())
4107 {
4108 /* WDI timeout had happened during load, so SSR is needed here */
4109 subsystem_restart("wcnss");
4110 msleep(5000);
4111 }
4112 hdd_set_ssr_required (VOS_FALSE);
4113
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004114 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004115
4116success:
4117 EXIT();
4118 return 0;
4119}
4120
4121/**---------------------------------------------------------------------------
4122
Jeff Johnson32d95a32012-09-10 13:15:23 -07004123 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004124
Jeff Johnson32d95a32012-09-10 13:15:23 -07004125 This is the driver entry point - called in different timeline depending
4126 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004127
4128 \param - None
4129
4130 \return - 0 for success, non zero for failure
4131
4132 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004133static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004134{
4135 VOS_STATUS status;
4136 v_CONTEXT_t pVosContext = NULL;
4137#ifdef ANI_BUS_TYPE_SDIO
4138 struct sdio_func *sdio_func_dev = NULL;
4139 unsigned int attempts = 0;
4140#endif // ANI_BUS_TYPE_SDIO
4141 struct device *dev = NULL;
4142 int ret_status = 0;
4143
4144 ENTER();
4145
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004146#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004147 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004148#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004149
4150 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4151 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4152
4153 //Power Up Libra WLAN card first if not already powered up
4154 status = vos_chipPowerUp(NULL,NULL,NULL);
4155 if (!VOS_IS_STATUS_SUCCESS(status))
4156 {
4157 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4158 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004159 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004160 }
4161
4162#ifdef ANI_BUS_TYPE_SDIO
4163 //SDIO Polling should be turned on for card detection. When using Android Wi-Fi GUI
4164 //users need not trigger SDIO polling explicitly. However when loading drivers via
4165 //command line (Adb shell), users must turn on SDIO polling prior to loading WLAN.
4166 do {
4167 sdio_func_dev = libra_getsdio_funcdev();
4168 if (NULL == sdio_func_dev) {
4169 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not detected yet.",__func__);
4170 attempts++;
4171 }
4172 else {
4173 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN detecton succeeded",__func__);
4174 dev = &sdio_func_dev->dev;
4175 break;
4176 }
4177
4178 if(attempts == 7)
4179 break;
4180
4181 msleep(250);
4182
4183 }while (attempts < 7);
4184
4185 //Retry to detect the card again by Powering Down the chip and Power up the chip
4186 //again. This retry is done to recover from CRC Error
4187 if (NULL == sdio_func_dev) {
4188
4189 attempts = 0;
4190
4191 //Vote off any PMIC voltage supplies
4192 vos_chipPowerDown(NULL, NULL, NULL);
4193
4194 msleep(1000);
4195
4196 //Power Up Libra WLAN card first if not already powered up
4197 status = vos_chipPowerUp(NULL,NULL,NULL);
4198 if (!VOS_IS_STATUS_SUCCESS(status))
4199 {
4200 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not Powered Up. "
4201 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004202 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004203 }
4204
4205 do {
4206 sdio_func_dev = libra_getsdio_funcdev();
4207 if (NULL == sdio_func_dev) {
4208 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not detected yet.",__func__);
4209 attempts++;
4210 }
4211 else {
4212 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN detecton succeeded",__func__);
4213 dev = &sdio_func_dev->dev;
4214 break;
4215 }
4216
4217 if(attempts == 2)
4218 break;
4219
4220 msleep(1000);
4221
4222 }while (attempts < 3);
4223 }
4224
4225#endif // ANI_BUS_TYPE_SDIO
4226
4227#ifdef ANI_BUS_TYPE_PCI
4228
4229 dev = wcnss_wlan_get_device();
4230
4231#endif // ANI_BUS_TYPE_PCI
4232
4233#ifdef ANI_BUS_TYPE_PLATFORM
4234 dev = wcnss_wlan_get_device();
4235#endif // ANI_BUS_TYPE_PLATFORM
4236
4237
4238 do {
4239 if (NULL == dev) {
4240 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4241 ret_status = -1;
4242 break;
4243 }
4244
4245#ifdef MEMORY_DEBUG
4246 vos_mem_init();
4247#endif
4248
4249#ifdef TIMER_MANAGER
4250 vos_timer_manager_init();
4251#endif
4252
4253 /* Preopen VOSS so that it is ready to start at least SAL */
4254 status = vos_preOpen(&pVosContext);
4255
4256 if (!VOS_IS_STATUS_SUCCESS(status))
4257 {
4258 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
4259 ret_status = -1;
4260 break;
4261 }
4262
4263#ifdef ANI_BUS_TYPE_SDIO
4264 /* Now Open SAL */
4265 status = WLANSAL_Open(pVosContext, 0);
4266
4267 if(!VOS_IS_STATUS_SUCCESS(status))
4268 {
4269 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to open SAL", __func__);
4270
4271 /* If unable to open, cleanup and return failure */
4272 vos_preClose( &pVosContext );
4273 ret_status = -1;
4274 break;
4275 }
4276#endif // ANI_BUS_TYPE_SDIO
4277
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004278#ifndef MODULE
4279 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
4280 */
4281 hdd_set_conparam((v_UINT_t)con_mode);
4282#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004283
4284 // Call our main init function
4285 if(hdd_wlan_startup(dev)) {
4286 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
4287 __func__);
4288#ifdef ANI_BUS_TYPE_SDIO
4289 WLANSAL_Close(pVosContext);
4290#endif // ANI_BUS_TYPE_SDIO
4291 vos_preClose( &pVosContext );
4292 ret_status = -1;
4293 break;
4294 }
4295
4296 /* Cancel the vote for XO Core ON
4297 * This is done here for safety purposes in case we re-initialize without turning
4298 * it OFF in any error scenario.
4299 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004300 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07004301 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004302 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07004303 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4304 {
4305 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
4306 " Power consumed will be high\n");
4307 }
4308 } while (0);
4309
4310 if (0 != ret_status)
4311 {
4312 //Assert Deep sleep signal now to put Libra HW in lowest power state
4313 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4314 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
4315
4316 //Vote off any PMIC voltage supplies
4317 vos_chipPowerDown(NULL, NULL, NULL);
4318#ifdef TIMER_MANAGER
4319 vos_timer_exit();
4320#endif
4321#ifdef MEMORY_DEBUG
4322 vos_mem_exit();
4323#endif
4324
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004325#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004326 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004327#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004328 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
4329 }
4330 else
4331 {
4332 //Send WLAN UP indication to Nlink Service
4333 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
4334
4335 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
4336
4337 }
4338
4339 EXIT();
4340
4341 return ret_status;
4342}
4343
Jeff Johnson32d95a32012-09-10 13:15:23 -07004344/**---------------------------------------------------------------------------
4345
4346 \brief hdd_module_init() - Init Function
4347
4348 This is the driver entry point (invoked when module is loaded using insmod)
4349
4350 \param - None
4351
4352 \return - 0 for success, non zero for failure
4353
4354 --------------------------------------------------------------------------*/
4355#ifdef MODULE
4356static int __init hdd_module_init ( void)
4357{
4358 return hdd_driver_init();
4359}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004360#else /* #ifdef MODULE */
4361static int __init hdd_module_init ( void)
4362{
4363 /* Driver initialization is delayed to fwpath_changed_handler */
4364 return 0;
4365}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004366#endif /* #ifdef MODULE */
4367
Jeff Johnson295189b2012-06-20 16:38:30 -07004368
4369/**---------------------------------------------------------------------------
4370
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004371 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07004372
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004373 This is the driver exit point (invoked when module is unloaded using rmmod
4374 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07004375
4376 \param - None
4377
4378 \return - None
4379
4380 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004381static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004382{
4383 hdd_context_t *pHddCtx = NULL;
4384 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004385
4386 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
4387
4388 //Get the global vos context
4389 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4390
4391 if(!pVosContext)
4392 {
4393 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
4394 goto done;
4395 }
4396
4397 //Get the HDD context.
4398 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
4399
4400 if(!pHddCtx)
4401 {
4402 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
4403 }
4404 else
4405 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004406 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07004407 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07004408 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
4409 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07004410 }
4411
4412 pHddCtx->isLoadUnloadInProgress = TRUE;
4413 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4414
4415 //Do all the cleanup before deregistering the driver
4416 hdd_wlan_exit(pHddCtx);
4417 }
4418
4419#ifdef ANI_BUS_TYPE_SDIO
4420 WLANSAL_Close(pVosContext);
4421#endif // ANI_BUS_TYPE_SDIO
4422
4423 vos_preClose( &pVosContext );
4424
4425#ifdef TIMER_MANAGER
4426 vos_timer_exit();
4427#endif
4428#ifdef MEMORY_DEBUG
4429 vos_mem_exit();
4430#endif
4431
4432done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004433#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004434 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004435#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004436 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
4437}
4438
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004439/**---------------------------------------------------------------------------
4440
4441 \brief hdd_module_exit() - Exit function
4442
4443 This is the driver exit point (invoked when module is unloaded using rmmod)
4444
4445 \param - None
4446
4447 \return - None
4448
4449 --------------------------------------------------------------------------*/
4450static void __exit hdd_module_exit(void)
4451{
4452 hdd_driver_exit();
4453}
4454
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004455#ifdef MODULE
4456static int fwpath_changed_handler(const char *kmessage,
4457 struct kernel_param *kp)
4458{
4459 /* nothing to do when driver is DLKM */
4460 return 0;
4461}
4462
4463static int con_mode_handler(const char *kmessage,
4464 struct kernel_param *kp)
4465{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07004466 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004467}
4468#else /* #ifdef MODULE */
4469/**---------------------------------------------------------------------------
4470
4471 \brief fwpath_changed_handler() - Handler Function
4472
4473 This is the driver entry point
4474 - delayed driver initialization when driver is statically linked
4475 - invoked when module parameter fwpath is modified from userpspace to signal
4476 initializing the WLAN driver
4477
4478 \return - 0 for success, non zero for failure
4479
4480 --------------------------------------------------------------------------*/
4481static int fwpath_changed_handler(const char *kmessage,
4482 struct kernel_param *kp)
4483{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004484 int ret_status;
4485
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004486 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004487 ret_status = hdd_driver_init();
4488 wlan_hdd_inited = ret_status ? 0 : 1;
4489 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004490 }
4491
4492 hdd_driver_exit();
4493
4494 msleep(200);
4495
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004496 ret_status = hdd_driver_init();
4497 wlan_hdd_inited = ret_status ? 0 : 1;
4498 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004499}
4500
Jeff Johnson295189b2012-06-20 16:38:30 -07004501/**---------------------------------------------------------------------------
4502
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004503 \brief con_mode_handler() -
4504
4505 Handler function for module param con_mode when it is changed by userspace
4506 Dynamically linked - do nothing
4507 Statically linked - exit and init driver, as in rmmod and insmod
4508
4509 \param -
4510
4511 \return -
4512
4513 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004514static int con_mode_handler(const char *kmessage,
4515 struct kernel_param *kp)
4516{
4517 int ret = param_set_int(kmessage, kp);
4518
4519 if (ret)
4520 return ret;
4521
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004522 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004523}
4524#endif /* #ifdef MODULE */
4525
4526/**---------------------------------------------------------------------------
4527
Jeff Johnson295189b2012-06-20 16:38:30 -07004528 \brief hdd_get_conparam() -
4529
4530 This is the driver exit point (invoked when module is unloaded using rmmod)
4531
4532 \param - None
4533
4534 \return - tVOS_CON_MODE
4535
4536 --------------------------------------------------------------------------*/
4537tVOS_CON_MODE hdd_get_conparam ( void )
4538{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004539#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07004540 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004541#else
4542 return (tVOS_CON_MODE)curr_con_mode;
4543#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004544}
4545void hdd_set_conparam ( v_UINT_t newParam )
4546{
4547 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004548#ifndef MODULE
4549 curr_con_mode = con_mode;
4550#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004551}
4552/**---------------------------------------------------------------------------
4553
4554 \brief hdd_softap_sta_deauth() - function
4555
4556 This to take counter measure to handle deauth req from HDD
4557
4558 \param - pAdapter - Pointer to the HDD
4559
4560 \param - enable - boolean value
4561
4562 \return - None
4563
4564 --------------------------------------------------------------------------*/
4565
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004566VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07004567{
Jeff Johnson295189b2012-06-20 16:38:30 -07004568 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004569 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07004570#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
4571 tHalHandle hHalHandle;
4572#endif
4573
4574 ENTER();
4575
4576 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4577
4578 //Ignore request to deauth bcmc station
4579 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004580 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004581
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004582 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07004583
4584 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004585 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004586}
4587
4588/**---------------------------------------------------------------------------
4589
4590 \brief hdd_softap_sta_disassoc() - function
4591
4592 This to take counter measure to handle deauth req from HDD
4593
4594 \param - pAdapter - Pointer to the HDD
4595
4596 \param - enable - boolean value
4597
4598 \return - None
4599
4600 --------------------------------------------------------------------------*/
4601
4602void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
4603{
4604 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4605
4606 ENTER();
4607
4608 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4609
4610 //Ignore request to disassoc bcmc station
4611 if( pDestMacAddress[0] & 0x1 )
4612 return;
4613
4614 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
4615}
4616
4617void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
4618{
4619 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4620
4621 ENTER();
4622
4623 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4624
4625 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
4626}
4627
Jeff Johnson295189b2012-06-20 16:38:30 -07004628/**---------------------------------------------------------------------------
4629 *
4630 * \brief hdd_get__concurrency_mode() -
4631 *
4632 *
4633 * \param - None
4634 *
4635 * \return - CONCURRENCY MODE
4636 *
4637 * --------------------------------------------------------------------------*/
4638tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
4639{
4640 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4641 hdd_context_t *pHddCtx;
4642
4643 if (NULL != pVosContext)
4644 {
4645 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4646 if (NULL != pHddCtx)
4647 {
4648 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
4649 }
4650 }
4651
4652 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004653 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004654 return VOS_STA;
4655}
4656
4657/* Decide whether to allow/not the apps power collapse.
4658 * Allow apps power collapse if we are in connected state.
4659 * if not, allow only if we are in IMPS */
4660v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
4661{
4662 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08004663 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07004664 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4665 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4666 hdd_adapter_t *pAdapter = NULL;
4667 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08004668 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004669
4670#ifdef WLAN_SOFTAP_FEATURE
4671 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4672 return TRUE;
4673#endif
4674
Yathish9f22e662012-12-10 14:21:35 -08004675 concurrent_state = hdd_get_concurrency_mode();
4676
4677#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4678 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
4679 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
4680 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
4681 return TRUE;
4682#endif
4683
Jeff Johnson295189b2012-06-20 16:38:30 -07004684 /*loop through all adapters. TBD fix for Concurrency */
4685 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4686 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4687 {
4688 pAdapter = pAdapterNode->pAdapter;
4689 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4690 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4691 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004692 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07004693 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08004694 && pmcState != STOPPED && pmcState != STANDBY)) ||
4695 (eANI_BOOLEAN_TRUE == scanRspPending))
Jeff Johnson295189b2012-06-20 16:38:30 -07004696 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004697 hddLog( LOGE, "%s: do not allow APPS power collapse-"
4698 "pmcState = %d scanRspPending = %d",
4699 __func__, pmcState, scanRspPending );
Jeff Johnson295189b2012-06-20 16:38:30 -07004700 return FALSE;
4701 }
4702 }
4703 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4704 pAdapterNode = pNext;
4705 }
4706 return TRUE;
4707}
4708
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08004709/* Decides whether to send suspend notification to Riva
4710 * if any adapter is in BMPS; then it is required */
4711v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
4712{
4713 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
4714 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4715
4716 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
4717 {
4718 return TRUE;
4719 }
4720 return FALSE;
4721}
4722
Jeff Johnson295189b2012-06-20 16:38:30 -07004723void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4724{
4725 switch(mode)
4726 {
4727 case WLAN_HDD_INFRA_STATION:
4728#ifdef WLAN_FEATURE_P2P
4729 case WLAN_HDD_P2P_CLIENT:
4730 case WLAN_HDD_P2P_GO:
4731#endif
4732 case WLAN_HDD_SOFTAP:
Jeff Johnsone7245742012-09-05 17:12:55 -07004733 pHddCtx->concurrency_mode |= (1 << mode);
4734 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07004735 break;
4736 default:
4737 break;
4738
4739 }
4740 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4741 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4742}
4743
4744
4745void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4746{
4747 switch(mode)
4748 {
4749 case WLAN_HDD_INFRA_STATION:
4750#ifdef WLAN_FEATURE_P2P
4751 case WLAN_HDD_P2P_CLIENT:
4752 case WLAN_HDD_P2P_GO:
4753#endif
4754 case WLAN_HDD_SOFTAP:
4755 pHddCtx->no_of_sessions[mode]--;
4756 if (!(pHddCtx->no_of_sessions[mode]))
4757 pHddCtx->concurrency_mode &= (~(1 << mode));
4758 break;
4759 default:
4760 break;
4761 }
4762 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4763 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4764}
4765
Jeff Johnsone7245742012-09-05 17:12:55 -07004766/**---------------------------------------------------------------------------
4767 *
4768 * \brief wlan_hdd_restart_init
4769 *
4770 * This function initalizes restart timer/flag. An internal function.
4771 *
4772 * \param - pHddCtx
4773 *
4774 * \return - None
4775 *
4776 * --------------------------------------------------------------------------*/
4777
4778static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
4779{
4780 /* Initialize */
4781 pHddCtx->hdd_restart_retries = 0;
4782 atomic_set(&pHddCtx->isRestartInProgress, 0);
4783 vos_timer_init(&pHddCtx->hdd_restart_timer,
4784 VOS_TIMER_TYPE_SW,
4785 wlan_hdd_restart_timer_cb,
4786 pHddCtx);
4787}
4788/**---------------------------------------------------------------------------
4789 *
4790 * \brief wlan_hdd_restart_deinit
4791 *
4792 * This function cleans up the resources used. An internal function.
4793 *
4794 * \param - pHddCtx
4795 *
4796 * \return - None
4797 *
4798 * --------------------------------------------------------------------------*/
4799
4800static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
4801{
4802
4803 VOS_STATUS vos_status;
4804 /* Block any further calls */
4805 atomic_set(&pHddCtx->isRestartInProgress, 1);
4806 /* Cleanup */
4807 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
4808 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004809 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07004810 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
4811 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004812 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07004813
4814}
4815
4816/**---------------------------------------------------------------------------
4817 *
4818 * \brief wlan_hdd_framework_restart
4819 *
4820 * This function uses a cfg80211 API to start a framework initiated WLAN
4821 * driver module unload/load.
4822 *
4823 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
4824 *
4825 *
4826 * \param - pHddCtx
4827 *
4828 * \return - VOS_STATUS_SUCCESS: Success
4829 * VOS_STATUS_E_EMPTY: Adapter is Empty
4830 * VOS_STATUS_E_NOMEM: No memory
4831
4832 * --------------------------------------------------------------------------*/
4833
4834static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
4835{
4836 VOS_STATUS status = VOS_STATUS_SUCCESS;
4837 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4838 int len = (sizeof (struct ieee80211_mgmt));
4839 struct ieee80211_mgmt *mgmt = NULL;
4840
4841 /* Prepare the DEAUTH managment frame with reason code */
4842 mgmt = kzalloc(len, GFP_KERNEL);
4843 if(mgmt == NULL)
4844 {
4845 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08004846 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07004847 return VOS_STATUS_E_NOMEM;
4848 }
4849 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
4850
4851 /* Iterate over all adapters/devices */
4852 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4853 do
4854 {
4855 if( (status == VOS_STATUS_SUCCESS) &&
4856 pAdapterNode &&
4857 pAdapterNode->pAdapter)
4858 {
4859 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4860 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
4861 pAdapterNode->pAdapter->dev->name,
4862 pAdapterNode->pAdapter->device_mode,
4863 pHddCtx->hdd_restart_retries + 1);
4864 /*
4865 * CFG80211 event to restart the driver
4866 *
4867 * 'cfg80211_send_unprot_deauth' sends a
4868 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
4869 * of SME(Linux Kernel) state machine.
4870 *
4871 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
4872 * the driver.
4873 *
4874 */
4875
4876 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
4877 }
4878 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4879 pAdapterNode = pNext;
4880 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
4881
4882
4883 /* Free the allocated management frame */
4884 kfree(mgmt);
4885
4886 /* Retry until we unload or reach max count */
4887 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
4888 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
4889
4890 return status;
4891
4892}
4893/**---------------------------------------------------------------------------
4894 *
4895 * \brief wlan_hdd_restart_timer_cb
4896 *
4897 * Restart timer callback. An internal function.
4898 *
4899 * \param - User data:
4900 *
4901 * \return - None
4902 *
4903 * --------------------------------------------------------------------------*/
4904
4905void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
4906{
4907 hdd_context_t *pHddCtx = usrDataForCallback;
4908 wlan_hdd_framework_restart(pHddCtx);
4909 return;
4910
4911}
4912
4913
4914/**---------------------------------------------------------------------------
4915 *
4916 * \brief wlan_hdd_restart_driver
4917 *
4918 * This function sends an event to supplicant to restart the WLAN driver.
4919 *
4920 * This function is called from vos_wlanRestart.
4921 *
4922 * \param - pHddCtx
4923 *
4924 * \return - VOS_STATUS_SUCCESS: Success
4925 * VOS_STATUS_E_EMPTY: Adapter is Empty
4926 * VOS_STATUS_E_ALREADY: Request already in progress
4927
4928 * --------------------------------------------------------------------------*/
4929VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
4930{
4931 VOS_STATUS status = VOS_STATUS_SUCCESS;
4932
4933 /* A tight check to make sure reentrancy */
4934 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
4935 {
4936 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
4937 "%s: WLAN restart is already in progress", __func__);
4938
4939 return VOS_STATUS_E_ALREADY;
4940 }
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004941 /* when WLAN driver is statically linked, then invoke SSR by sending
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07004942 * the reset interrupt. If it is DLKM, then use restart API
4943 */
4944#ifdef MODULE
Jeff Johnsone7245742012-09-05 17:12:55 -07004945 status = wlan_hdd_framework_restart(pHddCtx);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07004946#else
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08004947#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07004948 wcnss_reset_intr();
4949#endif
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08004950#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004951
Jeff Johnsone7245742012-09-05 17:12:55 -07004952 return status;
4953}
4954
4955
Jeff Johnson295189b2012-06-20 16:38:30 -07004956//Register the module init/exit functions
4957module_init(hdd_module_init);
4958module_exit(hdd_module_exit);
4959
4960MODULE_LICENSE("Dual BSD/GPL");
4961MODULE_AUTHOR("Qualcomm Atheros, Inc.");
4962MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
4963
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004964module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
4965 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07004966
4967module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
4968 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);