[PATCH v1 08/10] devfreq: Allow find_devfreq_governor() to get module refcount

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


Add a 'get' parameter for find_devfreq_governor() to optionally get a
refcount of the governor module.

Getting refcount in try_then_request_governor() prevents the governor
module from being removed during the governor setting phase.

However, in devfreq_add/remove_governor(), it doesn't need to get a
refcount of the governor module because it just checks whether a
governor registered with the same name exists or not.

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

diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index ba09948915ba..c6b670b8fd22 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -254,11 +254,13 @@ EXPORT_SYMBOL(devfreq_update_status);
 /**
  * find_devfreq_governor() - find devfreq governor from name
  * @name:	name of the governor
+ * @get:	whether to get a refcount of the governor module
  *
  * Search the list of devfreq governors and return the matched
  * governor's pointer.
  */
-static struct devfreq_governor *find_devfreq_governor(const char *name)
+static struct devfreq_governor *find_devfreq_governor(const char *name,
+						      bool get)
 {
 	struct devfreq_governor *tmp_governor;
 
@@ -269,8 +271,13 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
 
 	guard(mutex)(&devfreq_gov_lock);
 	list_for_each_entry(tmp_governor, &devfreq_governor_list, node) {
-		if (!strncmp(tmp_governor->name, name, DEVFREQ_NAME_LEN))
-			return tmp_governor;
+		if (strncmp(tmp_governor->name, name, DEVFREQ_NAME_LEN))
+			continue;
+
+		if (get && !try_module_get(tmp_governor->owner))
+			return ERR_PTR(-EBUSY);
+
+		return tmp_governor;
 	}
 
 	return ERR_PTR(-ENODEV);
@@ -285,6 +292,9 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
  * if is not found. This can happen when both drivers (the governor driver
  * and the driver that call devfreq_add_device) are built as modules.
  * Returns the matched governor's pointer or an error pointer.
+ * On success, this holds a refcount of the governor module to prevent the
+ * module from being unloaded during usage, so the caller should put a module
+ * refcount after using it.
  */
 static struct devfreq_governor *try_then_request_governor(const char *name)
 {
@@ -296,7 +306,7 @@ static struct devfreq_governor *try_then_request_governor(const char *name)
 		return ERR_PTR(-EINVAL);
 	}
 
-	governor = find_devfreq_governor(name);
+	governor = find_devfreq_governor(name, true);
 	if (IS_ERR(governor)) {
 		if (!strncmp(name, DEVFREQ_GOV_SIMPLE_ONDEMAND,
 			     DEVFREQ_NAME_LEN))
@@ -307,7 +317,7 @@ static struct devfreq_governor *try_then_request_governor(const char *name)
 		if (err)
 			return (err < 0) ? ERR_PTR(err) : ERR_PTR(-EINVAL);
 
-		governor = find_devfreq_governor(name);
+		governor = find_devfreq_governor(name, true);
 	}
 
 	return governor;
@@ -1007,6 +1017,8 @@ struct devfreq *devfreq_add_device(struct device *dev,
 	if (err)
 		goto err_devfreq;
 
+	module_put(governor->owner);
+
 	list_add(&devfreq->node, &devfreq_list);
 	mutex_unlock(&devfreq_list_lock);
 
@@ -1312,7 +1324,7 @@ int __devfreq_add_governor(struct devfreq_governor *governor,
 		return -EINVAL;
 	}
 
-	g = find_devfreq_governor(governor->name);
+	g = find_devfreq_governor(governor->name, false);
 	if (!IS_ERR(g)) {
 		pr_err("%s: governor %s already registered\n", __func__,
 		       g->name);
@@ -1361,7 +1373,7 @@ int devfreq_remove_governor(struct devfreq_governor *governor)
 		return -EINVAL;
 	}
 
-	g = find_devfreq_governor(governor->name);
+	g = find_devfreq_governor(governor->name, false);
 	if (IS_ERR(g)) {
 		pr_err("%s: governor %s not registered\n", __func__,
 		       governor->name);
@@ -1436,6 +1448,8 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
 
 	ret = devfreq_set_governor(df, governor);
 
+	module_put(governor->owner);
+
 	return ret ? ret : count;
 }
 static DEVICE_ATTR_RW(governor);
-- 
2.43.0




More information about the linux-arm-kernel mailing list