@@ -30,6 +30,25 @@ menuconfig PM_DEVFREQ
if PM_DEVFREQ
+config DEVFREQ_USE_DELAYED_WORK
+ bool "Use DELAYED_WORK in DEVFREQ monitoring subsystem"
+ help
+ This changes the default DEVFREQ framework monitoring subsystem
+ from using DEFERRABLE_WORK to DELAYED_WORK. The former uses
+ TIMER_DEFERRABLE, which will work normally when the system is busy,
+ but will not cause a CPU to come out of idle and serve the DEVFREQ
+ monitoring requests. This is especially important in the SMP systems
+ with many CPUs, when the load balance tries to keep some CPUs idle.
+ The next service request could not be triggered when the CPU went
+ idle in the meantime.
+
+ The DELAYED_WORK is going to be triggered even on an idle CPU. This
+ will allow to call the DEVFREQ driver in more reliable fashion and
+ prevent i.e. from overflowing the device's counters.
+
+ Enable this when you have SMP system and you do not see the DEVFREQ
+ monitoring to be triggered in your trace output.
+
comment "DEVFREQ Governors"
config DEVFREQ_GOV_SIMPLE_ONDEMAND
@@ -457,7 +457,11 @@ void devfreq_monitor_start(struct devfreq *devfreq)
if (devfreq->governor->interrupt_driven)
return;
- INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
+ if (IS_ENABLED(CONFIG_DEVFREQ_USE_DELAYED_WORK))
+ INIT_DELAYED_WORK(&devfreq->work, devfreq_monitor);
+ else
+ INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
+
if (devfreq->profile->polling_ms)
queue_delayed_work(devfreq_wq, &devfreq->work,
msecs_to_jiffies(devfreq->profile->polling_ms));