aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/ras.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/ras.c')
-rw-r--r--arch/powerpc/platforms/pseries/ras.c82
1 files changed, 53 insertions, 29 deletions
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index 9639c66b453d..9df783088b61 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -72,32 +72,62 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id,
72 72
73/* #define DEBUG */ 73/* #define DEBUG */
74 74
75static void request_ras_irqs(struct device_node *np, char *propname, 75
76static void request_ras_irqs(struct device_node *np,
76 irqreturn_t (*handler)(int, void *, struct pt_regs *), 77 irqreturn_t (*handler)(int, void *, struct pt_regs *),
77 const char *name) 78 const char *name)
78{ 79{
79 unsigned int *ireg, len, i; 80 int i, index, count = 0;
80 int virq, n_intr; 81 struct of_irq oirq;
81 82 u32 *opicprop;
82 ireg = (unsigned int *)get_property(np, propname, &len); 83 unsigned int opicplen;
83 if (ireg == NULL) 84 unsigned int virqs[16];
84 return; 85
85 n_intr = prom_n_intr_cells(np); 86 /* Check for obsolete "open-pic-interrupt" property. If present, then
86 len /= n_intr * sizeof(*ireg); 87 * map those interrupts using the default interrupt host and default
87 88 * trigger
88 for (i = 0; i < len; i++) { 89 */
89 virq = virt_irq_create_mapping(*ireg); 90 opicprop = (u32 *)get_property(np, "open-pic-interrupt", &opicplen);
90 if (virq == NO_IRQ) { 91 if (opicprop) {
91 printk(KERN_ERR "Unable to allocate interrupt " 92 opicplen /= sizeof(u32);
92 "number for %s\n", np->full_name); 93 for (i = 0; i < opicplen; i++) {
93 return; 94 if (count > 15)
95 break;
96 virqs[count] = irq_create_mapping(NULL, *(opicprop++),
97 IRQ_TYPE_NONE);
98 if (virqs[count] == NO_IRQ)
99 printk(KERN_ERR "Unable to allocate interrupt "
100 "number for %s\n", np->full_name);
101 else
102 count++;
103
94 } 104 }
95 if (request_irq(irq_offset_up(virq), handler, 0, name, NULL)) { 105 }
106 /* Else use normal interrupt tree parsing */
107 else {
108 /* First try to do a proper OF tree parsing */
109 for (index = 0; of_irq_map_one(np, index, &oirq) == 0;
110 index++) {
111 if (count > 15)
112 break;
113 virqs[count] = irq_create_of_mapping(oirq.controller,
114 oirq.specifier,
115 oirq.size);
116 if (virqs[count] == NO_IRQ)
117 printk(KERN_ERR "Unable to allocate interrupt "
118 "number for %s\n", np->full_name);
119 else
120 count++;
121 }
122 }
123
124 /* Now request them */
125 for (i = 0; i < count; i++) {
126 if (request_irq(virqs[i], handler, 0, name, NULL)) {
96 printk(KERN_ERR "Unable to request interrupt %d for " 127 printk(KERN_ERR "Unable to request interrupt %d for "
97 "%s\n", irq_offset_up(virq), np->full_name); 128 "%s\n", virqs[i], np->full_name);
98 return; 129 return;
99 } 130 }
100 ireg += n_intr;
101 } 131 }
102} 132}
103 133
@@ -115,20 +145,14 @@ static int __init init_ras_IRQ(void)
115 /* Internal Errors */ 145 /* Internal Errors */
116 np = of_find_node_by_path("/event-sources/internal-errors"); 146 np = of_find_node_by_path("/event-sources/internal-errors");
117 if (np != NULL) { 147 if (np != NULL) {
118 request_ras_irqs(np, "open-pic-interrupt", ras_error_interrupt, 148 request_ras_irqs(np, ras_error_interrupt, "RAS_ERROR");
119 "RAS_ERROR");
120 request_ras_irqs(np, "interrupts", ras_error_interrupt,
121 "RAS_ERROR");
122 of_node_put(np); 149 of_node_put(np);
123 } 150 }
124 151
125 /* EPOW Events */ 152 /* EPOW Events */
126 np = of_find_node_by_path("/event-sources/epow-events"); 153 np = of_find_node_by_path("/event-sources/epow-events");
127 if (np != NULL) { 154 if (np != NULL) {
128 request_ras_irqs(np, "open-pic-interrupt", ras_epow_interrupt, 155 request_ras_irqs(np, ras_epow_interrupt, "RAS_EPOW");
129 "RAS_EPOW");
130 request_ras_irqs(np, "interrupts", ras_epow_interrupt,
131 "RAS_EPOW");
132 of_node_put(np); 156 of_node_put(np);
133 } 157 }
134 158
@@ -162,7 +186,7 @@ ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs)
162 186
163 status = rtas_call(ras_check_exception_token, 6, 1, NULL, 187 status = rtas_call(ras_check_exception_token, 6, 1, NULL,
164 RAS_VECTOR_OFFSET, 188 RAS_VECTOR_OFFSET,
165 virt_irq_to_real(irq_offset_down(irq)), 189 irq_map[irq].hwirq,
166 RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS, 190 RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
167 critical, __pa(&ras_log_buf), 191 critical, __pa(&ras_log_buf),
168 rtas_get_error_log_max()); 192 rtas_get_error_log_max());
@@ -198,7 +222,7 @@ ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs)
198 222
199 status = rtas_call(ras_check_exception_token, 6, 1, NULL, 223 status = rtas_call(ras_check_exception_token, 6, 1, NULL,
200 RAS_VECTOR_OFFSET, 224 RAS_VECTOR_OFFSET,
201 virt_irq_to_real(irq_offset_down(irq)), 225 irq_map[irq].hwirq,
202 RTAS_INTERNAL_ERROR, 1 /*Time Critical */, 226 RTAS_INTERNAL_ERROR, 1 /*Time Critical */,
203 __pa(&ras_log_buf), 227 __pa(&ras_log_buf),
204 rtas_get_error_log_max()); 228 rtas_get_error_log_max());