aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2017-08-09 08:41:25 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2017-08-09 09:45:32 -0400
commit87607a30be92f1ecee3af6f4a5779e179db98118 (patch)
tree4892faf3ec13e7d62d2ad3e0bca788a795aa69e2
parent8e23692175ad465628b8c86c1acc154fecad97be (diff)
powerpc/watchdog: Fix marking of stuck CPUs
When the SMP detector finds other CPUs stuck, it iterates over them and marks them as stuck. This pulls them out of the pending mask and allows the detector to continue with remaining good CPUs (if nmi_watchdog=panic is not enabled). The code to dothat was buggy because when setting a CPU stuck, if the pending mask became empty, it resets it to keep the watchdog running. However the iterator will continue to run over the new pending mask and mark remaining good CPUs sas stuck. Fix this by doing it with cpumask bitwise operations. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/kernel/watchdog.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/watchdog.c b/arch/powerpc/kernel/watchdog.c
index 7d16dafa1bb6..12e90ae712fe 100644
--- a/arch/powerpc/kernel/watchdog.c
+++ b/arch/powerpc/kernel/watchdog.c
@@ -101,10 +101,10 @@ static void wd_lockup_ipi(struct pt_regs *regs)
101 nmi_panic(regs, "Hard LOCKUP"); 101 nmi_panic(regs, "Hard LOCKUP");
102} 102}
103 103
104static void set_cpu_stuck(int cpu, u64 tb) 104static void set_cpumask_stuck(const struct cpumask *cpumask, u64 tb)
105{ 105{
106 cpumask_set_cpu(cpu, &wd_smp_cpus_stuck); 106 cpumask_or(&wd_smp_cpus_stuck, &wd_smp_cpus_stuck, cpumask);
107 cpumask_clear_cpu(cpu, &wd_smp_cpus_pending); 107 cpumask_andnot(&wd_smp_cpus_pending, &wd_smp_cpus_pending, cpumask);
108 if (cpumask_empty(&wd_smp_cpus_pending)) { 108 if (cpumask_empty(&wd_smp_cpus_pending)) {
109 wd_smp_last_reset_tb = tb; 109 wd_smp_last_reset_tb = tb;
110 cpumask_andnot(&wd_smp_cpus_pending, 110 cpumask_andnot(&wd_smp_cpus_pending,
@@ -112,6 +112,10 @@ static void set_cpu_stuck(int cpu, u64 tb)
112 &wd_smp_cpus_stuck); 112 &wd_smp_cpus_stuck);
113 } 113 }
114} 114}
115static void set_cpu_stuck(int cpu, u64 tb)
116{
117 set_cpumask_stuck(cpumask_of(cpu), tb);
118}
115 119
116static void watchdog_smp_panic(int cpu, u64 tb) 120static void watchdog_smp_panic(int cpu, u64 tb)
117{ 121{
@@ -140,9 +144,8 @@ static void watchdog_smp_panic(int cpu, u64 tb)
140 } 144 }
141 smp_flush_nmi_ipi(1000000); 145 smp_flush_nmi_ipi(1000000);
142 146
143 /* Take the stuck CPU out of the watch group */ 147 /* Take the stuck CPUs out of the watch group */
144 for_each_cpu(c, &wd_smp_cpus_pending) 148 set_cpumask_stuck(&wd_smp_cpus_pending, tb);
145 set_cpu_stuck(c, tb);
146 149
147 wd_smp_unlock(&flags); 150 wd_smp_unlock(&flags);
148 151