[PATCH v1 07/10] devfreq: Get and put module refcount when switching governor

Jie Zhan zhanjie9 at hisilicon.com
Thu Mar 26 05:34:25 PDT 2026


When compiled as a kernel module, the governor module can be dynamically
inserted or removed.  'devfreq->governor' would become NULL if the
governor module is removed when it's in use.

To prevent the governor module from being removed (except for force
unload) when it's in use, get and put a refcount of the governor module
when starting and stopping the governor.

Now, unloading a governor module that is set for a devfreq device
returns an error, for example:
  # cat governor
  performance
  # rmmod governor_performance
  rmmod: ERROR: Module governor_performance is in use

Signed-off-by: Jie Zhan <zhanjie9 at hisilicon.com>
---
 drivers/devfreq/devfreq.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 9b078458d129..ba09948915ba 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -338,22 +338,31 @@ static int devfreq_set_governor_locked(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))
+		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);
 		if (!old_gov)
 			return ret;
 
 		/* Restore previous governor */
+		if (!try_module_get(old_gov->owner))
+			return -EINVAL;
+
 		df->governor = old_gov;
 		ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
 		if (ret) {
+			module_put(old_gov->owner);
 			dev_err(dev, "%s: restore Governor %s failed (%d)\n",
 				__func__, old_gov->name, ret);
 			df->governor = NULL;
-- 
2.43.0




More information about the linux-arm-kernel mailing list