[PATCH v3 4/4] devfreq: Refcount governor modules while in use

Jie Zhan zhanjie9 at hisilicon.com
Tue Jul 28 05:48:16 PDT 2026



On 6/1/2026 10:03 AM, Jie Zhan wrote:
> 
> 
> On 5/21/2026 4:13 PM, zhenglifeng (A) wrote:
>> On 5/19/2026 7:32 PM, Jie Zhan wrote:
>>> A governor module can be inserted or removed dynamically when built as a
>>> kernel module.  'devfreq->governor' would become NULL if the governor
>>> module is removed when it's in use.
>>>
>>> Add a refcount mechanism for governor modules to prevent the governor
>>> module from being removed (except for force unload):
>>> 1. Add an optional 'owner' member to struct devfreq_governor so the devfreq
>>>    core can identify the module that holds the governor code.
>>> 2. Get and put a refcount of the governor module when starting and stopping
>>>    the governor.
>>>
>>> The new 'owner' field is optional:
>>> - Common governor modules (performance, powersave, simple_ondemand,
>>>   userspace, passive) set 'owner' to THIS_MODULE.
>>> - Governors that are bundled into a device driver module must leave 'owner'
>>>   NULL.  The device's lifetime already pins that module, and setting
>>>   'owner' would create a self-reference that blocks the driver from being
>>>   unloaded.
>>>
>>> As a result, a non-forced rmmod of an in-use stand-alone governor now
>>> fails with -EBUSY, e.g.:
>>>
>>>   $ cat governor
>>>   performance
>>>   $ rmmod governor_performance
>>>   rmmod: ERROR: Module governor_performance is in use
>>>
>>> Force unloads (rmmod -f, if configured) can't be blocked.
>>>
>>> Signed-off-by: Jie Zhan <zhanjie9 at hisilicon.com>
>>> ---
>>>  drivers/devfreq/devfreq.c                 | 17 ++++++++++++++++-
>>>  drivers/devfreq/governor_passive.c        |  1 +
>>>  drivers/devfreq/governor_performance.c    |  1 +
>>>  drivers/devfreq/governor_powersave.c      |  1 +
>>>  drivers/devfreq/governor_simpleondemand.c |  1 +
>>>  drivers/devfreq/governor_userspace.c      |  1 +
>>>  include/linux/devfreq-governor.h          | 11 +++++++++++
>>>  7 files changed, 32 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>>> index 9e3e6a7348f8..1cee43636ded 100644
>>> --- a/drivers/devfreq/devfreq.c
>>> +++ b/drivers/devfreq/devfreq.c
>>> @@ -345,24 +345,37 @@ static int devfreq_set_governor(struct devfreq *df,
>>>  				 __func__, df->governor->name, ret);
>>>  			return ret;
>>>  		}
>>> +		module_put(old_gov->owner);
>>>  	}
>>>  
>>>  	/* Start the new governor */
>>> +	if (!try_module_get(new_gov->owner)) {
>>> +		df->governor = NULL;
>>
>> Shouldn't the old governor be restored here?
>>
> Yeah.  Perhaps we just move try_module_get() before stopping the old
> governor so as to avoid another hunk of restoring governor.

Follow up (after a long while though):
I found it quite hard to restore the old governor here while keep the code
clear.  I'd suggest that leaving it NULL for this rare error path.  The
current devfreq-next code is able to handle a NULL df->governor.

Thanks!
Jie



More information about the linux-arm-kernel mailing list