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 - |
