[PATCH v4 2/4] PM / QoS: add lockless read for flags
"Kevin Hilman (TI)" <[email protected]>
| Newsgroups | org.kernel.vger.linux-pm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <20260819-topic-lpm-pmdomain-device-constraints-v4-2-7ceb095f5474@baylibre.com> |
Add a lockless read for QoS flags similar to the lockless read for resume latency (dev_pm_qos_raw_resume_latency) which may be called from atomic context (e.g. genpd governors running under a raw spinlock or in the syscore suspend path), where taking that sleeping lock would be invalid on PREEMPT_RT. dev_pm_qos_raw_flags() now reads dev->power.qos->flags.effective_flags with READ_ONCE() so also add corresponding WRITE_ONCE() to the two effective_flags writes, the same way pm_qos_set_value() already does for target_value/pm_qos_read_value(). Signed-off-by: Kevin Hilman (TI) <[email protected]> --- include/linux/pm_qos.h | 7 +++++++ kernel/power/qos.c | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h index aededda52b6b..439a9e779d81 100644 --- a/include/linux/pm_qos.h +++ b/include/linux/pm_qos.h @@ -219,6 +219,12 @@ static inline s32 dev_pm_qos_raw_resume_latency(struct device *dev) PM_QOS_RESUME_LATENCY_NO_CONSTRAINT : pm_qos_read_value(&dev->power.qos->resume_latency); } + +static inline s32 dev_pm_qos_raw_flags(struct device *dev) +{ + return IS_ERR_OR_NULL(dev->power.qos) ? + 0 : READ_ONCE(dev->power.qos->flags.effective_flags); +} #else static inline enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask) @@ -300,6 +306,7 @@ static inline s32 dev_pm_qos_raw_resume_latency(struct device *dev) { return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; } +static inline s32 dev_pm_qos_raw_flags(struct device *dev) { return 0; } #endif static inline int freq_qos_request_active(struct freq_qos_request *req) diff --git a/kernel/power/qos.c b/kernel/power/qos.c index 1944dbeb0d4c..c241da5bccf6 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c @@ -159,7 +159,7 @@ static void pm_qos_flags_remove_req(struct pm_qos_flags *pqf, list_for_each_entry(req, &pqf->list, node) val |= req->flags; - pqf->effective_flags = val; + WRITE_ONCE(pqf->effective_flags, val); } /** @@ -193,7 +193,7 @@ bool pm_qos_update_flags(struct pm_qos_flags *pqf, req->flags = val; INIT_LIST_HEAD(&req->node); list_add_tail(&req->node, &pqf->list); - pqf->effective_flags |= val; + WRITE_ONCE(pqf->effective_flags, pqf->effective_flags | val); break; default: /* no action */ -- 2.47.3