#include <linux/device.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
+#include <linux/completion.h>
#define CPUFREQ_NAME_LEN 16
struct kobject kobj;
struct semaphore lock; /* CPU ->setpolicy or ->target may
only be called once a time */
+ struct completion kobj_unregister;
};
#define CPUFREQ_ADJUST (0)
#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
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,
static struct kobj_type ktype_cpufreq = {
.sysfs_ops = &sysfs_ops,
.default_attrs = default_attrs,
+ .release = cpufreq_sysfs_release,
};
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;
/* 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);
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;
}