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