blob: 9262a835550f61fa660a37f8c40a3077b8f9a60b [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* wlan_hdd_early_suspend.c
24*
25* \brief power management functions
26*
27* Description
28* Copyright 2009 (c) Qualcomm, Incorporated.
29* All Rights Reserved.
30* Qualcomm Confidential and Proprietary.
31*
32==============================================================================**/
33/* $HEADER$ */
34
35/**-----------------------------------------------------------------------------
36* Include files
37* ----------------------------------------------------------------------------*/
38#ifdef CONFIG_HAS_EARLYSUSPEND
39
40#include <linux/pm.h>
41#include <linux/wait.h>
42#include <linux/earlysuspend.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070043#include <wlan_hdd_includes.h>
44#include <wlan_qct_driver.h>
45#include <linux/wakelock.h>
46#endif
47
48#include "halTypes.h"
49#include "sme_Api.h"
50#include <vos_api.h>
51#include "vos_power.h"
52#include <vos_sched.h>
53#include <macInitApi.h>
54#ifdef ANI_BUS_TYPE_SDIO
55#include <wlan_qct_sal.h>
56#include <wlan_qct_bal.h>
57#endif
58#include <wlan_qct_sys.h>
59#include <wlan_btc_svc.h>
60#include <wlan_nlink_common.h>
61#include <wlan_hdd_main.h>
62#include <wlan_hdd_assoc.h>
63#include <wlan_hdd_dev_pwr.h>
64#ifdef ANI_BUS_TYPE_SDIO
65#include <wlan_sal_misc.h>
66#include <libra_sdioif.h>
67#endif
68#include <wlan_nlink_srv.h>
69#include <wlan_hdd_misc.h>
70
71#ifdef WLAN_SOFTAP_FEATURE
72#include <linux/semaphore.h>
73#include <wlan_hdd_hostapd.h>
74#endif
75#include "cfgApi.h"
76
77#ifdef WLAN_BTAMP_FEATURE
78#include "bapApi.h"
79#include "bap_hdd_main.h"
80#include "bap_hdd_misc.h"
81#endif
82
Jeff Johnsone7245742012-09-05 17:12:55 -070083#include <linux/wcnss_wlan.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070084#include <linux/inetdevice.h>
85#include <wlan_hdd_cfg.h>
86/**-----------------------------------------------------------------------------
87* Preprocessor definitions and constants
88* ----------------------------------------------------------------------------*/
89
90/**-----------------------------------------------------------------------------
91* Type declarations
92* ----------------------------------------------------------------------------*/
93
94/**-----------------------------------------------------------------------------
95* Function and variables declarations
96* ----------------------------------------------------------------------------*/
97#include "wlan_hdd_power.h"
98#include "wlan_hdd_packet_filtering.h"
99
100#ifdef CONFIG_HAS_EARLYSUSPEND
101static struct early_suspend wlan_early_suspend;
102#endif
103
104static eHalStatus g_full_pwr_status;
105static eHalStatus g_standby_status;
106
107extern VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx);
108extern VOS_STATUS vos_chipExitDeepSleepVREGHandler(
109 vos_call_status_type* status,
110 vos_power_cb_type callback,
111 v_PVOID_t user_data);
112extern void hdd_wlan_initial_scan(hdd_context_t *pHddCtx);
113void unregister_wlan_suspend(void);
114
115extern struct notifier_block hdd_netdev_notifier;
116#ifdef WLAN_SOFTAP_FEATURE
117extern tVOS_CON_MODE hdd_get_conparam ( void );
118#endif
119
120#ifdef WLAN_FEATURE_PACKET_FILTERING
Jeff Johnsone7245742012-09-05 17:12:55 -0700121extern void wlan_hdd_set_mc_addr_list(hdd_context_t *pHddCtx, v_U8_t set, v_U8_t sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700122#endif
123
124//Callback invoked by PMC to report status of standby request
125void hdd_suspend_standby_cbk (void *callbackContext, eHalStatus status)
126{
127 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
128 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Standby status = %d", __func__, status);
129 g_standby_status = status;
130
131 if(eHAL_STATUS_SUCCESS == status)
132 {
133 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
134 }
135 else
136 {
137 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
138 }
139
140 complete(&pHddCtx->standby_comp_var);
141}
142
143//Callback invoked by PMC to report status of full power request
144void hdd_suspend_full_pwr_callback(void *callbackContext, eHalStatus status)
145{
146 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
147 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Full Power status = %d", __func__, status);
148 g_full_pwr_status = status;
149
150 if(eHAL_STATUS_SUCCESS == status)
151 {
152 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
153 }
154 else
155 {
156 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
157 }
158
159 complete(&pHddCtx->full_pwr_comp_var);
160}
161
162eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx)
163{
164 eHalStatus status = VOS_STATUS_SUCCESS;
165
166 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from standby",__func__);
167 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
168
169 g_full_pwr_status = eHAL_STATUS_FAILURE;
170 status = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, pHddCtx,
171 eSME_FULL_PWR_NEEDED_BY_HDD);
172
173 if(status == eHAL_STATUS_PMC_PENDING)
174 {
175 //Block on a completion variable. Can't wait forever though
176 wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
177 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
178 status = g_full_pwr_status;
179 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
180 {
181 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
182 VOS_ASSERT(0);
183 goto failure;
184 }
185 }
186 else if(status != eHAL_STATUS_SUCCESS)
187 {
188 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
189 __func__, status);
190 VOS_ASSERT(0);
191 goto failure;
192 }
193 else
194 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
195
196failure:
197 //No blocking to reduce latency. No other device should be depending on WLAN
198 //to finish resume and WLAN won't be instantly on after resume
199 return status;
200}
201
202
203//Helper routine to put the chip into standby
204VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx)
205{
206 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
207 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
208
209 //Disable IMPS/BMPS as we do not want the device to enter any power
210 //save mode on its own during suspend sequence
211 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
212 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
213
214 //Note we do not disable queues unnecessarily. Queues should already be disabled
215 //if STA is disconnected or the queue will be disabled as and when disconnect
216 //happens because of standby procedure.
217
218 //Ensure that device is in full power first. There is scope for optimization
219 //here especially in scenarios where PMC is already in IMPS or REQUEST_IMPS.
220 //Core s/w needs to be optimized to handle this. Until then we request full
221 //power before issuing request for standby.
222 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
223 g_full_pwr_status = eHAL_STATUS_FAILURE;
224 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
225 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
226
227 if(halStatus == eHAL_STATUS_PMC_PENDING)
228 {
229 //Block on a completion variable. Can't wait forever though
230 wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
231 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
232 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
233 {
234 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower Failed",__func__);
235 VOS_ASSERT(0);
236 vosStatus = VOS_STATUS_E_FAILURE;
237 goto failure;
238 }
239 }
240 else if(halStatus != eHAL_STATUS_SUCCESS)
241 {
242 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
243 __func__, halStatus);
244 VOS_ASSERT(0);
245 vosStatus = VOS_STATUS_E_FAILURE;
246 goto failure;
247 }
248
249 if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) {
250 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
251 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
252 }
253
254 //Request standby. Standby will cause the STA to disassociate first. TX queues
255 //will be disabled (by HDD) when STA disconnects. You do not want to disable TX
256 //queues here. Also do not assert if the failure code is eHAL_STATUS_PMC_NOT_NOW as PMC
257 //will send this failure code in case of concurrent sessions. Power Save cannot be supported
258 //when there are concurrent sessions.
259 INIT_COMPLETION(pHddCtx->standby_comp_var);
260 g_standby_status = eHAL_STATUS_FAILURE;
261 halStatus = sme_RequestStandby(pHddCtx->hHal, hdd_suspend_standby_cbk, pHddCtx);
262
263 if (halStatus == eHAL_STATUS_PMC_PENDING)
264 {
265 //Wait till WLAN device enters standby mode
266 wait_for_completion_timeout(&pHddCtx->standby_comp_var,
267 msecs_to_jiffies(WLAN_WAIT_TIME_STANDBY));
268 if (g_standby_status != eHAL_STATUS_SUCCESS && g_standby_status != eHAL_STATUS_PMC_NOT_NOW)
269 {
270 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
271 VOS_ASSERT(0);
272 vosStatus = VOS_STATUS_E_FAILURE;
273 goto failure;
274 }
275 }
276 else if (halStatus != eHAL_STATUS_SUCCESS && halStatus != eHAL_STATUS_PMC_NOT_NOW) {
277 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed - status %d",
278 __func__, halStatus);
279 VOS_ASSERT(0);
280 vosStatus = VOS_STATUS_E_FAILURE;
281 goto failure;
282 }
283 else
284 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
285
286failure:
287 //Restore IMPS config
288 if(pHddCtx->cfg_ini->fIsImpsEnabled)
289 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
290
291 //Restore BMPS config
292 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
293 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
294
295 return vosStatus;
296}
297
298
299//Helper routine for Deep sleep entry
300VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
301{
302 eHalStatus halStatus;
303 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
304 vos_call_status_type callType;
305#ifdef ANI_BUS_TYPE_SDIO
306 struct sdio_func *sdio_func_dev_current = NULL;
307 int attempts = 0;
308#endif
309 //Stop the Interface TX queue.
310 netif_tx_disable(pAdapter->dev);
311 netif_carrier_off(pAdapter->dev);
312
313 //Disable IMPS,BMPS as we do not want the device to enter any power
314 //save mode on it own during suspend sequence
315 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
316 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
317
318 //Ensure that device is in full power as we will touch H/W during vos_Stop
319 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
320 g_full_pwr_status = eHAL_STATUS_FAILURE;
321 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
322 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
323
324 if(halStatus == eHAL_STATUS_PMC_PENDING)
325 {
326 //Block on a completion variable. Can't wait forever though
327 wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
328 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
329 if(g_full_pwr_status != eHAL_STATUS_SUCCESS){
330 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
331 VOS_ASSERT(0);
332 }
333 }
334 else if(halStatus != eHAL_STATUS_SUCCESS)
335 {
336 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Request for Full Power failed",__func__);
337 VOS_ASSERT(0);
338 }
339
340 //Issue a disconnect. This is required to inform the supplicant that
341 //STA is getting disassociated and for GUI to be updated properly
342 INIT_COMPLETION(pAdapter->disconnect_comp_var);
343 halStatus = sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
344
345 //Success implies disconnect command got queued up successfully
346 if(halStatus == eHAL_STATUS_SUCCESS)
347 {
348 //Block on a completion variable. Can't wait forever though.
349 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
350 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
351 }
352
353
354 //None of the steps should fail after this. Continue even in case of failure
355 vosStatus = vos_stop( pHddCtx->pvosContext );
356 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
357
358#ifdef ANI_BUS_TYPE_SDIO
359 vosStatus = WLANBAL_Stop( pHddCtx->pvosContext );
360 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
361
362 vosStatus = WLANBAL_SuspendChip( pHddCtx->pvosContext );
363 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
364
365 vosStatus = WLANSAL_Stop(pHddCtx->pvosContext);
366 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
367#endif
368
369 vosStatus = vos_chipAssertDeepSleep( &callType, NULL, NULL );
370 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
371
372 //Vote off any PMIC voltage supplies
373 vosStatus = vos_chipPowerDown(NULL, NULL, NULL);
374
375#ifdef ANI_BUS_TYPE_SDIO
376 //Get the Current SDIO Func
377 sdio_func_dev_current = libra_getsdio_funcdev();
378 if(NULL != sdio_func_dev_current) {
379 libra_detect_card_change();
380 do {
381 msleep(100);
382 //Get the SDIO func device
383 sdio_func_dev_current = libra_getsdio_funcdev();
384 if(NULL == sdio_func_dev_current) {
385 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Card Removed Successfully",__func__);
386 break;
387 }
388 else {
389 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Trying Again",__func__);
390 attempts++;
391 }
392 } while (attempts < LIBRA_CARD_REMOVE_DETECT_MAX_COUNT);
393
394 if(LIBRA_CARD_REMOVE_DETECT_MAX_COUNT == attempts) {
395 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Fatal",__func__);
396 goto err_fail;
397 }
398 }
399#endif
400
401 pHddCtx->hdd_ps_state = eHDD_SUSPEND_DEEP_SLEEP;
402
403 //Restore IMPS config
404 if(pHddCtx->cfg_ini->fIsImpsEnabled)
405 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
406
407 //Restore BMPS config
408 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
409 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
410
411#ifdef ANI_BUS_TYPE_SDIO
412err_fail:
413#endif
414 return vosStatus;
415}
416
417VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
418{
419 VOS_STATUS vosStatus;
420 eHalStatus halStatus;
421#ifdef ANI_BUS_TYPE_SDIO
422 int attempts = 0;
423 struct sdio_func *sdio_func_dev = NULL;
424#endif
425
426 //Power Up Libra WLAN card first if not already powered up
427 vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
428 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
429 {
430 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
431 "exiting", __func__);
432 goto err_deep_sleep;
433 }
434
435#ifdef ANI_BUS_TYPE_SDIO
436 libra_detect_card_change();
437
438 do {
439 sdio_func_dev = libra_getsdio_funcdev();
440 if (NULL == sdio_func_dev) {
441 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not detected yet.",__func__);
442 attempts++;
443 }
444 else {
445 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN detecton succeeded",__func__);
446 break;
447 }
448
449 if(LIBRA_CARD_INSERT_DETECT_MAX_COUNT == attempts)
450 break;
451
452 msleep(250);
453
454 }while (attempts < LIBRA_CARD_INSERT_DETECT_MAX_COUNT);
455
456 //Retry to detect the card again by Powering Down the chip and Power up the chip
457 //again. This retry is done to recover from CRC Error
458 if (NULL == sdio_func_dev) {
459
460 attempts = 0;
461
462 //Vote off any PMIC voltage supplies
463 vos_chipPowerDown(NULL, NULL, NULL);
464
465 msleep(1000);
466
467 //Power Up Libra WLAN card first if not already powered up
468 vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
469 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
470 {
471 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not Powered Up. "
472 "exiting", __func__);
473 goto err_deep_sleep;
474 }
475
476 do {
477 sdio_func_dev = libra_getsdio_funcdev();
478 if (NULL == sdio_func_dev) {
479 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not detected yet.",__func__);
480 attempts++;
481 }
482 else {
483 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN detecton succeeded",__func__);
484 break;
485 }
486
487 if(attempts == 2)
488 break;
489
490 msleep(1000);
491
492 }while (attempts < 3);
493
494 }
495
496 if (NULL == sdio_func_dev) {
497 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not found!!",__func__);
498 goto err_deep_sleep;
499 }
500
501 SET_NETDEV_DEV(pAdapter->dev, &sdio_func_dev->dev);
502 libra_sdio_setprivdata (sdio_func_dev, pHddCtx);
503 atomic_set(&pHddCtx->sdio_claim_count, 0);
504 pHddCtx->parent_dev = &sdio_func_dev->dev;
505
506 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
507 "%s: calling WLANSAL_Start",__func__);
508 vosStatus = WLANSAL_Start(pHddCtx->pvosContext);
509 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
510 {
511 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
512 "%s: Failed to start SAL",__func__);
513 goto err_deep_sleep;
514 }
515
516 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
517 "%s: calling WLANBAL_ResumeChip",__func__);
518 vosStatus = WLANBAL_ResumeChip( pHddCtx->pvosContext );
519 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
520 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
521 {
522 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
523 "%s: Failed in WLANBAL_ResumeChip",__func__);
524 goto err_sal_stop;
525 }
526
527 vosStatus = WLANBAL_Start(pHddCtx->pvosContext);
528
529 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
530 {
531 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
532 "%s: Failed to start BAL",__func__);
533 goto err_sal_stop;
534 }
535#endif
536
537 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
538 "%s: calling hdd_set_sme_config",__func__);
539 vosStatus = hdd_set_sme_config( pHddCtx );
540 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
541 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
542 {
543 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
544 "%s: Failed in hdd_set_sme_config",__func__);
545#ifdef ANI_BUS_TYPE_SDIO
546 goto err_bal_stop;
547#else
548 goto err_deep_sleep;
549#endif
550 }
551
552 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
553 "%s: calling vos_start",__func__);
554 vosStatus = vos_start( pHddCtx->pvosContext );
555 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
556 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
557 {
558 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
559 "%s: Failed in vos_start",__func__);
560#ifdef ANI_BUS_TYPE_SDIO
561 goto err_bal_stop;
562#else
563 goto err_deep_sleep;
564#endif
565 }
566
567 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
568 "%s: calling hdd_post_voss_start_config",__func__);
569 vosStatus = hdd_post_voss_start_config( pHddCtx );
570 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
571 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
572 {
573 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
574 "%s: Failed in hdd_post_voss_start_config",__func__);
575 goto err_voss_stop;
576 }
577
578
579 //Open a SME session for future operation
580 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pHddCtx,
581 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
582 if ( !HAL_STATUS_SUCCESS( halStatus ) )
583 {
584 hddLog(VOS_TRACE_LEVEL_FATAL,"sme_OpenSession() failed with status code %08d [x%08lx]",
585 halStatus, halStatus );
586 goto err_voss_stop;
587
588 }
589
590 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
591
592 //Trigger the initial scan
593 hdd_wlan_initial_scan(pHddCtx);
594
595 return VOS_STATUS_SUCCESS;
596
597err_voss_stop:
598 vos_stop(pHddCtx->pvosContext);
599#ifdef ANI_BUS_TYPE_SDIO
600err_bal_stop:
601 WLANBAL_Stop(pHddCtx->pvosContext);
602err_sal_stop:
603 WLANSAL_Stop(pHddCtx->pvosContext);
604#endif
605err_deep_sleep:
606 return VOS_STATUS_E_FAILURE;
607
608}
609
610VOS_STATUS hdd_conf_hostarpoffload(hdd_context_t* pHddCtx, v_BOOL_t fenable)
611{
612 struct in_ifaddr **ifap = NULL;
613 struct in_ifaddr *ifa = NULL;
614 struct in_device *in_dev;
615 int i = 0;
616 hdd_adapter_t *pAdapter = NULL;
617 tSirHostOffloadReq offLoadRequest;
618
619 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: \n", __func__);
620#ifdef WLAN_FEATURE_PACKET_FILTERING
621 if (pHddCtx->cfg_ini->isMcAddrListFilter)
622 {
623 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
624 if (pAdapter != NULL)
625 {
626 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
627 "%s: Can't set multicast addr filtering in P2P-GO HDD", __FUNCTION__);
628 return VOS_STATUS_E_FAILURE;
629 }
630
631 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
632 if (pAdapter == NULL)
633 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
634
635 if(pAdapter == NULL)
636 {
637 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
638 return VOS_STATUS_E_FAILURE;
639 }
640 }
641 else
642 {
643#endif
644 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_INFRA_STATION);
645 if(pAdapter == NULL)
646 {
647 pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_P2P_CLIENT);
648 if(pAdapter == NULL)
649 {
650 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: HDD adapter context is Null", __FUNCTION__);
651 return VOS_STATUS_E_FAILURE;
652 }
653 }
654#ifdef WLAN_FEATURE_PACKET_FILTERING
655 }
656#endif
657 if(fenable)
658 {
659 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
660 {
661 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
662 ifap = &ifa->ifa_next)
663 {
664 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
665 {
666 break; /* found */
667 }
668 }
669 }
670
671 if(ifa && ifa->ifa_local)
672 {
673 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
674 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
675
676 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Enabled \n", __func__);
677
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700678 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
Jeff Johnson295189b2012-06-20 16:38:30 -0700679 {
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700680 if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
681 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting) ||
682 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
683 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting))
684 {
685 offLoadRequest.enableOrDisable =
686 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
687 }
688 }
689 else if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
690 pHddCtx->cfg_ini->mcastBcastFilterSetting ) ||
691 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
692 pHddCtx->cfg_ini->mcastBcastFilterSetting))
693 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700694 offLoadRequest.enableOrDisable =
695 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
696 }
697
698 //converting u32 to IPV4 address
699 for(i = 0 ; i < 4; i++)
700 {
701 offLoadRequest.params.hostIpv4Addr[i] =
702 (ifa->ifa_local >> (i*8) ) & 0xFF ;
703 }
704 hddLog(VOS_TRACE_LEVEL_WARN, " Enable SME HostOffload: %d.%d.%d.%d",
705 offLoadRequest.params.hostIpv4Addr[0],
706 offLoadRequest.params.hostIpv4Addr[1],
707 offLoadRequest.params.hostIpv4Addr[2],
708 offLoadRequest.params.hostIpv4Addr[3]);
709
710 if (eHAL_STATUS_SUCCESS !=
Jeff Johnsone7245742012-09-05 17:12:55 -0700711 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
712 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700713 {
714 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
715 "feature\n", __func__);
716 return VOS_STATUS_E_FAILURE;
717 }
718 return VOS_STATUS_SUCCESS;
719 }
720 else
721 {
722 hddLog(VOS_TRACE_LEVEL_INFO, "%s:IP Address is not assigned \n", __func__);
723 return VOS_STATUS_E_AGAIN;
724 }
725 }
726 else
727 {
728 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
729 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
730 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
731
Jeff Johnsone7245742012-09-05 17:12:55 -0700732 if (eHAL_STATUS_SUCCESS != sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
733 &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700734 {
735 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
736 "offload feature\n", __func__);
737 return VOS_STATUS_E_FAILURE;
738 }
739 return VOS_STATUS_SUCCESS;
740 }
741}
742
743void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
744{
745 eHalStatus halStatus = eHAL_STATUS_FAILURE;
746#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
747 tpAniSirGlobal pMac = (tpAniSirGlobal) vos_get_context(VOS_MODULE_ID_SME, pHddCtx->pvosContext);
748#else
749 tpSirWlanSetRxpFilters wlanRxpFilterParam =
750 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
751 if(NULL == wlanRxpFilterParam)
752 {
753 hddLog(VOS_TRACE_LEVEL_FATAL,
754 "%s: vos_mem_alloc failed ", __func__);
755 return;
756 }
757#endif
758 hddLog(VOS_TRACE_LEVEL_INFO,
759 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
760#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
761 if ( pMac )
762 {
763 halStatus = halRxp_configureRxpFilterMcstBcst( pMac, setfilter);
764 }
765 else
766 {
767 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pMac is initialised to NULL",__func__ );
768 }
769#else
770 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
771 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
772 pHddCtx->cfg_ini->mcastBcastFilterSetting;
773 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
774#endif
775 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
776 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
777}
778
Jeff Johnsone7245742012-09-05 17:12:55 -0700779#ifdef CONFIG_HAS_EARLYSUSPEND
Jeff Johnson295189b2012-06-20 16:38:30 -0700780#ifdef FEATURE_WLAN_INTEGRATED_SOC
781static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
782 hdd_adapter_t *pAdapter)
783{
784 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Madan Mohan Koyyalamudi51d87f72012-09-24 12:05:23 -0700785 VOS_STATUS vstatus = VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700786 tpSirWlanSuspendParam wlanSuspendParam =
787 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
788
789 if(NULL == wlanSuspendParam)
790 {
791 hddLog(VOS_TRACE_LEVEL_FATAL,
792 "%s: vos_mem_alloc failed ", __func__);
793 return;
794 }
795
796 hddLog(VOS_TRACE_LEVEL_INFO,
797 "%s: send wlan suspend indication", __func__);
798
799 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
800 {
801 if((pHddCtx->cfg_ini->fhostArpOffload) &&
802 (eConnectionState_Associated ==
803 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
804 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700805 vstatus = hdd_conf_hostarpoffload(pHddCtx, TRUE);
806 if (!VOS_IS_STATUS_SUCCESS(vstatus))
Jeff Johnson295189b2012-06-20 16:38:30 -0700807 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700808 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
809 {
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700810 wlanSuspendParam->configuredMcstBcstFilterSetting =
811 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting;
812 pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE;
Jeff Johnson43971f52012-07-17 12:26:56 -0700813 }
814 else
815 {
816 wlanSuspendParam->configuredMcstBcstFilterSetting =
817 pHddCtx->cfg_ini->mcastBcastFilterSetting;
818 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700819 hddLog(VOS_TRACE_LEVEL_INFO,
820 "%s:Failed to enable ARPOFFLOAD Feature %d\n",
Jeff Johnson43971f52012-07-17 12:26:56 -0700821 __func__, vstatus);
Jeff Johnson295189b2012-06-20 16:38:30 -0700822 }
Jeff Johnson43971f52012-07-17 12:26:56 -0700823 else
824 {
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700825 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
826 {
827 if((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
828 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting))
829 {
830 wlanSuspendParam->configuredMcstBcstFilterSetting =
831 HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST;
832 }
833 else if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
834 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting))
835 {
836 wlanSuspendParam->configuredMcstBcstFilterSetting =
837 HDD_MCASTBCASTFILTER_FILTER_NONE;
838 }
839 else
840 {
841 wlanSuspendParam->configuredMcstBcstFilterSetting =
842 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting;
843 }
844
845 pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE;
846 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend =
847 wlanSuspendParam->configuredMcstBcstFilterSetting;
848 }
849 else
850 {
851 if (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
852 pHddCtx->cfg_ini->mcastBcastFilterSetting)
853 {
854 wlanSuspendParam->configuredMcstBcstFilterSetting =
855 HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST;
856 }
857 else if(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
858 pHddCtx->cfg_ini->mcastBcastFilterSetting)
859 {
860 wlanSuspendParam->configuredMcstBcstFilterSetting =
861 HDD_MCASTBCASTFILTER_FILTER_NONE;
862 }
863 else
864 {
865 wlanSuspendParam->configuredMcstBcstFilterSetting =
866 pHddCtx->cfg_ini->mcastBcastFilterSetting;
867 }
868
869 pHddCtx->dynamic_mcbc_filter.enableSuspend = FALSE;
870 }
871 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700872 }
873 else
874 {
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700875 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
876 {
877 wlanSuspendParam->configuredMcstBcstFilterSetting =
Jeff Johnson43971f52012-07-17 12:26:56 -0700878 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting;
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700879 pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE;
880 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend =
Jeff Johnson43971f52012-07-17 12:26:56 -0700881 wlanSuspendParam->configuredMcstBcstFilterSetting;
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700882 }
883 else
884 {
885 pHddCtx->dynamic_mcbc_filter.enableSuspend = FALSE;
886 wlanSuspendParam->configuredMcstBcstFilterSetting =
887 pHddCtx->cfg_ini->mcastBcastFilterSetting;
888 }
889 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700890
891#ifdef WLAN_FEATURE_PACKET_FILTERING
892 if (pHddCtx->cfg_ini->isMcAddrListFilter)
893 {
894 /*Multicast addr list filter is enabled during suspend*/
895 if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
896 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT))
897 && pHddCtx->mc_addr_list.mc_cnt
898 && (eConnectionState_Associated ==
899 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
900 {
901 /*set the filter*/
Jeff Johnsone7245742012-09-05 17:12:55 -0700902 wlan_hdd_set_mc_addr_list(pHddCtx, TRUE, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700903 }
904 }
905#endif
906 }
907
908 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
909 if(eHAL_STATUS_SUCCESS == halStatus)
910 {
911 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
912 }
913}
914
Jeff Johnsone7245742012-09-05 17:12:55 -0700915static void hdd_conf_resume_ind(hdd_context_t* pHddCtx, v_U8_t sessionId)
Jeff Johnson295189b2012-06-20 16:38:30 -0700916{
Jeff Johnson43971f52012-07-17 12:26:56 -0700917 VOS_STATUS vstatus;
Jeff Johnson295189b2012-06-20 16:38:30 -0700918 tpSirWlanResumeParam wlanResumeParam =
919 vos_mem_malloc(sizeof(tSirWlanResumeParam));
920
921 if(NULL == wlanResumeParam)
922 {
923 hddLog(VOS_TRACE_LEVEL_FATAL,
924 "%s: vos_mem_alloc failed ", __func__);
925 return;
926 }
927
928 hddLog(VOS_TRACE_LEVEL_INFO,
929 "%s: send wlan resume indication", __func__);
930
931 if(pHddCtx->cfg_ini->fhostArpOffload)
932 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700933 vstatus = hdd_conf_hostarpoffload(pHddCtx, FALSE);
934 if (!VOS_IS_STATUS_SUCCESS(vstatus))
Jeff Johnson295189b2012-06-20 16:38:30 -0700935 {
936 hddLog(VOS_TRACE_LEVEL_INFO, "%s:Failed to disable ARPOFFLOAD "
Jeff Johnson43971f52012-07-17 12:26:56 -0700937 "Feature %d\n", __func__, vstatus);
Jeff Johnson295189b2012-06-20 16:38:30 -0700938 }
939 }
940 if (pHddCtx->dynamic_mcbc_filter.enableSuspend)
941 {
942 wlanResumeParam->configuredMcstBcstFilterSetting =
943 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend;
944 }
945 else
946 {
947 wlanResumeParam->configuredMcstBcstFilterSetting =
948 pHddCtx->cfg_ini->mcastBcastFilterSetting;
949 }
950 sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
951
952#ifdef WLAN_FEATURE_PACKET_FILTERING
953 if (pHddCtx->cfg_ini->isMcAddrListFilter)
954 {
955 /*Mutlicast addr filtering is enabled*/
956 if(pHddCtx->mc_addr_list.isFilterApplied)
957 {
958 /*Filter applied during suspend mode*/
959 /*Clear it here*/
Jeff Johnsone7245742012-09-05 17:12:55 -0700960 wlan_hdd_set_mc_addr_list(pHddCtx, FALSE, sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700961 }
962 }
963#endif
964}
965#endif
966
Jeff Johnson295189b2012-06-20 16:38:30 -0700967//Suspend routine registered with Android OS
968void hdd_suspend_wlan(struct early_suspend *wlan_suspend)
969{
970 hdd_context_t *pHddCtx = NULL;
971 v_CONTEXT_t pVosContext = NULL;
972
973 hdd_adapter_t *pAdapter = NULL;
974 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
975 VOS_STATUS status;
976#ifdef ANI_BUS_TYPE_SDIO
977 struct sdio_func *sdio_func_dev = NULL;
978#endif
979 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
980
981 //Get the global VOSS context.
982 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
983 if(!pVosContext) {
984 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
985 return;
986 }
987
988 //Get the HDD context.
989 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
990
991 if(!pHddCtx) {
992 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
993 return;
994 }
995
996 if (pHddCtx->isLogpInProgress) {
997 hddLog(VOS_TRACE_LEVEL_ERROR,
998 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
999 return;
1000 }
1001
1002#ifdef ANI_BUS_TYPE_SDIO
1003 sdio_func_dev = libra_getsdio_funcdev();
1004
1005 if(sdio_func_dev == NULL)
1006 {
1007 /* Our card got removed */
1008 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1009 return;
1010 }
1011
1012 if(!sd_is_drvdata_available(sdio_func_dev))
1013 {
1014 /* Our card got removed */
1015 hddLog(VOS_TRACE_LEVEL_FATAL,
1016 "%s: HDD context is not available in sdio_func_dev!",__func__);
1017 return;
1018 }
1019
1020 sd_claim_host(sdio_func_dev);
1021
1022 // Prevent touching the pMac while LOGP reset in progress, we should never get here
1023 // as the wake lock is already acquired and it would prevent from entering suspend
1024 if (pHddCtx->isLogpInProgress) {
1025 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Ignore suspend wlan, LOGP in progress!", __func__);
1026 sd_release_host(sdio_func_dev);
1027 return;
1028 }
1029#endif
1030
1031 /*loop through all adapters. TBD fix for Concurrency */
1032 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1033 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1034 {
1035 pAdapter = pAdapterNode->pAdapter;
1036 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
1037 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1038
1039 { //just do for station interface
1040 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1041 pAdapterNode = pNext;
1042 continue;
1043 }
1044
1045#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1046 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1047 {
1048 //stop the interface before putting the chip to standby
1049 netif_tx_disable(pAdapter->dev);
1050 netif_carrier_off(pAdapter->dev);
1051 }
1052 else if (pHddCtx->cfg_ini->nEnableSuspend ==
1053 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
1054 {
1055 //Execute deep sleep procedure
1056 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1057 }
1058#endif
1059
Jeff Johnsone7245742012-09-05 17:12:55 -07001060 //Apply Dynamic Dtim For P2P
1061 //Only if ignoreDynamicDtimInP2pMode is not set in ini
Jeff Johnson295189b2012-06-20 16:38:30 -07001062 if((pHddCtx->cfg_ini->enableDynamicDTIM ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001063 pHddCtx->cfg_ini->enableModulatedDTIM) &&
1064 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
1065 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
1066 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07001067 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
1068 (eConnectionState_Associated ==
1069 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
1070 (pHddCtx->cfg_ini->fIsBmpsEnabled))
1071 {
1072 tSirSetPowerParamsReq powerRequest = { 0 };
1073
1074 powerRequest.uIgnoreDTIM = 1;
1075
1076 /*Back up the actual values from CFG */
1077 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM,
1078 &pHddCtx->hdd_actual_ignore_DTIM_value);
1079 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL,
1080 &pHddCtx->hdd_actual_LI_value);
1081
1082 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1083 {
1084 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
1085 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
1086 }
1087 else
1088 {
1089 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
1090 }
1091
1092 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
1093 *specified during Enter/Exit BMPS when LCD off*/
1094 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1095 NULL, eANI_BOOLEAN_FALSE);
1096 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1097 NULL, eANI_BOOLEAN_FALSE);
1098
1099 /* switch to the DTIM specified in cfg.ini */
1100 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1101 "Switch to DTIM%d \n", powerRequest.uListenInterval);
1102 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest);
1103
1104 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1105 {
1106 /* put the device into full power */
1107 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1108
1109 /* put the device back into BMPS */
1110 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1111
1112 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1113 }
1114 }
1115
1116#ifdef FEATURE_WLAN_INTEGRATED_SOC
1117 /*Suspend notification sent down to driver*/
1118 hdd_conf_suspend_ind(pHddCtx, pAdapter);
1119#else
1120 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER) {
1121 if(eConnectionState_Associated ==
1122 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) {
1123 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
1124 halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME,
1125 pHddCtx->pvosContext), FALSE);
1126 }
1127 }
1128#endif
1129 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1130 pAdapterNode = pNext;
1131 }
1132 pHddCtx->hdd_wlan_suspended = TRUE;
1133
1134#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1135 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1136 {
1137 hdd_enter_standby(pHddCtx);
1138 }
1139#endif
1140#ifdef ANI_BUS_TYPE_SDIO
1141 sd_release_host(sdio_func_dev);
1142#endif
1143
1144 return;
1145}
1146
1147static void hdd_PowerStateChangedCB
1148(
1149 v_PVOID_t callbackContext,
1150 tPmcState newState
1151)
1152{
1153 hdd_context_t *pHddCtx = callbackContext;
1154
1155 /* if the driver was not in BMPS during early suspend,
1156 * the dynamic DTIM is now updated at Riva */
1157 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1158 && pHddCtx->cfg_ini->enableDynamicDTIM
1159 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1160 {
1161 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1162 }
1163 spin_lock(&pHddCtx->filter_lock);
1164 if((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1165 && (pHddCtx->hdd_mcastbcast_filter_set != TRUE)) {
1166 spin_unlock(&pHddCtx->filter_lock);
1167 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
1168#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1169 halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME, pHddCtx->pvosContext), FALSE);
1170#endif
1171 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1172 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
1173 }
1174 else
1175 spin_unlock(&pHddCtx->filter_lock);
1176}
1177
1178
1179
1180void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1181{
1182 v_CONTEXT_t pVosContext;
1183 tHalHandle smeContext;
1184
1185 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1186 if (NULL == pVosContext)
1187 {
1188 hddLog(LOGE, "%s: Invalid pContext", __FUNCTION__);
1189 return;
1190 }
1191 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1192 if (NULL == smeContext)
1193 {
1194 hddLog(LOGE, "%s: Invalid smeContext", __FUNCTION__);
1195 return;
1196 }
1197
1198 spin_lock_init(&pHddCtx->filter_lock);
1199 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1200 pHddCtx->cfg_ini->nEnableSuspend)
1201 {
1202 pmcRegisterDeviceStateUpdateInd(smeContext,
1203 hdd_PowerStateChangedCB, pHddCtx);
1204 }
1205}
1206
1207void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1208{
1209 v_CONTEXT_t pVosContext;
1210 tHalHandle smeContext;
1211
1212 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1213 if (NULL == pVosContext)
1214 {
1215 hddLog(LOGE, "%s: Invalid pContext", __FUNCTION__);
1216 return;
1217 }
1218 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1219 if (NULL == smeContext)
1220 {
1221 hddLog(LOGE, "%s: Invalid smeContext", __FUNCTION__);
1222 return;
1223 }
1224
1225 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1226 pHddCtx->cfg_ini->nEnableSuspend)
1227 {
1228 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1229 }
1230}
1231
1232void hdd_resume_wlan(struct early_suspend *wlan_suspend)
1233{
1234 hdd_context_t *pHddCtx = NULL;
1235 hdd_adapter_t *pAdapter = NULL;
1236 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1237 VOS_STATUS status;
1238 v_CONTEXT_t pVosContext = NULL;
1239#ifdef ANI_BUS_TYPE_SDIO
1240 struct sdio_func *sdio_func_dev = NULL;
1241#endif
1242 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1243
1244 //Get the global VOSS context.
1245 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1246 if(!pVosContext) {
1247 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1248 return;
1249 }
1250
1251 //Get the HDD context.
1252 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1253
1254 if(!pHddCtx) {
1255 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1256 return;
1257 }
1258
1259 if (pHddCtx->isLogpInProgress) {
1260 hddLog(VOS_TRACE_LEVEL_INFO,
1261 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1262 return;
1263 }
1264
1265#ifdef ANI_BUS_TYPE_SDIO
1266 sdio_func_dev = libra_getsdio_funcdev();
1267
1268 if(sdio_func_dev == NULL)
1269 {
1270 /* Our card got removed */
1271 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1272 return;
1273 }
1274
1275 if(!sd_is_drvdata_available(sdio_func_dev))
1276 {
1277 /* Our card got removed */
1278 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD context is not available "
1279 "in sdio_func_dev!",__func__);
1280 return;
1281 }
1282
1283 sd_claim_host(sdio_func_dev);
1284
1285 // Prevent touching the pMac while LOGP reset in progress,
1286 if (pHddCtx->isLogpInProgress) {
1287 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Ignore resume wlan, LOGP in progress!", __func__);
1288 sd_release_host(sdio_func_dev);
1289 return;
1290 }
1291#endif
1292 pHddCtx->hdd_wlan_suspended = FALSE;
1293 /*loop through all adapters. Concurrency */
1294 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1295
1296 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1297 {
1298 pAdapter = pAdapterNode->pAdapter;
1299 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
1300 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1301 { //just do for station interface
1302 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1303 pAdapterNode = pNext;
1304 continue;
1305 }
1306#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1307 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1308 {
1309 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1310 hdd_exit_deep_sleep(pAdapter);
1311 }
1312#endif
1313
1314 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1315 {
1316 /*Switch back to DTIM 1*/
1317 tSirSetPowerParamsReq powerRequest = { 0 };
1318
1319 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1320 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
1321
1322 /*Disabled ModulatedDTIM if enabled on suspend*/
1323 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1324 powerRequest.uDTIMPeriod = 0;
1325
1326 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1327 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1328 NULL, eANI_BOOLEAN_FALSE);
1329 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1330 NULL, eANI_BOOLEAN_FALSE);
1331
1332 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1333 "Switch to DTIM%d \n",powerRequest.uListenInterval);
1334 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest);
1335
1336 /* put the device into full power */
1337 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1338
1339 /* put the device back into BMPS */
1340 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1341
1342 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1343 }
1344
1345 if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) {
1346#ifdef FEATURE_WLAN_INTEGRATED_SOC
Jeff Johnsone7245742012-09-05 17:12:55 -07001347 hdd_conf_resume_ind(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001348#else
1349 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
1350 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1351 halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME,
1352 pHddCtx->pvosContext), TRUE);
1353#endif
1354 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1355 }
1356 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1357 pAdapterNode = pNext;
1358 }
1359
1360#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1361 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1362 {
1363 hdd_exit_standby(pHddCtx);
1364 }
1365#endif
1366
1367#ifdef ANI_BUS_TYPE_SDIO
1368 sd_release_host(sdio_func_dev);
1369#endif
1370 return;
1371}
1372
1373VOS_STATUS hdd_wlan_reset(void)
1374{
1375 VOS_STATUS vosStatus;
1376 hdd_context_t *pHddCtx = NULL;
1377 v_CONTEXT_t pVosContext = NULL;
1378 pVosSchedContext vosSchedContext = NULL;
1379#ifdef ANI_BUS_TYPE_SDIO
1380 struct sdio_func *sdio_func_dev_new = NULL;
1381 struct sdio_func *sdio_func_dev_current = NULL;
1382 unsigned int attempts = 0;
1383#endif
1384 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1385
1386 //Get the global VOSS context.
1387 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1388 if(!pVosContext) {
1389 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1390 return VOS_STATUS_E_FAILURE;
1391 }
1392
1393 //Get the HDD context.
1394 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1395 if(!pHddCtx) {
1396 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1397 return VOS_STATUS_E_FAILURE;
1398 }
1399#ifdef ANI_BUS_TYPE_SDIO
1400 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SAL Stop",__func__);
1401 //Invoke SAL stop
1402 vosStatus = WLANSAL_Stop( pVosContext );
1403 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1404 {
1405 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1406 "%s: Failed to stop SAL",__func__);
1407 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1408 }
1409#endif
1410 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Asserting Deep Sleep",__func__);
1411 //Assert Deep sleep signal now to put Libra HW in lowest power state
1412 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
1413 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1414
1415 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Power Down Chip",__func__);
1416 //Vote off any PMIC voltage supplies
1417 vos_chipPowerDown(NULL, NULL, NULL);
1418
1419
1420 /**
1421 EVM issue is observed with 1.6Mhz freq for 1.3V supply in wlan standalone case.
1422 During concurrent operation (e.g. WLAN and WCDMA) this issue is not observed.
1423 To workaround, wlan will vote for 3.2Mhz during startup and will vote for 1.6Mhz
1424 during exit.
1425 */
1426 if (vos_chipVoteFreqFor1p3VSupply(NULL, NULL, NULL, VOS_NV_FREQUENCY_FOR_1_3V_SUPPLY_1P6MH) != VOS_STATUS_SUCCESS)
1427 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1428 "%s: Failed to set the freq to 1.6Mhz for 1.3V Supply",__func__ );
1429
1430 //Disable IMPS/BMPS as we do not want the device to enter any power
1431 //save mode on its own during reset sequence
1432 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1433 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1434 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1435
1436 //Kill all the threads first. We do not want any messages
1437 //to be a processed any more and the best way to ensure that
1438 //is to terminate the threads gracefully.
1439 vosSchedContext = get_vos_sched_ctxt();
1440
1441 /* Wakeup Mc Thread if Suspended */
1442 if(TRUE == pHddCtx->isMcThreadSuspended){
1443 complete(&vosSchedContext->ResumeMcEvent);
1444 pHddCtx->isMcThreadSuspended= FALSE;
1445 }
1446 /* Wakeup Tx Thread if Suspended */
1447 if(TRUE == pHddCtx->isTxThreadSuspended){
1448 complete(&vosSchedContext->ResumeTxEvent);
1449 pHddCtx->isTxThreadSuspended= FALSE;
1450 }
1451#ifdef FEATURE_WLAN_INTEGRATED_SOC
1452 /* Wakeup Rx Thread if Suspended */
1453 if(TRUE == pHddCtx->isRxThreadSuspended){
1454 complete(&vosSchedContext->ResumeRxEvent);
1455 pHddCtx->isRxThreadSuspended= FALSE;
1456 }
1457#endif
1458
1459 /* Reset the Suspend Variable */
1460 pHddCtx->isWlanSuspended = FALSE;
1461
1462 //Wait for MC to exit
1463 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1464 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1465 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1466 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
1467 wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1468
1469 //Wait for TX to exit
1470 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1471 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1472 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1473 wake_up_interruptible(&vosSchedContext->txWaitQueue);
1474 wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1475
1476#ifdef FEATURE_WLAN_INTEGRATED_SOC
1477 //Wait for RX to exit
1478 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1479 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1480 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1481 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
1482 wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1483#endif
1484
1485 /* Cancel the vote for XO Core ON in LOGP since we are reinitializing our driver
1486 * This is done here to ensure there is no race condition since MC and TX thread have
1487 * exited at this point
1488 */
1489 hddLog(VOS_TRACE_LEVEL_WARN, "In LOGP: Cancel XO Core ON vote\n");
1490 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
1491 {
1492 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
1493 "Power consumed will be high\n");
1494 }
1495
1496 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1497 //Stop SME - Cannot invoke vos_stop as vos_stop relies
1498 //on threads being running to process the SYS Stop
1499 vosStatus = sme_Stop( pHddCtx->hHal, TRUE );
1500 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1501
1502 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1503 //Stop MAC (PE and HAL)
1504 vosStatus = macStop( pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
1505 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1506
1507 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1508 //Stop TL
1509 vosStatus = WLANTL_Stop( pVosContext );
1510 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1511
1512#ifdef ANI_BUS_TYPE_SDIO
1513 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing BAL STOP",__func__);
1514 vosStatus = WLANBAL_Stop( pVosContext );
1515 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1516 {
1517 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1518 "%s: Failed to stop BAL",__func__);
1519 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1520 }
1521#endif
1522#ifdef CONFIG_HAS_EARLYSUSPEND
1523 hdd_unregister_mcast_bcast_filter(pHddCtx);
1524#endif
1525
1526 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Flush Queues",__func__);
1527 //Clean up message queues of TX and MC thread
1528 vos_sched_flush_mc_mqs(vosSchedContext);
1529 vos_sched_flush_tx_mqs(vosSchedContext);
1530#ifdef FEATURE_WLAN_INTEGRATED_SOC
1531 vos_sched_flush_rx_mqs(vosSchedContext);
1532#endif
1533
1534 //Deinit all the TX and MC queues
1535 vos_sched_deinit_mqs(vosSchedContext);
1536
1537 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing VOS Close",__func__);
1538
1539 //Close VOSS
1540 vos_close(pVosContext);
1541
1542#ifdef ANI_BUS_TYPE_SDIO
1543 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing BAL Close",__func__);
1544 vosStatus = WLANBAL_Close(pVosContext);
1545 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1546 {
1547 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1548 "%s: Failed to close BAL",__func__);
1549 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1550 }
1551 //Get the Current SDIO Func
1552 sdio_func_dev_current = libra_getsdio_funcdev();
1553
1554 if(NULL != sdio_func_dev_current) {
1555 libra_detect_card_change();
1556 attempts = 0;
1557 do {
1558 msleep(100);
1559 //Get the SDIO func device
1560 sdio_func_dev_current = libra_getsdio_funcdev();
1561 if(NULL == sdio_func_dev_current) {
1562 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Card Removed Successfully",__func__);
1563 break;
1564 }
1565 else {
1566 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Trying Again",__func__);
1567 attempts++;
1568 }
1569 } while (attempts < LIBRA_CARD_REMOVE_DETECT_MAX_COUNT);
1570
1571 if(LIBRA_CARD_REMOVE_DETECT_MAX_COUNT == attempts) {
1572 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Fatal",__func__);
1573 goto err_fail;
1574 }
1575 }
1576#endif
1577
1578#ifdef TIMER_MANAGER
1579 vos_timer_exit();
1580#endif
1581
1582#ifdef MEMORY_DEBUG
1583 vos_mem_clean();
1584#endif
1585#ifdef ANI_BUS_TYPE_SDIO
1586 //Reinitialize the variable
1587 attempts = 0;
1588#endif
1589
1590 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Powering Up chip Again",__func__);
1591 //Power Up Libra WLAN card first if not already powered up
1592 vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
1593 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1594 {
1595 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
1596 "exiting", __func__);
1597 goto err_pwr_fail;
1598 }
1599
1600#ifdef ANI_BUS_TYPE_SDIO
1601 // Trigger card detect
1602 libra_detect_card_change();
1603
1604 //Reinitialize the variable
1605 attempts = 0;
1606
1607 do {
1608 msleep(500);
1609
1610 //Get the SDIO func device
1611 sdio_func_dev_new = libra_getsdio_funcdev();
1612 if(sdio_func_dev_new != NULL)
1613 {
1614 //Not needed but in case it causes probs then put a loop and set for each adapter
1615 //SET_NETDEV_DEV(pAdapter->dev, &sdio_func_dev_new->dev);
1616 libra_sdio_setprivdata (sdio_func_dev_new, pHddCtx);
1617 atomic_set(&pHddCtx->sdio_claim_count, 0);
1618 pHddCtx->parent_dev = &sdio_func_dev_new->dev;
1619 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1620 "%s: Card Detected Successfully %p",__func__,
1621 sdio_func_dev_new);
1622 break;
1623 }
1624 else
1625 {
1626 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1627 "%s: Failed to detect card change %p",__func__,
1628 sdio_func_dev_new);
1629 attempts++;
1630 }
1631 }while (attempts < LIBRA_CARD_INSERT_DETECT_MAX_COUNT);
1632
1633 if(LIBRA_CARD_INSERT_DETECT_MAX_COUNT == attempts){
1634 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN fail to detect in reset, "
1635 "exiting", __func__);
1636 goto err_fail;
1637 }
1638 //Get the SDIO func device
1639 sdio_func_dev_new = libra_getsdio_funcdev();
1640 if(sdio_func_dev_new != NULL)
1641 {
1642 sd_claim_host(sdio_func_dev_new);
1643 /* Enable IRQ capabilities in host controller */
1644 libra_disable_sdio_irq_capability(sdio_func_dev_new, 0);
1645 libra_enable_sdio_irq(sdio_func_dev_new, 1);
1646 sd_release_host(sdio_func_dev_new);
1647 }
1648 else
1649 {
1650 /* Our card got removed before LOGP. */
1651 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1652 goto err_fail;
1653 }
1654
1655 vosStatus = WLANBAL_Open(pVosContext);
1656 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1657 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1658 {
1659 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1660 "%s: Failed to open BAL",__func__);
1661 goto err_fail;
1662 }
1663
1664 vosStatus = WLANSAL_Start(pVosContext);
1665 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1666 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1667 {
1668 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to start SAL",__func__);
1669 goto err_balclose;
1670 }
1671
1672 /* Chip is reset so allow Lower MAC to start accessing WLAN registers. Note HDD is still blocked */
1673 vos_set_logp_in_progress(VOS_MODULE_ID_HDD, FALSE);
1674
1675 /* Start BAL */
1676 vosStatus = WLANBAL_Start(pVosContext);
1677
1678 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1679 {
1680 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1681 "%s: Failed to start BAL",__func__);
1682 goto err_salstop;
1683 }
1684#endif
1685 // Open VOSS
1686 vosStatus = vos_open( &pVosContext, 0);
1687
1688 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1689 {
1690 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1691#ifdef ANI_BUS_TYPE_SDIO
1692 goto err_balstop;
1693#else
1694 goto err_pwr_fail;
1695#endif
1696 }
1697
1698 /* Save the hal context in Adapter */
1699 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1700
1701 if ( NULL == pHddCtx->hHal )
1702 {
1703 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1704 goto err_vosclose;
1705 }
1706 // Set the SME configuration parameters...
1707 vosStatus = hdd_set_sme_config(pHddCtx);
1708
1709 if ( VOS_STATUS_SUCCESS != vosStatus )
1710 {
1711 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1712 goto err_vosclose;
1713 }
1714
1715 //Initialize the WMM module
1716 vosStatus = hdd_wmm_init(pHddCtx);
1717 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1718 {
1719 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __FUNCTION__);
1720 goto err_vosclose;
1721 }
1722
1723 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
1724 Note: Firmware image will be read and downloaded inside vos_start API */
1725 vosStatus = vos_start( pVosContext );
1726 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1727 {
1728 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
1729 goto err_vosclose;
1730 }
1731
1732 vosStatus = hdd_post_voss_start_config( pHddCtx );
1733 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1734 {
1735 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
1736 __func__);
1737 goto err_vosstop;
1738 }
1739
1740 /* Restart all adapters */
1741 hdd_start_all_adapters(pHddCtx);
1742 pHddCtx->isLogpInProgress = FALSE;
1743 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1744#ifdef CONFIG_HAS_EARLYSUSPEND
1745 hdd_register_mcast_bcast_filter(pHddCtx);
1746#endif
1747
1748 // Allow the phone to go to sleep
1749 hdd_allow_suspend();
1750
1751 goto success;
1752
1753err_vosstop:
1754 vos_stop(pVosContext);
1755
1756err_vosclose:
1757 vos_close(pVosContext );
1758 vos_sched_close(pVosContext);
1759
1760#ifdef ANI_BUS_TYPE_SDIO
1761err_balstop:
1762#ifndef ANI_MANF_DIAG
1763 wlan_hdd_enable_deepsleep(pVosContext);
1764#endif
1765 WLANBAL_Stop(pVosContext);
1766 WLANBAL_SuspendChip(pVosContext);
1767
1768err_salstop:
1769 WLANSAL_Stop(pVosContext);
1770
1771err_balclose:
1772 WLANBAL_Close(pVosContext);
1773
1774err_fail:
1775 //Assert Deep sleep signal now to put Libra HW in lowest power state
1776 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
1777
1778 //Vote off any PMIC voltage supplies
1779 vos_chipPowerDown(NULL, NULL, NULL);
1780#endif
1781
1782err_pwr_fail:
1783 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
1784
1785 // Allow the phone to go to sleep
1786 hdd_allow_suspend();
1787
1788#ifdef CONFIG_HAS_EARLYSUSPEND
1789 // unregister suspend/resume callbacks
1790 if(pHddCtx->cfg_ini->nEnableSuspend)
1791 unregister_wlan_suspend();
1792#endif
1793
1794 // Unregister the Net Device Notifier
1795 unregister_netdevice_notifier(&hdd_netdev_notifier);
1796
1797 //Clean up HDD Nlink Service
1798 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1799 nl_srv_exit();
1800
1801 hdd_close_all_adapters(pHddCtx);
1802 //Free up dynamically allocated members inside HDD Adapter
1803 kfree(pHddCtx->cfg_ini);
1804 pHddCtx->cfg_ini= NULL;
1805
1806#ifdef CONFIG_CFG80211
1807 wiphy_unregister(pHddCtx->wiphy);
1808 wiphy_free(pHddCtx->wiphy);
1809#else
1810 vos_mem_free(pHddCtx);
1811#endif
1812
1813#ifdef ANI_BUS_TYPE_SDIO
1814 WLANSAL_Close(pVosContext);
1815#endif
1816 vos_preClose(&pVosContext);
1817
1818#ifdef MEMORY_DEBUG
1819 vos_mem_exit();
1820#endif
1821
1822 return -1;
1823
1824success:
1825 //Trigger replay of BTC events
1826 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1827 return VOS_STATUS_SUCCESS;
1828
1829}
1830
1831
1832
1833VOS_STATUS hdd_wlan_reset_initialization(void)
1834{
1835#ifdef ANI_BUS_TYPE_SDIO
1836 struct sdio_func *sdio_func_dev = NULL;
1837 v_U8_t regValue = 0;
1838 int err_ret = 0;
1839#endif
1840 v_CONTEXT_t pVosContext = NULL;
1841
1842 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1843
1844 //Get the global VOSS context.
1845 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1846 if(!pVosContext)
1847 {
1848 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1849 return VOS_STATUS_E_FAILURE;
1850 }
1851
1852 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1853
1854 // Prevent the phone from going to sleep
1855 hdd_prevent_suspend();
1856
1857#ifdef ANI_BUS_TYPE_SDIO
1858 /* Clear pending interrupt and disable Interrupts. Use only CMD52 */
1859 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1860 "%s LOGP in progress. Disabling Interrupt", __func__);
1861
1862 sdio_func_dev = libra_getsdio_funcdev();
1863
1864 if(sdio_func_dev == NULL)
1865 {
1866 /* Our card got removed before LOGP. Continue with reset anyways */
1867 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1868 return VOS_STATUS_SUCCESS;
1869 }
1870
1871 sd_claim_host(sdio_func_dev);
1872
1873 regValue = 0;
1874 libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_SIF_INT_EN_REG,
1875 &regValue, 1, &err_ret);
1876
1877 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1878 "%s LOGP Cleared SIF_SIF_INT_EN_REG status:%d", __func__,err_ret);
1879
1880 regValue = 0;
1881 libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_BAR4_INT_PEND_REG,
1882 &regValue, 1, &err_ret);
1883
1884 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1885 "%s LOGP Cleared SIF_BAR4_INT_PEND_REG status :%d", __func__,err_ret);
1886
1887 regValue = 0;
1888 libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_BAR4_INT_ENABLE_REG,
1889 &regValue, 1, &err_ret);
1890
1891 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1892 "%s LOGP Cleared SIF_BAR4_INT_ENABLE_REG: Status:%d", __func__,err_ret);
1893
1894 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing Suspend Chip",__func__);
1895
1896 //Put the chip is standby before asserting deep sleep
1897 WLANBAL_SuspendChip_NoLock( pVosContext );
1898
1899 sd_release_host(sdio_func_dev);
1900#endif
1901
1902 return VOS_STATUS_SUCCESS;
1903}
1904
1905
1906void register_wlan_suspend(void)
1907{
1908 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Register WLAN suspend/resume "
1909 "callbacks",__func__);
1910 wlan_early_suspend.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING;
1911 wlan_early_suspend.suspend = hdd_suspend_wlan;
1912 wlan_early_suspend.resume = hdd_resume_wlan;
1913 register_early_suspend(&wlan_early_suspend);
1914}
1915
1916void unregister_wlan_suspend(void)
1917{
1918 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Unregister WLAN suspend/resume "
1919 "callbacks",__func__);
1920 unregister_early_suspend(&wlan_early_suspend);
1921}
1922#endif
1923
1924/* the HDD interface to WLAN driver shutdown,
1925 * the primary shutdown function in SSR
1926 */
1927VOS_STATUS hdd_wlan_shutdown(void)
1928{
1929 VOS_STATUS vosStatus;
1930 v_CONTEXT_t pVosContext = NULL;
1931 hdd_context_t *pHddCtx = NULL;
1932 pVosSchedContext vosSchedContext = NULL;
1933
1934 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1935
1936 /* Get the global VOSS context. */
1937 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1938 if(!pVosContext) {
1939 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1940 return VOS_STATUS_E_FAILURE;
1941 }
1942 /* Get the HDD context. */
1943 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1944 if(!pHddCtx) {
1945 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1946 return VOS_STATUS_E_FAILURE;
1947 }
1948 hdd_reset_all_adapters(pHddCtx);
1949#ifdef CONFIG_HAS_EARLYSUSPEND
1950 /* unregister suspend/resume callbacks */
1951 if(pHddCtx->cfg_ini->nEnableSuspend)
1952 {
1953 unregister_wlan_suspend();
1954 }
1955#endif
1956 /* DeRegister with platform driver as client for Suspend/Resume */
1957 vosStatus = hddDeregisterPmOps(pHddCtx);
1958 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1959 {
1960 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1961 }
1962
1963 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1964 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1965 {
1966 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1967 }
1968
1969 /* Disable IMPS/BMPS as we do not want the device to enter any power
1970 * save mode on its own during reset sequence
1971 */
1972 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1973 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1974 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1975
1976 vosSchedContext = get_vos_sched_ctxt();
1977
1978 /* Wakeup all driver threads */
1979 if(TRUE == pHddCtx->isMcThreadSuspended){
1980 complete(&vosSchedContext->ResumeMcEvent);
1981 pHddCtx->isMcThreadSuspended= FALSE;
1982 }
1983 if(TRUE == pHddCtx->isTxThreadSuspended){
1984 complete(&vosSchedContext->ResumeTxEvent);
1985 pHddCtx->isTxThreadSuspended= FALSE;
1986 }
1987 if(TRUE == pHddCtx->isRxThreadSuspended){
1988 complete(&vosSchedContext->ResumeRxEvent);
1989 pHddCtx->isRxThreadSuspended= FALSE;
1990 }
1991 /* Reset the Suspend Variable */
1992 pHddCtx->isWlanSuspended = FALSE;
1993
1994 /* Stop all the threads; we do not want any messages to be a processed,
1995 * any more and the best way to ensure that is to terminate the threads
1996 * gracefully.
1997 */
1998 /* Wait for MC to exit */
1999 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
2000 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
2001 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
2002 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
2003 wait_for_completion_interruptible(&vosSchedContext->McShutdown);
2004
2005 /* Wait for TX to exit */
2006 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
2007 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
2008 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
2009 wake_up_interruptible(&vosSchedContext->txWaitQueue);
2010 wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
2011
2012 /* Wait for RX to exit */
2013 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
2014 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
2015 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
2016 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
2017 wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
2018
2019#ifdef WLAN_BTAMP_FEATURE
2020 vosStatus = WLANBAP_Stop(pVosContext);
2021 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2022 {
2023 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2024 "%s: Failed to stop BAP",__func__);
2025 }
2026#endif //WLAN_BTAMP_FEATURE
2027 vosStatus = vos_wda_shutdown(pVosContext);
2028 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2029
2030 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
2031 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
2032 * on threads being running to process the SYS Stop
2033 */
2034 vosStatus = sme_Stop(pHddCtx->hHal, TRUE);
2035 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2036
2037 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
2038 /* Stop MAC (PE and HAL) */
2039 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
2040 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2041
2042 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
2043 /* Stop TL */
2044 vosStatus = WLANTL_Stop(pVosContext);
2045 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2046
2047#ifdef CONFIG_HAS_EARLYSUSPEND
2048 hdd_unregister_mcast_bcast_filter(pHddCtx);
2049#endif
2050 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
2051 /* Clean up message queues of TX and MC thread */
2052 vos_sched_flush_mc_mqs(vosSchedContext);
2053 vos_sched_flush_tx_mqs(vosSchedContext);
2054 vos_sched_flush_rx_mqs(vosSchedContext);
2055
2056 /* Deinit all the TX and MC queues */
2057 vos_sched_deinit_mqs(vosSchedContext);
2058 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
2059
2060 /* shutdown VOSS */
2061 vos_shutdown(pVosContext);
2062 if (free_riva_power_on_lock("wlan"))
2063 {
2064 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
2065 __func__);
2066 }
2067 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
2068 ,__func__);
2069 return VOS_STATUS_SUCCESS;
2070}
2071
2072
2073
2074/* the HDD interface to WLAN driver re-init.
2075 * This is called to initialize/start WLAN driver after a shutdown.
2076 */
2077VOS_STATUS hdd_wlan_re_init(void)
2078{
2079 VOS_STATUS vosStatus;
2080 v_CONTEXT_t pVosContext = NULL;
2081 hdd_context_t *pHddCtx = NULL;
2082 eHalStatus halStatus;
2083#ifdef WLAN_BTAMP_FEATURE
2084 hdd_config_t *pConfig = NULL;
2085 WLANBAP_ConfigType btAmpConfig;
2086#endif
2087
2088 hdd_prevent_suspend();
2089 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
2090 vosStatus = vos_open(&pVosContext, 0);
2091 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2092 {
2093 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
2094 goto err_re_init;
2095 }
2096
2097 /* Get the HDD context. */
2098 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
2099 if(!pHddCtx)
2100 {
2101 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
2102 goto err_vosclose;
2103 }
2104
2105 /* Save the hal context in Adapter */
2106 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
2107 if ( NULL == pHddCtx->hHal )
2108 {
2109 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
2110 goto err_vosclose;
2111 }
2112
2113 /* Set the SME configuration parameters. */
2114 vosStatus = hdd_set_sme_config(pHddCtx);
2115 if ( VOS_STATUS_SUCCESS != vosStatus )
2116 {
2117 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
2118 goto err_vosclose;
2119 }
2120
2121 /* Initialize the WMM module */
2122 vosStatus = hdd_wmm_init(pHddCtx);
2123 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
2124 {
2125 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __FUNCTION__);
2126 goto err_vosclose;
2127 }
2128
2129 vosStatus = vos_preStart( pHddCtx->pvosContext );
2130 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2131 {
2132 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
2133 goto err_vosclose;
2134 }
2135
2136 /* In the integrated architecture we update the configuration from
2137 the INI file and from NV before vOSS has been started so that
2138 the final contents are available to send down to the cCPU */
2139 /* Apply the cfg.ini to cfg.dat */
2140 if (FALSE == hdd_update_config_dat(pHddCtx))
2141 {
2142 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
2143 goto err_vosclose;
2144 }
2145
2146 /* Set the MAC Address, currently this is used by HAL to add self sta.
2147 * Remove this once self sta is added as part of session open. */
2148 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
2149 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
2150 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
2151 if (!HAL_STATUS_SUCCESS(halStatus))
2152 {
2153 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
2154 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
2155 goto err_vosclose;
2156 }
2157
2158 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
2159 Note: Firmware image will be read and downloaded inside vos_start API */
2160 vosStatus = vos_start( pVosContext );
2161 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2162 {
2163 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
2164 goto err_vosclose;
2165 }
2166
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07002167 /* Exchange capability info between Host and FW and also get versioning info from FW */
2168 hdd_exchange_version_and_caps(pHddCtx);
2169
Jeff Johnson295189b2012-06-20 16:38:30 -07002170 vosStatus = hdd_post_voss_start_config( pHddCtx );
2171 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2172 {
2173 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
2174 __func__);
2175 goto err_vosstop;
2176 }
2177
2178#ifdef WLAN_BTAMP_FEATURE
2179 vosStatus = WLANBAP_Open(pVosContext);
2180 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2181 {
2182 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2183 "%s: Failed to open BAP",__func__);
2184 goto err_vosstop;
2185 }
2186 vosStatus = BSL_Init(pVosContext);
2187 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2188 {
2189 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2190 "%s: Failed to Init BSL",__func__);
2191 goto err_bap_close;
2192 }
2193 vosStatus = WLANBAP_Start(pVosContext);
2194 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2195 {
2196 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2197 "%s: Failed to start TL",__func__);
2198 goto err_bap_close;
2199 }
2200 pConfig = pHddCtx->cfg_ini;
2201 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
2202 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
2203#endif //WLAN_BTAMP_FEATURE
2204
2205 /* Restart all adapters */
2206 hdd_start_all_adapters(pHddCtx);
2207 pHddCtx->isLogpInProgress = FALSE;
2208 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
2209#ifdef CONFIG_HAS_EARLYSUSPEND
2210 hdd_register_mcast_bcast_filter(pHddCtx);
2211#endif
2212
2213 /* Register with platform driver as client for Suspend/Resume */
2214 vosStatus = hddRegisterPmOps(pHddCtx);
2215 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2216 {
2217 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
2218 goto err_bap_stop;
2219 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002220#ifdef CONFIG_HAS_EARLYSUSPEND
Jeff Johnson295189b2012-06-20 16:38:30 -07002221 // Register suspend/resume callbacks
2222 if(pHddCtx->cfg_ini->nEnableSuspend)
2223 {
2224 register_wlan_suspend();
2225 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002226#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002227 /* Allow the phone to go to sleep */
2228 hdd_allow_suspend();
2229 /* register for riva power on lock */
2230 if (req_riva_power_on_lock("wlan"))
2231 {
2232 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
2233 __func__);
2234 goto err_unregister_pmops;
2235 }
2236 goto success;
2237
2238err_unregister_pmops:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002239#ifdef CONFIG_HAS_EARLYSUSPEND
2240 /* unregister suspend/resume callbacks */
2241 if (pHddCtx->cfg_ini->nEnableSuspend)
2242 unregister_wlan_suspend();
2243#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002244 hddDeregisterPmOps(pHddCtx);
2245
2246err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07002247#ifdef CONFIG_HAS_EARLYSUSPEND
2248 hdd_unregister_mcast_bcast_filter(pHddCtx);
2249#endif
2250 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002251#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07002252 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07002253#endif
2254
2255#ifdef WLAN_BTAMP_FEATURE
2256err_bap_close:
2257 WLANBAP_Close(pVosContext);
2258#endif
2259
2260err_vosstop:
2261 vos_stop(pVosContext);
2262
2263err_vosclose:
2264 vos_close(pVosContext);
2265 vos_sched_close(pVosContext);
2266 if (pHddCtx)
2267 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002268 /* Unregister the Net Device Notifier */
2269 unregister_netdevice_notifier(&hdd_netdev_notifier);
2270 /* Clean up HDD Nlink Service */
2271 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2272 nl_srv_exit();
Jeff Johnson295189b2012-06-20 16:38:30 -07002273 /* Free up dynamically allocated members inside HDD Adapter */
2274 kfree(pHddCtx->cfg_ini);
2275 pHddCtx->cfg_ini= NULL;
2276
2277#ifdef CONFIG_CFG80211
2278 wiphy_unregister(pHddCtx->wiphy);
2279 wiphy_free(pHddCtx->wiphy);
2280#else
2281 vos_mem_free(pHddCtx);
2282#endif
2283 }
2284 vos_preClose(&pVosContext);
2285
2286#ifdef MEMORY_DEBUG
2287 vos_mem_exit();
2288#endif
2289
2290err_re_init:
2291 /* Allow the phone to go to sleep */
2292 hdd_allow_suspend();
2293 return -1;
2294
2295success:
2296 /* Trigger replay of BTC events */
2297 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2298 return VOS_STATUS_SUCCESS;
2299}