diff options
Diffstat (limited to 'arch/ia64/kernel/crash.c')
-rw-r--r-- | arch/ia64/kernel/crash.c | 47 |
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 @@ | |||
23 | int kdump_status[NR_CPUS]; | 23 | int kdump_status[NR_CPUS]; |
24 | static atomic_t kdump_cpu_frozen; | 24 | static atomic_t kdump_cpu_frozen; |
25 | atomic_t kdump_in_progress; | 25 | atomic_t kdump_in_progress; |
26 | static int kdump_freeze_monarch; | ||
26 | static int kdump_on_init = 1; | 27 | static int kdump_on_init = 1; |
27 | static int kdump_on_fatal_mca = 1; | 28 | static 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 | } |