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