X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=arch%2Fmips%2Fkernel%2Fcpu-probe.c;h=9fbf8430c8499972ab80047026c803e64306a253;hb=60a6c3777ec607c5b19df9eac35088db4e142a6b;hp=8c2c359a05f413bd089a8eb40cf64781ac8bb89a;hpb=2e84abe742c42f7b063b141db55e5793ce4c502c;p=linux-2.6-omap-h63xx.git diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 8c2c359a05f..9fbf8430c84 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -11,7 +11,6 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include #include #include #include @@ -39,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 @@ -57,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)); } @@ -112,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: @@ -126,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: @@ -460,7 +487,7 @@ static inline unsigned int decode_config0(struct cpuinfo_mips *c) isa = (config0 & MIPS_CONF_AT) >> 13; switch (isa) { case 0: - switch ((config0 >> 10) & 7) { + switch ((config0 & MIPS_CONF_AR) >> 10) { case 0: c->isa_level = MIPS_CPU_ISA_M32R1; break; @@ -472,7 +499,7 @@ static inline unsigned int decode_config0(struct cpuinfo_mips *c) } break; case 2: - switch ((config0 >> 10) & 7) { + switch ((config0 & MIPS_CONF_AR) >> 10) { case 0: c->isa_level = MIPS_CPU_ISA_M64R1; break; @@ -549,7 +576,7 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) return config3 & MIPS_CONF_M; } -static inline void decode_configs(struct cpuinfo_mips *c) +static void __init decode_configs(struct cpuinfo_mips *c) { /* MIPS32 or MIPS64 compliant CPU. */ c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER | @@ -597,8 +624,6 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c) break; case PRID_IMP_25KF: c->cputype = CPU_25KF; - /* Probe for L2 cache */ - c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; break; case PRID_IMP_34K: c->cputype = CPU_34K;