aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/crash.c67
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c2
-rw-r--r--include/asm-powerpc/spu.h8
3 files changed, 76 insertions, 1 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}
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index 96a8f609690c..c563066e640d 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -676,7 +676,7 @@ static int __init init_spu_base(void)
676 } 676 }
677 677
678 xmon_register_spus(&spu_full_list); 678 xmon_register_spus(&spu_full_list);
679 679 crash_register_spus(&spu_full_list);
680 spu_add_sysdev_attr(&attr_stat); 680 spu_add_sysdev_attr(&attr_stat);
681 681
682 return 0; 682 return 0;
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index eedc828cef2d..42d88a6d2dfd 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -188,6 +188,14 @@ int spu_irq_class_0_bottom(struct spu *spu);
188int spu_irq_class_1_bottom(struct spu *spu); 188int spu_irq_class_1_bottom(struct spu *spu);
189void spu_irq_setaffinity(struct spu *spu, int cpu); 189void spu_irq_setaffinity(struct spu *spu, int cpu);
190 190
191#ifdef CONFIG_KEXEC
192void crash_register_spus(struct list_head *list);
193#else
194static inline void crash_register_spus(struct list_head *list)
195{
196}
197#endif
198
191extern void spu_invalidate_slbs(struct spu *spu); 199extern void spu_invalidate_slbs(struct spu *spu);
192extern void spu_associate_mm(struct spu *spu, struct mm_struct *mm); 200extern void spu_associate_mm(struct spu *spu, struct mm_struct *mm);
193 201