Commit 30c91d57 authored by David S. Miller's avatar David S. Miller

[SPARC64]: Use sun4v_cpu_idle() in cpu_idle() on SUN4V.

We have to turn off the "polling nrflag" bit when we sleep
the cpu like this, so that we'll get a cross-cpu interrupt
to wake the processor up from the yield.

We also have to disable PSTATE_IE in %pstate around the yield
call and recheck need_resched() in order to avoid any races.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 689126a4
...@@ -46,62 +46,47 @@ ...@@ -46,62 +46,47 @@
#include <asm/cpudata.h> #include <asm/cpudata.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/unistd.h> #include <asm/unistd.h>
#include <asm/hypervisor.h>
/* #define VERBOSE_SHOWREGS */ /* #define VERBOSE_SHOWREGS */
/* static void sparc64_yield(void)
* Nothing special yet...
*/
void default_idle(void)
{
}
#ifndef CONFIG_SMP
/*
* the idle loop on a Sparc... ;)
*/
void cpu_idle(void)
{ {
/* endless idle loop with no priority at all */ if (tlb_type != hypervisor)
for (;;) { return;
/* If current->work.need_resched is zero we should really
* setup for a system wakup event and execute a shutdown
* instruction.
*
* But this requires writing back the contents of the
* L2 cache etc. so implement this later. -DaveM
*/
while (!need_resched())
barrier();
preempt_enable_no_resched(); clear_thread_flag(TIF_POLLING_NRFLAG);
schedule(); smp_mb__after_clear_bit();
preempt_disable();
check_pgt_cache(); while (!need_resched()) {
unsigned long pstate;
/* Disable interrupts. */
__asm__ __volatile__(
"rdpr %%pstate, %0\n\t"
"andn %0, %1, %0\n\t"
"wrpr %0, %%g0, %%pstate"
: "=&r" (pstate)
: "i" (PSTATE_IE));
if (!need_resched())
sun4v_cpu_yield();
/* Re-enable interrupts. */
__asm__ __volatile__(
"rdpr %%pstate, %0\n\t"
"or %0, %1, %0\n\t"
"wrpr %0, %%g0, %%pstate"
: "=&r" (pstate)
: "i" (PSTATE_IE));
} }
}
#else set_thread_flag(TIF_POLLING_NRFLAG);
}
/* /* The idle loop on sparc64. */
* the idle loop on a UltraMultiPenguin...
*
* TIF_POLLING_NRFLAG is set because we do not sleep the cpu
* inside of the idler task, so an interrupt is not needed
* to get a clean fast response.
*
* XXX Reverify this assumption... -DaveM
*
* Addendum: We do want it to do something for the signal
* delivery case, we detect that by just seeing
* if we are trying to send this to an idler or not.
*/
void cpu_idle(void) void cpu_idle(void)
{ {
cpuinfo_sparc *cpuinfo = &local_cpu_data();
set_thread_flag(TIF_POLLING_NRFLAG); set_thread_flag(TIF_POLLING_NRFLAG);
while(1) { while(1) {
...@@ -109,13 +94,11 @@ void cpu_idle(void) ...@@ -109,13 +94,11 @@ void cpu_idle(void)
preempt_enable_no_resched(); preempt_enable_no_resched();
schedule(); schedule();
preempt_disable(); preempt_disable();
check_pgt_cache();
} }
sparc64_yield();
} }
} }
#endif
extern char reboot_command []; extern char reboot_command [];
extern void (*prom_palette)(int); extern void (*prom_palette)(int);
......
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