diff options
-rw-r--r-- | arch/mips/kernel/cpu-probe.c | 62 |
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 | ||
39 | static void r39xx_wait(void) | 39 | static 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 | */ | ||
45 | static void r4k_wait(void) | 53 | static 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 | */ | ||
67 | static 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; | |||
56 | static void au1k_wait(void) | 81 | static 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: |