Re: [PATCH v2 3/4] PM / devfreq: Fix governor_store() failing when device has no current governor

From: Jie Zhan

Date: Thu Apr 02 2026 - 02:53:11 EST




On 4/2/2026 1:47 PM, Yaxiong Tian wrote:
>
> 在 2026/4/2 11:21, Jie Zhan 写道:
>>
>> On 4/1/2026 11:31 AM, Yaxiong Tian wrote:
>>> Since devfreq_remove_governor() may clear the device's current governor
>>> in certain situations, while governors actually exist independently
>>> of the device, directly returning EINVAL in this case is inaccurate.
>>>
>>> To fix this issue, remove this check and add relevant logic for when
>>> df->governor is NULL.
>>>
>>> Fixes: 483d557ee9a3 ("PM / devfreq: Clean up the devfreq instance name in sysfs attr")
>>> Signed-off-by: Yaxiong Tian <tianyaxiong@xxxxxxxxxx>
>>> ---
>>> drivers/devfreq/devfreq.c | 17 ++++++++++++++---
>>> 1 file changed, 14 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>>> index 2977b07be939..975f82d7a9d1 100644
>>> --- a/drivers/devfreq/devfreq.c
>>> +++ b/drivers/devfreq/devfreq.c
>>> @@ -1390,9 +1390,6 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>> char str_governor[DEVFREQ_NAME_LEN + 1];
>>> const struct devfreq_governor *governor, *prev_governor;
>>> - if (!df->governor)
>>> - return -EINVAL;
>>> -
>>> ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
>>> if (ret != 1)
>>> return -EINVAL;
>>> @@ -1403,6 +1400,20 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>>> ret = PTR_ERR(governor);
>>> goto out;
>>> }
>>> +
>>> + if (!df->governor) {
>>> + df->governor = governor;
>>> + ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
>>> + if (ret) {
>>> + dev_warn(dev, "%s: Governor %s not started(%d)\n",
>>> + __func__, df->governor->name, ret);
>>> + df->governor = NULL;
>>> + } else {
>>> + ret = sysfs_update_group(&df->dev.kobj, &gov_attr_group);
>>> + }
>>> + goto out;
>>> + }
>>> +
>>> if (df->governor == governor) {
>>> ret = 0;
>>> goto out;
>> Hi Yaxiong,
>>
>> I'd suggest something like this, such that the main body of the function is
>> not changed.
>>
>> Note that this is just an example. Not tested or carefully checked.
> "I still prefer my modification. It's clearer and more straightforward, and the increase in code size is very small compared to the alternatives. Moreover, if we later want to implement 'cannot unload the last governor' (which might be the module reference approach you mentioned), we can simply remove this code."
>
OK. I'm fine with the above.
Reviewed-by: Jie Zhan <zhanjie9@xxxxxxxxxxxxx>
>
>>
>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>> index 2977b07be939..aa0f1db3225c 100644
>> --- a/drivers/devfreq/devfreq.c
>> +++ b/drivers/devfreq/devfreq.c
>> @@ -1390,9 +1390,6 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>> char str_governor[DEVFREQ_NAME_LEN + 1];
>> const struct devfreq_governor *governor, *prev_governor;
>>
>> - if (!df->governor)
>> - return -EINVAL;
>> -
>> ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
>> if (ret != 1)
>> return -EINVAL;
>> @@ -1403,6 +1400,10 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>> ret = PTR_ERR(governor);
>> goto out;
>> }
>> +
>> + if (!df->governor)
>> + goto skip_stop;
>> +
>> if (df->governor == governor) {
>> ret = 0;
>> goto out;
>> @@ -1423,6 +1424,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>> goto out;
>> }
>>
>> +skip_stop:
>> /*
>> * Start the new governor and create the specific sysfs files
>> * which depend on the new governor.
>> @@ -1435,6 +1437,8 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
>> __func__, df->governor->name, ret);
>>
>> /* Restore previous governor */
>> + if (!prev_governor)
>> + goto out;
>> df->governor = prev_governor;
>> ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
>> if (ret) {