diff options
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r-- | arch/powerpc/sysdev/uic.c | 36 |
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 | ||
61 | static void uic_unmask_irq(unsigned int virq) | 58 | static 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 | ||
224 | irqreturn_t uic_cascade(int virq, void *data) | 221 | void 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; | 244 | uic_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 | ||
243 | static struct uic * __init uic_init_one(struct device_node *node) | 253 | static 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 | } |