diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 3c3a9c9a4d6e..84ebc32790be 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -1027,6 +1027,8 @@ int hif_pm_runtime_prevent_suspend(struct hif_opaque_softc *ol_sc, int hif_pm_runtime_allow_suspend(struct hif_opaque_softc *ol_sc, struct hif_pm_runtime_lock *lock); bool hif_pm_runtime_is_suspended(struct hif_opaque_softc *hif_ctx); +void hif_pm_runtime_suspend_lock(struct hif_opaque_softc *hif_ctx); +void hif_pm_runtime_suspend_unlock(struct hif_opaque_softc *hif_ctx); int hif_pm_runtime_get_monitor_wake_intr(struct hif_opaque_softc *hif_ctx); void hif_pm_runtime_set_monitor_wake_intr(struct hif_opaque_softc *hif_ctx, int val); @@ -1083,6 +1085,12 @@ static inline int hif_pm_runtime_allow_suspend(struct hif_opaque_softc *ol_sc, { return 0; } static inline bool hif_pm_runtime_is_suspended(struct hif_opaque_softc *hif_ctx) { return false; } +static inline void +hif_pm_runtime_suspend_lock(struct hif_opaque_softc *hif_ctx) +{ return; } +static inline void +hif_pm_runtime_suspend_unlock(struct hif_opaque_softc *hif_ctx) +{ return; } static inline int hif_pm_runtime_get_monitor_wake_intr(struct hif_opaque_softc *hif_ctx) { return 0; } diff --git a/hif/src/hif_runtime_pm.c b/hif/src/hif_runtime_pm.c index e986bd97b5aa..2412fe56a8a4 100644 --- a/hif/src/hif_runtime_pm.c +++ b/hif/src/hif_runtime_pm.c @@ -438,6 +438,7 @@ void hif_pm_runtime_open(struct hif_softc *scn) struct hif_runtime_pm_ctx *rpm_ctx = hif_bus_get_rpm_ctx(scn); spin_lock_init(&rpm_ctx->runtime_lock); + qdf_spinlock_create(&rpm_ctx->runtime_suspend_lock); qdf_atomic_init(&rpm_ctx->pm_state); hif_runtime_lock_init(&rpm_ctx->prevent_linkdown_lock, "prevent_linkdown_lock"); @@ -554,6 +555,8 @@ void hif_pm_runtime_close(struct hif_softc *scn) hif_is_recovery_in_progress(scn) ? hif_pm_runtime_sanitize_on_ssr_exit(scn) : hif_pm_runtime_sanitize_on_exit(scn); + + qdf_spinlock_destroy(&rpm_ctx->runtime_suspend_lock); } /** @@ -1592,6 +1595,34 @@ bool hif_pm_runtime_is_suspended(struct hif_opaque_softc *hif_ctx) HIF_PM_RUNTIME_STATE_SUSPENDED; } +/* + * hif_pm_runtime_suspend_lock() - spin_lock on marking runtime suspend + * @hif_ctx: HIF context + * + * Return: void + */ +void hif_pm_runtime_suspend_lock(struct hif_opaque_softc *hif_ctx) +{ + struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); + struct hif_runtime_pm_ctx *rpm_ctx = hif_bus_get_rpm_ctx(scn); + + qdf_spin_lock_irqsave(&rpm_ctx->runtime_suspend_lock); +} + +/* + * hif_pm_runtime_suspend_unlock() - spin_unlock on marking runtime suspend + * @hif_ctx: HIF context + * + * Return: void + */ +void hif_pm_runtime_suspend_unlock(struct hif_opaque_softc *hif_ctx) +{ + struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); + struct hif_runtime_pm_ctx *rpm_ctx = hif_bus_get_rpm_ctx(scn); + + qdf_spin_unlock_irqrestore(&rpm_ctx->runtime_suspend_lock); +} + /** * hif_pm_runtime_get_monitor_wake_intr() - API to get monitor_wake_intr * @hif_ctx: HIF context @@ -1640,9 +1671,12 @@ void hif_pm_runtime_set_monitor_wake_intr(struct hif_opaque_softc *hif_ctx, */ void hif_pm_runtime_check_and_request_resume(struct hif_opaque_softc *hif_ctx) { - if (hif_pm_runtime_get_monitor_wake_intr(hif_ctx)) { - hif_pm_runtime_set_monitor_wake_intr(hif_ctx, 0); + hif_pm_runtime_suspend_lock(hif_ctx); + if (hif_pm_runtime_is_suspended(hif_ctx)) { + hif_pm_runtime_suspend_unlock(hif_ctx); hif_pm_runtime_request_resume(hif_ctx); + } else { + hif_pm_runtime_suspend_unlock(hif_ctx); } } diff --git a/hif/src/hif_runtime_pm.h b/hif/src/hif_runtime_pm.h index 26a38e0364db..a1e1476501e2 100644 --- a/hif/src/hif_runtime_pm.h +++ b/hif/src/hif_runtime_pm.h @@ -78,6 +78,7 @@ struct hif_runtime_pm_ctx { struct hif_pci_pm_stats pm_stats; struct work_struct pm_work; spinlock_t runtime_lock; /* Generic spinlock for Runtime PM */ + qdf_spinlock_t runtime_suspend_lock; qdf_timer_t runtime_timer; struct list_head prevent_suspend_list; unsigned long runtime_timer_expires;