blob: 3ad6fd0af265a805db3fbb0d824c1d9e913b6823 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
2 * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/**=============================================================================
23* 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
678 if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
679 pHddCtx->cfg_ini->mcastBcastFilterSetting )
680 || (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
681 pHddCtx->cfg_ini->mcastBcastFilterSetting))
682 {
683 //MCAST filter is set by hdd_conf_mcastbcast_filter fn call
684 offLoadRequest.enableOrDisable =
685 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
686 }
687
688 //converting u32 to IPV4 address
689 for(i = 0 ; i < 4; i++)
690 {
691 offLoadRequest.params.hostIpv4Addr[i] =
692 (ifa->ifa_local >> (i*8) ) & 0xFF ;
693 }
694 hddLog(VOS_TRACE_LEVEL_WARN, " Enable SME HostOffload: %d.%d.%d.%d",
695 offLoadRequest.params.hostIpv4Addr[0],
696 offLoadRequest.params.hostIpv4Addr[1],
697 offLoadRequest.params.hostIpv4Addr[2],
698 offLoadRequest.params.hostIpv4Addr[3]);
699
700 if (eHAL_STATUS_SUCCESS !=
Jeff Johnsone7245742012-09-05 17:12:55 -0700701 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
702 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700703 {
704 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
705 "feature\n", __func__);
706 return VOS_STATUS_E_FAILURE;
707 }
708 return VOS_STATUS_SUCCESS;
709 }
710 else
711 {
712 hddLog(VOS_TRACE_LEVEL_INFO, "%s:IP Address is not assigned \n", __func__);
713 return VOS_STATUS_E_AGAIN;
714 }
715 }
716 else
717 {
718 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
719 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
720 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
721
Jeff Johnsone7245742012-09-05 17:12:55 -0700722 if (eHAL_STATUS_SUCCESS != sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
723 &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700724 {
725 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
726 "offload feature\n", __func__);
727 return VOS_STATUS_E_FAILURE;
728 }
729 return VOS_STATUS_SUCCESS;
730 }
731}
732
733void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
734{
735 eHalStatus halStatus = eHAL_STATUS_FAILURE;
736#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
737 tpAniSirGlobal pMac = (tpAniSirGlobal) vos_get_context(VOS_MODULE_ID_SME, pHddCtx->pvosContext);
738#else
739 tpSirWlanSetRxpFilters wlanRxpFilterParam =
740 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
741 if(NULL == wlanRxpFilterParam)
742 {
743 hddLog(VOS_TRACE_LEVEL_FATAL,
744 "%s: vos_mem_alloc failed ", __func__);
745 return;
746 }
747#endif
748 hddLog(VOS_TRACE_LEVEL_INFO,
749 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
750#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
751 if ( pMac )
752 {
753 halStatus = halRxp_configureRxpFilterMcstBcst( pMac, setfilter);
754 }
755 else
756 {
757 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pMac is initialised to NULL",__func__ );
758 }
759#else
760 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
761 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
762 pHddCtx->cfg_ini->mcastBcastFilterSetting;
763 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
764#endif
765 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
766 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
767}
768
Jeff Johnsone7245742012-09-05 17:12:55 -0700769#ifdef CONFIG_HAS_EARLYSUSPEND
Jeff Johnson295189b2012-06-20 16:38:30 -0700770#ifdef FEATURE_WLAN_INTEGRATED_SOC
771static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
772 hdd_adapter_t *pAdapter)
773{
774 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Jeff Johnson43971f52012-07-17 12:26:56 -0700775 VOS_STATUS vstatus;
Jeff Johnson295189b2012-06-20 16:38:30 -0700776 tpSirWlanSuspendParam wlanSuspendParam =
777 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
778
779 if(NULL == wlanSuspendParam)
780 {
781 hddLog(VOS_TRACE_LEVEL_FATAL,
782 "%s: vos_mem_alloc failed ", __func__);
783 return;
784 }
785
786 hddLog(VOS_TRACE_LEVEL_INFO,
787 "%s: send wlan suspend indication", __func__);
788
789 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
790 {
791 if((pHddCtx->cfg_ini->fhostArpOffload) &&
792 (eConnectionState_Associated ==
793 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
794 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700795 vstatus = hdd_conf_hostarpoffload(pHddCtx, TRUE);
796 if (!VOS_IS_STATUS_SUCCESS(vstatus))
Jeff Johnson295189b2012-06-20 16:38:30 -0700797 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700798 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
799 {
800 wlanSuspendParam->configuredMcstBcstFilterSetting =
801 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting;
802 }
803 else
804 {
805 wlanSuspendParam->configuredMcstBcstFilterSetting =
806 pHddCtx->cfg_ini->mcastBcastFilterSetting;
807 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700808 hddLog(VOS_TRACE_LEVEL_INFO,
809 "%s:Failed to enable ARPOFFLOAD Feature %d\n",
Jeff Johnson43971f52012-07-17 12:26:56 -0700810 __func__, vstatus);
Jeff Johnson295189b2012-06-20 16:38:30 -0700811 }
Jeff Johnson43971f52012-07-17 12:26:56 -0700812 else
813 {
814 if (((pHddCtx->dynamic_mcbc_filter.enableCfg) &&
815 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
816 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting)) ||
817 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
818 pHddCtx->cfg_ini->mcastBcastFilterSetting))
819 {
820 wlanSuspendParam->configuredMcstBcstFilterSetting =
821 HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST;
822 }
823 else if(((pHddCtx->dynamic_mcbc_filter.enableCfg) &&
824 (HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
825 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting)) ||
826 (HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
827 pHddCtx->cfg_ini->mcastBcastFilterSetting))
828 {
829 wlanSuspendParam->configuredMcstBcstFilterSetting =
830 HDD_MCASTBCASTFILTER_FILTER_NONE;
831 }
832 else
833 {
834 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
835 {
836 wlanSuspendParam->configuredMcstBcstFilterSetting =
837 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting;
838 }
839 else
840 {
841 wlanSuspendParam->configuredMcstBcstFilterSetting =
842 pHddCtx->cfg_ini->mcastBcastFilterSetting;
843 }
844 }
845 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700846 }
847 else
848 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700849 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
850 {
851 wlanSuspendParam->configuredMcstBcstFilterSetting =
852 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting;
853 }
854 else
855 {
856 wlanSuspendParam->configuredMcstBcstFilterSetting =
857 pHddCtx->cfg_ini->mcastBcastFilterSetting;
858 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700859 }
Jeff Johnson43971f52012-07-17 12:26:56 -0700860
861 pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE;
862 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend =
863 wlanSuspendParam->configuredMcstBcstFilterSetting;
864
Jeff Johnson295189b2012-06-20 16:38:30 -0700865
866#ifdef WLAN_FEATURE_PACKET_FILTERING
867 if (pHddCtx->cfg_ini->isMcAddrListFilter)
868 {
869 /*Multicast addr list filter is enabled during suspend*/
870 if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
871 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT))
872 && pHddCtx->mc_addr_list.mc_cnt
873 && (eConnectionState_Associated ==
874 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
875 {
876 /*set the filter*/
Jeff Johnsone7245742012-09-05 17:12:55 -0700877 wlan_hdd_set_mc_addr_list(pHddCtx, TRUE, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700878 }
879 }
880#endif
881 }
882
883 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
884 if(eHAL_STATUS_SUCCESS == halStatus)
885 {
886 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
887 }
888}
889
Jeff Johnsone7245742012-09-05 17:12:55 -0700890static void hdd_conf_resume_ind(hdd_context_t* pHddCtx, v_U8_t sessionId)
Jeff Johnson295189b2012-06-20 16:38:30 -0700891{
Jeff Johnson43971f52012-07-17 12:26:56 -0700892 VOS_STATUS vstatus;
Jeff Johnson295189b2012-06-20 16:38:30 -0700893 tpSirWlanResumeParam wlanResumeParam =
894 vos_mem_malloc(sizeof(tSirWlanResumeParam));
895
896 if(NULL == wlanResumeParam)
897 {
898 hddLog(VOS_TRACE_LEVEL_FATAL,
899 "%s: vos_mem_alloc failed ", __func__);
900 return;
901 }
902
903 hddLog(VOS_TRACE_LEVEL_INFO,
904 "%s: send wlan resume indication", __func__);
905
906 if(pHddCtx->cfg_ini->fhostArpOffload)
907 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700908 vstatus = hdd_conf_hostarpoffload(pHddCtx, FALSE);
909 if (!VOS_IS_STATUS_SUCCESS(vstatus))
Jeff Johnson295189b2012-06-20 16:38:30 -0700910 {
911 hddLog(VOS_TRACE_LEVEL_INFO, "%s:Failed to disable ARPOFFLOAD "
Jeff Johnson43971f52012-07-17 12:26:56 -0700912 "Feature %d\n", __func__, vstatus);
Jeff Johnson295189b2012-06-20 16:38:30 -0700913 }
914 }
915 if (pHddCtx->dynamic_mcbc_filter.enableSuspend)
916 {
917 wlanResumeParam->configuredMcstBcstFilterSetting =
918 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend;
919 }
920 else
921 {
922 wlanResumeParam->configuredMcstBcstFilterSetting =
923 pHddCtx->cfg_ini->mcastBcastFilterSetting;
924 }
925 sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
926
927#ifdef WLAN_FEATURE_PACKET_FILTERING
928 if (pHddCtx->cfg_ini->isMcAddrListFilter)
929 {
930 /*Mutlicast addr filtering is enabled*/
931 if(pHddCtx->mc_addr_list.isFilterApplied)
932 {
933 /*Filter applied during suspend mode*/
934 /*Clear it here*/
Jeff Johnsone7245742012-09-05 17:12:55 -0700935 wlan_hdd_set_mc_addr_list(pHddCtx, FALSE, sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700936 }
937 }
938#endif
939}
940#endif
941
Jeff Johnson295189b2012-06-20 16:38:30 -0700942//Suspend routine registered with Android OS
943void hdd_suspend_wlan(struct early_suspend *wlan_suspend)
944{
945 hdd_context_t *pHddCtx = NULL;
946 v_CONTEXT_t pVosContext = NULL;
947
948 hdd_adapter_t *pAdapter = NULL;
949 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
950 VOS_STATUS status;
951#ifdef ANI_BUS_TYPE_SDIO
952 struct sdio_func *sdio_func_dev = NULL;
953#endif
954 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
955
956 //Get the global VOSS context.
957 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
958 if(!pVosContext) {
959 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
960 return;
961 }
962
963 //Get the HDD context.
964 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
965
966 if(!pHddCtx) {
967 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
968 return;
969 }
970
971 if (pHddCtx->isLogpInProgress) {
972 hddLog(VOS_TRACE_LEVEL_ERROR,
973 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
974 return;
975 }
976
977#ifdef ANI_BUS_TYPE_SDIO
978 sdio_func_dev = libra_getsdio_funcdev();
979
980 if(sdio_func_dev == NULL)
981 {
982 /* Our card got removed */
983 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
984 return;
985 }
986
987 if(!sd_is_drvdata_available(sdio_func_dev))
988 {
989 /* Our card got removed */
990 hddLog(VOS_TRACE_LEVEL_FATAL,
991 "%s: HDD context is not available in sdio_func_dev!",__func__);
992 return;
993 }
994
995 sd_claim_host(sdio_func_dev);
996
997 // Prevent touching the pMac while LOGP reset in progress, we should never get here
998 // as the wake lock is already acquired and it would prevent from entering suspend
999 if (pHddCtx->isLogpInProgress) {
1000 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Ignore suspend wlan, LOGP in progress!", __func__);
1001 sd_release_host(sdio_func_dev);
1002 return;
1003 }
1004#endif
1005
1006 /*loop through all adapters. TBD fix for Concurrency */
1007 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1008 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1009 {
1010 pAdapter = pAdapterNode->pAdapter;
1011 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
1012 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1013
1014 { //just do for station interface
1015 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1016 pAdapterNode = pNext;
1017 continue;
1018 }
1019
1020#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1021 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1022 {
1023 //stop the interface before putting the chip to standby
1024 netif_tx_disable(pAdapter->dev);
1025 netif_carrier_off(pAdapter->dev);
1026 }
1027 else if (pHddCtx->cfg_ini->nEnableSuspend ==
1028 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
1029 {
1030 //Execute deep sleep procedure
1031 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1032 }
1033#endif
1034
Jeff Johnsone7245742012-09-05 17:12:55 -07001035 //Apply Dynamic Dtim For P2P
1036 //Only if ignoreDynamicDtimInP2pMode is not set in ini
Jeff Johnson295189b2012-06-20 16:38:30 -07001037 if((pHddCtx->cfg_ini->enableDynamicDTIM ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001038 pHddCtx->cfg_ini->enableModulatedDTIM) &&
1039 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
1040 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
1041 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07001042 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
1043 (eConnectionState_Associated ==
1044 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
1045 (pHddCtx->cfg_ini->fIsBmpsEnabled))
1046 {
1047 tSirSetPowerParamsReq powerRequest = { 0 };
1048
1049 powerRequest.uIgnoreDTIM = 1;
1050
1051 /*Back up the actual values from CFG */
1052 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM,
1053 &pHddCtx->hdd_actual_ignore_DTIM_value);
1054 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL,
1055 &pHddCtx->hdd_actual_LI_value);
1056
1057 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1058 {
1059 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
1060 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
1061 }
1062 else
1063 {
1064 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
1065 }
1066
1067 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
1068 *specified during Enter/Exit BMPS when LCD off*/
1069 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1070 NULL, eANI_BOOLEAN_FALSE);
1071 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1072 NULL, eANI_BOOLEAN_FALSE);
1073
1074 /* switch to the DTIM specified in cfg.ini */
1075 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1076 "Switch to DTIM%d \n", powerRequest.uListenInterval);
1077 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest);
1078
1079 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1080 {
1081 /* put the device into full power */
1082 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1083
1084 /* put the device back into BMPS */
1085 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1086
1087 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1088 }
1089 }
1090
1091#ifdef FEATURE_WLAN_INTEGRATED_SOC
1092 /*Suspend notification sent down to driver*/
1093 hdd_conf_suspend_ind(pHddCtx, pAdapter);
1094#else
1095 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER) {
1096 if(eConnectionState_Associated ==
1097 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) {
1098 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
1099 halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME,
1100 pHddCtx->pvosContext), FALSE);
1101 }
1102 }
1103#endif
1104 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1105 pAdapterNode = pNext;
1106 }
1107 pHddCtx->hdd_wlan_suspended = TRUE;
1108
1109#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1110 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1111 {
1112 hdd_enter_standby(pHddCtx);
1113 }
1114#endif
1115#ifdef ANI_BUS_TYPE_SDIO
1116 sd_release_host(sdio_func_dev);
1117#endif
1118
1119 return;
1120}
1121
1122static void hdd_PowerStateChangedCB
1123(
1124 v_PVOID_t callbackContext,
1125 tPmcState newState
1126)
1127{
1128 hdd_context_t *pHddCtx = callbackContext;
1129
1130 /* if the driver was not in BMPS during early suspend,
1131 * the dynamic DTIM is now updated at Riva */
1132 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1133 && pHddCtx->cfg_ini->enableDynamicDTIM
1134 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1135 {
1136 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1137 }
1138 spin_lock(&pHddCtx->filter_lock);
1139 if((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1140 && (pHddCtx->hdd_mcastbcast_filter_set != TRUE)) {
1141 spin_unlock(&pHddCtx->filter_lock);
1142 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
1143#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1144 halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME, pHddCtx->pvosContext), FALSE);
1145#endif
1146 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1147 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
1148 }
1149 else
1150 spin_unlock(&pHddCtx->filter_lock);
1151}
1152
1153
1154
1155void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1156{
1157 v_CONTEXT_t pVosContext;
1158 tHalHandle smeContext;
1159
1160 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1161 if (NULL == pVosContext)
1162 {
1163 hddLog(LOGE, "%s: Invalid pContext", __FUNCTION__);
1164 return;
1165 }
1166 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1167 if (NULL == smeContext)
1168 {
1169 hddLog(LOGE, "%s: Invalid smeContext", __FUNCTION__);
1170 return;
1171 }
1172
1173 spin_lock_init(&pHddCtx->filter_lock);
1174 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1175 pHddCtx->cfg_ini->nEnableSuspend)
1176 {
1177 pmcRegisterDeviceStateUpdateInd(smeContext,
1178 hdd_PowerStateChangedCB, pHddCtx);
1179 }
1180}
1181
1182void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1183{
1184 v_CONTEXT_t pVosContext;
1185 tHalHandle smeContext;
1186
1187 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1188 if (NULL == pVosContext)
1189 {
1190 hddLog(LOGE, "%s: Invalid pContext", __FUNCTION__);
1191 return;
1192 }
1193 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1194 if (NULL == smeContext)
1195 {
1196 hddLog(LOGE, "%s: Invalid smeContext", __FUNCTION__);
1197 return;
1198 }
1199
1200 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1201 pHddCtx->cfg_ini->nEnableSuspend)
1202 {
1203 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1204 }
1205}
1206
1207void hdd_resume_wlan(struct early_suspend *wlan_suspend)
1208{
1209 hdd_context_t *pHddCtx = NULL;
1210 hdd_adapter_t *pAdapter = NULL;
1211 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1212 VOS_STATUS status;
1213 v_CONTEXT_t pVosContext = NULL;
1214#ifdef ANI_BUS_TYPE_SDIO
1215 struct sdio_func *sdio_func_dev = NULL;
1216#endif
1217 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1218
1219 //Get the global VOSS context.
1220 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1221 if(!pVosContext) {
1222 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1223 return;
1224 }
1225
1226 //Get the HDD context.
1227 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1228
1229 if(!pHddCtx) {
1230 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1231 return;
1232 }
1233
1234 if (pHddCtx->isLogpInProgress) {
1235 hddLog(VOS_TRACE_LEVEL_INFO,
1236 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1237 return;
1238 }
1239
1240#ifdef ANI_BUS_TYPE_SDIO
1241 sdio_func_dev = libra_getsdio_funcdev();
1242
1243 if(sdio_func_dev == NULL)
1244 {
1245 /* Our card got removed */
1246 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1247 return;
1248 }
1249
1250 if(!sd_is_drvdata_available(sdio_func_dev))
1251 {
1252 /* Our card got removed */
1253 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD context is not available "
1254 "in sdio_func_dev!",__func__);
1255 return;
1256 }
1257
1258 sd_claim_host(sdio_func_dev);
1259
1260 // Prevent touching the pMac while LOGP reset in progress,
1261 if (pHddCtx->isLogpInProgress) {
1262 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Ignore resume wlan, LOGP in progress!", __func__);
1263 sd_release_host(sdio_func_dev);
1264 return;
1265 }
1266#endif
1267 pHddCtx->hdd_wlan_suspended = FALSE;
1268 /*loop through all adapters. Concurrency */
1269 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1270
1271 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1272 {
1273 pAdapter = pAdapterNode->pAdapter;
1274 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
1275 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1276 { //just do for station interface
1277 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1278 pAdapterNode = pNext;
1279 continue;
1280 }
1281#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1282 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1283 {
1284 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1285 hdd_exit_deep_sleep(pAdapter);
1286 }
1287#endif
1288
1289 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1290 {
1291 /*Switch back to DTIM 1*/
1292 tSirSetPowerParamsReq powerRequest = { 0 };
1293
1294 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1295 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
1296
1297 /*Disabled ModulatedDTIM if enabled on suspend*/
1298 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1299 powerRequest.uDTIMPeriod = 0;
1300
1301 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1302 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1303 NULL, eANI_BOOLEAN_FALSE);
1304 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1305 NULL, eANI_BOOLEAN_FALSE);
1306
1307 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1308 "Switch to DTIM%d \n",powerRequest.uListenInterval);
1309 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest);
1310
1311 /* put the device into full power */
1312 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1313
1314 /* put the device back into BMPS */
1315 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1316
1317 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1318 }
1319
1320 if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) {
1321#ifdef FEATURE_WLAN_INTEGRATED_SOC
Jeff Johnsone7245742012-09-05 17:12:55 -07001322 hdd_conf_resume_ind(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07001323#else
1324 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
1325 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1326 halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME,
1327 pHddCtx->pvosContext), TRUE);
1328#endif
1329 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1330 }
1331 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1332 pAdapterNode = pNext;
1333 }
1334
1335#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1336 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1337 {
1338 hdd_exit_standby(pHddCtx);
1339 }
1340#endif
1341
1342#ifdef ANI_BUS_TYPE_SDIO
1343 sd_release_host(sdio_func_dev);
1344#endif
1345 return;
1346}
1347
1348VOS_STATUS hdd_wlan_reset(void)
1349{
1350 VOS_STATUS vosStatus;
1351 hdd_context_t *pHddCtx = NULL;
1352 v_CONTEXT_t pVosContext = NULL;
1353 pVosSchedContext vosSchedContext = NULL;
1354#ifdef ANI_BUS_TYPE_SDIO
1355 struct sdio_func *sdio_func_dev_new = NULL;
1356 struct sdio_func *sdio_func_dev_current = NULL;
1357 unsigned int attempts = 0;
1358#endif
1359 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1360
1361 //Get the global VOSS context.
1362 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1363 if(!pVosContext) {
1364 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1365 return VOS_STATUS_E_FAILURE;
1366 }
1367
1368 //Get the HDD context.
1369 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1370 if(!pHddCtx) {
1371 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1372 return VOS_STATUS_E_FAILURE;
1373 }
1374#ifdef ANI_BUS_TYPE_SDIO
1375 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SAL Stop",__func__);
1376 //Invoke SAL stop
1377 vosStatus = WLANSAL_Stop( pVosContext );
1378 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1379 {
1380 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1381 "%s: Failed to stop SAL",__func__);
1382 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1383 }
1384#endif
1385 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Asserting Deep Sleep",__func__);
1386 //Assert Deep sleep signal now to put Libra HW in lowest power state
1387 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
1388 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1389
1390 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Power Down Chip",__func__);
1391 //Vote off any PMIC voltage supplies
1392 vos_chipPowerDown(NULL, NULL, NULL);
1393
1394
1395 /**
1396 EVM issue is observed with 1.6Mhz freq for 1.3V supply in wlan standalone case.
1397 During concurrent operation (e.g. WLAN and WCDMA) this issue is not observed.
1398 To workaround, wlan will vote for 3.2Mhz during startup and will vote for 1.6Mhz
1399 during exit.
1400 */
1401 if (vos_chipVoteFreqFor1p3VSupply(NULL, NULL, NULL, VOS_NV_FREQUENCY_FOR_1_3V_SUPPLY_1P6MH) != VOS_STATUS_SUCCESS)
1402 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1403 "%s: Failed to set the freq to 1.6Mhz for 1.3V Supply",__func__ );
1404
1405 //Disable IMPS/BMPS as we do not want the device to enter any power
1406 //save mode on its own during reset sequence
1407 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1408 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1409 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1410
1411 //Kill all the threads first. We do not want any messages
1412 //to be a processed any more and the best way to ensure that
1413 //is to terminate the threads gracefully.
1414 vosSchedContext = get_vos_sched_ctxt();
1415
1416 /* Wakeup Mc Thread if Suspended */
1417 if(TRUE == pHddCtx->isMcThreadSuspended){
1418 complete(&vosSchedContext->ResumeMcEvent);
1419 pHddCtx->isMcThreadSuspended= FALSE;
1420 }
1421 /* Wakeup Tx Thread if Suspended */
1422 if(TRUE == pHddCtx->isTxThreadSuspended){
1423 complete(&vosSchedContext->ResumeTxEvent);
1424 pHddCtx->isTxThreadSuspended= FALSE;
1425 }
1426#ifdef FEATURE_WLAN_INTEGRATED_SOC
1427 /* Wakeup Rx Thread if Suspended */
1428 if(TRUE == pHddCtx->isRxThreadSuspended){
1429 complete(&vosSchedContext->ResumeRxEvent);
1430 pHddCtx->isRxThreadSuspended= FALSE;
1431 }
1432#endif
1433
1434 /* Reset the Suspend Variable */
1435 pHddCtx->isWlanSuspended = FALSE;
1436
1437 //Wait for MC to exit
1438 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1439 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1440 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1441 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
1442 wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1443
1444 //Wait for TX to exit
1445 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1446 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1447 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1448 wake_up_interruptible(&vosSchedContext->txWaitQueue);
1449 wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1450
1451#ifdef FEATURE_WLAN_INTEGRATED_SOC
1452 //Wait for RX to exit
1453 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1454 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1455 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1456 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
1457 wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1458#endif
1459
1460 /* Cancel the vote for XO Core ON in LOGP since we are reinitializing our driver
1461 * This is done here to ensure there is no race condition since MC and TX thread have
1462 * exited at this point
1463 */
1464 hddLog(VOS_TRACE_LEVEL_WARN, "In LOGP: Cancel XO Core ON vote\n");
1465 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
1466 {
1467 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
1468 "Power consumed will be high\n");
1469 }
1470
1471 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1472 //Stop SME - Cannot invoke vos_stop as vos_stop relies
1473 //on threads being running to process the SYS Stop
1474 vosStatus = sme_Stop( pHddCtx->hHal, TRUE );
1475 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1476
1477 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1478 //Stop MAC (PE and HAL)
1479 vosStatus = macStop( pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
1480 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1481
1482 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1483 //Stop TL
1484 vosStatus = WLANTL_Stop( pVosContext );
1485 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1486
1487#ifdef ANI_BUS_TYPE_SDIO
1488 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing BAL STOP",__func__);
1489 vosStatus = WLANBAL_Stop( pVosContext );
1490 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1491 {
1492 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1493 "%s: Failed to stop BAL",__func__);
1494 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1495 }
1496#endif
1497#ifdef CONFIG_HAS_EARLYSUSPEND
1498 hdd_unregister_mcast_bcast_filter(pHddCtx);
1499#endif
1500
1501 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Flush Queues",__func__);
1502 //Clean up message queues of TX and MC thread
1503 vos_sched_flush_mc_mqs(vosSchedContext);
1504 vos_sched_flush_tx_mqs(vosSchedContext);
1505#ifdef FEATURE_WLAN_INTEGRATED_SOC
1506 vos_sched_flush_rx_mqs(vosSchedContext);
1507#endif
1508
1509 //Deinit all the TX and MC queues
1510 vos_sched_deinit_mqs(vosSchedContext);
1511
1512 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing VOS Close",__func__);
1513
1514 //Close VOSS
1515 vos_close(pVosContext);
1516
1517#ifdef ANI_BUS_TYPE_SDIO
1518 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing BAL Close",__func__);
1519 vosStatus = WLANBAL_Close(pVosContext);
1520 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1521 {
1522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1523 "%s: Failed to close BAL",__func__);
1524 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1525 }
1526 //Get the Current SDIO Func
1527 sdio_func_dev_current = libra_getsdio_funcdev();
1528
1529 if(NULL != sdio_func_dev_current) {
1530 libra_detect_card_change();
1531 attempts = 0;
1532 do {
1533 msleep(100);
1534 //Get the SDIO func device
1535 sdio_func_dev_current = libra_getsdio_funcdev();
1536 if(NULL == sdio_func_dev_current) {
1537 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Card Removed Successfully",__func__);
1538 break;
1539 }
1540 else {
1541 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Trying Again",__func__);
1542 attempts++;
1543 }
1544 } while (attempts < LIBRA_CARD_REMOVE_DETECT_MAX_COUNT);
1545
1546 if(LIBRA_CARD_REMOVE_DETECT_MAX_COUNT == attempts) {
1547 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Fatal",__func__);
1548 goto err_fail;
1549 }
1550 }
1551#endif
1552
1553#ifdef TIMER_MANAGER
1554 vos_timer_exit();
1555#endif
1556
1557#ifdef MEMORY_DEBUG
1558 vos_mem_clean();
1559#endif
1560#ifdef ANI_BUS_TYPE_SDIO
1561 //Reinitialize the variable
1562 attempts = 0;
1563#endif
1564
1565 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Powering Up chip Again",__func__);
1566 //Power Up Libra WLAN card first if not already powered up
1567 vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
1568 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1569 {
1570 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
1571 "exiting", __func__);
1572 goto err_pwr_fail;
1573 }
1574
1575#ifdef ANI_BUS_TYPE_SDIO
1576 // Trigger card detect
1577 libra_detect_card_change();
1578
1579 //Reinitialize the variable
1580 attempts = 0;
1581
1582 do {
1583 msleep(500);
1584
1585 //Get the SDIO func device
1586 sdio_func_dev_new = libra_getsdio_funcdev();
1587 if(sdio_func_dev_new != NULL)
1588 {
1589 //Not needed but in case it causes probs then put a loop and set for each adapter
1590 //SET_NETDEV_DEV(pAdapter->dev, &sdio_func_dev_new->dev);
1591 libra_sdio_setprivdata (sdio_func_dev_new, pHddCtx);
1592 atomic_set(&pHddCtx->sdio_claim_count, 0);
1593 pHddCtx->parent_dev = &sdio_func_dev_new->dev;
1594 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1595 "%s: Card Detected Successfully %p",__func__,
1596 sdio_func_dev_new);
1597 break;
1598 }
1599 else
1600 {
1601 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1602 "%s: Failed to detect card change %p",__func__,
1603 sdio_func_dev_new);
1604 attempts++;
1605 }
1606 }while (attempts < LIBRA_CARD_INSERT_DETECT_MAX_COUNT);
1607
1608 if(LIBRA_CARD_INSERT_DETECT_MAX_COUNT == attempts){
1609 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN fail to detect in reset, "
1610 "exiting", __func__);
1611 goto err_fail;
1612 }
1613 //Get the SDIO func device
1614 sdio_func_dev_new = libra_getsdio_funcdev();
1615 if(sdio_func_dev_new != NULL)
1616 {
1617 sd_claim_host(sdio_func_dev_new);
1618 /* Enable IRQ capabilities in host controller */
1619 libra_disable_sdio_irq_capability(sdio_func_dev_new, 0);
1620 libra_enable_sdio_irq(sdio_func_dev_new, 1);
1621 sd_release_host(sdio_func_dev_new);
1622 }
1623 else
1624 {
1625 /* Our card got removed before LOGP. */
1626 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1627 goto err_fail;
1628 }
1629
1630 vosStatus = WLANBAL_Open(pVosContext);
1631 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1632 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1633 {
1634 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
1635 "%s: Failed to open BAL",__func__);
1636 goto err_fail;
1637 }
1638
1639 vosStatus = WLANSAL_Start(pVosContext);
1640 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
1641 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1642 {
1643 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to start SAL",__func__);
1644 goto err_balclose;
1645 }
1646
1647 /* Chip is reset so allow Lower MAC to start accessing WLAN registers. Note HDD is still blocked */
1648 vos_set_logp_in_progress(VOS_MODULE_ID_HDD, FALSE);
1649
1650 /* Start BAL */
1651 vosStatus = WLANBAL_Start(pVosContext);
1652
1653 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1654 {
1655 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1656 "%s: Failed to start BAL",__func__);
1657 goto err_salstop;
1658 }
1659#endif
1660 // Open VOSS
1661 vosStatus = vos_open( &pVosContext, 0);
1662
1663 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1664 {
1665 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1666#ifdef ANI_BUS_TYPE_SDIO
1667 goto err_balstop;
1668#else
1669 goto err_pwr_fail;
1670#endif
1671 }
1672
1673 /* Save the hal context in Adapter */
1674 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1675
1676 if ( NULL == pHddCtx->hHal )
1677 {
1678 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1679 goto err_vosclose;
1680 }
1681 // Set the SME configuration parameters...
1682 vosStatus = hdd_set_sme_config(pHddCtx);
1683
1684 if ( VOS_STATUS_SUCCESS != vosStatus )
1685 {
1686 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1687 goto err_vosclose;
1688 }
1689
1690 //Initialize the WMM module
1691 vosStatus = hdd_wmm_init(pHddCtx);
1692 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1693 {
1694 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __FUNCTION__);
1695 goto err_vosclose;
1696 }
1697
1698 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
1699 Note: Firmware image will be read and downloaded inside vos_start API */
1700 vosStatus = vos_start( pVosContext );
1701 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1702 {
1703 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
1704 goto err_vosclose;
1705 }
1706
1707 vosStatus = hdd_post_voss_start_config( pHddCtx );
1708 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1709 {
1710 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
1711 __func__);
1712 goto err_vosstop;
1713 }
1714
1715 /* Restart all adapters */
1716 hdd_start_all_adapters(pHddCtx);
1717 pHddCtx->isLogpInProgress = FALSE;
1718 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
1719#ifdef CONFIG_HAS_EARLYSUSPEND
1720 hdd_register_mcast_bcast_filter(pHddCtx);
1721#endif
1722
1723 // Allow the phone to go to sleep
1724 hdd_allow_suspend();
1725
1726 goto success;
1727
1728err_vosstop:
1729 vos_stop(pVosContext);
1730
1731err_vosclose:
1732 vos_close(pVosContext );
1733 vos_sched_close(pVosContext);
1734
1735#ifdef ANI_BUS_TYPE_SDIO
1736err_balstop:
1737#ifndef ANI_MANF_DIAG
1738 wlan_hdd_enable_deepsleep(pVosContext);
1739#endif
1740 WLANBAL_Stop(pVosContext);
1741 WLANBAL_SuspendChip(pVosContext);
1742
1743err_salstop:
1744 WLANSAL_Stop(pVosContext);
1745
1746err_balclose:
1747 WLANBAL_Close(pVosContext);
1748
1749err_fail:
1750 //Assert Deep sleep signal now to put Libra HW in lowest power state
1751 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
1752
1753 //Vote off any PMIC voltage supplies
1754 vos_chipPowerDown(NULL, NULL, NULL);
1755#endif
1756
1757err_pwr_fail:
1758 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
1759
1760 // Allow the phone to go to sleep
1761 hdd_allow_suspend();
1762
1763#ifdef CONFIG_HAS_EARLYSUSPEND
1764 // unregister suspend/resume callbacks
1765 if(pHddCtx->cfg_ini->nEnableSuspend)
1766 unregister_wlan_suspend();
1767#endif
1768
1769 // Unregister the Net Device Notifier
1770 unregister_netdevice_notifier(&hdd_netdev_notifier);
1771
1772 //Clean up HDD Nlink Service
1773 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1774 nl_srv_exit();
1775
1776 hdd_close_all_adapters(pHddCtx);
1777 //Free up dynamically allocated members inside HDD Adapter
1778 kfree(pHddCtx->cfg_ini);
1779 pHddCtx->cfg_ini= NULL;
1780
1781#ifdef CONFIG_CFG80211
1782 wiphy_unregister(pHddCtx->wiphy);
1783 wiphy_free(pHddCtx->wiphy);
1784#else
1785 vos_mem_free(pHddCtx);
1786#endif
1787
1788#ifdef ANI_BUS_TYPE_SDIO
1789 WLANSAL_Close(pVosContext);
1790#endif
1791 vos_preClose(&pVosContext);
1792
1793#ifdef MEMORY_DEBUG
1794 vos_mem_exit();
1795#endif
1796
1797 return -1;
1798
1799success:
1800 //Trigger replay of BTC events
1801 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1802 return VOS_STATUS_SUCCESS;
1803
1804}
1805
1806
1807
1808VOS_STATUS hdd_wlan_reset_initialization(void)
1809{
1810#ifdef ANI_BUS_TYPE_SDIO
1811 struct sdio_func *sdio_func_dev = NULL;
1812 v_U8_t regValue = 0;
1813 int err_ret = 0;
1814#endif
1815 v_CONTEXT_t pVosContext = NULL;
1816
1817 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1818
1819 //Get the global VOSS context.
1820 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1821 if(!pVosContext)
1822 {
1823 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1824 return VOS_STATUS_E_FAILURE;
1825 }
1826
1827 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1828
1829 // Prevent the phone from going to sleep
1830 hdd_prevent_suspend();
1831
1832#ifdef ANI_BUS_TYPE_SDIO
1833 /* Clear pending interrupt and disable Interrupts. Use only CMD52 */
1834 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1835 "%s LOGP in progress. Disabling Interrupt", __func__);
1836
1837 sdio_func_dev = libra_getsdio_funcdev();
1838
1839 if(sdio_func_dev == NULL)
1840 {
1841 /* Our card got removed before LOGP. Continue with reset anyways */
1842 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1843 return VOS_STATUS_SUCCESS;
1844 }
1845
1846 sd_claim_host(sdio_func_dev);
1847
1848 regValue = 0;
1849 libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_SIF_INT_EN_REG,
1850 &regValue, 1, &err_ret);
1851
1852 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1853 "%s LOGP Cleared SIF_SIF_INT_EN_REG status:%d", __func__,err_ret);
1854
1855 regValue = 0;
1856 libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_BAR4_INT_PEND_REG,
1857 &regValue, 1, &err_ret);
1858
1859 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1860 "%s LOGP Cleared SIF_BAR4_INT_PEND_REG status :%d", __func__,err_ret);
1861
1862 regValue = 0;
1863 libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_BAR4_INT_ENABLE_REG,
1864 &regValue, 1, &err_ret);
1865
1866 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1867 "%s LOGP Cleared SIF_BAR4_INT_ENABLE_REG: Status:%d", __func__,err_ret);
1868
1869 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing Suspend Chip",__func__);
1870
1871 //Put the chip is standby before asserting deep sleep
1872 WLANBAL_SuspendChip_NoLock( pVosContext );
1873
1874 sd_release_host(sdio_func_dev);
1875#endif
1876
1877 return VOS_STATUS_SUCCESS;
1878}
1879
1880
1881void register_wlan_suspend(void)
1882{
1883 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Register WLAN suspend/resume "
1884 "callbacks",__func__);
1885 wlan_early_suspend.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING;
1886 wlan_early_suspend.suspend = hdd_suspend_wlan;
1887 wlan_early_suspend.resume = hdd_resume_wlan;
1888 register_early_suspend(&wlan_early_suspend);
1889}
1890
1891void unregister_wlan_suspend(void)
1892{
1893 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Unregister WLAN suspend/resume "
1894 "callbacks",__func__);
1895 unregister_early_suspend(&wlan_early_suspend);
1896}
1897#endif
1898
1899/* the HDD interface to WLAN driver shutdown,
1900 * the primary shutdown function in SSR
1901 */
1902VOS_STATUS hdd_wlan_shutdown(void)
1903{
1904 VOS_STATUS vosStatus;
1905 v_CONTEXT_t pVosContext = NULL;
1906 hdd_context_t *pHddCtx = NULL;
1907 pVosSchedContext vosSchedContext = NULL;
1908
1909 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1910
1911 /* Get the global VOSS context. */
1912 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1913 if(!pVosContext) {
1914 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1915 return VOS_STATUS_E_FAILURE;
1916 }
1917 /* Get the HDD context. */
1918 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1919 if(!pHddCtx) {
1920 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1921 return VOS_STATUS_E_FAILURE;
1922 }
1923 hdd_reset_all_adapters(pHddCtx);
1924#ifdef CONFIG_HAS_EARLYSUSPEND
1925 /* unregister suspend/resume callbacks */
1926 if(pHddCtx->cfg_ini->nEnableSuspend)
1927 {
1928 unregister_wlan_suspend();
1929 }
1930#endif
1931 /* DeRegister with platform driver as client for Suspend/Resume */
1932 vosStatus = hddDeregisterPmOps(pHddCtx);
1933 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1934 {
1935 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1936 }
1937
1938 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1939 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1940 {
1941 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1942 }
1943
1944 /* Disable IMPS/BMPS as we do not want the device to enter any power
1945 * save mode on its own during reset sequence
1946 */
1947 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1948 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1949 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1950
1951 vosSchedContext = get_vos_sched_ctxt();
1952
1953 /* Wakeup all driver threads */
1954 if(TRUE == pHddCtx->isMcThreadSuspended){
1955 complete(&vosSchedContext->ResumeMcEvent);
1956 pHddCtx->isMcThreadSuspended= FALSE;
1957 }
1958 if(TRUE == pHddCtx->isTxThreadSuspended){
1959 complete(&vosSchedContext->ResumeTxEvent);
1960 pHddCtx->isTxThreadSuspended= FALSE;
1961 }
1962 if(TRUE == pHddCtx->isRxThreadSuspended){
1963 complete(&vosSchedContext->ResumeRxEvent);
1964 pHddCtx->isRxThreadSuspended= FALSE;
1965 }
1966 /* Reset the Suspend Variable */
1967 pHddCtx->isWlanSuspended = FALSE;
1968
1969 /* Stop all the threads; we do not want any messages to be a processed,
1970 * any more and the best way to ensure that is to terminate the threads
1971 * gracefully.
1972 */
1973 /* Wait for MC to exit */
1974 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1975 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1976 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1977 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
1978 wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1979
1980 /* Wait for TX to exit */
1981 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1982 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1983 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1984 wake_up_interruptible(&vosSchedContext->txWaitQueue);
1985 wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1986
1987 /* Wait for RX to exit */
1988 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1989 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1990 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1991 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
1992 wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1993
1994#ifdef WLAN_BTAMP_FEATURE
1995 vosStatus = WLANBAP_Stop(pVosContext);
1996 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1997 {
1998 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1999 "%s: Failed to stop BAP",__func__);
2000 }
2001#endif //WLAN_BTAMP_FEATURE
2002 vosStatus = vos_wda_shutdown(pVosContext);
2003 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2004
2005 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
2006 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
2007 * on threads being running to process the SYS Stop
2008 */
2009 vosStatus = sme_Stop(pHddCtx->hHal, TRUE);
2010 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2011
2012 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
2013 /* Stop MAC (PE and HAL) */
2014 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
2015 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2016
2017 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
2018 /* Stop TL */
2019 vosStatus = WLANTL_Stop(pVosContext);
2020 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
2021
2022#ifdef CONFIG_HAS_EARLYSUSPEND
2023 hdd_unregister_mcast_bcast_filter(pHddCtx);
2024#endif
2025 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
2026 /* Clean up message queues of TX and MC thread */
2027 vos_sched_flush_mc_mqs(vosSchedContext);
2028 vos_sched_flush_tx_mqs(vosSchedContext);
2029 vos_sched_flush_rx_mqs(vosSchedContext);
2030
2031 /* Deinit all the TX and MC queues */
2032 vos_sched_deinit_mqs(vosSchedContext);
2033 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
2034
2035 /* shutdown VOSS */
2036 vos_shutdown(pVosContext);
2037 if (free_riva_power_on_lock("wlan"))
2038 {
2039 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
2040 __func__);
2041 }
2042 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
2043 ,__func__);
2044 return VOS_STATUS_SUCCESS;
2045}
2046
2047
2048
2049/* the HDD interface to WLAN driver re-init.
2050 * This is called to initialize/start WLAN driver after a shutdown.
2051 */
2052VOS_STATUS hdd_wlan_re_init(void)
2053{
2054 VOS_STATUS vosStatus;
2055 v_CONTEXT_t pVosContext = NULL;
2056 hdd_context_t *pHddCtx = NULL;
2057 eHalStatus halStatus;
2058#ifdef WLAN_BTAMP_FEATURE
2059 hdd_config_t *pConfig = NULL;
2060 WLANBAP_ConfigType btAmpConfig;
2061#endif
2062
2063 hdd_prevent_suspend();
2064 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
2065 vosStatus = vos_open(&pVosContext, 0);
2066 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2067 {
2068 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
2069 goto err_re_init;
2070 }
2071
2072 /* Get the HDD context. */
2073 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
2074 if(!pHddCtx)
2075 {
2076 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
2077 goto err_vosclose;
2078 }
2079
2080 /* Save the hal context in Adapter */
2081 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
2082 if ( NULL == pHddCtx->hHal )
2083 {
2084 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
2085 goto err_vosclose;
2086 }
2087
2088 /* Set the SME configuration parameters. */
2089 vosStatus = hdd_set_sme_config(pHddCtx);
2090 if ( VOS_STATUS_SUCCESS != vosStatus )
2091 {
2092 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
2093 goto err_vosclose;
2094 }
2095
2096 /* Initialize the WMM module */
2097 vosStatus = hdd_wmm_init(pHddCtx);
2098 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
2099 {
2100 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __FUNCTION__);
2101 goto err_vosclose;
2102 }
2103
2104 vosStatus = vos_preStart( pHddCtx->pvosContext );
2105 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2106 {
2107 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
2108 goto err_vosclose;
2109 }
2110
2111 /* In the integrated architecture we update the configuration from
2112 the INI file and from NV before vOSS has been started so that
2113 the final contents are available to send down to the cCPU */
2114 /* Apply the cfg.ini to cfg.dat */
2115 if (FALSE == hdd_update_config_dat(pHddCtx))
2116 {
2117 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
2118 goto err_vosclose;
2119 }
2120
2121 /* Set the MAC Address, currently this is used by HAL to add self sta.
2122 * Remove this once self sta is added as part of session open. */
2123 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
2124 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
2125 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
2126 if (!HAL_STATUS_SUCCESS(halStatus))
2127 {
2128 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
2129 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
2130 goto err_vosclose;
2131 }
2132
2133 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
2134 Note: Firmware image will be read and downloaded inside vos_start API */
2135 vosStatus = vos_start( pVosContext );
2136 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2137 {
2138 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
2139 goto err_vosclose;
2140 }
2141
2142 vosStatus = hdd_post_voss_start_config( pHddCtx );
2143 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2144 {
2145 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
2146 __func__);
2147 goto err_vosstop;
2148 }
2149
2150#ifdef WLAN_BTAMP_FEATURE
2151 vosStatus = WLANBAP_Open(pVosContext);
2152 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2153 {
2154 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2155 "%s: Failed to open BAP",__func__);
2156 goto err_vosstop;
2157 }
2158 vosStatus = BSL_Init(pVosContext);
2159 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
2160 {
2161 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2162 "%s: Failed to Init BSL",__func__);
2163 goto err_bap_close;
2164 }
2165 vosStatus = WLANBAP_Start(pVosContext);
2166 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2167 {
2168 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2169 "%s: Failed to start TL",__func__);
2170 goto err_bap_close;
2171 }
2172 pConfig = pHddCtx->cfg_ini;
2173 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
2174 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
2175#endif //WLAN_BTAMP_FEATURE
2176
2177 /* Restart all adapters */
2178 hdd_start_all_adapters(pHddCtx);
2179 pHddCtx->isLogpInProgress = FALSE;
2180 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
2181#ifdef CONFIG_HAS_EARLYSUSPEND
2182 hdd_register_mcast_bcast_filter(pHddCtx);
2183#endif
2184
2185 /* Register with platform driver as client for Suspend/Resume */
2186 vosStatus = hddRegisterPmOps(pHddCtx);
2187 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2188 {
2189 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
2190 goto err_bap_stop;
2191 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002192#ifdef CONFIG_HAS_EARLYSUSPEND
Jeff Johnson295189b2012-06-20 16:38:30 -07002193 // Register suspend/resume callbacks
2194 if(pHddCtx->cfg_ini->nEnableSuspend)
2195 {
2196 register_wlan_suspend();
2197 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002198#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002199 /* Allow the phone to go to sleep */
2200 hdd_allow_suspend();
2201 /* register for riva power on lock */
2202 if (req_riva_power_on_lock("wlan"))
2203 {
2204 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
2205 __func__);
2206 goto err_unregister_pmops;
2207 }
2208 goto success;
2209
2210err_unregister_pmops:
2211 hddDeregisterPmOps(pHddCtx);
2212
2213err_bap_stop:
2214#ifdef WLAN_BTAMP_FEATURE
2215 WLANBAP_Stop(pVosContext);
2216#endif
2217
2218#ifdef WLAN_BTAMP_FEATURE
2219err_bap_close:
2220 WLANBAP_Close(pVosContext);
2221#endif
2222
2223err_vosstop:
2224 vos_stop(pVosContext);
2225
2226err_vosclose:
2227 vos_close(pVosContext);
2228 vos_sched_close(pVosContext);
2229 if (pHddCtx)
2230 {
2231#ifdef CONFIG_HAS_EARLYSUSPEND
2232 /* unregister suspend/resume callbacks */
2233 if (pHddCtx->cfg_ini->nEnableSuspend)
2234 unregister_wlan_suspend();
2235#endif
2236 /* Unregister the Net Device Notifier */
2237 unregister_netdevice_notifier(&hdd_netdev_notifier);
2238 /* Clean up HDD Nlink Service */
2239 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2240 nl_srv_exit();
2241 hdd_close_all_adapters(pHddCtx);
2242 /* Free up dynamically allocated members inside HDD Adapter */
2243 kfree(pHddCtx->cfg_ini);
2244 pHddCtx->cfg_ini= NULL;
2245
2246#ifdef CONFIG_CFG80211
2247 wiphy_unregister(pHddCtx->wiphy);
2248 wiphy_free(pHddCtx->wiphy);
2249#else
2250 vos_mem_free(pHddCtx);
2251#endif
2252 }
2253 vos_preClose(&pVosContext);
2254
2255#ifdef MEMORY_DEBUG
2256 vos_mem_exit();
2257#endif
2258
2259err_re_init:
2260 /* Allow the phone to go to sleep */
2261 hdd_allow_suspend();
2262 return -1;
2263
2264success:
2265 /* Trigger replay of BTC events */
2266 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2267 return VOS_STATUS_SUCCESS;
2268}