diff options
author | Nathan Zimmer <nzimmer@sgi.com> | 2013-02-22 11:24:34 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-03-31 19:11:34 -0400 |
commit | 0d1857a1b987ef874aeb4b99c9c385fa5645bf61 (patch) | |
tree | b26ccf9c501ae14055b8c5a5e5a1e40a8b164f08 | |
parent | 07961ac7c0ee8b546658717034fe692fd12eefa9 (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.c | 52 |
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 */ |
46 | static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor); | 46 | static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor); |
47 | #endif | 47 | #endif |
48 | static DEFINE_SPINLOCK(cpufreq_driver_lock); | 48 | static 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 | ||
161 | err_out_put_module: | 161 | err_out_put_module: |
162 | module_put(cpufreq_driver->owner); | 162 | module_put(cpufreq_driver->owner); |
163 | err_out_unlock: | 163 | err_out_unlock: |
164 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); | 164 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); |
165 | err_out: | 165 | err_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 | ||
954 | err_out_unregister: | 954 | err_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) | |||
1886 | err_if_unreg: | 1886 | err_if_unreg: |
1887 | subsys_interface_unregister(&cpufreq_interface); | 1887 | subsys_interface_unregister(&cpufreq_interface); |
1888 | err_null_driver: | 1888 | err_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 | } |
1894 | EXPORT_SYMBOL_GPL(cpufreq_register_driver); | 1894 | EXPORT_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 | } |