aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/cpu-probe.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/cpu-probe.c')
-rw-r--r--arch/mips/kernel/cpu-probe.c62
1 files changed, 45 insertions, 17 deletions
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index aa2caa67299a..9fbf8430c849 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -38,15 +38,40 @@ static void r3081_wait(void)
38 38
39static void r39xx_wait(void) 39static void r39xx_wait(void)
40{ 40{
41 unsigned long cfg = read_c0_conf(); 41 local_irq_disable();
42 write_c0_conf(cfg | TX39_CONF_HALT); 42 if (!need_resched())
43 write_c0_conf(read_c0_conf() | TX39_CONF_HALT);
44 local_irq_enable();
43} 45}
44 46
47/*
48 * There is a race when WAIT instruction executed with interrupt
49 * enabled.
50 * But it is implementation-dependent wheter the pipelie restarts when
51 * a non-enabled interrupt is requested.
52 */
45static void r4k_wait(void) 53static void r4k_wait(void)
46{ 54{
47 __asm__(".set\tmips3\n\t" 55 __asm__(" .set mips3 \n"
48 "wait\n\t" 56 " wait \n"
49 ".set\tmips0"); 57 " .set mips0 \n");
58}
59
60/*
61 * This variant is preferable as it allows testing need_resched and going to
62 * sleep depending on the outcome atomically. Unfortunately the "It is
63 * implementation-dependent whether the pipeline restarts when a non-enabled
64 * interrupt is requested" restriction in the MIPS32/MIPS64 architecture makes
65 * using this version a gamble.
66 */
67static void r4k_wait_irqoff(void)
68{
69 local_irq_disable();
70 if (!need_resched())
71 __asm__(" .set mips3 \n"
72 " wait \n"
73 " .set mips0 \n");
74 local_irq_enable();
50} 75}
51 76
52/* The Au1xxx wait is available only if using 32khz counter or 77/* The Au1xxx wait is available only if using 32khz counter or
@@ -56,17 +81,17 @@ int allow_au1k_wait;
56static void au1k_wait(void) 81static void au1k_wait(void)
57{ 82{
58 /* using the wait instruction makes CP0 counter unusable */ 83 /* using the wait instruction makes CP0 counter unusable */
59 __asm__(".set mips3\n\t" 84 __asm__(" .set mips3 \n"
60 "cache 0x14, 0(%0)\n\t" 85 " cache 0x14, 0(%0) \n"
61 "cache 0x14, 32(%0)\n\t" 86 " cache 0x14, 32(%0) \n"
62 "sync\n\t" 87 " sync \n"
63 "nop\n\t" 88 " nop \n"
64 "wait\n\t" 89 " wait \n"
65 "nop\n\t" 90 " nop \n"
66 "nop\n\t" 91 " nop \n"
67 "nop\n\t" 92 " nop \n"
68 "nop\n\t" 93 " nop \n"
69 ".set mips0\n\t" 94 " .set mips0 \n"
70 : : "r" (au1k_wait)); 95 : : "r" (au1k_wait));
71} 96}
72 97
@@ -111,7 +136,6 @@ static inline void check_wait(void)
111 case CPU_NEVADA: 136 case CPU_NEVADA:
112 case CPU_RM7000: 137 case CPU_RM7000:
113 case CPU_RM9000: 138 case CPU_RM9000:
114 case CPU_TX49XX:
115 case CPU_4KC: 139 case CPU_4KC:
116 case CPU_4KEC: 140 case CPU_4KEC:
117 case CPU_4KSC: 141 case CPU_4KSC:
@@ -125,6 +149,10 @@ static inline void check_wait(void)
125 cpu_wait = r4k_wait; 149 cpu_wait = r4k_wait;
126 printk(" available.\n"); 150 printk(" available.\n");
127 break; 151 break;
152 case CPU_TX49XX:
153 cpu_wait = r4k_wait_irqoff;
154 printk(" available.\n");
155 break;
128 case CPU_AU1000: 156 case CPU_AU1000:
129 case CPU_AU1100: 157 case CPU_AU1100:
130 case CPU_AU1500: 158 case CPU_AU1500: