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