summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorDave Jones <davej@codemonkey.org.uk>2003-07-09 18:21:45 +0100
committerDave Jones <davej@tetrachloride.(none)>2003-07-09 18:21:45 +0100
commit1c576b19a92e6a4b489c033d77bf2bd512fa7b8e (patch)
tree3d2f1d971dc81232be761ac26229cd840409d377 /kernel
parent2c3b4f8952b94576e4958af9e821716545bee9cc (diff)
[CPUFREQ] kobj refcount fixes.
Wait with the destruction of cpufreq objects until all references are gone (code partly based on rmk's comparable patch for the PCMCIA subsystem. From Dominik.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cpufreq.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/kernel/cpufreq.c b/kernel/cpufreq.c
index 18245832d8c9..0701eed77ab4 100644
--- a/kernel/cpufreq.c
+++ b/kernel/cpufreq.c
@@ -23,6 +23,7 @@
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/cpu.h>
+#include <linux/completion.h>
/**
* The "cpufreq driver" - the arch- or hardware-dependend low
@@ -297,6 +298,12 @@ static ssize_t store(struct kobject * kobj, struct attribute * attr,
return ret;
}
+static void cpufreq_sysfs_release(struct kobject * kobj)
+{
+ struct cpufreq_policy * policy = to_policy(kobj);
+ complete(&policy->kobj_unregister);
+}
+
static struct sysfs_ops sysfs_ops = {
.show = show,
.store = store,
@@ -305,6 +312,7 @@ static struct sysfs_ops sysfs_ops = {
static struct kobj_type ktype_cpufreq = {
.sysfs_ops = &sysfs_ops,
.default_attrs = default_attrs,
+ .release = cpufreq_sysfs_release,
};
@@ -343,6 +351,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
up(&cpufreq_driver_sem);
init_MUTEX(&policy->lock);
+ init_completion(&policy->kobj_unregister);
+
/* prepare interface data */
policy->kobj.parent = &sys_dev->kobj;
policy->kobj.ktype = &ktype_cpufreq;
@@ -361,8 +371,10 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
/* set default policy */
ret = cpufreq_set_policy(&new_policy);
- if (ret)
+ if (ret) {
kobject_unregister(&policy->kobj);
+ wait_for_completion(&policy->kobj_unregister);
+ }
out:
module_put(cpufreq_driver->owner);
@@ -400,6 +412,13 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
up(&cpufreq_driver_sem);
kobject_put(&cpufreq_driver->policy[cpu].kobj);
+
+ /* we need to make sure that the underlying kobj is actually
+ * destroyed before we proceed e.g. with cpufreq driver module
+ * unloading
+ */
+ wait_for_completion(&cpufreq_driver->policy[cpu].kobj_unregister);
+
return 0;
}