[PATCH RFC v7 5/9] PM / devfreq: Add new track_remote flag for governors
Pragnesh Papaniya
pragnesh.papaniya at oss.qualcomm.com
Wed Jun 10 01:51:32 PDT 2026
From: Sibi Sankar <sibi.sankar at oss.qualcomm.com>
Some devfreq governors need to track frequency changes performed on remote
devices rather than driving the frequency updates themselves. In such
cases, the device's frequency is already updated by an external entity and
devfreq only needs to keep its transition statistics and notifier
subscribers in sync.
Add a new DEVFREQ_GOV_FLAG_TRACK_REMOTE governor flag. When set,
devfreq_set_target() skips the profile->target() update sequence but still
emits the DEVFREQ_PRECHANGE/DEVFREQ_POSTCHANGE notification pair and the
devfreq_frequency trace event, so transition-notifier subscribers (passive
governor, devfreq cooling, etc.) and tracing observe the remote frequency
change exactly as they would on the normal path, and the transition
statistics are refreshed.
Signed-off-by: Sibi Sankar <sibi.sankar at oss.qualcomm.com>
Signed-off-by: Pragnesh Papaniya <pragnesh.papaniya at oss.qualcomm.com>
---
drivers/devfreq/devfreq.c | 21 +++++++++++++++++++++
include/linux/devfreq-governor.h | 5 +++++
2 files changed, 26 insertions(+)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 2f27a239e34a..71c6ced9e4e1 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -348,6 +348,26 @@ static int devfreq_set_target(struct devfreq *devfreq, unsigned long new_freq,
unsigned long cur_freq;
int err = 0;
+ /*
+ * When a remote agent (e.g. firmware) owns the frequency, skip the
+ * local profile->target() call. Still emit the PRECHANGE/POSTCHANGE
+ * pair and the trace event so that transition-notifier subscribers
+ * (passive governor, devfreq cooling, etc.) and tracing observe the
+ * frequency change exactly as they would on the normal path.
+ */
+ if (devfreq->governor &&
+ IS_SUPPORTED_FLAG(devfreq->governor->flags, TRACK_REMOTE)) {
+ freqs.old = devfreq->previous_freq;
+ freqs.new = new_freq;
+ devfreq_notify_transition(devfreq, &freqs, DEVFREQ_PRECHANGE);
+
+ if (trace_devfreq_frequency_enabled() && new_freq != freqs.old)
+ trace_devfreq_frequency(devfreq, new_freq, freqs.old);
+
+ devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
+ goto update_status;
+ }
+
if (devfreq->profile->get_cur_freq)
devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq);
else
@@ -375,6 +395,7 @@ static int devfreq_set_target(struct devfreq *devfreq, unsigned long new_freq,
freqs.new = new_freq;
devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
+update_status:
if (devfreq_update_status(devfreq, new_freq))
dev_warn(&devfreq->dev,
"Couldn't update frequency transition information.\n");
diff --git a/include/linux/devfreq-governor.h b/include/linux/devfreq-governor.h
index 2853f571dfdf..e4f7b6cb07bc 100644
--- a/include/linux/devfreq-governor.h
+++ b/include/linux/devfreq-governor.h
@@ -33,9 +33,14 @@
* : This governor is never changeable to other governors.
* - DEVFREQ_GOV_FLAG_IRQ_DRIVEN
* : The devfreq won't schedule the work for this governor.
+ * - DEVFREQ_GOV_FLAG_TRACK_REMOTE
+ * : The governor only tracks frequency changes performed by a remote
+ * agent (e.g. firmware); devfreq skips the local profile->target()
+ * call and just keeps its statistics and notifiers in sync.
*/
#define DEVFREQ_GOV_FLAG_IMMUTABLE BIT(0)
#define DEVFREQ_GOV_FLAG_IRQ_DRIVEN BIT(1)
+#define DEVFREQ_GOV_FLAG_TRACK_REMOTE BIT(2)
/*
* Definition of governor attribute flags except for common sysfs attributes
--
2.34.1
More information about the linux-arm-kernel
mailing list