This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 674e5ef4d8bce0d9fec173377bb5c076f9ece7f0 Author: guanyi3 <[email protected]> AuthorDate: Fri Mar 6 14:17:58 2026 +0800 drivers/devfreq: use hardware frequency instead of cached value in driver_target The cached devfreq->cur may become stale when the hardware frequency is changed externally (e.g. by another core or governor). This causes driver_target to incorrectly skip frequency transitions when the target matches the cached value but differs from the actual hardware frequency. Use driver->get_frequency() to read the real hardware frequency for the unchanged check, and sync devfreq->cur on match to keep the cache correct. Signed-off-by: guanyi3 <[email protected]> --- drivers/devfreq/devfreq.c | 20 +++++++++++++++----- drivers/devfreq/devfreq_ondemand.c | 5 +++-- drivers/devfreq/devfreq_procfs.c | 2 +- include/nuttx/devfreq.h | 1 - 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index bf152c73ec8..5b0a17c0465 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -401,6 +401,7 @@ static int devfreq_driver_target(FAR struct devfreq_s *devfreq, int relation) { struct devfreq_notifier_s freq; + uint32_t cur_freq; ssize_t idx; int ret; @@ -416,12 +417,18 @@ static int devfreq_driver_target(FAR struct devfreq_s *devfreq, } target_freq = devfreq->freq_table[idx]; - if (target_freq == devfreq->cur) + + /* Get current hardware frequency to check if transition is needed, + * and to record the old frequency for notifier chain. + */ + + cur_freq = devfreq_get_frequency(devfreq); + if (target_freq == cur_freq) { return 0; } - freq.old = devfreq->cur; + freq.old = cur_freq; freq.new = target_freq; blocking_notifier_call_chain(&devfreq->notifier_list, @@ -431,8 +438,13 @@ static int devfreq_driver_target(FAR struct devfreq_s *devfreq, DEVFREQ_POSTCHANGE, &freq); if (ret < 0) { + /* Frequency transition failed. Re-read the actual hardware frequency + * and send a compensating PRECHANGE/POSTCHANGE pair so that all + * notifier listeners stay in sync with the real hardware state. + */ + freq.old = target_freq; - freq.new = devfreq->cur; + freq.new = devfreq_get_frequency(devfreq); blocking_notifier_call_chain(&devfreq->notifier_list, DEVFREQ_PRECHANGE, &freq); blocking_notifier_call_chain(&devfreq->notifier_list, @@ -440,7 +452,6 @@ static int devfreq_driver_target(FAR struct devfreq_s *devfreq, return ret; } - devfreq->cur = target_freq; return 0; } @@ -496,7 +507,6 @@ FAR struct devfreq_s *devfreq_register( devfreq->freq_table = driver->get_table(devfreq); devfreq->min = 0; devfreq->max = UINT32_MAX; - devfreq->cur = driver->get_frequency(devfreq); if (!devfreq->freq_table) { goto out; diff --git a/drivers/devfreq/devfreq_ondemand.c b/drivers/devfreq/devfreq_ondemand.c index a5b3e524046..b6557ee38d2 100644 --- a/drivers/devfreq/devfreq_ondemand.c +++ b/drivers/devfreq/devfreq_ondemand.c @@ -109,13 +109,14 @@ static void devfreq_ondemand_worker(FAR void *arg) if (cpuload > CONFIG_DEVFREQ_LOAD_THRESHOLD) { - if (dev->cur < dev->max) + uint32_t cur_freq = devfreq_get_frequency(dev); + if (cur_freq < dev->max) { data->target_freq = dev->max; } else { - data->target_freq = dev->cur; + data->target_freq = cur_freq; } } else diff --git a/drivers/devfreq/devfreq_procfs.c b/drivers/devfreq/devfreq_procfs.c index bf1fe7b09be..99f92d50ac2 100644 --- a/drivers/devfreq/devfreq_procfs.c +++ b/drivers/devfreq/devfreq_procfs.c @@ -184,7 +184,7 @@ static ssize_t devfreq_read(FAR struct file *filep, " suspended: %s\n", devfreq->name, devfreq->governor->name, - devfreq->cur, + devfreq_get_frequency(devfreq), devfreq->suspended ? "True" : "False"); if (devfreq->freq_table) diff --git a/include/nuttx/devfreq.h b/include/nuttx/devfreq.h index e17044be4ec..13c28d1787b 100644 --- a/include/nuttx/devfreq.h +++ b/include/nuttx/devfreq.h @@ -70,7 +70,6 @@ struct devfreq_s uint32_t min; /* in kHz */ uint32_t max; /* in kHz */ - uint32_t cur; /* in kHz */ bool suspended;
