aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Zimmer <nzimmer@sgi.com>2013-02-22 11:24:34 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-03-31 19:11:34 -0400
commit0d1857a1b987ef874aeb4b99c9c385fa5645bf61 (patch)
treeb26ccf9c501ae14055b8c5a5e5a1e40a8b164f08
parent07961ac7c0ee8b546658717034fe692fd12eefa9 (diff)
cpufreq: Convert the cpufreq_driver_lock to a rwlock
This eliminates the contention I am seeing in __cpufreq_cpu_get. It also nicely stages the lock to be replaced by the rcu. Signed-off-by: Nathan Zimmer <nzimmer@sgi.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/cpufreq/cpufreq.c52
1 files changed, 26 insertions, 26 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index b02824d092e7..c5996fe7250e 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -45,7 +45,7 @@ static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
45/* This one keeps track of the previously set governor of a removed CPU */ 45/* This one keeps track of the previously set governor of a removed CPU */
46static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor); 46static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
47#endif 47#endif
48static DEFINE_SPINLOCK(cpufreq_driver_lock); 48static DEFINE_RWLOCK(cpufreq_driver_lock);
49 49
50/* 50/*
51 * cpu_policy_rwsem is a per CPU reader-writer semaphore designed to cure 51 * cpu_policy_rwsem is a per CPU reader-writer semaphore designed to cure
@@ -137,7 +137,7 @@ static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs)
137 goto err_out; 137 goto err_out;
138 138
139 /* get the cpufreq driver */ 139 /* get the cpufreq driver */
140 spin_lock_irqsave(&cpufreq_driver_lock, flags); 140 read_lock_irqsave(&cpufreq_driver_lock, flags);
141 141
142 if (!cpufreq_driver) 142 if (!cpufreq_driver)
143 goto err_out_unlock; 143 goto err_out_unlock;
@@ -155,13 +155,13 @@ static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs)
155 if (!sysfs && !kobject_get(&data->kobj)) 155 if (!sysfs && !kobject_get(&data->kobj))
156 goto err_out_put_module; 156 goto err_out_put_module;
157 157
158 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 158 read_unlock_irqrestore(&cpufreq_driver_lock, flags);
159 return data; 159 return data;
160 160
161err_out_put_module: 161err_out_put_module:
162 module_put(cpufreq_driver->owner); 162 module_put(cpufreq_driver->owner);
163err_out_unlock: 163err_out_unlock:
164 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 164 read_unlock_irqrestore(&cpufreq_driver_lock, flags);
165err_out: 165err_out:
166 return NULL; 166 return NULL;
167} 167}
@@ -266,9 +266,9 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
266 pr_debug("notification %u of frequency transition to %u kHz\n", 266 pr_debug("notification %u of frequency transition to %u kHz\n",
267 state, freqs->new); 267 state, freqs->new);
268 268
269 spin_lock_irqsave(&cpufreq_driver_lock, flags); 269 read_lock_irqsave(&cpufreq_driver_lock, flags);
270 policy = per_cpu(cpufreq_cpu_data, freqs->cpu); 270 policy = per_cpu(cpufreq_cpu_data, freqs->cpu);
271 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 271 read_unlock_irqrestore(&cpufreq_driver_lock, flags);
272 272
273 switch (state) { 273 switch (state) {
274 274
@@ -765,12 +765,12 @@ static int cpufreq_add_dev_interface(unsigned int cpu,
765 goto err_out_kobj_put; 765 goto err_out_kobj_put;
766 } 766 }
767 767
768 spin_lock_irqsave(&cpufreq_driver_lock, flags); 768 write_lock_irqsave(&cpufreq_driver_lock, flags);
769 for_each_cpu(j, policy->cpus) { 769 for_each_cpu(j, policy->cpus) {
770 per_cpu(cpufreq_cpu_data, j) = policy; 770 per_cpu(cpufreq_cpu_data, j) = policy;
771 per_cpu(cpufreq_policy_cpu, j) = policy->cpu; 771 per_cpu(cpufreq_policy_cpu, j) = policy->cpu;
772 } 772 }
773 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 773 write_unlock_irqrestore(&cpufreq_driver_lock, flags);
774 774
775 ret = cpufreq_add_dev_symlink(cpu, policy); 775 ret = cpufreq_add_dev_symlink(cpu, policy);
776 if (ret) 776 if (ret)
@@ -813,12 +813,12 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling,
813 813
814 lock_policy_rwsem_write(sibling); 814 lock_policy_rwsem_write(sibling);
815 815
816 spin_lock_irqsave(&cpufreq_driver_lock, flags); 816 write_lock_irqsave(&cpufreq_driver_lock, flags);
817 817
818 cpumask_set_cpu(cpu, policy->cpus); 818 cpumask_set_cpu(cpu, policy->cpus);
819 per_cpu(cpufreq_policy_cpu, cpu) = policy->cpu; 819 per_cpu(cpufreq_policy_cpu, cpu) = policy->cpu;
820 per_cpu(cpufreq_cpu_data, cpu) = policy; 820 per_cpu(cpufreq_cpu_data, cpu) = policy;
821 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 821 write_unlock_irqrestore(&cpufreq_driver_lock, flags);
822 822
823 unlock_policy_rwsem_write(sibling); 823 unlock_policy_rwsem_write(sibling);
824 824
@@ -871,15 +871,15 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
871 871
872#ifdef CONFIG_HOTPLUG_CPU 872#ifdef CONFIG_HOTPLUG_CPU
873 /* Check if this cpu was hot-unplugged earlier and has siblings */ 873 /* Check if this cpu was hot-unplugged earlier and has siblings */
874 spin_lock_irqsave(&cpufreq_driver_lock, flags); 874 read_lock_irqsave(&cpufreq_driver_lock, flags);
875 for_each_online_cpu(sibling) { 875 for_each_online_cpu(sibling) {
876 struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling); 876 struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling);
877 if (cp && cpumask_test_cpu(cpu, cp->related_cpus)) { 877 if (cp && cpumask_test_cpu(cpu, cp->related_cpus)) {
878 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 878 read_unlock_irqrestore(&cpufreq_driver_lock, flags);
879 return cpufreq_add_policy_cpu(cpu, sibling, dev); 879 return cpufreq_add_policy_cpu(cpu, sibling, dev);
880 } 880 }
881 } 881 }
882 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 882 read_unlock_irqrestore(&cpufreq_driver_lock, flags);
883#endif 883#endif
884#endif 884#endif
885 885
@@ -952,10 +952,10 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
952 return 0; 952 return 0;
953 953
954err_out_unregister: 954err_out_unregister:
955 spin_lock_irqsave(&cpufreq_driver_lock, flags); 955 write_lock_irqsave(&cpufreq_driver_lock, flags);
956 for_each_cpu(j, policy->cpus) 956 for_each_cpu(j, policy->cpus)
957 per_cpu(cpufreq_cpu_data, j) = NULL; 957 per_cpu(cpufreq_cpu_data, j) = NULL;
958 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 958 write_unlock_irqrestore(&cpufreq_driver_lock, flags);
959 959
960 kobject_put(&policy->kobj); 960 kobject_put(&policy->kobj);
961 wait_for_completion(&policy->kobj_unregister); 961 wait_for_completion(&policy->kobj_unregister);
@@ -1008,12 +1008,12 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif
1008 1008
1009 pr_debug("%s: unregistering CPU %u\n", __func__, cpu); 1009 pr_debug("%s: unregistering CPU %u\n", __func__, cpu);
1010 1010
1011 spin_lock_irqsave(&cpufreq_driver_lock, flags); 1011 write_lock_irqsave(&cpufreq_driver_lock, flags);
1012 1012
1013 data = per_cpu(cpufreq_cpu_data, cpu); 1013 data = per_cpu(cpufreq_cpu_data, cpu);
1014 per_cpu(cpufreq_cpu_data, cpu) = NULL; 1014 per_cpu(cpufreq_cpu_data, cpu) = NULL;
1015 1015
1016 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 1016 write_unlock_irqrestore(&cpufreq_driver_lock, flags);
1017 1017
1018 if (!data) { 1018 if (!data) {
1019 pr_debug("%s: No cpu_data found\n", __func__); 1019 pr_debug("%s: No cpu_data found\n", __func__);
@@ -1047,9 +1047,9 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif
1047 WARN_ON(lock_policy_rwsem_write(cpu)); 1047 WARN_ON(lock_policy_rwsem_write(cpu));
1048 cpumask_set_cpu(cpu, data->cpus); 1048 cpumask_set_cpu(cpu, data->cpus);
1049 1049
1050 spin_lock_irqsave(&cpufreq_driver_lock, flags); 1050 write_lock_irqsave(&cpufreq_driver_lock, flags);
1051 per_cpu(cpufreq_cpu_data, cpu) = data; 1051 per_cpu(cpufreq_cpu_data, cpu) = data;
1052 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 1052 write_unlock_irqrestore(&cpufreq_driver_lock, flags);
1053 1053
1054 unlock_policy_rwsem_write(cpu); 1054 unlock_policy_rwsem_write(cpu);
1055 1055
@@ -1848,13 +1848,13 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
1848 if (driver_data->setpolicy) 1848 if (driver_data->setpolicy)
1849 driver_data->flags |= CPUFREQ_CONST_LOOPS; 1849 driver_data->flags |= CPUFREQ_CONST_LOOPS;
1850 1850
1851 spin_lock_irqsave(&cpufreq_driver_lock, flags); 1851 write_lock_irqsave(&cpufreq_driver_lock, flags);
1852 if (cpufreq_driver) { 1852 if (cpufreq_driver) {
1853 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 1853 write_unlock_irqrestore(&cpufreq_driver_lock, flags);
1854 return -EBUSY; 1854 return -EBUSY;
1855 } 1855 }
1856 cpufreq_driver = driver_data; 1856 cpufreq_driver = driver_data;
1857 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 1857 write_unlock_irqrestore(&cpufreq_driver_lock, flags);
1858 1858
1859 ret = subsys_interface_register(&cpufreq_interface); 1859 ret = subsys_interface_register(&cpufreq_interface);
1860 if (ret) 1860 if (ret)
@@ -1886,9 +1886,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
1886err_if_unreg: 1886err_if_unreg:
1887 subsys_interface_unregister(&cpufreq_interface); 1887 subsys_interface_unregister(&cpufreq_interface);
1888err_null_driver: 1888err_null_driver:
1889 spin_lock_irqsave(&cpufreq_driver_lock, flags); 1889 write_lock_irqsave(&cpufreq_driver_lock, flags);
1890 cpufreq_driver = NULL; 1890 cpufreq_driver = NULL;
1891 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 1891 write_unlock_irqrestore(&cpufreq_driver_lock, flags);
1892 return ret; 1892 return ret;
1893} 1893}
1894EXPORT_SYMBOL_GPL(cpufreq_register_driver); 1894EXPORT_SYMBOL_GPL(cpufreq_register_driver);
@@ -1914,9 +1914,9 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
1914 subsys_interface_unregister(&cpufreq_interface); 1914 subsys_interface_unregister(&cpufreq_interface);
1915 unregister_hotcpu_notifier(&cpufreq_cpu_notifier); 1915 unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
1916 1916
1917 spin_lock_irqsave(&cpufreq_driver_lock, flags); 1917 write_lock_irqsave(&cpufreq_driver_lock, flags);
1918 cpufreq_driver = NULL; 1918 cpufreq_driver = NULL;
1919 spin_unlock_irqrestore(&cpufreq_driver_lock, flags); 1919 write_unlock_irqrestore(&cpufreq_driver_lock, flags);
1920 1920
1921 return 0; 1921 return 0;
1922} 1922}