From: Amerigo Wang <amwang@xxxxxxxxxx> There is no need to do sysfs_remove_link() or kobject_put() etc. when policy_rwsem_write is held, move them after releasing the lock. This fixes the lockdep warning: halt/4071 is trying to acquire lock: (s_active){++++.+}, at: [<c0000000001ef868>] .sysfs_addrm_finish+0x58/0xc0 but task is already holding lock: (&per_cpu(cpu_policy_rwsem, cpu)){+.+.+.}, at: [<c0000000004cd6ac>] .lock_policy_rwsem_write+0x84/0xf4 Signed-off-by: WANG Cong <amwang@xxxxxxxxxx> Reported-by: Benjamin Herrenschmidt <benh@xxxxxxxxxxxxxxxxxxx> Cc: Johannes Berg <johannes@xxxxxxxxxxxxxxxx> Cc: Venkatesh Pallipadi <venkatesh.pallipadi@xxxxxxxxx> Cc: Dave Jones <davej@xxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- drivers/cpufreq/cpufreq.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff -puN drivers/cpufreq/cpufreq.c~cpufreq-fix-a-lockdep-warning drivers/cpufreq/cpufreq.c --- a/drivers/cpufreq/cpufreq.c~cpufreq-fix-a-lockdep-warning +++ a/drivers/cpufreq/cpufreq.c @@ -1109,6 +1109,8 @@ static int __cpufreq_remove_dev(struct s unsigned int cpu = sys_dev->id; unsigned long flags; struct cpufreq_policy *data; + struct kobject *kobj; + struct completion *cmp; #ifdef CONFIG_SMP struct sys_device *cpu_sys_dev; unsigned int j; @@ -1137,10 +1139,11 @@ static int __cpufreq_remove_dev(struct s dprintk("removing link\n"); cpumask_clear_cpu(cpu, data->cpus); spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - sysfs_remove_link(&sys_dev->kobj, "cpufreq"); + kobj = &sys_dev->kobj; cpufreq_cpu_put(data); cpufreq_debug_enable_ratelimit(); unlock_policy_rwsem_write(cpu); + sysfs_remove_link(kobj, "cpufreq"); return 0; } #endif @@ -1177,7 +1180,10 @@ static int __cpufreq_remove_dev(struct s data->governor->name, CPUFREQ_NAME_LEN); #endif cpu_sys_dev = get_cpu_sysdev(j); - sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq"); + kobj = &cpu_sys_dev->kobj; + unlock_policy_rwsem_write(cpu); + sysfs_remove_link(kobj, "cpufreq"); + lock_policy_rwsem_write(cpu); cpufreq_cpu_put(data); } } @@ -1188,19 +1194,22 @@ static int __cpufreq_remove_dev(struct s if (cpufreq_driver->target) __cpufreq_governor(data, CPUFREQ_GOV_STOP); - kobject_put(&data->kobj); + kobj = &data->kobj; + cmp = &data->kobj_unregister; + unlock_policy_rwsem_write(cpu); + kobject_put(kobj); /* we need to make sure that the underlying kobj is actually * not referenced anymore by anybody before we proceed with * unloading. */ dprintk("waiting for dropping of refcount\n"); - wait_for_completion(&data->kobj_unregister); + wait_for_completion(cmp); dprintk("wait complete\n"); + lock_policy_rwsem_write(cpu); if (cpufreq_driver->exit) cpufreq_driver->exit(data); - unlock_policy_rwsem_write(cpu); free_cpumask_var(data->related_cpus); _ -- 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