Commit 0ddd3e7d authored by Anton Blanchard's avatar Anton Blanchard Committed by Paul Mackerras

[POWERPC] Always call cede in pseries dedicated idle loop

The smt_snooze_delay logic changed a bit when the idle loops were
consolidated. A value of 0 used to mean we always polled, now it means
we always sleep. Instead of restoring the old behaviour, lets put a
reasonable default in smt_snooze_delay. This means we spin for a bit
(in case an external interrupt comes in) and then sleep.

Also the pseries dedicated idle loop currently does not cede both
threads in an SMT pair. The hypervisor wants us to call in so it can
power manage, so lets do that.
Signed-off-by: default avatarAnton Blanchard <anton@samba.org>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent e1251465
...@@ -25,8 +25,8 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices); ...@@ -25,8 +25,8 @@ static DEFINE_PER_CPU(struct cpu, cpu_devices);
/* SMT stuff */ /* SMT stuff */
#ifdef CONFIG_PPC_MULTIPLATFORM #ifdef CONFIG_PPC_MULTIPLATFORM
/* default to snooze disabled */ /* Time in microseconds we delay before sleeping in the idle loop */
DEFINE_PER_CPU(unsigned long, smt_snooze_delay); DEFINE_PER_CPU(unsigned long, smt_snooze_delay) = { 100 };
static ssize_t store_smt_snooze_delay(struct sys_device *dev, const char *buf, static ssize_t store_smt_snooze_delay(struct sys_device *dev, const char *buf,
size_t count) size_t count)
......
...@@ -477,7 +477,6 @@ static void pseries_dedicated_idle_sleep(void) ...@@ -477,7 +477,6 @@ static void pseries_dedicated_idle_sleep(void)
{ {
unsigned int cpu = smp_processor_id(); unsigned int cpu = smp_processor_id();
unsigned long start_snooze; unsigned long start_snooze;
unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
/* /*
* Indicate to the HV that we are idle. Now would be * Indicate to the HV that we are idle. Now would be
...@@ -490,9 +489,9 @@ static void pseries_dedicated_idle_sleep(void) ...@@ -490,9 +489,9 @@ static void pseries_dedicated_idle_sleep(void)
* has been checked recently. If we should poll for a little * has been checked recently. If we should poll for a little
* while, do so. * while, do so.
*/ */
if (*smt_snooze_delay) { if (__get_cpu_var(smt_snooze_delay)) {
start_snooze = get_tb() + start_snooze = get_tb() +
*smt_snooze_delay * tb_ticks_per_usec; __get_cpu_var(smt_snooze_delay) * tb_ticks_per_usec;
local_irq_enable(); local_irq_enable();
set_thread_flag(TIF_POLLING_NRFLAG); set_thread_flag(TIF_POLLING_NRFLAG);
...@@ -512,24 +511,7 @@ static void pseries_dedicated_idle_sleep(void) ...@@ -512,24 +511,7 @@ static void pseries_dedicated_idle_sleep(void)
goto out; goto out;
} }
/* cede_processor();
* If not SMT, cede processor. If CPU is running SMT
* cede if the other thread is not idle, so that it can
* go single-threaded. If the other thread is idle,
* we ask the hypervisor if it has pending work it
* wants to do and cede if it does. Otherwise we keep
* polling in order to reduce interrupt latency.
*
* Doing the cede when the other thread is active will
* result in this thread going dormant, meaning the other
* thread gets to run in single-threaded (ST) mode, which
* is slightly faster than SMT mode with this thread at
* very low priority. The cede enables interrupts, which
* doesn't matter here.
*/
if (!cpu_has_feature(CPU_FTR_SMT) || !lppaca[cpu ^ 1].idle
|| poll_pending() == H_PENDING)
cede_processor();
out: out:
HMT_medium(); HMT_medium();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment