diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/include/asm/spu.h | 8 | ||||
-rw-r--r-- | arch/powerpc/kernel/crash.c | 72 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spu_base.c | 70 |
3 files changed, 72 insertions, 78 deletions
diff --git a/arch/powerpc/include/asm/spu.h b/arch/powerpc/include/asm/spu.h index 0ab8d869e3d..0c8b35d7523 100644 --- a/arch/powerpc/include/asm/spu.h +++ b/arch/powerpc/include/asm/spu.h | |||
@@ -203,14 +203,6 @@ void spu_irq_setaffinity(struct spu *spu, int cpu); | |||
203 | void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa, | 203 | void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa, |
204 | void *code, int code_size); | 204 | void *code, int code_size); |
205 | 205 | ||
206 | #ifdef CONFIG_KEXEC | ||
207 | void crash_register_spus(struct list_head *list); | ||
208 | #else | ||
209 | static inline void crash_register_spus(struct list_head *list) | ||
210 | { | ||
211 | } | ||
212 | #endif | ||
213 | |||
214 | extern void spu_invalidate_slbs(struct spu *spu); | 206 | extern void spu_invalidate_slbs(struct spu *spu); |
215 | extern void spu_associate_mm(struct spu *spu, struct mm_struct *mm); | 207 | extern void spu_associate_mm(struct spu *spu, struct mm_struct *mm); |
216 | int spu_64k_pages_available(void); | 208 | int spu_64k_pages_available(void); |
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 832c8c4db25..3d569e2aff1 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c | |||
@@ -48,7 +48,7 @@ int crashing_cpu = -1; | |||
48 | static cpumask_t cpus_in_crash = CPU_MASK_NONE; | 48 | static cpumask_t cpus_in_crash = CPU_MASK_NONE; |
49 | cpumask_t cpus_in_sr = CPU_MASK_NONE; | 49 | cpumask_t cpus_in_sr = CPU_MASK_NONE; |
50 | 50 | ||
51 | #define CRASH_HANDLER_MAX 2 | 51 | #define CRASH_HANDLER_MAX 3 |
52 | /* NULL terminated list of shutdown handles */ | 52 | /* NULL terminated list of shutdown handles */ |
53 | static crash_shutdown_t crash_shutdown_handles[CRASH_HANDLER_MAX+1]; | 53 | static crash_shutdown_t crash_shutdown_handles[CRASH_HANDLER_MAX+1]; |
54 | static DEFINE_SPINLOCK(crash_handlers_lock); | 54 | static DEFINE_SPINLOCK(crash_handlers_lock); |
@@ -125,7 +125,7 @@ static void crash_kexec_prepare_cpus(int cpu) | |||
125 | smp_wmb(); | 125 | smp_wmb(); |
126 | 126 | ||
127 | /* | 127 | /* |
128 | * FIXME: Until we will have the way to stop other CPUSs reliabally, | 128 | * FIXME: Until we will have the way to stop other CPUs reliably, |
129 | * the crash CPU will send an IPI and wait for other CPUs to | 129 | * the crash CPU will send an IPI and wait for other CPUs to |
130 | * respond. | 130 | * respond. |
131 | * Delay of at least 10 seconds. | 131 | * Delay of at least 10 seconds. |
@@ -254,72 +254,6 @@ void crash_kexec_secondary(struct pt_regs *regs) | |||
254 | cpus_in_sr = CPU_MASK_NONE; | 254 | cpus_in_sr = CPU_MASK_NONE; |
255 | } | 255 | } |
256 | #endif | 256 | #endif |
257 | #ifdef CONFIG_SPU_BASE | ||
258 | |||
259 | #include <asm/spu.h> | ||
260 | #include <asm/spu_priv1.h> | ||
261 | |||
262 | struct crash_spu_info { | ||
263 | struct spu *spu; | ||
264 | u32 saved_spu_runcntl_RW; | ||
265 | u32 saved_spu_status_R; | ||
266 | u32 saved_spu_npc_RW; | ||
267 | u64 saved_mfc_sr1_RW; | ||
268 | u64 saved_mfc_dar; | ||
269 | u64 saved_mfc_dsisr; | ||
270 | }; | ||
271 | |||
272 | #define CRASH_NUM_SPUS 16 /* Enough for current hardware */ | ||
273 | static struct crash_spu_info crash_spu_info[CRASH_NUM_SPUS]; | ||
274 | |||
275 | static void crash_kexec_stop_spus(void) | ||
276 | { | ||
277 | struct spu *spu; | ||
278 | int i; | ||
279 | u64 tmp; | ||
280 | |||
281 | for (i = 0; i < CRASH_NUM_SPUS; i++) { | ||
282 | if (!crash_spu_info[i].spu) | ||
283 | continue; | ||
284 | |||
285 | spu = crash_spu_info[i].spu; | ||
286 | |||
287 | crash_spu_info[i].saved_spu_runcntl_RW = | ||
288 | in_be32(&spu->problem->spu_runcntl_RW); | ||
289 | crash_spu_info[i].saved_spu_status_R = | ||
290 | in_be32(&spu->problem->spu_status_R); | ||
291 | crash_spu_info[i].saved_spu_npc_RW = | ||
292 | in_be32(&spu->problem->spu_npc_RW); | ||
293 | |||
294 | crash_spu_info[i].saved_mfc_dar = spu_mfc_dar_get(spu); | ||
295 | crash_spu_info[i].saved_mfc_dsisr = spu_mfc_dsisr_get(spu); | ||
296 | tmp = spu_mfc_sr1_get(spu); | ||
297 | crash_spu_info[i].saved_mfc_sr1_RW = tmp; | ||
298 | |||
299 | tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK; | ||
300 | spu_mfc_sr1_set(spu, tmp); | ||
301 | |||
302 | __delay(200); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | void crash_register_spus(struct list_head *list) | ||
307 | { | ||
308 | struct spu *spu; | ||
309 | |||
310 | list_for_each_entry(spu, list, full_list) { | ||
311 | if (WARN_ON(spu->number >= CRASH_NUM_SPUS)) | ||
312 | continue; | ||
313 | |||
314 | crash_spu_info[spu->number].spu = spu; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | #else | ||
319 | static inline void crash_kexec_stop_spus(void) | ||
320 | { | ||
321 | } | ||
322 | #endif /* CONFIG_SPU_BASE */ | ||
323 | 257 | ||
324 | /* | 258 | /* |
325 | * Register a function to be called on shutdown. Only use this if you | 259 | * Register a function to be called on shutdown. Only use this if you |
@@ -439,8 +373,6 @@ void default_machine_crash_shutdown(struct pt_regs *regs) | |||
439 | crash_shutdown_cpu = -1; | 373 | crash_shutdown_cpu = -1; |
440 | __debugger_fault_handler = old_handler; | 374 | __debugger_fault_handler = old_handler; |
441 | 375 | ||
442 | crash_kexec_stop_spus(); | ||
443 | |||
444 | if (ppc_md.kexec_cpu_down) | 376 | if (ppc_md.kexec_cpu_down) |
445 | ppc_md.kexec_cpu_down(1, 0); | 377 | ppc_md.kexec_cpu_down(1, 0); |
446 | } | 378 | } |
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 8547e86bfb4..acfaccea5f4 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <asm/spu_csa.h> | 37 | #include <asm/spu_csa.h> |
38 | #include <asm/xmon.h> | 38 | #include <asm/xmon.h> |
39 | #include <asm/prom.h> | 39 | #include <asm/prom.h> |
40 | #include <asm/kexec.h> | ||
40 | 41 | ||
41 | const struct spu_management_ops *spu_management_ops; | 42 | const struct spu_management_ops *spu_management_ops; |
42 | EXPORT_SYMBOL_GPL(spu_management_ops); | 43 | EXPORT_SYMBOL_GPL(spu_management_ops); |
@@ -727,6 +728,75 @@ static ssize_t spu_stat_show(struct sys_device *sysdev, | |||
727 | 728 | ||
728 | static SYSDEV_ATTR(stat, 0644, spu_stat_show, NULL); | 729 | static SYSDEV_ATTR(stat, 0644, spu_stat_show, NULL); |
729 | 730 | ||
731 | #ifdef CONFIG_KEXEC | ||
732 | |||
733 | struct crash_spu_info { | ||
734 | struct spu *spu; | ||
735 | u32 saved_spu_runcntl_RW; | ||
736 | u32 saved_spu_status_R; | ||
737 | u32 saved_spu_npc_RW; | ||
738 | u64 saved_mfc_sr1_RW; | ||
739 | u64 saved_mfc_dar; | ||
740 | u64 saved_mfc_dsisr; | ||
741 | }; | ||
742 | |||
743 | #define CRASH_NUM_SPUS 16 /* Enough for current hardware */ | ||
744 | static struct crash_spu_info crash_spu_info[CRASH_NUM_SPUS]; | ||
745 | |||
746 | static void crash_kexec_stop_spus(void) | ||
747 | { | ||
748 | struct spu *spu; | ||
749 | int i; | ||
750 | u64 tmp; | ||
751 | |||
752 | for (i = 0; i < CRASH_NUM_SPUS; i++) { | ||
753 | if (!crash_spu_info[i].spu) | ||
754 | continue; | ||
755 | |||
756 | spu = crash_spu_info[i].spu; | ||
757 | |||
758 | crash_spu_info[i].saved_spu_runcntl_RW = | ||
759 | in_be32(&spu->problem->spu_runcntl_RW); | ||
760 | crash_spu_info[i].saved_spu_status_R = | ||
761 | in_be32(&spu->problem->spu_status_R); | ||
762 | crash_spu_info[i].saved_spu_npc_RW = | ||
763 | in_be32(&spu->problem->spu_npc_RW); | ||
764 | |||
765 | crash_spu_info[i].saved_mfc_dar = spu_mfc_dar_get(spu); | ||
766 | crash_spu_info[i].saved_mfc_dsisr = spu_mfc_dsisr_get(spu); | ||
767 | tmp = spu_mfc_sr1_get(spu); | ||
768 | crash_spu_info[i].saved_mfc_sr1_RW = tmp; | ||
769 | |||
770 | tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK; | ||
771 | spu_mfc_sr1_set(spu, tmp); | ||
772 | |||
773 | __delay(200); | ||
774 | } | ||
775 | } | ||
776 | |||
777 | static void crash_register_spus(struct list_head *list) | ||
778 | { | ||
779 | struct spu *spu; | ||
780 | int ret; | ||
781 | |||
782 | list_for_each_entry(spu, list, full_list) { | ||
783 | if (WARN_ON(spu->number >= CRASH_NUM_SPUS)) | ||
784 | continue; | ||
785 | |||
786 | crash_spu_info[spu->number].spu = spu; | ||
787 | } | ||
788 | |||
789 | ret = crash_shutdown_register(&crash_kexec_stop_spus); | ||
790 | if (ret) | ||
791 | printk(KERN_ERR "Could not register SPU crash handler"); | ||
792 | } | ||
793 | |||
794 | #else | ||
795 | static inline void crash_register_spus(struct list_head *list) | ||
796 | { | ||
797 | } | ||
798 | #endif | ||
799 | |||
730 | static int __init init_spu_base(void) | 800 | static int __init init_spu_base(void) |
731 | { | 801 | { |
732 | int i, ret = 0; | 802 | int i, ret = 0; |