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