Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-serial
[linux-2.6] / arch / powerpc / platforms / cell / ras.c
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 }