aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/uic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/uic.c')
-rw-r--r--arch/powerpc/sysdev/uic.c36
1 files changed, 19 insertions, 17 deletions
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index ba024985e66a..ae3eadddddbd 100644
--- a/arch/powerpc/sysdev/uic.c
+++ b/arch/powerpc/sysdev/uic.c
@@ -53,9 +53,6 @@ struct uic {
53 53
54 /* The remapper for this UIC */ 54 /* The remapper for this UIC */
55 struct irq_host *irqhost; 55 struct irq_host *irqhost;
56
57 /* For secondary UICs, the cascade interrupt's irqaction */
58 struct irqaction cascade;
59}; 56};
60 57
61static void uic_unmask_irq(unsigned int virq) 58static void uic_unmask_irq(unsigned int virq)
@@ -221,23 +218,36 @@ static struct irq_host_ops uic_host_ops = {
221 .xlate = uic_host_xlate, 218 .xlate = uic_host_xlate,
222}; 219};
223 220
224irqreturn_t uic_cascade(int virq, void *data) 221void uic_irq_cascade(unsigned int virq, struct irq_desc *desc)
225{ 222{
226 struct uic *uic = data; 223 struct uic *uic = get_irq_data(virq);
227 u32 msr; 224 u32 msr;
228 int src; 225 int src;
229 int subvirq; 226 int subvirq;
230 227
228 spin_lock(&desc->lock);
229 if (desc->status & IRQ_LEVEL)
230 desc->chip->mask(virq);
231 else
232 desc->chip->mask_ack(virq);
233 spin_unlock(&desc->lock);
234
231 msr = mfdcr(uic->dcrbase + UIC_MSR); 235 msr = mfdcr(uic->dcrbase + UIC_MSR);
232 if (!msr) /* spurious interrupt */ 236 if (!msr) /* spurious interrupt */
233 return IRQ_HANDLED; 237 goto uic_irq_ret;
234 238
235 src = 32 - ffs(msr); 239 src = 32 - ffs(msr);
236 240
237 subvirq = irq_linear_revmap(uic->irqhost, src); 241 subvirq = irq_linear_revmap(uic->irqhost, src);
238 generic_handle_irq(subvirq); 242 generic_handle_irq(subvirq);
239 243
240 return IRQ_HANDLED; 244uic_irq_ret:
245 spin_lock(&desc->lock);
246 if (desc->status & IRQ_LEVEL)
247 desc->chip->ack(virq);
248 if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
249 desc->chip->unmask(virq);
250 spin_unlock(&desc->lock);
241} 251}
242 252
243static struct uic * __init uic_init_one(struct device_node *node) 253static struct uic * __init uic_init_one(struct device_node *node)
@@ -325,7 +335,6 @@ void __init uic_init_tree(void)
325 if (interrupts) { 335 if (interrupts) {
326 /* Secondary UIC */ 336 /* Secondary UIC */
327 int cascade_virq; 337 int cascade_virq;
328 int ret;
329 338
330 uic = uic_init_one(np); 339 uic = uic_init_one(np);
331 if (! uic) 340 if (! uic)
@@ -334,15 +343,8 @@ void __init uic_init_tree(void)
334 343
335 cascade_virq = irq_of_parse_and_map(np, 0); 344 cascade_virq = irq_of_parse_and_map(np, 0);
336 345
337 uic->cascade.handler = uic_cascade; 346 set_irq_data(cascade_virq, uic);
338 uic->cascade.name = "UIC cascade"; 347 set_irq_chained_handler(cascade_virq, uic_irq_cascade);
339 uic->cascade.dev_id = uic;
340
341 ret = setup_irq(cascade_virq, &uic->cascade);
342 if (ret)
343 printk(KERN_ERR "Failed to setup_irq(%d) for "
344 "UIC%d cascade\n", cascade_virq,
345 uic->index);
346 348
347 /* FIXME: setup critical cascade?? */ 349 /* FIXME: setup critical cascade?? */
348 } 350 }