From 0f29e974ec32428bfd59932a0809e00abe2d3178 Mon Sep 17 00:00:00 2001 From: Alan Chen Date: Wed, 4 Sep 2019 12:04:22 -0700 Subject: [PATCH] qcacld-3.0: Wait for PM freeze when turning wifi on Add a wait for PM freeze when wifi is turning on to make sure file system and QMI are still accessible before attempting to download the FW and trigger a QMI handshake with FW. Change-Id: Ia2f3dc28abb9cab4b5dd8038ea02ac016eb74bbb CRs-Fixed: 2521009 --- core/hdd/inc/wlan_hdd_driver_ops.h | 4 ++-- core/hdd/src/wlan_hdd_driver_ops.c | 36 ++++++++++++++++++++++++++++-- core/hdd/src/wlan_hdd_main.c | 12 +++++++--- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_driver_ops.h b/core/hdd/inc/wlan_hdd_driver_ops.h index 9ab05df7d021..543d37642886 100644 --- a/core/hdd/inc/wlan_hdd_driver_ops.h +++ b/core/hdd/inc/wlan_hdd_driver_ops.h @@ -124,9 +124,9 @@ int hdd_hif_open(struct device *dev, void *bdev, const struct hif_bus_id *bid, * * This function takes wakelock to prevent suspend during idle restart * - * Return: none + * Return: 0 for success and non zero for error */ -void hdd_soc_idle_restart_lock(struct device *dev); +int hdd_soc_idle_restart_lock(struct device *dev); /** * hdd_soc_idle_restart_unlock() - Releases wakelock for idle restart diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 60444487bfed..ade1843120a8 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -42,6 +42,7 @@ #include "wlan_ipa_ucfg_api.h" #include "wlan_hdd_debugfs.h" #include "cfg_ucfg_api.h" +#include #ifdef MODULE #define WLAN_MODULE_NAME module_name(THIS_MODULE) @@ -386,10 +387,41 @@ static void hdd_abort_system_suspend(struct device *dev) } #endif -void hdd_soc_idle_restart_lock(struct device *dev) +/* Total wait time for pm freeze is 10 seconds */ +#define HDD_SLEEP_FOR_PM_FREEZE_TIME (500) +#define HDD_MAX_ATTEMPT_SLEEP_FOR_PM_FREEZE_TIME (20) + +static int hdd_wait_for_pm_freeze(void) +{ + uint8_t count = 0; + + while (pm_freezing) { + hdd_info("pm freezing wait for %d ms", + HDD_SLEEP_FOR_PM_FREEZE_TIME); + msleep(HDD_SLEEP_FOR_PM_FREEZE_TIME); + count++; + if (count > HDD_MAX_ATTEMPT_SLEEP_FOR_PM_FREEZE_TIME) { + hdd_err("timeout occurred for pm freezing"); + return -EBUSY; + } + } + + return 0; +} + +int hdd_soc_idle_restart_lock(struct device *dev) { - hdd_abort_system_suspend(dev); hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_IDLE_RESTART); + + hdd_abort_system_suspend(dev); + + if (hdd_wait_for_pm_freeze()) { + hdd_allow_suspend( + WIFI_POWER_EVENT_WAKELOCK_DRIVER_IDLE_RESTART); + return -EBUSY; + } + + return 0; } void hdd_soc_idle_restart_unlock(void) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 47f86888ad20..a23a2a71d304 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -9776,7 +9776,9 @@ static int __hdd_psoc_idle_restart(struct hdd_context *hdd_ctx) { int ret; - hdd_soc_idle_restart_lock(hdd_ctx->parent_dev); + ret = hdd_soc_idle_restart_lock(hdd_ctx->parent_dev); + if (ret) + return ret; ret = hdd_wlan_start_modules(hdd_ctx, false); @@ -9809,7 +9811,9 @@ int hdd_trigger_psoc_idle_restart(struct hdd_context *hdd_ctx) return 0; } - hdd_soc_idle_restart_lock(hdd_ctx->parent_dev); + ret = hdd_soc_idle_restart_lock(hdd_ctx->parent_dev); + if (ret) + return ret; ret = pld_idle_restart(hdd_ctx->parent_dev, hdd_psoc_idle_restart); hdd_soc_idle_restart_unlock(); @@ -14111,7 +14115,9 @@ static int hdd_mode_change_psoc_idle_restart(struct device *dev) if (!hdd_ctx) return -EINVAL; - hdd_soc_idle_restart_lock(dev); + ret = hdd_soc_idle_restart_lock(dev); + if (ret) + return ret; ret = hdd_wlan_start_modules(hdd_ctx, false); hdd_soc_idle_restart_unlock();