qcacmn: add sync between suspend and wow resume in runtime pm

In moselle, once wow enabled there is a possibility that wow wake
interrupt can be fired from FW during runtime suspend in-progress
in host, this will introduce a race between runtime suspend and
resume, so adding a synchronization between runtime suspend and
wow triggered runtime resume.

Change-Id: I38d6a24e4421697cc2d0090ba8d19884885596cb
CRs-Fixed: 2845672
This commit is contained in:
Vevek Venkatesan
2020-12-28 02:22:36 +05:30
committed by snandini
parent 82acedd149
commit 86f4aa6017
3 changed files with 45 additions and 2 deletions

View File

@@ -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; }

View File

@@ -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);
}
}

View File

@@ -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;