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