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