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