blob: 0199fdb95eb43c18fa3ad6f8ef55745226defdc8 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. 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/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/**=============================================================================
43* wlan_hdd_early_suspend.c
44*
45* \brief power management functions
46*
47* Description
48* Copyright 2009 (c) Qualcomm, Incorporated.
49* All Rights Reserved.
50* Qualcomm Confidential and Proprietary.
51*
52==============================================================================**/
53/* $HEADER$ */
54
55/**-----------------------------------------------------------------------------
56* Include files
57* ----------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -070058
59#include <linux/pm.h>
60#include <linux/wait.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070061#include <wlan_hdd_includes.h>
62#include <wlan_qct_driver.h>
63#include <linux/wakelock.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070064
65#include "halTypes.h"
66#include "sme_Api.h"
67#include <vos_api.h>
68#include "vos_power.h"
69#include <vos_sched.h>
70#include <macInitApi.h>
71#ifdef ANI_BUS_TYPE_SDIO
72#include <wlan_qct_sal.h>
73#include <wlan_qct_bal.h>
74#endif
75#include <wlan_qct_sys.h>
76#include <wlan_btc_svc.h>
77#include <wlan_nlink_common.h>
78#include <wlan_hdd_main.h>
79#include <wlan_hdd_assoc.h>
80#include <wlan_hdd_dev_pwr.h>
81#ifdef ANI_BUS_TYPE_SDIO
82#include <wlan_sal_misc.h>
83#include <libra_sdioif.h>
84#endif
85#include <wlan_nlink_srv.h>
86#include <wlan_hdd_misc.h>
87
88#ifdef WLAN_SOFTAP_FEATURE
89#include <linux/semaphore.h>
90#include <wlan_hdd_hostapd.h>
91#endif
92#include "cfgApi.h"
93
94#ifdef WLAN_BTAMP_FEATURE
95#include "bapApi.h"
96#include "bap_hdd_main.h"
97#include "bap_hdd_misc.h"
98#endif
99
Jeff Johnsone7245742012-09-05 17:12:55 -0700100#include <linux/wcnss_wlan.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700101#include <linux/inetdevice.h>
102#include <wlan_hdd_cfg.h>
103/**-----------------------------------------------------------------------------
104* Preprocessor definitions and constants
105* ----------------------------------------------------------------------------*/
106
107/**-----------------------------------------------------------------------------
108* Type declarations
109* ----------------------------------------------------------------------------*/
110
111/**-----------------------------------------------------------------------------
112* Function and variables declarations
113* ----------------------------------------------------------------------------*/
114#include "wlan_hdd_power.h"
115#include "wlan_hdd_packet_filtering.h"
116
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -0700117#define HDD_SSR_BRING_UP_TIME 10000
Jeff Johnson295189b2012-06-20 16:38:30 -0700118
119static eHalStatus g_full_pwr_status;
120static eHalStatus g_standby_status;
121
122extern VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx);
123extern VOS_STATUS vos_chipExitDeepSleepVREGHandler(
124 vos_call_status_type* status,
125 vos_power_cb_type callback,
126 v_PVOID_t user_data);
127extern void hdd_wlan_initial_scan(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700128
129extern struct notifier_block hdd_netdev_notifier;
130#ifdef WLAN_SOFTAP_FEATURE
131extern tVOS_CON_MODE hdd_get_conparam ( void );
132#endif
133
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -0700134static struct timer_list ssr_timer;
135static bool ssr_timer_started;
Jeff Johnson295189b2012-06-20 16:38:30 -0700136
137//Callback invoked by PMC to report status of standby request
138void hdd_suspend_standby_cbk (void *callbackContext, eHalStatus status)
139{
140 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
141 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Standby status = %d", __func__, status);
142 g_standby_status = status;
143
144 if(eHAL_STATUS_SUCCESS == status)
145 {
146 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
147 }
148 else
149 {
150 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
151 }
152
153 complete(&pHddCtx->standby_comp_var);
154}
155
156//Callback invoked by PMC to report status of full power request
157void hdd_suspend_full_pwr_callback(void *callbackContext, eHalStatus status)
158{
159 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
160 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Full Power status = %d", __func__, status);
161 g_full_pwr_status = status;
162
163 if(eHAL_STATUS_SUCCESS == status)
164 {
165 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
166 }
167 else
168 {
169 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
170 }
171
172 complete(&pHddCtx->full_pwr_comp_var);
173}
174
175eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx)
176{
177 eHalStatus status = VOS_STATUS_SUCCESS;
178
179 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from standby",__func__);
180 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
181
182 g_full_pwr_status = eHAL_STATUS_FAILURE;
183 status = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, pHddCtx,
184 eSME_FULL_PWR_NEEDED_BY_HDD);
185
186 if(status == eHAL_STATUS_PMC_PENDING)
187 {
188 //Block on a completion variable. Can't wait forever though
189 wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
190 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
191 status = g_full_pwr_status;
192 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
193 {
194 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
195 VOS_ASSERT(0);
196 goto failure;
197 }
198 }
199 else if(status != eHAL_STATUS_SUCCESS)
200 {
201 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
202 __func__, status);
203 VOS_ASSERT(0);
204 goto failure;
205 }
206 else
207 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
208
209failure:
210 //No blocking to reduce latency. No other device should be depending on WLAN
211 //to finish resume and WLAN won't be instantly on after resume
212 return status;
213}
214
215
216//Helper routine to put the chip into standby
217VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx)
218{
219 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
220 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
221
222 //Disable IMPS/BMPS as we do not want the device to enter any power
223 //save mode on its own during suspend sequence
224 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
225 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
226
227 //Note we do not disable queues unnecessarily. Queues should already be disabled
228 //if STA is disconnected or the queue will be disabled as and when disconnect
229 //happens because of standby procedure.
230
231 //Ensure that device is in full power first. There is scope for optimization
232 //here especially in scenarios where PMC is already in IMPS or REQUEST_IMPS.
233 //Core s/w needs to be optimized to handle this. Until then we request full
234 //power before issuing request for standby.
235 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
236 g_full_pwr_status = eHAL_STATUS_FAILURE;
237 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
238 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
239
240 if(halStatus == eHAL_STATUS_PMC_PENDING)
241 {
242 //Block on a completion variable. Can't wait forever though
243 wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
244 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
245 if(g_full_pwr_status != eHAL_STATUS_SUCCESS)
246 {
247 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower Failed",__func__);
248 VOS_ASSERT(0);
249 vosStatus = VOS_STATUS_E_FAILURE;
250 goto failure;
251 }
252 }
253 else if(halStatus != eHAL_STATUS_SUCCESS)
254 {
255 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed - status %d",
256 __func__, halStatus);
257 VOS_ASSERT(0);
258 vosStatus = VOS_STATUS_E_FAILURE;
259 goto failure;
260 }
261
262 if(pHddCtx->hdd_mcastbcast_filter_set == TRUE) {
263 hdd_conf_mcastbcast_filter(pHddCtx, FALSE);
264 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
265 }
266
267 //Request standby. Standby will cause the STA to disassociate first. TX queues
268 //will be disabled (by HDD) when STA disconnects. You do not want to disable TX
269 //queues here. Also do not assert if the failure code is eHAL_STATUS_PMC_NOT_NOW as PMC
270 //will send this failure code in case of concurrent sessions. Power Save cannot be supported
271 //when there are concurrent sessions.
272 INIT_COMPLETION(pHddCtx->standby_comp_var);
273 g_standby_status = eHAL_STATUS_FAILURE;
274 halStatus = sme_RequestStandby(pHddCtx->hHal, hdd_suspend_standby_cbk, pHddCtx);
275
276 if (halStatus == eHAL_STATUS_PMC_PENDING)
277 {
278 //Wait till WLAN device enters standby mode
279 wait_for_completion_timeout(&pHddCtx->standby_comp_var,
280 msecs_to_jiffies(WLAN_WAIT_TIME_STANDBY));
281 if (g_standby_status != eHAL_STATUS_SUCCESS && g_standby_status != eHAL_STATUS_PMC_NOT_NOW)
282 {
283 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed",__func__);
284 VOS_ASSERT(0);
285 vosStatus = VOS_STATUS_E_FAILURE;
286 goto failure;
287 }
288 }
289 else if (halStatus != eHAL_STATUS_SUCCESS && halStatus != eHAL_STATUS_PMC_NOT_NOW) {
290 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestStandby failed - status %d",
291 __func__, halStatus);
292 VOS_ASSERT(0);
293 vosStatus = VOS_STATUS_E_FAILURE;
294 goto failure;
295 }
296 else
297 pHddCtx->hdd_ps_state = eHDD_SUSPEND_STANDBY;
298
299failure:
300 //Restore IMPS config
301 if(pHddCtx->cfg_ini->fIsImpsEnabled)
302 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
303
304 //Restore BMPS config
305 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
306 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
307
308 return vosStatus;
309}
310
311
312//Helper routine for Deep sleep entry
313VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
314{
315 eHalStatus halStatus;
316 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
317 vos_call_status_type callType;
318#ifdef ANI_BUS_TYPE_SDIO
319 struct sdio_func *sdio_func_dev_current = NULL;
320 int attempts = 0;
321#endif
322 //Stop the Interface TX queue.
323 netif_tx_disable(pAdapter->dev);
324 netif_carrier_off(pAdapter->dev);
325
326 //Disable IMPS,BMPS as we do not want the device to enter any power
327 //save mode on it own during suspend sequence
328 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
329 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
330
331 //Ensure that device is in full power as we will touch H/W during vos_Stop
332 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
333 g_full_pwr_status = eHAL_STATUS_FAILURE;
334 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback,
335 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
336
337 if(halStatus == eHAL_STATUS_PMC_PENDING)
338 {
339 //Block on a completion variable. Can't wait forever though
340 wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var,
341 msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR));
342 if(g_full_pwr_status != eHAL_STATUS_SUCCESS){
343 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__);
344 VOS_ASSERT(0);
345 }
346 }
347 else if(halStatus != eHAL_STATUS_SUCCESS)
348 {
349 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Request for Full Power failed",__func__);
350 VOS_ASSERT(0);
351 }
352
353 //Issue a disconnect. This is required to inform the supplicant that
354 //STA is getting disassociated and for GUI to be updated properly
355 INIT_COMPLETION(pAdapter->disconnect_comp_var);
356 halStatus = sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
357
358 //Success implies disconnect command got queued up successfully
359 if(halStatus == eHAL_STATUS_SUCCESS)
360 {
361 //Block on a completion variable. Can't wait forever though.
362 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
363 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
364 }
365
366
367 //None of the steps should fail after this. Continue even in case of failure
368 vosStatus = vos_stop( pHddCtx->pvosContext );
369 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
370
371#ifdef ANI_BUS_TYPE_SDIO
372 vosStatus = WLANBAL_Stop( pHddCtx->pvosContext );
373 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
374
375 vosStatus = WLANBAL_SuspendChip( pHddCtx->pvosContext );
376 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
377
378 vosStatus = WLANSAL_Stop(pHddCtx->pvosContext);
379 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
380#endif
381
382 vosStatus = vos_chipAssertDeepSleep( &callType, NULL, NULL );
383 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
384
385 //Vote off any PMIC voltage supplies
386 vosStatus = vos_chipPowerDown(NULL, NULL, NULL);
387
388#ifdef ANI_BUS_TYPE_SDIO
389 //Get the Current SDIO Func
390 sdio_func_dev_current = libra_getsdio_funcdev();
391 if(NULL != sdio_func_dev_current) {
392 libra_detect_card_change();
393 do {
394 msleep(100);
395 //Get the SDIO func device
396 sdio_func_dev_current = libra_getsdio_funcdev();
397 if(NULL == sdio_func_dev_current) {
398 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Card Removed Successfully",__func__);
399 break;
400 }
401 else {
402 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Trying Again",__func__);
403 attempts++;
404 }
405 } while (attempts < LIBRA_CARD_REMOVE_DETECT_MAX_COUNT);
406
407 if(LIBRA_CARD_REMOVE_DETECT_MAX_COUNT == attempts) {
408 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to Remove the Card: Fatal",__func__);
409 goto err_fail;
410 }
411 }
412#endif
413
414 pHddCtx->hdd_ps_state = eHDD_SUSPEND_DEEP_SLEEP;
415
416 //Restore IMPS config
417 if(pHddCtx->cfg_ini->fIsImpsEnabled)
418 sme_EnablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
419
420 //Restore BMPS config
421 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
422 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
423
424#ifdef ANI_BUS_TYPE_SDIO
425err_fail:
426#endif
427 return vosStatus;
428}
429
430VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter)
431{
432 VOS_STATUS vosStatus;
433 eHalStatus halStatus;
434#ifdef ANI_BUS_TYPE_SDIO
435 int attempts = 0;
436 struct sdio_func *sdio_func_dev = NULL;
437#endif
438
439 //Power Up Libra WLAN card first if not already powered up
440 vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
441 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
442 {
443 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
444 "exiting", __func__);
445 goto err_deep_sleep;
446 }
447
448#ifdef ANI_BUS_TYPE_SDIO
449 libra_detect_card_change();
450
451 do {
452 sdio_func_dev = libra_getsdio_funcdev();
453 if (NULL == sdio_func_dev) {
454 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not detected yet.",__func__);
455 attempts++;
456 }
457 else {
458 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN detecton succeeded",__func__);
459 break;
460 }
461
462 if(LIBRA_CARD_INSERT_DETECT_MAX_COUNT == attempts)
463 break;
464
465 msleep(250);
466
467 }while (attempts < LIBRA_CARD_INSERT_DETECT_MAX_COUNT);
468
469 //Retry to detect the card again by Powering Down the chip and Power up the chip
470 //again. This retry is done to recover from CRC Error
471 if (NULL == sdio_func_dev) {
472
473 attempts = 0;
474
475 //Vote off any PMIC voltage supplies
476 vos_chipPowerDown(NULL, NULL, NULL);
477
478 msleep(1000);
479
480 //Power Up Libra WLAN card first if not already powered up
481 vosStatus = vos_chipPowerUp(NULL,NULL,NULL);
482 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
483 {
484 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not Powered Up. "
485 "exiting", __func__);
486 goto err_deep_sleep;
487 }
488
489 do {
490 sdio_func_dev = libra_getsdio_funcdev();
491 if (NULL == sdio_func_dev) {
492 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not detected yet.",__func__);
493 attempts++;
494 }
495 else {
496 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN detecton succeeded",__func__);
497 break;
498 }
499
500 if(attempts == 2)
501 break;
502
503 msleep(1000);
504
505 }while (attempts < 3);
506
507 }
508
509 if (NULL == sdio_func_dev) {
510 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not found!!",__func__);
511 goto err_deep_sleep;
512 }
513
514 SET_NETDEV_DEV(pAdapter->dev, &sdio_func_dev->dev);
515 libra_sdio_setprivdata (sdio_func_dev, pHddCtx);
516 atomic_set(&pHddCtx->sdio_claim_count, 0);
517 pHddCtx->parent_dev = &sdio_func_dev->dev;
518
519 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
520 "%s: calling WLANSAL_Start",__func__);
521 vosStatus = WLANSAL_Start(pHddCtx->pvosContext);
522 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
523 {
524 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
525 "%s: Failed to start SAL",__func__);
526 goto err_deep_sleep;
527 }
528
529 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
530 "%s: calling WLANBAL_ResumeChip",__func__);
531 vosStatus = WLANBAL_ResumeChip( pHddCtx->pvosContext );
532 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
533 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
534 {
535 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
536 "%s: Failed in WLANBAL_ResumeChip",__func__);
537 goto err_sal_stop;
538 }
539
540 vosStatus = WLANBAL_Start(pHddCtx->pvosContext);
541
542 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
543 {
544 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
545 "%s: Failed to start BAL",__func__);
546 goto err_sal_stop;
547 }
548#endif
549
550 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
551 "%s: calling hdd_set_sme_config",__func__);
552 vosStatus = hdd_set_sme_config( pHddCtx );
553 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
554 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
555 {
556 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
557 "%s: Failed in hdd_set_sme_config",__func__);
558#ifdef ANI_BUS_TYPE_SDIO
559 goto err_bal_stop;
560#else
561 goto err_deep_sleep;
562#endif
563 }
564
565 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
566 "%s: calling vos_start",__func__);
567 vosStatus = vos_start( pHddCtx->pvosContext );
568 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
569 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
570 {
571 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
572 "%s: Failed in vos_start",__func__);
573#ifdef ANI_BUS_TYPE_SDIO
574 goto err_bal_stop;
575#else
576 goto err_deep_sleep;
577#endif
578 }
579
580 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
581 "%s: calling hdd_post_voss_start_config",__func__);
582 vosStatus = hdd_post_voss_start_config( pHddCtx );
583 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
584 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
585 {
586 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
587 "%s: Failed in hdd_post_voss_start_config",__func__);
588 goto err_voss_stop;
589 }
590
591
592 //Open a SME session for future operation
593 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pHddCtx,
594 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
595 if ( !HAL_STATUS_SUCCESS( halStatus ) )
596 {
597 hddLog(VOS_TRACE_LEVEL_FATAL,"sme_OpenSession() failed with status code %08d [x%08lx]",
598 halStatus, halStatus );
599 goto err_voss_stop;
600
601 }
602
603 pHddCtx->hdd_ps_state = eHDD_SUSPEND_NONE;
604
605 //Trigger the initial scan
606 hdd_wlan_initial_scan(pHddCtx);
607
608 return VOS_STATUS_SUCCESS;
609
610err_voss_stop:
611 vos_stop(pHddCtx->pvosContext);
612#ifdef ANI_BUS_TYPE_SDIO
613err_bal_stop:
614 WLANBAL_Stop(pHddCtx->pvosContext);
615err_sal_stop:
616 WLANSAL_Stop(pHddCtx->pvosContext);
617#endif
618err_deep_sleep:
619 return VOS_STATUS_E_FAILURE;
620
621}
622
Yathish9f22e662012-12-10 14:21:35 -0800623VOS_STATUS hdd_conf_hostarpoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable)
Jeff Johnson295189b2012-06-20 16:38:30 -0700624{
625 struct in_ifaddr **ifap = NULL;
626 struct in_ifaddr *ifa = NULL;
627 struct in_device *in_dev;
628 int i = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700629 tSirHostOffloadReq offLoadRequest;
Yathish9f22e662012-12-10 14:21:35 -0800630 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700631
632 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700633
Jeff Johnson295189b2012-06-20 16:38:30 -0700634 if(fenable)
635 {
636 if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL)
637 {
638 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
639 ifap = &ifa->ifa_next)
640 {
641 if (!strcmp(pAdapter->dev->name, ifa->ifa_label))
642 {
643 break; /* found */
644 }
645 }
646 }
647
648 if(ifa && ifa->ifa_local)
649 {
650 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
651 offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE;
652
653 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Enabled \n", __func__);
654
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700655 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
Jeff Johnson295189b2012-06-20 16:38:30 -0700656 {
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700657 if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
658 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting) ||
659 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
660 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting))
661 {
662 offLoadRequest.enableOrDisable =
663 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
664 }
665 }
666 else if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
667 pHddCtx->cfg_ini->mcastBcastFilterSetting ) ||
668 (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
669 pHddCtx->cfg_ini->mcastBcastFilterSetting))
670 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700671 offLoadRequest.enableOrDisable =
672 SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE;
673 }
674
675 //converting u32 to IPV4 address
676 for(i = 0 ; i < 4; i++)
677 {
678 offLoadRequest.params.hostIpv4Addr[i] =
679 (ifa->ifa_local >> (i*8) ) & 0xFF ;
680 }
681 hddLog(VOS_TRACE_LEVEL_WARN, " Enable SME HostOffload: %d.%d.%d.%d",
682 offLoadRequest.params.hostIpv4Addr[0],
683 offLoadRequest.params.hostIpv4Addr[1],
684 offLoadRequest.params.hostIpv4Addr[2],
685 offLoadRequest.params.hostIpv4Addr[3]);
686
687 if (eHAL_STATUS_SUCCESS !=
Jeff Johnsone7245742012-09-05 17:12:55 -0700688 sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter),
689 pAdapter->sessionId, &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700690 {
691 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload "
692 "feature\n", __func__);
693 return VOS_STATUS_E_FAILURE;
694 }
695 return VOS_STATUS_SUCCESS;
696 }
697 else
698 {
699 hddLog(VOS_TRACE_LEVEL_INFO, "%s:IP Address is not assigned \n", __func__);
700 return VOS_STATUS_E_AGAIN;
701 }
702 }
703 else
704 {
705 vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq));
706 offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE;
707 offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD;
708
Jeff Johnsone7245742012-09-05 17:12:55 -0700709 if (eHAL_STATUS_SUCCESS != sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
710 &offLoadRequest))
Jeff Johnson295189b2012-06-20 16:38:30 -0700711 {
712 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host "
713 "offload feature\n", __func__);
714 return VOS_STATUS_E_FAILURE;
715 }
716 return VOS_STATUS_SUCCESS;
717 }
718}
719
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530720/*
721 * This function is called before setting mcbc filters
722 * to modify filter value considering ARP
723*/
724void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx, v_BOOL_t arpFlag,
725 tANI_U8 *pMcBcFilter)
726{
727 if (TRUE == arpFlag)
728 {
729 /*ARP offload is enabled, do not block bcast packets at RXP*/
730 if (pHddCtx->dynamic_mcbc_filter.enableCfg)
731 {
732 if ((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
733 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting))
734 {
735 *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST;
736 }
737 else if ((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
738 pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting))
739 {
740 *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_NONE;
741 }
742 else
743 {
744 *pMcBcFilter = pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting;
745 }
746
747 pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE;
748 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend = *pMcBcFilter;
749 }
750 else
751 {
752 if (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST ==
753 pHddCtx->cfg_ini->mcastBcastFilterSetting)
754 {
755 *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST;
756 }
757 else if (HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST ==
758 pHddCtx->cfg_ini->mcastBcastFilterSetting)
759 {
760 *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_NONE;
761 }
762 else
763 {
764 *pMcBcFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
765 }
766
767 pHddCtx->dynamic_mcbc_filter.enableSuspend = FALSE;
768 }
769 }
770 else
771 {
772 if (pHddCtx->dynamic_mcbc_filter.enableCfg)
773 {
774 *pMcBcFilter = pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting;
775 pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE;
776 }
777 else
778 {
779 pHddCtx->dynamic_mcbc_filter.enableSuspend = FALSE;
780 *pMcBcFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
781 }
782 }
783}
784
Jeff Johnson295189b2012-06-20 16:38:30 -0700785void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter)
786{
787 eHalStatus halStatus = eHAL_STATUS_FAILURE;
788#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
789 tpAniSirGlobal pMac = (tpAniSirGlobal) vos_get_context(VOS_MODULE_ID_SME, pHddCtx->pvosContext);
790#else
791 tpSirWlanSetRxpFilters wlanRxpFilterParam =
792 vos_mem_malloc(sizeof(tSirWlanSetRxpFilters));
793 if(NULL == wlanRxpFilterParam)
794 {
795 hddLog(VOS_TRACE_LEVEL_FATAL,
796 "%s: vos_mem_alloc failed ", __func__);
797 return;
798 }
799#endif
800 hddLog(VOS_TRACE_LEVEL_INFO,
801 "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter);
802#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
803 if ( pMac )
804 {
805 halStatus = halRxp_configureRxpFilterMcstBcst( pMac, setfilter);
806 }
807 else
808 {
809 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pMac is initialised to NULL",__func__ );
810 }
811#else
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530812 if (TRUE == setfilter)
813 {
814 if (pHddCtx->cfg_ini->fhostArpOffload)
815 {
816 hdd_mcbc_filter_modification(pHddCtx, TRUE,
817 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
818 }
819 else
820 {
821 hdd_mcbc_filter_modification(pHddCtx, FALSE,
822 &wlanRxpFilterParam->configuredMcstBcstFilterSetting);
823 }
824 }
825 else
826 wlanRxpFilterParam->configuredMcstBcstFilterSetting =
827 pHddCtx->cfg_ini->mcastBcastFilterSetting;
828
Jeff Johnson295189b2012-06-20 16:38:30 -0700829 wlanRxpFilterParam->setMcstBcstFilter = setfilter;
Jeff Johnson295189b2012-06-20 16:38:30 -0700830 halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam);
831#endif
832 if(setfilter && (eHAL_STATUS_SUCCESS == halStatus))
833 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
834}
835
836#ifdef FEATURE_WLAN_INTEGRATED_SOC
837static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx,
838 hdd_adapter_t *pAdapter)
839{
840 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Madan Mohan Koyyalamudi51d87f72012-09-24 12:05:23 -0700841 VOS_STATUS vstatus = VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700842 tpSirWlanSuspendParam wlanSuspendParam =
843 vos_mem_malloc(sizeof(tSirWlanSuspendParam));
844
845 if(NULL == wlanSuspendParam)
846 {
847 hddLog(VOS_TRACE_LEVEL_FATAL,
848 "%s: vos_mem_alloc failed ", __func__);
849 return;
850 }
851
852 hddLog(VOS_TRACE_LEVEL_INFO,
853 "%s: send wlan suspend indication", __func__);
854
855 if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER))
856 {
857 if((pHddCtx->cfg_ini->fhostArpOffload) &&
858 (eConnectionState_Associated ==
859 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
860 {
Yathish9f22e662012-12-10 14:21:35 -0800861 vstatus = hdd_conf_hostarpoffload(pAdapter, TRUE);
Jeff Johnson43971f52012-07-17 12:26:56 -0700862 if (!VOS_IS_STATUS_SUCCESS(vstatus))
Jeff Johnson295189b2012-06-20 16:38:30 -0700863 {
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530864 hdd_mcbc_filter_modification(pHddCtx, FALSE,
865 &wlanSuspendParam->configuredMcstBcstFilterSetting);
Jeff Johnson295189b2012-06-20 16:38:30 -0700866 hddLog(VOS_TRACE_LEVEL_INFO,
867 "%s:Failed to enable ARPOFFLOAD Feature %d\n",
Jeff Johnson43971f52012-07-17 12:26:56 -0700868 __func__, vstatus);
Jeff Johnson295189b2012-06-20 16:38:30 -0700869 }
Jeff Johnson43971f52012-07-17 12:26:56 -0700870 else
871 {
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530872 hdd_mcbc_filter_modification(pHddCtx, TRUE,
873 &wlanSuspendParam->configuredMcstBcstFilterSetting);
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700874 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700875 }
876 else
877 {
Gopichand Nakkalab8ddf462013-02-20 18:53:50 +0530878 hdd_mcbc_filter_modification(pHddCtx, FALSE,
879 &wlanSuspendParam->configuredMcstBcstFilterSetting);
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700880 if(pHddCtx->dynamic_mcbc_filter.enableCfg)
881 {
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700882 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend =
Jeff Johnson43971f52012-07-17 12:26:56 -0700883 wlanSuspendParam->configuredMcstBcstFilterSetting;
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700884 }
Madan Mohan Koyyalamudif55e62a2012-09-24 11:14:27 -0700885 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700886
887#ifdef WLAN_FEATURE_PACKET_FILTERING
888 if (pHddCtx->cfg_ini->isMcAddrListFilter)
889 {
890 /*Multicast addr list filter is enabled during suspend*/
891 if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
892 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT))
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530893 && pAdapter->mc_addr_list.mc_cnt
Jeff Johnson295189b2012-06-20 16:38:30 -0700894 && (eConnectionState_Associated ==
895 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
896 {
897 /*set the filter*/
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530898 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700899 }
900 }
901#endif
902 }
903
904 halStatus = sme_ConfigureSuspendInd(pHddCtx->hHal, wlanSuspendParam);
905 if(eHAL_STATUS_SUCCESS == halStatus)
906 {
907 pHddCtx->hdd_mcastbcast_filter_set = TRUE;
908 }
909}
910
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530911static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700912{
Jeff Johnson43971f52012-07-17 12:26:56 -0700913 VOS_STATUS vstatus;
Yathish9f22e662012-12-10 14:21:35 -0800914 hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700915 tpSirWlanResumeParam wlanResumeParam =
916 vos_mem_malloc(sizeof(tSirWlanResumeParam));
917
918 if(NULL == wlanResumeParam)
919 {
920 hddLog(VOS_TRACE_LEVEL_FATAL,
921 "%s: vos_mem_alloc failed ", __func__);
922 return;
923 }
924
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530925 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700926 "%s: send wlan resume indication", __func__);
927
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530928 if (pHddCtx->hdd_mcastbcast_filter_set == TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700929 {
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530930 if (pHddCtx->cfg_ini->fhostArpOffload)
Jeff Johnson295189b2012-06-20 16:38:30 -0700931 {
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530932 vstatus = hdd_conf_hostarpoffload(pAdapter, FALSE);
933 if (!VOS_IS_STATUS_SUCCESS(vstatus))
934 {
935 hddLog(VOS_TRACE_LEVEL_INFO, "%s:Failed to disable ARPOFFLOAD "
936 "Feature %d\n", __func__, vstatus);
937 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700938 }
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530939 if (pHddCtx->dynamic_mcbc_filter.enableSuspend)
940 {
941 wlanResumeParam->configuredMcstBcstFilterSetting =
942 pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend;
943 }
944 else
945 {
946 wlanResumeParam->configuredMcstBcstFilterSetting =
947 pHddCtx->cfg_ini->mcastBcastFilterSetting;
948 }
949 sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam);
950 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700951 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700952
953#ifdef WLAN_FEATURE_PACKET_FILTERING
954 if (pHddCtx->cfg_ini->isMcAddrListFilter)
955 {
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530956 /*Multicast addr filtering is enabled*/
957 if (pAdapter->mc_addr_list.isFilterApplied)
Jeff Johnson295189b2012-06-20 16:38:30 -0700958 {
959 /*Filter applied during suspend mode*/
960 /*Clear it here*/
Gopichand Nakkala0f276812013-02-24 14:45:51 +0530961 wlan_hdd_set_mc_addr_list(pAdapter, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700962 }
963 }
964#endif
965}
966#endif
967
Jeff Johnson295189b2012-06-20 16:38:30 -0700968//Suspend routine registered with Android OS
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800969void hdd_suspend_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -0700970{
971 hdd_context_t *pHddCtx = NULL;
972 v_CONTEXT_t pVosContext = NULL;
973
974 hdd_adapter_t *pAdapter = NULL;
975 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
976 VOS_STATUS status;
977#ifdef ANI_BUS_TYPE_SDIO
978 struct sdio_func *sdio_func_dev = NULL;
979#endif
980 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__);
981
982 //Get the global VOSS context.
983 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
984 if(!pVosContext) {
985 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
986 return;
987 }
988
989 //Get the HDD context.
990 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
991
992 if(!pHddCtx) {
993 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
994 return;
995 }
996
997 if (pHddCtx->isLogpInProgress) {
998 hddLog(VOS_TRACE_LEVEL_ERROR,
999 "%s: Ignore suspend wlan, LOGP in progress!", __func__);
1000 return;
1001 }
1002
1003#ifdef ANI_BUS_TYPE_SDIO
1004 sdio_func_dev = libra_getsdio_funcdev();
1005
1006 if(sdio_func_dev == NULL)
1007 {
1008 /* Our card got removed */
1009 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1010 return;
1011 }
1012
1013 if(!sd_is_drvdata_available(sdio_func_dev))
1014 {
1015 /* Our card got removed */
1016 hddLog(VOS_TRACE_LEVEL_FATAL,
1017 "%s: HDD context is not available in sdio_func_dev!",__func__);
1018 return;
1019 }
1020
1021 sd_claim_host(sdio_func_dev);
1022
1023 // Prevent touching the pMac while LOGP reset in progress, we should never get here
1024 // as the wake lock is already acquired and it would prevent from entering suspend
1025 if (pHddCtx->isLogpInProgress) {
1026 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Ignore suspend wlan, LOGP in progress!", __func__);
1027 sd_release_host(sdio_func_dev);
1028 return;
1029 }
1030#endif
1031
1032 /*loop through all adapters. TBD fix for Concurrency */
1033 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1034 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1035 {
1036 pAdapter = pAdapterNode->pAdapter;
1037 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001038 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001039 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
1040
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001041 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001042 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1043 pAdapterNode = pNext;
1044 continue;
1045 }
1046
1047#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1048 if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1049 {
1050 //stop the interface before putting the chip to standby
1051 netif_tx_disable(pAdapter->dev);
1052 netif_carrier_off(pAdapter->dev);
1053 }
1054 else if (pHddCtx->cfg_ini->nEnableSuspend ==
1055 WLAN_MAP_SUSPEND_TO_DEEP_SLEEP)
1056 {
1057 //Execute deep sleep procedure
1058 hdd_enter_deep_sleep(pHddCtx, pAdapter);
1059 }
1060#endif
1061
Jeff Johnsone7245742012-09-05 17:12:55 -07001062 //Apply Dynamic Dtim For P2P
1063 //Only if ignoreDynamicDtimInP2pMode is not set in ini
Jeff Johnson295189b2012-06-20 16:38:30 -07001064 if((pHddCtx->cfg_ini->enableDynamicDTIM ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001065 pHddCtx->cfg_ini->enableModulatedDTIM) &&
1066 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
1067 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
1068 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07001069 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
1070 (eConnectionState_Associated ==
1071 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
1072 (pHddCtx->cfg_ini->fIsBmpsEnabled))
1073 {
1074 tSirSetPowerParamsReq powerRequest = { 0 };
1075
1076 powerRequest.uIgnoreDTIM = 1;
1077
1078 /*Back up the actual values from CFG */
1079 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM,
1080 &pHddCtx->hdd_actual_ignore_DTIM_value);
1081 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL,
1082 &pHddCtx->hdd_actual_LI_value);
1083
1084 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1085 {
1086 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
1087 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
1088 }
1089 else
1090 {
1091 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
1092 }
1093
1094 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
1095 *specified during Enter/Exit BMPS when LCD off*/
1096 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1097 NULL, eANI_BOOLEAN_FALSE);
1098 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1099 NULL, eANI_BOOLEAN_FALSE);
1100
1101 /* switch to the DTIM specified in cfg.ini */
1102 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1103 "Switch to DTIM%d \n", powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001104 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001105
1106 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1107 {
1108 /* put the device into full power */
1109 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
1110
1111 /* put the device back into BMPS */
1112 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
1113
1114 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1115 }
1116 }
1117
Jeff Johnson295189b2012-06-20 16:38:30 -07001118 /*Suspend notification sent down to driver*/
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301119 hdd_conf_suspend_ind(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001120 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1121 pAdapterNode = pNext;
1122 }
1123 pHddCtx->hdd_wlan_suspended = TRUE;
1124
1125#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1126 if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY)
1127 {
1128 hdd_enter_standby(pHddCtx);
1129 }
1130#endif
1131#ifdef ANI_BUS_TYPE_SDIO
1132 sd_release_host(sdio_func_dev);
1133#endif
1134
1135 return;
1136}
1137
1138static void hdd_PowerStateChangedCB
1139(
1140 v_PVOID_t callbackContext,
1141 tPmcState newState
1142)
1143{
1144 hdd_context_t *pHddCtx = callbackContext;
1145
1146 /* if the driver was not in BMPS during early suspend,
1147 * the dynamic DTIM is now updated at Riva */
1148 if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1149 && pHddCtx->cfg_ini->enableDynamicDTIM
1150 && (pHddCtx->hdd_ignore_dtim_enabled == FALSE))
1151 {
1152 pHddCtx->hdd_ignore_dtim_enabled = TRUE;
1153 }
1154 spin_lock(&pHddCtx->filter_lock);
1155 if((newState == BMPS) && pHddCtx->hdd_wlan_suspended
1156 && (pHddCtx->hdd_mcastbcast_filter_set != TRUE)) {
1157 spin_unlock(&pHddCtx->filter_lock);
1158 hdd_conf_mcastbcast_filter(pHddCtx, TRUE);
1159#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1160 halPSAppsCpuWakeupState(vos_get_context(VOS_MODULE_ID_SME, pHddCtx->pvosContext), FALSE);
1161#endif
1162 if(pHddCtx->hdd_mcastbcast_filter_set != TRUE)
1163 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__);
1164 }
1165 else
1166 spin_unlock(&pHddCtx->filter_lock);
1167}
1168
1169
1170
1171void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx)
1172{
1173 v_CONTEXT_t pVosContext;
1174 tHalHandle smeContext;
1175
1176 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1177 if (NULL == pVosContext)
1178 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001179 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001180 return;
1181 }
1182 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1183 if (NULL == smeContext)
1184 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001185 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001186 return;
1187 }
1188
1189 spin_lock_init(&pHddCtx->filter_lock);
1190 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1191 pHddCtx->cfg_ini->nEnableSuspend)
1192 {
1193 pmcRegisterDeviceStateUpdateInd(smeContext,
1194 hdd_PowerStateChangedCB, pHddCtx);
1195 }
1196}
1197
1198void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx)
1199{
1200 v_CONTEXT_t pVosContext;
1201 tHalHandle smeContext;
1202
1203 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1204 if (NULL == pVosContext)
1205 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001206 hddLog(LOGE, "%s: Invalid pContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001207 return;
1208 }
1209 smeContext = vos_get_context(VOS_MODULE_ID_SME, pVosContext);
1210 if (NULL == smeContext)
1211 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001212 hddLog(LOGE, "%s: Invalid smeContext", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001213 return;
1214 }
1215
1216 if (WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER ==
1217 pHddCtx->cfg_ini->nEnableSuspend)
1218 {
1219 pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB);
1220 }
1221}
1222
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001223void hdd_resume_wlan(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07001224{
1225 hdd_context_t *pHddCtx = NULL;
1226 hdd_adapter_t *pAdapter = NULL;
1227 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1228 VOS_STATUS status;
1229 v_CONTEXT_t pVosContext = NULL;
1230#ifdef ANI_BUS_TYPE_SDIO
1231 struct sdio_func *sdio_func_dev = NULL;
1232#endif
1233 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed by Android OS",__func__);
1234
1235 //Get the global VOSS context.
1236 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1237 if(!pVosContext) {
1238 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1239 return;
1240 }
1241
1242 //Get the HDD context.
1243 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
1244
1245 if(!pHddCtx) {
1246 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1247 return;
1248 }
1249
1250 if (pHddCtx->isLogpInProgress) {
1251 hddLog(VOS_TRACE_LEVEL_INFO,
1252 "%s: Ignore resume wlan, LOGP in progress!", __func__);
1253 return;
1254 }
1255
1256#ifdef ANI_BUS_TYPE_SDIO
1257 sdio_func_dev = libra_getsdio_funcdev();
1258
1259 if(sdio_func_dev == NULL)
1260 {
1261 /* Our card got removed */
1262 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1263 return;
1264 }
1265
1266 if(!sd_is_drvdata_available(sdio_func_dev))
1267 {
1268 /* Our card got removed */
1269 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD context is not available "
1270 "in sdio_func_dev!",__func__);
1271 return;
1272 }
1273
1274 sd_claim_host(sdio_func_dev);
1275
1276 // Prevent touching the pMac while LOGP reset in progress,
1277 if (pHddCtx->isLogpInProgress) {
1278 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Ignore resume wlan, LOGP in progress!", __func__);
1279 sd_release_host(sdio_func_dev);
1280 return;
1281 }
1282#endif
1283 pHddCtx->hdd_wlan_suspended = FALSE;
1284 /*loop through all adapters. Concurrency */
1285 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1286
1287 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
1288 {
1289 pAdapter = pAdapterNode->pAdapter;
1290 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001291 && (WLAN_HDD_SOFTAP != pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001292 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Madan Mohan Koyyalamudi802d7582012-10-31 14:19:40 -07001293 { // we skip this registration for modes other than STA, SAP and P2P client modes.
Jeff Johnson295189b2012-06-20 16:38:30 -07001294 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1295 pAdapterNode = pNext;
1296 continue;
1297 }
1298#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1299 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP)
1300 {
1301 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__);
1302 hdd_exit_deep_sleep(pAdapter);
1303 }
1304#endif
1305
1306 if(pHddCtx->hdd_ignore_dtim_enabled == TRUE)
1307 {
1308 /*Switch back to DTIM 1*/
1309 tSirSetPowerParamsReq powerRequest = { 0 };
1310
1311 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
1312 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
1313
1314 /*Disabled ModulatedDTIM if enabled on suspend*/
1315 if(pHddCtx->cfg_ini->enableModulatedDTIM)
1316 powerRequest.uDTIMPeriod = 0;
1317
1318 /* Update ignoreDTIM and ListedInterval in CFG with default values */
1319 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
1320 NULL, eANI_BOOLEAN_FALSE);
1321 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
1322 NULL, eANI_BOOLEAN_FALSE);
1323
1324 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1325 "Switch to DTIM%d \n",powerRequest.uListenInterval);
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08001326 sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001327
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301328 if (BMPS == pmcGetPmcState(pHddCtx->hHal))
1329 {
1330 /* put the device into full power */
1331 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE);
Jeff Johnson295189b2012-06-20 16:38:30 -07001332
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301333 /* put the device back into BMPS */
1334 wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO);
Jeff Johnson295189b2012-06-20 16:38:30 -07001335
Madan Mohan Koyyalamudi69b34182013-01-16 08:51:40 +05301336 pHddCtx->hdd_ignore_dtim_enabled = FALSE;
1337 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001338 }
1339
Gopichand Nakkala0f276812013-02-24 14:45:51 +05301340 hdd_conf_resume_ind(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07001341 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1342 pAdapterNode = pNext;
1343 }
1344
1345#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP
1346 if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY)
1347 {
1348 hdd_exit_standby(pHddCtx);
1349 }
1350#endif
1351
1352#ifdef ANI_BUS_TYPE_SDIO
1353 sd_release_host(sdio_func_dev);
1354#endif
1355 return;
1356}
1357
Jeff Johnson295189b2012-06-20 16:38:30 -07001358VOS_STATUS hdd_wlan_reset_initialization(void)
1359{
1360#ifdef ANI_BUS_TYPE_SDIO
1361 struct sdio_func *sdio_func_dev = NULL;
1362 v_U8_t regValue = 0;
1363 int err_ret = 0;
1364#endif
1365 v_CONTEXT_t pVosContext = NULL;
1366
1367 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__);
1368
1369 //Get the global VOSS context.
1370 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1371 if(!pVosContext)
1372 {
1373 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1374 return VOS_STATUS_E_FAILURE;
1375 }
1376
1377 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Preventing the phone from going to suspend",__func__);
1378
1379 // Prevent the phone from going to sleep
1380 hdd_prevent_suspend();
1381
1382#ifdef ANI_BUS_TYPE_SDIO
1383 /* Clear pending interrupt and disable Interrupts. Use only CMD52 */
1384 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1385 "%s LOGP in progress. Disabling Interrupt", __func__);
1386
1387 sdio_func_dev = libra_getsdio_funcdev();
1388
1389 if(sdio_func_dev == NULL)
1390 {
1391 /* Our card got removed before LOGP. Continue with reset anyways */
1392 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
1393 return VOS_STATUS_SUCCESS;
1394 }
1395
1396 sd_claim_host(sdio_func_dev);
1397
1398 regValue = 0;
1399 libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_SIF_INT_EN_REG,
1400 &regValue, 1, &err_ret);
1401
1402 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1403 "%s LOGP Cleared SIF_SIF_INT_EN_REG status:%d", __func__,err_ret);
1404
1405 regValue = 0;
1406 libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_BAR4_INT_PEND_REG,
1407 &regValue, 1, &err_ret);
1408
1409 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1410 "%s LOGP Cleared SIF_BAR4_INT_PEND_REG status :%d", __func__,err_ret);
1411
1412 regValue = 0;
1413 libra_sdiocmd52(sdio_func_dev, QWLAN_SIF_BAR4_INT_ENABLE_REG,
1414 &regValue, 1, &err_ret);
1415
1416 VOS_TRACE( VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_FATAL,
1417 "%s LOGP Cleared SIF_BAR4_INT_ENABLE_REG: Status:%d", __func__,err_ret);
1418
1419 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing Suspend Chip",__func__);
1420
1421 //Put the chip is standby before asserting deep sleep
1422 WLANBAL_SuspendChip_NoLock( pVosContext );
1423
1424 sd_release_host(sdio_func_dev);
1425#endif
1426
1427 return VOS_STATUS_SUCCESS;
1428}
1429
1430
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001431/*
1432 * Based on the ioctl command recieved by HDD, put WLAN driver
1433 * into the quiet mode. This is the same as the early suspend
1434 * notification that driver used to listen
1435 */
1436void hdd_set_wlan_suspend_mode(bool suspend)
Jeff Johnson295189b2012-06-20 16:38:30 -07001437{
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001438 if (suspend)
1439 hdd_suspend_wlan();
1440 else
1441 hdd_resume_wlan();
Jeff Johnson295189b2012-06-20 16:38:30 -07001442}
1443
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001444static void hdd_ssr_timer_init(void)
1445{
1446 init_timer(&ssr_timer);
1447}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001448
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001449static void hdd_ssr_timer_del(void)
1450{
1451 del_timer(&ssr_timer);
1452 ssr_timer_started = false;
1453}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001454
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001455static void hdd_ssr_timer_cb(unsigned long data)
1456{
1457 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD SSR timer expired", __func__);
1458 VOS_BUG(0);
1459}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001460
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001461static void hdd_ssr_timer_start(int msec)
1462{
1463 if(ssr_timer_started)
1464 {
1465 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: trying to start SSR timer when it's running"
1466 ,__func__);
1467 }
1468 ssr_timer.expires = jiffies + msecs_to_jiffies(msec);
1469 ssr_timer.function = hdd_ssr_timer_cb;
1470 add_timer(&ssr_timer);
1471 ssr_timer_started = true;
1472}
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001473
Jeff Johnson295189b2012-06-20 16:38:30 -07001474/* the HDD interface to WLAN driver shutdown,
1475 * the primary shutdown function in SSR
1476 */
1477VOS_STATUS hdd_wlan_shutdown(void)
1478{
1479 VOS_STATUS vosStatus;
1480 v_CONTEXT_t pVosContext = NULL;
1481 hdd_context_t *pHddCtx = NULL;
1482 pVosSchedContext vosSchedContext = NULL;
1483
1484 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutting down! ",__func__);
1485
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001486 /* if re-init never happens, then do SSR1 */
1487 hdd_ssr_timer_init();
1488 hdd_ssr_timer_start(HDD_SSR_BRING_UP_TIME);
1489
Jeff Johnson295189b2012-06-20 16:38:30 -07001490 /* Get the global VOSS context. */
1491 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
1492 if(!pVosContext) {
1493 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
1494 return VOS_STATUS_E_FAILURE;
1495 }
1496 /* Get the HDD context. */
1497 pHddCtx = (hdd_context_t*)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1498 if(!pHddCtx) {
1499 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1500 return VOS_STATUS_E_FAILURE;
1501 }
1502 hdd_reset_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001503 /* DeRegister with platform driver as client for Suspend/Resume */
1504 vosStatus = hddDeregisterPmOps(pHddCtx);
1505 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1506 {
1507 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
1508 }
1509
1510 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
1511 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1512 {
1513 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
1514 }
1515
1516 /* Disable IMPS/BMPS as we do not want the device to enter any power
1517 * save mode on its own during reset sequence
1518 */
1519 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1520 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1521 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
1522
1523 vosSchedContext = get_vos_sched_ctxt();
1524
1525 /* Wakeup all driver threads */
1526 if(TRUE == pHddCtx->isMcThreadSuspended){
1527 complete(&vosSchedContext->ResumeMcEvent);
1528 pHddCtx->isMcThreadSuspended= FALSE;
1529 }
1530 if(TRUE == pHddCtx->isTxThreadSuspended){
1531 complete(&vosSchedContext->ResumeTxEvent);
1532 pHddCtx->isTxThreadSuspended= FALSE;
1533 }
1534 if(TRUE == pHddCtx->isRxThreadSuspended){
1535 complete(&vosSchedContext->ResumeRxEvent);
1536 pHddCtx->isRxThreadSuspended= FALSE;
1537 }
1538 /* Reset the Suspend Variable */
1539 pHddCtx->isWlanSuspended = FALSE;
1540
1541 /* Stop all the threads; we do not want any messages to be a processed,
1542 * any more and the best way to ensure that is to terminate the threads
1543 * gracefully.
1544 */
1545 /* Wait for MC to exit */
1546 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down MC thread",__func__);
1547 set_bit(MC_SHUTDOWN_EVENT_MASK, &vosSchedContext->mcEventFlag);
1548 set_bit(MC_POST_EVENT_MASK, &vosSchedContext->mcEventFlag);
1549 wake_up_interruptible(&vosSchedContext->mcWaitQueue);
1550 wait_for_completion_interruptible(&vosSchedContext->McShutdown);
1551
1552 /* Wait for TX to exit */
1553 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down TX thread",__func__);
1554 set_bit(TX_SHUTDOWN_EVENT_MASK, &vosSchedContext->txEventFlag);
1555 set_bit(TX_POST_EVENT_MASK, &vosSchedContext->txEventFlag);
1556 wake_up_interruptible(&vosSchedContext->txWaitQueue);
1557 wait_for_completion_interruptible(&vosSchedContext->TxShutdown);
1558
1559 /* Wait for RX to exit */
1560 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Shutting down RX thread",__func__);
1561 set_bit(RX_SHUTDOWN_EVENT_MASK, &vosSchedContext->rxEventFlag);
1562 set_bit(RX_POST_EVENT_MASK, &vosSchedContext->rxEventFlag);
1563 wake_up_interruptible(&vosSchedContext->rxWaitQueue);
1564 wait_for_completion_interruptible(&vosSchedContext->RxShutdown);
1565
1566#ifdef WLAN_BTAMP_FEATURE
1567 vosStatus = WLANBAP_Stop(pVosContext);
1568 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1569 {
1570 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1571 "%s: Failed to stop BAP",__func__);
1572 }
1573#endif //WLAN_BTAMP_FEATURE
1574 vosStatus = vos_wda_shutdown(pVosContext);
1575 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1576
1577 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing SME STOP",__func__);
1578 /* Stop SME - Cannot invoke vos_stop as vos_stop relies
1579 * on threads being running to process the SYS Stop
1580 */
1581 vosStatus = sme_Stop(pHddCtx->hHal, TRUE);
1582 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1583
1584 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing MAC STOP",__func__);
1585 /* Stop MAC (PE and HAL) */
1586 vosStatus = macStop(pHddCtx->hHal, HAL_STOP_TYPE_SYS_RESET);
1587 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1588
1589 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Doing TL STOP",__func__);
1590 /* Stop TL */
1591 vosStatus = WLANTL_Stop(pVosContext);
1592 VOS_ASSERT(VOS_IS_STATUS_SUCCESS(vosStatus));
1593
Jeff Johnson295189b2012-06-20 16:38:30 -07001594 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001595 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Flush Queues",__func__);
1596 /* Clean up message queues of TX and MC thread */
1597 vos_sched_flush_mc_mqs(vosSchedContext);
1598 vos_sched_flush_tx_mqs(vosSchedContext);
1599 vos_sched_flush_rx_mqs(vosSchedContext);
1600
1601 /* Deinit all the TX and MC queues */
1602 vos_sched_deinit_mqs(vosSchedContext);
1603 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Doing VOS Shutdown",__func__);
1604
1605 /* shutdown VOSS */
1606 vos_shutdown(pVosContext);
Gopichand Nakkala05ab1322013-02-15 11:28:38 +05301607
1608 /*mac context has already been released in mac_close call
1609 so setting it to NULL in hdd context*/
1610 pHddCtx->hHal = (tHalHandle)NULL;
1611
Jeff Johnson295189b2012-06-20 16:38:30 -07001612 if (free_riva_power_on_lock("wlan"))
1613 {
1614 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
1615 __func__);
1616 }
1617 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete"
1618 ,__func__);
1619 return VOS_STATUS_SUCCESS;
1620}
1621
1622
1623
1624/* the HDD interface to WLAN driver re-init.
1625 * This is called to initialize/start WLAN driver after a shutdown.
1626 */
1627VOS_STATUS hdd_wlan_re_init(void)
1628{
1629 VOS_STATUS vosStatus;
1630 v_CONTEXT_t pVosContext = NULL;
1631 hdd_context_t *pHddCtx = NULL;
1632 eHalStatus halStatus;
1633#ifdef WLAN_BTAMP_FEATURE
1634 hdd_config_t *pConfig = NULL;
1635 WLANBAP_ConfigType btAmpConfig;
1636#endif
1637
Madan Mohan Koyyalamudib0e70642012-10-11 12:20:22 -07001638 hdd_ssr_timer_del();
Jeff Johnson295189b2012-06-20 16:38:30 -07001639 hdd_prevent_suspend();
Sameer Thalappil5d7a33f2013-01-30 08:36:16 -08001640
1641 /* The driver should always be initialized in STA mode after SSR */
1642 hdd_set_conparam(0);
1643
Jeff Johnson295189b2012-06-20 16:38:30 -07001644 /* Re-open VOSS, it is a re-open b'se control transport was never closed. */
1645 vosStatus = vos_open(&pVosContext, 0);
1646 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1647 {
1648 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
1649 goto err_re_init;
1650 }
1651
1652 /* Get the HDD context. */
1653 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext);
1654 if(!pHddCtx)
1655 {
1656 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__);
1657 goto err_vosclose;
1658 }
1659
1660 /* Save the hal context in Adapter */
1661 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
1662 if ( NULL == pHddCtx->hHal )
1663 {
1664 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
1665 goto err_vosclose;
1666 }
1667
1668 /* Set the SME configuration parameters. */
1669 vosStatus = hdd_set_sme_config(pHddCtx);
1670 if ( VOS_STATUS_SUCCESS != vosStatus )
1671 {
1672 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
1673 goto err_vosclose;
1674 }
1675
1676 /* Initialize the WMM module */
1677 vosStatus = hdd_wmm_init(pHddCtx);
1678 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ))
1679 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001680 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001681 goto err_vosclose;
1682 }
1683
1684 vosStatus = vos_preStart( pHddCtx->pvosContext );
1685 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1686 {
1687 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
1688 goto err_vosclose;
1689 }
1690
1691 /* In the integrated architecture we update the configuration from
1692 the INI file and from NV before vOSS has been started so that
1693 the final contents are available to send down to the cCPU */
1694 /* Apply the cfg.ini to cfg.dat */
1695 if (FALSE == hdd_update_config_dat(pHddCtx))
1696 {
1697 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
1698 goto err_vosclose;
1699 }
1700
1701 /* Set the MAC Address, currently this is used by HAL to add self sta.
1702 * Remove this once self sta is added as part of session open. */
1703 halStatus = cfgSetStr(pHddCtx->hHal, WNI_CFG_STA_ID,
1704 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
1705 sizeof(pHddCtx->cfg_ini->intfMacAddr[0]));
1706 if (!HAL_STATUS_SUCCESS(halStatus))
1707 {
1708 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
1709 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus);
1710 goto err_vosclose;
1711 }
1712
1713 /* Start VOSS which starts up the SME/MAC/HAL modules and everything else
1714 Note: Firmware image will be read and downloaded inside vos_start API */
1715 vosStatus = vos_start( pVosContext );
1716 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1717 {
1718 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
1719 goto err_vosclose;
1720 }
1721
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07001722 /* Exchange capability info between Host and FW and also get versioning info from FW */
1723 hdd_exchange_version_and_caps(pHddCtx);
1724
Jeff Johnson295189b2012-06-20 16:38:30 -07001725 vosStatus = hdd_post_voss_start_config( pHddCtx );
1726 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1727 {
1728 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
1729 __func__);
1730 goto err_vosstop;
1731 }
1732
1733#ifdef WLAN_BTAMP_FEATURE
1734 vosStatus = WLANBAP_Open(pVosContext);
1735 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1736 {
1737 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1738 "%s: Failed to open BAP",__func__);
1739 goto err_vosstop;
1740 }
1741 vosStatus = BSL_Init(pVosContext);
1742 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1743 {
1744 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1745 "%s: Failed to Init BSL",__func__);
1746 goto err_bap_close;
1747 }
1748 vosStatus = WLANBAP_Start(pVosContext);
1749 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1750 {
1751 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1752 "%s: Failed to start TL",__func__);
1753 goto err_bap_close;
1754 }
1755 pConfig = pHddCtx->cfg_ini;
1756 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
1757 vosStatus = WLANBAP_SetConfig(&btAmpConfig);
1758#endif //WLAN_BTAMP_FEATURE
1759
1760 /* Restart all adapters */
1761 hdd_start_all_adapters(pHddCtx);
1762 pHddCtx->isLogpInProgress = FALSE;
1763 pHddCtx->hdd_mcastbcast_filter_set = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001764 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001765
1766 /* Register with platform driver as client for Suspend/Resume */
1767 vosStatus = hddRegisterPmOps(pHddCtx);
1768 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
1769 {
1770 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
1771 goto err_bap_stop;
1772 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001773 /* Allow the phone to go to sleep */
1774 hdd_allow_suspend();
1775 /* register for riva power on lock */
1776 if (req_riva_power_on_lock("wlan"))
1777 {
1778 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
1779 __func__);
1780 goto err_unregister_pmops;
1781 }
1782 goto success;
1783
1784err_unregister_pmops:
1785 hddDeregisterPmOps(pHddCtx);
1786
1787err_bap_stop:
Jeff Johnson32d95a32012-09-10 13:15:23 -07001788#ifdef CONFIG_HAS_EARLYSUSPEND
1789 hdd_unregister_mcast_bcast_filter(pHddCtx);
1790#endif
1791 hdd_close_all_adapters(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07001792#ifdef WLAN_BTAMP_FEATURE
Jeff Johnson32d95a32012-09-10 13:15:23 -07001793 WLANBAP_Stop(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07001794#endif
1795
1796#ifdef WLAN_BTAMP_FEATURE
1797err_bap_close:
1798 WLANBAP_Close(pVosContext);
1799#endif
1800
1801err_vosstop:
1802 vos_stop(pVosContext);
1803
1804err_vosclose:
1805 vos_close(pVosContext);
1806 vos_sched_close(pVosContext);
1807 if (pHddCtx)
1808 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001809 /* Unregister the Net Device Notifier */
1810 unregister_netdevice_notifier(&hdd_netdev_notifier);
1811 /* Clean up HDD Nlink Service */
1812 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1813 nl_srv_exit();
Jeff Johnson295189b2012-06-20 16:38:30 -07001814 /* Free up dynamically allocated members inside HDD Adapter */
1815 kfree(pHddCtx->cfg_ini);
1816 pHddCtx->cfg_ini= NULL;
1817
1818#ifdef CONFIG_CFG80211
1819 wiphy_unregister(pHddCtx->wiphy);
1820 wiphy_free(pHddCtx->wiphy);
1821#else
1822 vos_mem_free(pHddCtx);
1823#endif
1824 }
1825 vos_preClose(&pVosContext);
1826
1827#ifdef MEMORY_DEBUG
1828 vos_mem_exit();
1829#endif
1830
1831err_re_init:
1832 /* Allow the phone to go to sleep */
1833 hdd_allow_suspend();
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001834 return -EPERM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001835
1836success:
1837 /* Trigger replay of BTC events */
1838 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
1839 return VOS_STATUS_SUCCESS;
1840}