diff options
Diffstat (limited to 'arch/powerpc/platforms/cell/ras.c')
-rw-r--r-- | arch/powerpc/platforms/cell/ras.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c new file mode 100644 index 000000000000..033ad6e2827b --- /dev/null +++ b/arch/powerpc/platforms/cell/ras.c | |||
@@ -0,0 +1,112 @@ | |||
1 | #define DEBUG | ||
2 | |||
3 | #include <linux/config.h> | ||
4 | #include <linux/types.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/smp.h> | ||
7 | |||
8 | #include <asm/reg.h> | ||
9 | #include <asm/io.h> | ||
10 | #include <asm/prom.h> | ||
11 | #include <asm/machdep.h> | ||
12 | |||
13 | #include "ras.h" | ||
14 | #include "cbe_regs.h" | ||
15 | |||
16 | |||
17 | static void dump_fir(int cpu) | ||
18 | { | ||
19 | struct cbe_pmd_regs __iomem *pregs = cbe_get_cpu_pmd_regs(cpu); | ||
20 | struct cbe_iic_regs __iomem *iregs = cbe_get_cpu_iic_regs(cpu); | ||
21 | |||
22 | if (pregs == NULL) | ||
23 | return; | ||
24 | |||
25 | /* Todo: do some nicer parsing of bits and based on them go down | ||
26 | * to other sub-units FIRs and not only IIC | ||
27 | */ | ||
28 | printk(KERN_ERR "Global Checkstop FIR : 0x%016lx\n", | ||
29 | in_be64(&pregs->checkstop_fir)); | ||
30 | printk(KERN_ERR "Global Recoverable FIR : 0x%016lx\n", | ||
31 | in_be64(&pregs->checkstop_fir)); | ||
32 | printk(KERN_ERR "Global MachineCheck FIR : 0x%016lx\n", | ||
33 | in_be64(&pregs->spec_att_mchk_fir)); | ||
34 | |||
35 | if (iregs == NULL) | ||
36 | return; | ||
37 | printk(KERN_ERR "IOC FIR : 0x%016lx\n", | ||
38 | in_be64(&iregs->ioc_fir)); | ||
39 | |||
40 | } | ||
41 | |||
42 | void cbe_system_error_exception(struct pt_regs *regs) | ||
43 | { | ||
44 | int cpu = smp_processor_id(); | ||
45 | |||
46 | printk(KERN_ERR "System Error Interrupt on CPU %d !\n", cpu); | ||
47 | dump_fir(cpu); | ||
48 | dump_stack(); | ||
49 | } | ||
50 | |||
51 | void cbe_maintenance_exception(struct pt_regs *regs) | ||
52 | { | ||
53 | int cpu = smp_processor_id(); | ||
54 | |||
55 | /* | ||
56 | * Nothing implemented for the maintenance interrupt at this point | ||
57 | */ | ||
58 | |||
59 | printk(KERN_ERR "Unhandled Maintenance interrupt on CPU %d !\n", cpu); | ||
60 | dump_stack(); | ||
61 | } | ||
62 | |||
63 | void cbe_thermal_exception(struct pt_regs *regs) | ||
64 | { | ||
65 | int cpu = smp_processor_id(); | ||
66 | |||
67 | /* | ||
68 | * Nothing implemented for the thermal interrupt at this point | ||
69 | */ | ||
70 | |||
71 | printk(KERN_ERR "Unhandled Thermal interrupt on CPU %d !\n", cpu); | ||
72 | dump_stack(); | ||
73 | } | ||
74 | |||
75 | static int cbe_machine_check_handler(struct pt_regs *regs) | ||
76 | { | ||
77 | int cpu = smp_processor_id(); | ||
78 | |||
79 | printk(KERN_ERR "Machine Check Interrupt on CPU %d !\n", cpu); | ||
80 | dump_fir(cpu); | ||
81 | |||
82 | /* No recovery from this code now, lets continue */ | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | void __init cbe_ras_init(void) | ||
87 | { | ||
88 | unsigned long hid0; | ||
89 | |||
90 | /* | ||
91 | * Enable System Error & thermal interrupts and wakeup conditions | ||
92 | */ | ||
93 | |||
94 | hid0 = mfspr(SPRN_HID0); | ||
95 | hid0 |= HID0_CBE_THERM_INT_EN | HID0_CBE_THERM_WAKEUP | | ||
96 | HID0_CBE_SYSERR_INT_EN | HID0_CBE_SYSERR_WAKEUP; | ||
97 | mtspr(SPRN_HID0, hid0); | ||
98 | mb(); | ||
99 | |||
100 | /* | ||
101 | * Install machine check handler. Leave setting of precise mode to | ||
102 | * what the firmware did for now | ||
103 | */ | ||
104 | ppc_md.machine_check_exception = cbe_machine_check_handler; | ||
105 | mb(); | ||
106 | |||
107 | /* | ||
108 | * For now, we assume that IOC_FIR is already set to forward some | ||
109 | * error conditions to the System Error handler. If that is not true | ||
110 | * then it will have to be fixed up here. | ||
111 | */ | ||
112 | } | ||