aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mn10300/kernel/mn10300-watchdog.c
diff options
context:
space:
mode:
authorAkira Takeuchi <takeuchi.akr@jp.panasonic.com>2010-10-27 12:28:55 -0400
committerDavid Howells <dhowells@redhat.com>2010-10-27 12:28:55 -0400
commit368dd5acd154b09c043cc4392a74da01599b37d5 (patch)
treedd94ae3d044f6e774dec2437613515bd6b46dacb /arch/mn10300/kernel/mn10300-watchdog.c
parent04157a6e7df99fd5ed64955233d6e00ab6613614 (diff)
MN10300: And Panasonic AM34 subarch and implement SMP
Implement the Panasonic MN10300 AM34 CPU subarch and implement SMP support for MN10300. Also implement support for the MN2WS0060 processor and the ASB2364 evaluation board which are AM34 based. Signed-off-by: Akira Takeuchi <takeuchi.akr@jp.panasonic.com> Signed-off-by: Kiyoshi Owada <owada.kiyoshi@jp.panasonic.com> Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'arch/mn10300/kernel/mn10300-watchdog.c')
-rw-r--r--arch/mn10300/kernel/mn10300-watchdog.c100
1 files changed, 61 insertions, 39 deletions
diff --git a/arch/mn10300/kernel/mn10300-watchdog.c b/arch/mn10300/kernel/mn10300-watchdog.c
index f362d9d138f1..965dd61656c3 100644
--- a/arch/mn10300/kernel/mn10300-watchdog.c
+++ b/arch/mn10300/kernel/mn10300-watchdog.c
@@ -30,7 +30,7 @@
30static DEFINE_SPINLOCK(watchdog_print_lock); 30static DEFINE_SPINLOCK(watchdog_print_lock);
31static unsigned int watchdog; 31static unsigned int watchdog;
32static unsigned int watchdog_hz = 1; 32static unsigned int watchdog_hz = 1;
33unsigned int watchdog_alert_counter; 33unsigned int watchdog_alert_counter[NR_CPUS];
34 34
35EXPORT_SYMBOL(touch_nmi_watchdog); 35EXPORT_SYMBOL(touch_nmi_watchdog);
36 36
@@ -39,9 +39,6 @@ EXPORT_SYMBOL(touch_nmi_watchdog);
39 * is to check its timer makes IRQ counts. If they are not 39 * is to check its timer makes IRQ counts. If they are not
40 * changing then that CPU has some problem. 40 * changing then that CPU has some problem.
41 * 41 *
42 * as these watchdog NMI IRQs are generated on every CPU, we only
43 * have to check the current processor.
44 *
45 * since NMIs dont listen to _any_ locks, we have to be extremely 42 * since NMIs dont listen to _any_ locks, we have to be extremely
46 * careful not to rely on unsafe variables. The printk might lock 43 * careful not to rely on unsafe variables. The printk might lock
47 * up though, so we have to break up any console locks first ... 44 * up though, so we have to break up any console locks first ...
@@ -69,8 +66,8 @@ int __init check_watchdog(void)
69 66
70 printk(KERN_INFO "OK.\n"); 67 printk(KERN_INFO "OK.\n");
71 68
72 /* now that we know it works we can reduce NMI frequency to 69 /* now that we know it works we can reduce NMI frequency to something
73 * something more reasonable; makes a difference in some configs 70 * more reasonable; makes a difference in some configs
74 */ 71 */
75 watchdog_hz = 1; 72 watchdog_hz = 1;
76 73
@@ -121,15 +118,22 @@ void __init watchdog_go(void)
121 } 118 }
122} 119}
123 120
121#ifdef CONFIG_SMP
122static void watchdog_dump_register(void *dummy)
123{
124 printk(KERN_ERR "--- Register Dump (CPU%d) ---\n", CPUID);
125 show_registers(__frame);
126}
127#endif
128
124asmlinkage 129asmlinkage
125void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep) 130void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep)
126{ 131{
127
128 /* 132 /*
129 * Since current-> is always on the stack, and we always switch 133 * Since current-> is always on the stack, and we always switch
130 * the stack NMI-atomically, it's safe to use smp_processor_id(). 134 * the stack NMI-atomically, it's safe to use smp_processor_id().
131 */ 135 */
132 int sum, cpu = smp_processor_id(); 136 int sum, cpu;
133 int irq = NMIIRQ; 137 int irq = NMIIRQ;
134 u8 wdt, tmp; 138 u8 wdt, tmp;
135 139
@@ -138,43 +142,61 @@ void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep)
138 tmp = WDCTR; 142 tmp = WDCTR;
139 NMICR = NMICR_WDIF; 143 NMICR = NMICR_WDIF;
140 144
141 nmi_count(cpu)++; 145 nmi_count(smp_processor_id())++;
142 kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); 146 kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
143 sum = irq_stat[cpu].__irq_count; 147
144 148 for_each_online_cpu(cpu) {
145 if (last_irq_sums[cpu] == sum) { 149
146 /* 150 sum = irq_stat[cpu].__irq_count;
147 * Ayiee, looks like this CPU is stuck ... 151
148 * wait a few IRQs (5 seconds) before doing the oops ... 152 if ((last_irq_sums[cpu] == sum)
149 */ 153#if defined(CONFIG_GDBSTUB) && defined(CONFIG_SMP)
150 watchdog_alert_counter++; 154 && !(CHK_GDBSTUB_BUSY()
151 if (watchdog_alert_counter == 5 * watchdog_hz) { 155 || atomic_read(&cpu_doing_single_step))
152 spin_lock(&watchdog_print_lock); 156#endif
157 ) {
153 /* 158 /*
154 * We are in trouble anyway, lets at least try 159 * Ayiee, looks like this CPU is stuck ...
155 * to get a message out. 160 * wait a few IRQs (5 seconds) before doing the oops ...
156 */ 161 */
157 bust_spinlocks(1); 162 watchdog_alert_counter[cpu]++;
158 printk(KERN_ERR 163 if (watchdog_alert_counter[cpu] == 5 * watchdog_hz) {
159 "NMI Watchdog detected LOCKUP on CPU%d," 164 spin_lock(&watchdog_print_lock);
160 " pc %08lx, registers:\n", 165 /*
161 cpu, regs->pc); 166 * We are in trouble anyway, lets at least try
162 show_registers(regs); 167 * to get a message out.
163 printk("console shuts up ...\n"); 168 */
164 console_silent(); 169 bust_spinlocks(1);
165 spin_unlock(&watchdog_print_lock); 170 printk(KERN_ERR
166 bust_spinlocks(0); 171 "NMI Watchdog detected LOCKUP on CPU%d,"
172 " pc %08lx, registers:\n",
173 cpu, regs->pc);
174#ifdef CONFIG_SMP
175 printk(KERN_ERR
176 "--- Register Dump (CPU%d) ---\n",
177 CPUID);
178#endif
179 show_registers(regs);
180#ifdef CONFIG_SMP
181 smp_nmi_call_function(watchdog_dump_register,
182 NULL, 1);
183#endif
184 printk(KERN_NOTICE "console shuts up ...\n");
185 console_silent();
186 spin_unlock(&watchdog_print_lock);
187 bust_spinlocks(0);
167#ifdef CONFIG_GDBSTUB 188#ifdef CONFIG_GDBSTUB
168 if (gdbstub_busy) 189 if (CHK_GDBSTUB_BUSY_AND_ACTIVE())
169 gdbstub_exception(regs, excep); 190 gdbstub_exception(regs, excep);
170 else 191 else
171 gdbstub_intercept(regs, excep); 192 gdbstub_intercept(regs, excep);
172#endif 193#endif
173 do_exit(SIGSEGV); 194 do_exit(SIGSEGV);
195 }
196 } else {
197 last_irq_sums[cpu] = sum;
198 watchdog_alert_counter[cpu] = 0;
174 } 199 }
175 } else {
176 last_irq_sums[cpu] = sum;
177 watchdog_alert_counter = 0;
178 } 200 }
179 201
180 WDCTR = wdt | WDCTR_WDRST; 202 WDCTR = wdt | WDCTR_WDRST;