From 090fc68bdff6186d48a99db746da220f9ff757d8 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Thu, 8 Jun 2006 01:09:01 +0900 Subject: [PATCH] --- yaml --- r: 36023 b: refs/heads/master c: 60a6c3777ec607c5b19df9eac35088db4e142a6b h: refs/heads/master i: 36021: d086bec223e0206ea2bae9520bf9b7443bb9804f 36019: 82f1b746cad8ec47a89428733a9955270288f82a 36015: aa0f79964a0e0caefc43a5002059eda6f1e642d2 v: v3 --- [refs] | 2 +- trunk/arch/mips/kernel/cpu-probe.c | 62 ++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/[refs] b/[refs] index 53ecbf32a844..47d08b0896e2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 7fdeb048141b363a23b8cf6f6a226d74aca4d724 +refs/heads/master: 60a6c3777ec607c5b19df9eac35088db4e142a6b diff --git a/trunk/arch/mips/kernel/cpu-probe.c b/trunk/arch/mips/kernel/cpu-probe.c index aa2caa67299a..9fbf8430c849 100644 --- a/trunk/arch/mips/kernel/cpu-probe.c +++ b/trunk/arch/mips/kernel/cpu-probe.c @@ -38,15 +38,40 @@ static void r3081_wait(void) static void r39xx_wait(void) { - unsigned long cfg = read_c0_conf(); - write_c0_conf(cfg | TX39_CONF_HALT); + local_irq_disable(); + if (!need_resched()) + write_c0_conf(read_c0_conf() | TX39_CONF_HALT); + local_irq_enable(); } +/* + * There is a race when WAIT instruction executed with interrupt + * enabled. + * But it is implementation-dependent wheter the pipelie restarts when + * a non-enabled interrupt is requested. + */ static void r4k_wait(void) { - __asm__(".set\tmips3\n\t" - "wait\n\t" - ".set\tmips0"); + __asm__(" .set mips3 \n" + " wait \n" + " .set mips0 \n"); +} + +/* + * This variant is preferable as it allows testing need_resched and going to + * sleep depending on the outcome atomically. Unfortunately the "It is + * implementation-dependent whether the pipeline restarts when a non-enabled + * interrupt is requested" restriction in the MIPS32/MIPS64 architecture makes + * using this version a gamble. + */ +static void r4k_wait_irqoff(void) +{ + local_irq_disable(); + if (!need_resched()) + __asm__(" .set mips3 \n" + " wait \n" + " .set mips0 \n"); + local_irq_enable(); } /* The Au1xxx wait is available only if using 32khz counter or @@ -56,17 +81,17 @@ int allow_au1k_wait; static void au1k_wait(void) { /* using the wait instruction makes CP0 counter unusable */ - __asm__(".set mips3\n\t" - "cache 0x14, 0(%0)\n\t" - "cache 0x14, 32(%0)\n\t" - "sync\n\t" - "nop\n\t" - "wait\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - ".set mips0\n\t" + __asm__(" .set mips3 \n" + " cache 0x14, 0(%0) \n" + " cache 0x14, 32(%0) \n" + " sync \n" + " nop \n" + " wait \n" + " nop \n" + " nop \n" + " nop \n" + " nop \n" + " .set mips0 \n" : : "r" (au1k_wait)); } @@ -111,7 +136,6 @@ static inline void check_wait(void) case CPU_NEVADA: case CPU_RM7000: case CPU_RM9000: - case CPU_TX49XX: case CPU_4KC: case CPU_4KEC: case CPU_4KSC: @@ -125,6 +149,10 @@ static inline void check_wait(void) cpu_wait = r4k_wait; printk(" available.\n"); break; + case CPU_TX49XX: + cpu_wait = r4k_wait_irqoff; + printk(" available.\n"); + break; case CPU_AU1000: case CPU_AU1100: case CPU_AU1500: