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