*/
struct uncore_data {
struct kobject kobj;
+ struct completion kobj_unregister;
u64 stored_uncore_data;
u32 initial_min_freq_khz;
u32 initial_max_freq_khz;
/* Storage for uncore data for all instances */
static struct uncore_data *uncore_instances;
/* Root of the all uncore sysfs kobjs */
-struct kobject uncore_root_kobj;
+struct kobject *uncore_root_kobj;
/* Stores the CPU mask of the target CPUs to use during uncore read/write */
static cpumask_t uncore_cpu_mask;
/* CPU online callback register instance */
NULL
};
+static void uncore_sysfs_entry_release(struct kobject *kobj)
+{
+ struct uncore_data *data = to_uncore_data(kobj);
+
+ complete(&data->kobj_unregister);
+}
+
static struct kobj_type uncore_ktype = {
+ .release = uncore_sysfs_entry_release,
.sysfs_ops = &kobj_sysfs_ops,
.default_attrs = uncore_attrs,
};
-static struct kobj_type uncore_root_ktype = {
- .sysfs_ops = &kobj_sysfs_ops,
-};
-
/* Caller provides protection */
static struct uncore_data *uncore_get_instance(unsigned int cpu)
{
uncore_read_ratio(data, &data->initial_min_freq_khz,
&data->initial_max_freq_khz);
+ init_completion(&data->kobj_unregister);
+
ret = kobject_init_and_add(&data->kobj, &uncore_ktype,
- &uncore_root_kobj, str);
+ uncore_root_kobj, str);
if (!ret) {
data->control_cpu = cpu;
data->valid = true;
if (!uncore_instances)
return -ENOMEM;
- ret = kobject_init_and_add(&uncore_root_kobj, &uncore_root_ktype,
- &cpu_subsys.dev_root->kobj,
- "intel_uncore_frequency");
- if (ret)
+ uncore_root_kobj = kobject_create_and_add("intel_uncore_frequency",
+ &cpu_subsys.dev_root->kobj);
+ if (!uncore_root_kobj) {
+ ret = -ENOMEM;
goto err_free;
+ }
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
"platform/x86/uncore-freq:online",
err_rem_state:
cpuhp_remove_state(uncore_hp_state);
err_rem_kobj:
- kobject_put(&uncore_root_kobj);
+ kobject_put(uncore_root_kobj);
err_free:
kfree(uncore_instances);
unregister_pm_notifier(&uncore_pm_nb);
cpuhp_remove_state(uncore_hp_state);
for (i = 0; i < uncore_max_entries; ++i) {
- if (uncore_instances[i].valid)
+ if (uncore_instances[i].valid) {
kobject_put(&uncore_instances[i].kobj);
+ wait_for_completion(&uncore_instances[i].kobj_unregister);
+ }
}
- kobject_put(&uncore_root_kobj);
+ kobject_put(uncore_root_kobj);
kfree(uncore_instances);
}
module_exit(intel_uncore_exit)