aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/crash.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel/crash.c')
-rw-r--r--arch/ia64/kernel/crash.c47
1 files changed, 41 insertions, 6 deletions
diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c
index b2a8b3da8af3..9c851b73f276 100644
--- a/arch/ia64/kernel/crash.c
+++ b/arch/ia64/kernel/crash.c
@@ -23,6 +23,7 @@
23int kdump_status[NR_CPUS]; 23int kdump_status[NR_CPUS];
24static atomic_t kdump_cpu_frozen; 24static atomic_t kdump_cpu_frozen;
25atomic_t kdump_in_progress; 25atomic_t kdump_in_progress;
26static int kdump_freeze_monarch;
26static int kdump_on_init = 1; 27static int kdump_on_init = 1;
27static int kdump_on_fatal_mca = 1; 28static int kdump_on_fatal_mca = 1;
28 29
@@ -108,6 +109,33 @@ machine_crash_shutdown(struct pt_regs *pt)
108 */ 109 */
109 kexec_disable_iosapic(); 110 kexec_disable_iosapic();
110#ifdef CONFIG_SMP 111#ifdef CONFIG_SMP
112 /*
113 * If kdump_on_init is set and an INIT is asserted here, kdump will
114 * be started again via INIT monarch.
115 */
116 local_irq_disable();
117 ia64_set_psr_mc(); /* mask MCA/INIT */
118 if (atomic_inc_return(&kdump_in_progress) != 1)
119 unw_init_running(kdump_cpu_freeze, NULL);
120
121 /*
122 * Now this cpu is ready for kdump.
123 * Stop all others by IPI or INIT. They could receive INIT from
124 * outside and might be INIT monarch, but only thing they have to
125 * do is falling into kdump_cpu_freeze().
126 *
127 * If an INIT is asserted here:
128 * - All receivers might be slaves, since some of cpus could already
129 * be frozen and INIT might be masked on monarch. In this case,
130 * all slaves will park in while (monarch_cpu == -1) loop before
131 * DIE_INIT_SLAVE_ENTER that for waiting monarch enters.
132 * => TBD: freeze all slaves
133 * - One might be a monarch, but INIT rendezvous will fail since
134 * at least this cpu already have INIT masked so it never join
135 * to the rendezvous. In this case, all slaves and monarch will
136 * be frozen after timeout of the INIT rendezvous.
137 * => TBD: freeze them without waiting timeout
138 */
111 kdump_smp_send_stop(); 139 kdump_smp_send_stop();
112 /* not all cpu response to IPI, send INIT to freeze them */ 140 /* not all cpu response to IPI, send INIT to freeze them */
113 if (kdump_wait_cpu_freeze() && kdump_on_init) { 141 if (kdump_wait_cpu_freeze() && kdump_on_init) {
@@ -177,13 +205,18 @@ kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data)
177 switch (val) { 205 switch (val) {
178 case DIE_INIT_MONARCH_PROCESS: 206 case DIE_INIT_MONARCH_PROCESS:
179 if (kdump_on_init) { 207 if (kdump_on_init) {
180 atomic_set(&kdump_in_progress, 1); 208 if (atomic_inc_return(&kdump_in_progress) != 1)
209 kdump_freeze_monarch = 1;
181 *(nd->monarch_cpu) = -1; 210 *(nd->monarch_cpu) = -1;
182 } 211 }
183 break; 212 break;
184 case DIE_INIT_MONARCH_LEAVE: 213 case DIE_INIT_MONARCH_LEAVE:
185 if (kdump_on_init) 214 if (kdump_on_init) {
186 machine_kdump_on_init(); 215 if (kdump_freeze_monarch)
216 unw_init_running(kdump_cpu_freeze, NULL);
217 else
218 machine_kdump_on_init();
219 }
187 break; 220 break;
188 case DIE_INIT_SLAVE_LEAVE: 221 case DIE_INIT_SLAVE_LEAVE:
189 if (atomic_read(&kdump_in_progress)) 222 if (atomic_read(&kdump_in_progress))
@@ -196,9 +229,11 @@ kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data)
196 case DIE_MCA_MONARCH_LEAVE: 229 case DIE_MCA_MONARCH_LEAVE:
197 /* *(nd->data) indicate if MCA is recoverable */ 230 /* *(nd->data) indicate if MCA is recoverable */
198 if (kdump_on_fatal_mca && !(*(nd->data))) { 231 if (kdump_on_fatal_mca && !(*(nd->data))) {
199 atomic_set(&kdump_in_progress, 1); 232 if (atomic_inc_return(&kdump_in_progress) == 1) {
200 *(nd->monarch_cpu) = -1; 233 *(nd->monarch_cpu) = -1;
201 machine_kdump_on_init(); 234 machine_kdump_on_init();
235 }
236 /* We got fatal MCA while kdump!? No way!! */
202 } 237 }
203 break; 238 break;
204 } 239 }