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