diff --git a/core/hdd/inc/wlan_hdd_driver_ops.h b/core/hdd/inc/wlan_hdd_driver_ops.h index 9ab05df7d0..543d376428 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 60444487bf..ade1843120 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 47f86888ad..a23a2a71d3 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();