diff options
Diffstat (limited to 'arch/powerpc/kernel/crash.c')
-rw-r--r-- | arch/powerpc/kernel/crash.c | 67 |
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 | |||
227 | struct 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 */ | ||
238 | static struct crash_spu_info crash_spu_info[CRASH_NUM_SPUS]; | ||
239 | |||
240 | static 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 | |||
271 | void 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 | ||
284 | static inline void crash_kexec_stop_spus(void) | ||
285 | { | ||
286 | } | ||
287 | #endif /* CONFIG_SPU_BASE */ | ||
222 | 288 | ||
223 | void default_machine_crash_shutdown(struct pt_regs *regs) | 289 | void 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 | } |