aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2010-05-16 16:02:39 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-05-21 03:31:12 -0400
commitb878dc00595440586874952dd85ce9b803360b87 (patch)
tree172832984c2ca6661cb48899c40b5734cdfa82a3
parentdd04c63c96425af9b6741f3abf0ad25d6b1c0e8d (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.c17
-rw-r--r--arch/powerpc/platforms/pseries/setup.c10
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 */
38DEFINE_PER_CPU(unsigned long, smt_snooze_delay) = { 100 }; 38DEFINE_PER_CPU(long, smt_snooze_delay) = { 100 };
39 39
40static ssize_t store_smt_snooze_delay(struct sys_device *dev, 40static 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
67static SYSDEV_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay, 67static 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,
70static int __init setup_smt_snooze_delay(char *str) 70static 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
499DECLARE_PER_CPU(unsigned long, smt_snooze_delay); 499DECLARE_PER_CPU(long, smt_snooze_delay);
500 500
501static void pseries_dedicated_idle_sleep(void) 501static 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();