diff options
author | Anton Blanchard <anton@samba.org> | 2010-05-16 16:02:39 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-05-21 03:31:12 -0400 |
commit | b878dc00595440586874952dd85ce9b803360b87 (patch) | |
tree | 172832984c2ca6661cb48899c40b5734cdfa82a3 | |
parent | dd04c63c96425af9b6741f3abf0ad25d6b1c0e8d (diff) |
powerpc: Use smt_snooze_delay=-1 to always busy loop
Right now if we want to busy loop and not give up any time to the hypervisor
we put a very large value into smt_snooze_delay. This is sometimes useful
when running a single partition and you want to avoid any latencies due
to the hypervisor or CPU power state transitions. While this works, it's a bit
ugly - how big a number is enough now we have NO_HZ and can be idle for a very
long time.
The patch below makes smt_snooze_delay signed, and a negative value means loop
forever:
echo -1 > /sys/devices/system/cpu/cpu0/smt_snooze_delay
This change shouldn't affect the existing userspace tools (eg ppc64_cpu), but
I'm cc-ing Nathan just to be sure.
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | arch/powerpc/kernel/sysfs.c | 17 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 10 |
2 files changed, 13 insertions, 14 deletions
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 158fb731e199..c0d8c2006bf4 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
@@ -35,7 +35,7 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices); | |||
35 | #ifdef CONFIG_PPC64 | 35 | #ifdef CONFIG_PPC64 |
36 | 36 | ||
37 | /* Time in microseconds we delay before sleeping in the idle loop */ | 37 | /* Time in microseconds we delay before sleeping in the idle loop */ |
38 | DEFINE_PER_CPU(unsigned long, smt_snooze_delay) = { 100 }; | 38 | DEFINE_PER_CPU(long, smt_snooze_delay) = { 100 }; |
39 | 39 | ||
40 | static ssize_t store_smt_snooze_delay(struct sys_device *dev, | 40 | static ssize_t store_smt_snooze_delay(struct sys_device *dev, |
41 | struct sysdev_attribute *attr, | 41 | struct sysdev_attribute *attr, |
@@ -44,9 +44,9 @@ static ssize_t store_smt_snooze_delay(struct sys_device *dev, | |||
44 | { | 44 | { |
45 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); | 45 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); |
46 | ssize_t ret; | 46 | ssize_t ret; |
47 | unsigned long snooze; | 47 | long snooze; |
48 | 48 | ||
49 | ret = sscanf(buf, "%lu", &snooze); | 49 | ret = sscanf(buf, "%ld", &snooze); |
50 | if (ret != 1) | 50 | if (ret != 1) |
51 | return -EINVAL; | 51 | return -EINVAL; |
52 | 52 | ||
@@ -61,7 +61,7 @@ static ssize_t show_smt_snooze_delay(struct sys_device *dev, | |||
61 | { | 61 | { |
62 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); | 62 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); |
63 | 63 | ||
64 | return sprintf(buf, "%lu\n", per_cpu(smt_snooze_delay, cpu->sysdev.id)); | 64 | return sprintf(buf, "%ld\n", per_cpu(smt_snooze_delay, cpu->sysdev.id)); |
65 | } | 65 | } |
66 | 66 | ||
67 | static SYSDEV_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay, | 67 | static SYSDEV_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay, |
@@ -70,15 +70,14 @@ static SYSDEV_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay, | |||
70 | static int __init setup_smt_snooze_delay(char *str) | 70 | static int __init setup_smt_snooze_delay(char *str) |
71 | { | 71 | { |
72 | unsigned int cpu; | 72 | unsigned int cpu; |
73 | int snooze; | 73 | long snooze; |
74 | 74 | ||
75 | if (!cpu_has_feature(CPU_FTR_SMT)) | 75 | if (!cpu_has_feature(CPU_FTR_SMT)) |
76 | return 1; | 76 | return 1; |
77 | 77 | ||
78 | if (get_option(&str, &snooze)) { | 78 | snooze = simple_strtol(str, NULL, 10); |
79 | for_each_possible_cpu(cpu) | 79 | for_each_possible_cpu(cpu) |
80 | per_cpu(smt_snooze_delay, cpu) = snooze; | 80 | per_cpu(smt_snooze_delay, cpu) = snooze; |
81 | } | ||
82 | 81 | ||
83 | return 1; | 82 | return 1; |
84 | } | 83 | } |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 6710761bf60f..a6d19e3a505e 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -496,13 +496,14 @@ static int __init pSeries_probe(void) | |||
496 | } | 496 | } |
497 | 497 | ||
498 | 498 | ||
499 | DECLARE_PER_CPU(unsigned long, smt_snooze_delay); | 499 | DECLARE_PER_CPU(long, smt_snooze_delay); |
500 | 500 | ||
501 | static void pseries_dedicated_idle_sleep(void) | 501 | static void pseries_dedicated_idle_sleep(void) |
502 | { | 502 | { |
503 | unsigned int cpu = smp_processor_id(); | 503 | unsigned int cpu = smp_processor_id(); |
504 | unsigned long start_snooze; | 504 | unsigned long start_snooze; |
505 | unsigned long in_purr, out_purr; | 505 | unsigned long in_purr, out_purr; |
506 | long snooze = __get_cpu_var(smt_snooze_delay); | ||
506 | 507 | ||
507 | /* | 508 | /* |
508 | * Indicate to the HV that we are idle. Now would be | 509 | * Indicate to the HV that we are idle. Now would be |
@@ -517,13 +518,12 @@ static void pseries_dedicated_idle_sleep(void) | |||
517 | * has been checked recently. If we should poll for a little | 518 | * has been checked recently. If we should poll for a little |
518 | * while, do so. | 519 | * while, do so. |
519 | */ | 520 | */ |
520 | if (__get_cpu_var(smt_snooze_delay)) { | 521 | if (snooze) { |
521 | start_snooze = get_tb() + | 522 | start_snooze = get_tb() + snooze * tb_ticks_per_usec; |
522 | __get_cpu_var(smt_snooze_delay) * tb_ticks_per_usec; | ||
523 | local_irq_enable(); | 523 | local_irq_enable(); |
524 | set_thread_flag(TIF_POLLING_NRFLAG); | 524 | set_thread_flag(TIF_POLLING_NRFLAG); |
525 | 525 | ||
526 | while (get_tb() < start_snooze) { | 526 | while ((snooze < 0) || (get_tb() < start_snooze)) { |
527 | if (need_resched() || cpu_is_offline(cpu)) | 527 | if (need_resched() || cpu_is_offline(cpu)) |
528 | goto out; | 528 | goto out; |
529 | ppc64_runlatch_off(); | 529 | ppc64_runlatch_off(); |