[PATCH v3 4/4] devfreq: Refcount governor modules while in use
Jie Zhan
zhanjie9 at hisilicon.com
Sun May 31 19:03:17 PDT 2026
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.
>> + return -EINVAL;
>> + }
>> +
>> df->governor = new_gov;
>> 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);
>> + module_put(new_gov->owner);
>>
>> /* Restore previous governor */
>> df->governor = old_gov;
>> if (!df->governor)
>> return ret;
>>
>> + if (!try_module_get(old_gov->owner)) {
>> + df->governor = NULL;
>> + return -EINVAL;
>> + }
>> +
>> ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
>> if (ret) {
>> dev_err(dev, "%s: restore Governor %s failed (%d)\n",
>> __func__, df->governor->name, ret);
>> + module_put(old_gov->owner);
>> df->governor = NULL;
>> return ret;
>> }
[ ... ]
More information about the linux-arm-kernel
mailing list