Re: [PATCH v5 2/4] PM / QoS: add lockless read for flags
From: Rafael J. Wysocki (Intel)
Date: Fri Sep 11 2026 - 10:23:18 EST
On Thu, Aug 27, 2026 at 12:23 AM Kevin Hilman (TI) <khilman@xxxxxxxxxxxx> wrote:
>
> 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().
>
> Reviewed-by: Kendall Willis <k-willis@xxxxxx>
> Signed-off-by: Kevin Hilman (TI) <khilman@xxxxxxxxxxxx>
Acked-by: Rafael J. Wysocki (Intel) <rafael@xxxxxxxxxx>
and please route this one as suitable.
And sorry for the delay.
> ---
> 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
>