aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>2009-07-03 11:25:16 -0400
committerDave Jones <davej@redhat.com>2009-07-06 21:38:28 -0400
commit3f4a782b5ce2698b1870b5a7b573cd721d4fce33 (patch)
treebed89982d8baa4d086ae6edbab92065d712a3793
parentee88415caf736b89500f16e0a545614541a45005 (diff)
[CPUFREQ] fix (utter) cpufreq_add_dev mess
OK, I've tried to clean it up the best I could, but please test this with concurrent cpu hotplug and cpufreq add/remove in loops. I'm sure we will make other interesting findings. This is step one of fixing the overall locking dependency mess in cpufreq. Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> CC: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> CC: rjw@sisk.pl CC: mingo@elte.hu CC: Shaohua Li <shaohua.li@intel.com> CC: Pekka Enberg <penberg@cs.helsinki.fi> CC: Dave Young <hidave.darkstar@gmail.com> CC: "Rafael J. Wysocki" <rjw@sisk.pl> CC: Rusty Russell <rusty@rustcorp.com.au> CC: sven.wegener@stealer.net CC: cpufreq@vger.kernel.org CC: Thomas Renninger <trenn@suse.de> Signed-off-by: Dave Jones <davej@redhat.com>
-rw-r--r--drivers/cpufreq/cpufreq.c65
1 files changed, 40 insertions, 25 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index c7fe16e0474b..c668ac855f71 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -761,6 +761,10 @@ static struct kobj_type ktype_cpufreq = {
761 * cpufreq_add_dev - add a CPU device 761 * cpufreq_add_dev - add a CPU device
762 * 762 *
763 * Adds the cpufreq interface for a CPU device. 763 * Adds the cpufreq interface for a CPU device.
764 *
765 * The Oracle says: try running cpufreq registration/unregistration concurrently
766 * with with cpu hotplugging and all hell will break loose. Tried to clean this
767 * mess up, but more thorough testing is needed. - Mathieu
764 */ 768 */
765static int cpufreq_add_dev(struct sys_device *sys_dev) 769static int cpufreq_add_dev(struct sys_device *sys_dev)
766{ 770{
@@ -804,15 +808,12 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
804 goto nomem_out; 808 goto nomem_out;
805 } 809 }
806 if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL)) { 810 if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL)) {
807 kfree(policy);
808 ret = -ENOMEM; 811 ret = -ENOMEM;
809 goto nomem_out; 812 goto err_free_policy;
810 } 813 }
811 if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) { 814 if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) {
812 free_cpumask_var(policy->cpus);
813 kfree(policy);
814 ret = -ENOMEM; 815 ret = -ENOMEM;
815 goto nomem_out; 816 goto err_free_cpumask;
816 } 817 }
817 818
818 policy->cpu = cpu; 819 policy->cpu = cpu;
@@ -820,7 +821,8 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
820 821
821 /* Initially set CPU itself as the policy_cpu */ 822 /* Initially set CPU itself as the policy_cpu */
822 per_cpu(policy_cpu, cpu) = cpu; 823 per_cpu(policy_cpu, cpu) = cpu;
823 lock_policy_rwsem_write(cpu); 824 ret = (lock_policy_rwsem_write(cpu) < 0);
825 WARN_ON(ret);
824 826
825 init_completion(&policy->kobj_unregister); 827 init_completion(&policy->kobj_unregister);
826 INIT_WORK(&policy->update, handle_update); 828 INIT_WORK(&policy->update, handle_update);
@@ -833,7 +835,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
833 ret = cpufreq_driver->init(policy); 835 ret = cpufreq_driver->init(policy);
834 if (ret) { 836 if (ret) {
835 dprintk("initialization failed\n"); 837 dprintk("initialization failed\n");
836 goto err_out; 838 goto err_unlock_policy;
837 } 839 }
838 policy->user_policy.min = policy->min; 840 policy->user_policy.min = policy->min;
839 policy->user_policy.max = policy->max; 841 policy->user_policy.max = policy->max;
@@ -858,15 +860,21 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
858 /* Check for existing affected CPUs. 860 /* Check for existing affected CPUs.
859 * They may not be aware of it due to CPU Hotplug. 861 * They may not be aware of it due to CPU Hotplug.
860 */ 862 */
861 managed_policy = cpufreq_cpu_get(j); /* FIXME: Where is this released? What about error paths? */ 863 managed_policy = cpufreq_cpu_get(j);
862 if (unlikely(managed_policy)) { 864 if (unlikely(managed_policy)) {
863 865
864 /* Set proper policy_cpu */ 866 /* Set proper policy_cpu */
865 unlock_policy_rwsem_write(cpu); 867 unlock_policy_rwsem_write(cpu);
866 per_cpu(policy_cpu, cpu) = managed_policy->cpu; 868 per_cpu(policy_cpu, cpu) = managed_policy->cpu;
867 869
868 if (lock_policy_rwsem_write(cpu) < 0) 870 if (lock_policy_rwsem_write(cpu) < 0) {
869 goto err_out_driver_exit; 871 /* Should not go through policy unlock path */
872 if (cpufreq_driver->exit)
873 cpufreq_driver->exit(policy);
874 ret = -EBUSY;
875 cpufreq_cpu_put(managed_policy);
876 goto err_free_cpumask;
877 }
870 878
871 spin_lock_irqsave(&cpufreq_driver_lock, flags); 879 spin_lock_irqsave(&cpufreq_driver_lock, flags);
872 cpumask_copy(managed_policy->cpus, policy->cpus); 880 cpumask_copy(managed_policy->cpus, policy->cpus);
@@ -877,12 +885,14 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
877 ret = sysfs_create_link(&sys_dev->kobj, 885 ret = sysfs_create_link(&sys_dev->kobj,
878 &managed_policy->kobj, 886 &managed_policy->kobj,
879 "cpufreq"); 887 "cpufreq");
880 if (ret) 888 if (!ret)
881 goto err_out_driver_exit; 889 cpufreq_cpu_put(managed_policy);
882 890 /*
883 cpufreq_debug_enable_ratelimit(); 891 * Success. We only needed to be added to the mask.
884 ret = 0; 892 * Call driver->exit() because only the cpu parent of
885 goto err_out_driver_exit; /* call driver->exit() */ 893 * the kobj needed to call init().
894 */
895 goto out_driver_exit; /* call driver->exit() */
886 } 896 }
887 } 897 }
888#endif 898#endif
@@ -892,25 +902,25 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
892 ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj, 902 ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj,
893 "cpufreq"); 903 "cpufreq");
894 if (ret) 904 if (ret)
895 goto err_out_driver_exit; 905 goto out_driver_exit;
896 906
897 /* set up files for this cpu device */ 907 /* set up files for this cpu device */
898 drv_attr = cpufreq_driver->attr; 908 drv_attr = cpufreq_driver->attr;
899 while ((drv_attr) && (*drv_attr)) { 909 while ((drv_attr) && (*drv_attr)) {
900 ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); 910 ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
901 if (ret) 911 if (ret)
902 goto err_out_driver_exit; 912 goto err_out_kobj_put;
903 drv_attr++; 913 drv_attr++;
904 } 914 }
905 if (cpufreq_driver->get) { 915 if (cpufreq_driver->get) {
906 ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); 916 ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
907 if (ret) 917 if (ret)
908 goto err_out_driver_exit; 918 goto err_out_kobj_put;
909 } 919 }
910 if (cpufreq_driver->target) { 920 if (cpufreq_driver->target) {
911 ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); 921 ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
912 if (ret) 922 if (ret)
913 goto err_out_driver_exit; 923 goto err_out_kobj_put;
914 } 924 }
915 925
916 spin_lock_irqsave(&cpufreq_driver_lock, flags); 926 spin_lock_irqsave(&cpufreq_driver_lock, flags);
@@ -928,12 +938,14 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
928 continue; 938 continue;
929 939
930 dprintk("CPU %u already managed, adding link\n", j); 940 dprintk("CPU %u already managed, adding link\n", j);
931 cpufreq_cpu_get(cpu); 941 managed_policy = cpufreq_cpu_get(cpu);
932 cpu_sys_dev = get_cpu_sysdev(j); 942 cpu_sys_dev = get_cpu_sysdev(j);
933 ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj, 943 ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
934 "cpufreq"); 944 "cpufreq");
935 if (ret) 945 if (ret) {
946 cpufreq_cpu_put(managed_policy);
936 goto err_out_unregister; 947 goto err_out_unregister;
948 }
937 } 949 }
938 950
939 policy->governor = NULL; /* to assure that the starting sequence is 951 policy->governor = NULL; /* to assure that the starting sequence is
@@ -965,17 +977,20 @@ err_out_unregister:
965 per_cpu(cpufreq_cpu_data, j) = NULL; 977 per_cpu(cpufreq_cpu_data, j) = NULL;
966 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 978 spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
967 979
980err_out_kobj_put:
968 kobject_put(&policy->kobj); 981 kobject_put(&policy->kobj);
969 wait_for_completion(&policy->kobj_unregister); 982 wait_for_completion(&policy->kobj_unregister);
970 983
971err_out_driver_exit: 984out_driver_exit:
972 if (cpufreq_driver->exit) 985 if (cpufreq_driver->exit)
973 cpufreq_driver->exit(policy); 986 cpufreq_driver->exit(policy);
974 987
975err_out: 988err_unlock_policy:
976 unlock_policy_rwsem_write(cpu); 989 unlock_policy_rwsem_write(cpu);
990err_free_cpumask:
991 free_cpumask_var(policy->cpus);
992err_free_policy:
977 kfree(policy); 993 kfree(policy);
978
979nomem_out: 994nomem_out:
980 module_put(cpufreq_driver->owner); 995 module_put(cpufreq_driver->owner);
981module_out: 996module_out: