drivers/devfreq/devfreq.c | 5 ++--- drivers/ufs/core/ufshcd.c | 37 +++++++++++++++++++++++++++++++------ include/linux/devfreq.h | 7 +++++-- 3 files changed, 38 insertions(+), 11 deletions(-)
The devfreq core has three users of the optional ->get_cur_freq() callback. Two of them check the return value, the third one does not and passes an uninitialized frequency to the transition notifiers when the callback fails. Patch 1 fixes that. Patch 2 writes down what a driver is expected to return from the callback. Today this has to be found by reading the devfreq core. Patch 3 records the frequency the controller starts at. ufshcd_init_clocks() puts the controller at its highest frequency, but nothing writes that down, so clk_scaling.target_freq stays 0 and devfreq starts with previous_freq at 0 as well. With use_pm_opp this makes ufshcd_devfreq_get_dev_status() report 0 Hz, the ondemand governor then asks for the maximum frequency, and ufshcd_devfreq_target() runs a full ufshcd_devfreq_scale() that holds up the queue for up to a second only to set the same OPP and the same gear again. Patch 4 adds the ->get_cur_freq() callback to ufshcd. Without it the cur_freq attribute shows the last frequency the governor selected, which is wrong whenever the controller is scaled outside the governor, for example after writing 0 to clkscale_enable. The patches touch two subsystems. Patches 1 and 2 are for the devfreq tree, patches 3 and 4 are for the SCSI tree. The two halves are independent, at build time and at run time, and can be applied in either order. Patch was tested on a Radxa Dragon Q6A (1d84000.ufshc): before "echo 0 > clkscale_enable": cur_freq 75000000, target_freq 75000000 after "echo 0 > clkscale_enable": cur_freq 300000000, target_freq 75000000 Without it both files report 75000000 and keep doing so for as long as clock scaling stays disabled. A 4 GiB direct read after enabling clock scaling again counted the transitions in trans_stat and attributed time to the 300000000 state, so the frequency the callback returns is one that devfreq recognises. One thing to be aware of: devfreq_monitor_resume() copies previous_freq from the callback, but it does not call devfreq_update_status(). A frequency change made while the governor was suspended therefore does not show up as a transition. That is how devfreq behaves today and this series does not change it. Changes since v1: - New patch 3, so that target_freq and devfreq's previous_freq are not 0 at boot (suggested by Stanley Jhu). - Patch 4: drop the !cur_freq check, it cannot happen any more. - Drop the now stale comment in ufshcd_devfreq_get_dev_status(). - Patches 1 and 2 are unchanged. - The devfreq and the ufshcd patches no longer depend on each other. - Avri's Reviewed-by is on patches 1, 2 and 4. Patch 3 is new, so it does not carry it. Avri, please note that patch 4 changed since you reviewed it, the !cur_freq check is gone. Tell me if you want the tag dropped. Bean Huo (4): PM / devfreq: Fall back to previous_freq when get_cur_freq() fails PM / devfreq: Add more details to the get_cur_freq() comment scsi: ufs: core: Record the frequency the controller starts at scsi: ufs: core: Report the current clock frequency to devfreq drivers/devfreq/devfreq.c | 5 ++--- drivers/ufs/core/ufshcd.c | 37 +++++++++++++++++++++++++++++++------ include/linux/devfreq.h | 7 +++++-- 3 files changed, 38 insertions(+), 11 deletions(-) base-commit: e30626823a406725ce29bc75cb8ec467d3e1e326 -- 2.34.1
On Mon, 07 Sep 2026 21:21:36 +0200, Bean Huo wrote:
> The devfreq core has three users of the optional ->get_cur_freq()
> callback. Two of them check the return value, the third one does not and
> passes an uninitialized frequency to the transition notifiers when the
> callback fails. Patch 1 fixes that.
>
> Patch 2 writes down what a driver is expected to return from the
> callback. Today this has to be found by reading the devfreq core.
>
> [...]
Applied to 7.4/scsi-queue, thanks!
[3/4] scsi: ufs: core: Record the frequency the controller starts at
https://git.kernel.org/mkp/scsi/c/20ae446921e7
[4/4] scsi: ufs: core: Report the current clock frequency to devfreq
https://git.kernel.org/mkp/scsi/c/55ad5deeea92
--
Martin K. Petersen
Hi Chanwoo, A quick check. the patch 1/4, and patch 2/4 in this series would be queueing up for your pull requst? Regards, Bean On Mon, 2026-09-07 at 21:21 +0200, Bean Huo wrote: > The devfreq core has three users of the optional ->get_cur_freq() > callback. Two of them check the return value, the third one does not and > passes an uninitialized frequency to the transition notifiers when the > callback fails. Patch 1 fixes that. > > Patch 2 writes down what a driver is expected to return from the > callback. Today this has to be found by reading the devfreq core. > > Patch 3 records the frequency the controller starts at. > ufshcd_init_clocks() puts the controller at its highest frequency, but > nothing writes that down, so clk_scaling.target_freq stays 0 and devfreq > starts with previous_freq at 0 as well. With use_pm_opp this makes > ufshcd_devfreq_get_dev_status() report 0 Hz, the ondemand governor then > asks for the maximum frequency, and ufshcd_devfreq_target() runs a full > ufshcd_devfreq_scale() that holds up the queue for up to a second only to > set the same OPP and the same gear again. > > Patch 4 adds the ->get_cur_freq() callback to ufshcd. Without it the > cur_freq attribute shows the last frequency the governor selected, which > is wrong whenever the controller is scaled outside the governor, for > example after writing 0 to clkscale_enable. > > The patches touch two subsystems. Patches 1 and 2 are for the devfreq > tree, patches 3 and 4 are for the SCSI tree. The two halves are > independent, at build time and at run time, and can be applied in either > order. > > Patch was tested on a Radxa Dragon Q6A (1d84000.ufshc): > > before "echo 0 > clkscale_enable": cur_freq 75000000, target_freq 75000000 > after "echo 0 > clkscale_enable": cur_freq 300000000, target_freq 75000000 > > Without it both files report 75000000 and keep doing so for as long as > clock scaling stays disabled. A 4 GiB direct read after enabling clock > scaling again counted the transitions in trans_stat and attributed time > to the 300000000 state, so the frequency the callback returns is one that > devfreq recognises. > > One thing to be aware of: devfreq_monitor_resume() copies previous_freq > from the callback, but it does not call devfreq_update_status(). A > frequency change made while the governor was suspended therefore does not > show up as a transition. That is how devfreq behaves today and this > series does not change it. > > Changes since v1: > - New patch 3, so that target_freq and devfreq's previous_freq are not 0 > at boot (suggested by Stanley Jhu). > - Patch 4: drop the !cur_freq check, it cannot happen any more. > - Drop the now stale comment in ufshcd_devfreq_get_dev_status(). > - Patches 1 and 2 are unchanged. > - The devfreq and the ufshcd patches no longer depend on each other. > - Avri's Reviewed-by is on patches 1, 2 and 4. Patch 3 is new, so it does > not carry it. Avri, please note that patch 4 changed since you reviewed > it, the !cur_freq check is gone. Tell me if you want the tag dropped. > > > Bean Huo (4): > PM / devfreq: Fall back to previous_freq when get_cur_freq() fails > PM / devfreq: Add more details to the get_cur_freq() comment > scsi: ufs: core: Record the frequency the controller starts at > scsi: ufs: core: Report the current clock frequency to devfreq > > drivers/devfreq/devfreq.c | 5 ++--- > drivers/ufs/core/ufshcd.c | 37 +++++++++++++++++++++++++++++++------ > include/linux/devfreq.h | 7 +++++-- > 3 files changed, 38 insertions(+), 11 deletions(-) > > > base-commit: e30626823a406725ce29bc75cb8ec467d3e1e326
Bean, > The patches touch two subsystems. Patches 1 and 2 are for the devfreq > tree, patches 3 and 4 are for the SCSI tree. The two halves are > independent, at build time and at run time, and can be applied in either > order. Patches 3 + 4 applied to 7.4/scsi-staging, thanks! -- Martin K. Petersen
On Mon, 7 Sep 2026 21:21:36 +0200, Bean Huo wrote: > Changes since v1: > - New patch 3, so that target_freq and devfreq's previous_freq are not 0 > at boot (suggested by Stanley Jhu). > - Patch 4: drop the !cur_freq check, it cannot happen any more. Thanks for addressing the initial frequency desync in v2. For the series: Reviewed-by: Stanley Jhu <stanleyjhu@google.com>
© 2016 - 2026 Red Hat, Inc.