aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
authorValentine Barshak <vbarshak@ru.mvista.com>2007-12-06 08:48:26 -0500
committerJosh Boyer <jwboyer@linux.vnet.ibm.com>2007-12-23 14:24:54 -0500
commit5aac48dc1a7bf0e8c5d01a2d6b16f8063d157649 (patch)
tree39a5bbb134c02f8779b2faff5851e43189bef33f /arch/powerpc/sysdev
parentc80905637efb4af6e58da91fae89ffcb2cf8f1aa (diff)
[POWERPC] 4xx: rework UIC cascade irq handling
This is a UIC cascade handler rework to use set_irq_chained_handler() for cascade, just like othe ppc platforms do. With current implementation we have additional redirection for irq handler and we call generic_handle_irq twice (once for the primary uic and the other time for handling cascade interrupt). This causes Ingo's realtime support patch to stop working on 4xx. Not sure of any other possible problems though, but with set_irq_chained_handler() we can abolish "struct irqaction cascade" from the chip descriptor and call generic_handle_irq() once, directly for cascade irq. Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com> Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Diffstat (limited to 'arch/powerpc/sysdev')
-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 }