aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/crash.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/crash.c')
-rw-r--r--arch/powerpc/kernel/crash.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index d3f2080d2eee..37658ea417fa 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -219,6 +219,72 @@ void crash_kexec_secondary(struct pt_regs *regs)
219 cpus_in_sr = CPU_MASK_NONE; 219 cpus_in_sr = CPU_MASK_NONE;
220} 220}
221#endif 221#endif
222#ifdef CONFIG_SPU_BASE
223
224#include <asm/spu.h>
225#include <asm/spu_priv1.h>
226
227struct crash_spu_info {
228 struct spu *spu;
229 u32 saved_spu_runcntl_RW;
230 u32 saved_spu_status_R;
231 u32 saved_spu_npc_RW;
232 u64 saved_mfc_sr1_RW;
233 u64 saved_mfc_dar;
234 u64 saved_mfc_dsisr;
235};
236
237#define CRASH_NUM_SPUS 16 /* Enough for current hardware */
238static struct crash_spu_info crash_spu_info[CRASH_NUM_SPUS];
239
240static void crash_kexec_stop_spus(void)
241{
242 struct spu *spu;
243 int i;
244 u64 tmp;
245
246 for (i = 0; i < CRASH_NUM_SPUS; i++) {
247 if (!crash_spu_info[i].spu)
248 continue;
249
250 spu = crash_spu_info[i].spu;
251
252 crash_spu_info[i].saved_spu_runcntl_RW =
253 in_be32(&spu->problem->spu_runcntl_RW);
254 crash_spu_info[i].saved_spu_status_R =
255 in_be32(&spu->problem->spu_status_R);
256 crash_spu_info[i].saved_spu_npc_RW =
257 in_be32(&spu->problem->spu_npc_RW);
258
259 crash_spu_info[i].saved_mfc_dar = spu_mfc_dar_get(spu);
260 crash_spu_info[i].saved_mfc_dsisr = spu_mfc_dsisr_get(spu);
261 tmp = spu_mfc_sr1_get(spu);
262 crash_spu_info[i].saved_mfc_sr1_RW = tmp;
263
264 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
265 spu_mfc_sr1_set(spu, tmp);
266
267 __delay(200);
268 }
269}
270
271void crash_register_spus(struct list_head *list)
272{
273 struct spu *spu;
274
275 list_for_each_entry(spu, list, full_list) {
276 if (WARN_ON(spu->number >= CRASH_NUM_SPUS))
277 continue;
278
279 crash_spu_info[spu->number].spu = spu;
280 }
281}
282
283#else
284static inline void crash_kexec_stop_spus(void)
285{
286}
287#endif /* CONFIG_SPU_BASE */
222 288
223void default_machine_crash_shutdown(struct pt_regs *regs) 289void default_machine_crash_shutdown(struct pt_regs *regs)
224{ 290{
@@ -254,6 +320,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
254 crash_save_cpu(regs, crashing_cpu); 320 crash_save_cpu(regs, crashing_cpu);
255 crash_kexec_prepare_cpus(crashing_cpu); 321 crash_kexec_prepare_cpus(crashing_cpu);
256 cpu_set(crashing_cpu, cpus_in_crash); 322 cpu_set(crashing_cpu, cpus_in_crash);
323 crash_kexec_stop_spus();
257 if (ppc_md.kexec_cpu_down) 324 if (ppc_md.kexec_cpu_down)
258 ppc_md.kexec_cpu_down(1, 0); 325 ppc_md.kexec_cpu_down(1, 0);
259} 326}