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;
 

Reply via email to