[PATCH] cpufreq: Fix the driver can not be unloaded issue

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Tang Yuantian <yuantian.tang@xxxxxxxxxxxxx>

The driver compiled as a module can not be unloaded if there
are more than one cpu in policy->cpus. That's caused by
cpufreq_cpu_get() in cpufreq_add_dev_symlink(); It keep increasing
the module reference count.
This patch splites the module and policy reference count. It keeps
the module reference count unchanged and uses the policy reference
count to track the resource.

Signed-off-by: Tang Yuantian <Yuantian.Tang@xxxxxxxxxxxxx>
---
 drivers/cpufreq/cpufreq.c | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index a6f6595..86abee5 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -154,26 +154,22 @@ static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs)
 	if (!driver)
 		goto err_out_unlock;
 
-	if (!try_module_get(driver->owner))
-		goto err_out_unlock;
-
 	read_lock_irqsave(&cpufreq_driver_lock, flags);
 
 	/* get the CPU */
 	data = per_cpu(cpufreq_cpu_data, cpu);
 
 	if (!data)
-		goto err_out_put_module;
+		goto err_out_read_unlock;
 
 	if (!sysfs && !kobject_get(&data->kobj))
-		goto err_out_put_module;
+		goto err_out_read_unlock;
 
 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 	rcu_read_unlock();
 	return data;
 
-err_out_put_module:
-	module_put(driver->owner);
+err_out_read_unlock:
 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 err_out_unlock:
 	rcu_read_unlock();
@@ -199,9 +195,6 @@ static void __cpufreq_cpu_put(struct cpufreq_policy *data, bool sysfs)
 {
 	if (!sysfs)
 		kobject_put(&data->kobj);
-	rcu_read_lock();
-	module_put(rcu_dereference(cpufreq_driver)->owner);
-	rcu_read_unlock();
 }
 
 void cpufreq_cpu_put(struct cpufreq_policy *data)
@@ -1076,7 +1069,6 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif
 	unsigned long flags;
 	struct cpufreq_policy *data;
 	struct cpufreq_driver *driver;
-	struct kobject *kobj;
 	struct completion *cmp;
 	struct device *cpu_dev;
 	bool has_target;
@@ -1157,10 +1149,8 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif
 			__cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
 
 		lock_policy_rwsem_read(cpu);
-		kobj = &data->kobj;
 		cmp = &data->kobj_unregister;
 		unlock_policy_rwsem_read(cpu);
-		kobject_put(kobj);
 
 		/* we need to make sure that the underlying kobj is actually
 		 * not referenced anymore by anybody before we proceed with
-- 
1.8.0


--
To unsubscribe from this list: send the line "unsubscribe cpufreq" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel Devel]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Forum]     [Linux SCSI]

  Powered by Linux