diff options
author | Andrew Morton <akpm@linux-foundation.org> | 2009-04-13 13:27:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-13 14:09:46 -0400 |
commit | 01599fca6758d2cd133e78f87426fc851c9ea725 (patch) | |
tree | 26a3f1d69c955de2c5388e5855dfe4ff3ff8687b /arch | |
parent | 8371f87c9994d9942af5984309835aeb948ba579 (diff) |
cpufreq: use smp_call_function_[single|many]() in acpi-cpufreq.c
Atttempting to rid us of the problematic work_on_cpu(). Just use
smp_call_fuction_single() here.
This repairs a 10% sysbench(oltp)+mysql regression which Mike reported,
due to
commit 6b44003e5ca66a3fffeb5bc90f40ada2c4340896
Author: Andrew Morton <akpm@linux-foundation.org>
Date: Thu Apr 9 09:50:37 2009 -0600
work_on_cpu(): rewrite it to create a kernel thread on demand
It seems that the kernel calls these acpi-cpufreq functions at a quite
high frequency.
Valdis Kletnieks also reports that this causes 70-90 forks per second on
his hardware.
Cc: Valdis.Kletnieks@vt.edu
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Cc: Len Brown <len.brown@intel.com>
Cc: Zhao Yakui <yakui.zhao@intel.com>
Acked-by: Dave Jones <davej@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Mike Galbraith <efault@gmx.de>
Cc: "Zhang, Yanmin" <yanmin_zhang@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Acked-by: Ingo Molnar <mingo@elte.hu>
[ Made it use smp_call_function_many() instead of looping over cpu's
with smp_call_function_single() - Linus ]
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 24 |
1 files changed, 9 insertions, 15 deletions
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 9d3af380c6bd..3e3cd3db7a0c 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | |||
@@ -153,7 +153,8 @@ struct drv_cmd { | |||
153 | u32 val; | 153 | u32 val; |
154 | }; | 154 | }; |
155 | 155 | ||
156 | static long do_drv_read(void *_cmd) | 156 | /* Called via smp_call_function_single(), on the target CPU */ |
157 | static void do_drv_read(void *_cmd) | ||
157 | { | 158 | { |
158 | struct drv_cmd *cmd = _cmd; | 159 | struct drv_cmd *cmd = _cmd; |
159 | u32 h; | 160 | u32 h; |
@@ -170,10 +171,10 @@ static long do_drv_read(void *_cmd) | |||
170 | default: | 171 | default: |
171 | break; | 172 | break; |
172 | } | 173 | } |
173 | return 0; | ||
174 | } | 174 | } |
175 | 175 | ||
176 | static long do_drv_write(void *_cmd) | 176 | /* Called via smp_call_function_many(), on the target CPUs */ |
177 | static void do_drv_write(void *_cmd) | ||
177 | { | 178 | { |
178 | struct drv_cmd *cmd = _cmd; | 179 | struct drv_cmd *cmd = _cmd; |
179 | u32 lo, hi; | 180 | u32 lo, hi; |
@@ -192,23 +193,18 @@ static long do_drv_write(void *_cmd) | |||
192 | default: | 193 | default: |
193 | break; | 194 | break; |
194 | } | 195 | } |
195 | return 0; | ||
196 | } | 196 | } |
197 | 197 | ||
198 | static void drv_read(struct drv_cmd *cmd) | 198 | static void drv_read(struct drv_cmd *cmd) |
199 | { | 199 | { |
200 | cmd->val = 0; | 200 | cmd->val = 0; |
201 | 201 | ||
202 | work_on_cpu(cpumask_any(cmd->mask), do_drv_read, cmd); | 202 | smp_call_function_single(cpumask_any(cmd->mask), do_drv_read, cmd, 1); |
203 | } | 203 | } |
204 | 204 | ||
205 | static void drv_write(struct drv_cmd *cmd) | 205 | static void drv_write(struct drv_cmd *cmd) |
206 | { | 206 | { |
207 | unsigned int i; | 207 | smp_call_function_many(cmd->mask, do_drv_write, cmd, 1); |
208 | |||
209 | for_each_cpu(i, cmd->mask) { | ||
210 | work_on_cpu(i, do_drv_write, cmd); | ||
211 | } | ||
212 | } | 208 | } |
213 | 209 | ||
214 | static u32 get_cur_val(const struct cpumask *mask) | 210 | static u32 get_cur_val(const struct cpumask *mask) |
@@ -252,15 +248,13 @@ struct perf_pair { | |||
252 | } aperf, mperf; | 248 | } aperf, mperf; |
253 | }; | 249 | }; |
254 | 250 | ||
255 | 251 | /* Called via smp_call_function_single(), on the target CPU */ | |
256 | static long read_measured_perf_ctrs(void *_cur) | 252 | static void read_measured_perf_ctrs(void *_cur) |
257 | { | 253 | { |
258 | struct perf_pair *cur = _cur; | 254 | struct perf_pair *cur = _cur; |
259 | 255 | ||
260 | rdmsr(MSR_IA32_APERF, cur->aperf.split.lo, cur->aperf.split.hi); | 256 | rdmsr(MSR_IA32_APERF, cur->aperf.split.lo, cur->aperf.split.hi); |
261 | rdmsr(MSR_IA32_MPERF, cur->mperf.split.lo, cur->mperf.split.hi); | 257 | rdmsr(MSR_IA32_MPERF, cur->mperf.split.lo, cur->mperf.split.hi); |
262 | |||
263 | return 0; | ||
264 | } | 258 | } |
265 | 259 | ||
266 | /* | 260 | /* |
@@ -283,7 +277,7 @@ static unsigned int get_measured_perf(struct cpufreq_policy *policy, | |||
283 | unsigned int perf_percent; | 277 | unsigned int perf_percent; |
284 | unsigned int retval; | 278 | unsigned int retval; |
285 | 279 | ||
286 | if (!work_on_cpu(cpu, read_measured_perf_ctrs, &readin)) | 280 | if (smp_call_function_single(cpu, read_measured_perf_ctrs, &cur, 1)) |
287 | return 0; | 281 | return 0; |
288 | 282 | ||
289 | cur.aperf.whole = readin.aperf.whole - | 283 | cur.aperf.whole = readin.aperf.whole - |