aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip/irq-mips-gic.c
diff options
context:
space:
mode:
authorQais Yousef <qais.yousef@imgtec.com>2015-01-19 06:51:29 -0500
committerThomas Gleixner <tglx@linutronix.de>2015-01-26 05:38:23 -0500
commitd7eb4f2ecccd71f701bc8873bcf07c2d3b0375f6 (patch)
tree293479773c2e028aff2ea9ae1d3c2dc14bbb7f16 /drivers/irqchip/irq-mips-gic.c
parent8041dfbd31cfff31309a2469c3d692595381c38e (diff)
irqchip: mips-gic: Handle pending interrupts once in __gic_irq_dispatch()
When an interrupt occurs __gic_irq_dispatch() continuously reads local and shared pending registers until all is serviced before returning. The problem with that is that it could introduce a long delay before returning if a piece of hardware keeps triggering while in one of these loops. To ensure fairness and priority doesn't get skewed a lot, read local and shared pending registers once to service each pending IRQ once. If another interupt triggers while servicing the current ones, then we shall re-enter the handler after we return. Signed-off-by: Qais Yousef <qais.yousef@imgtec.com> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Andrew Bresticker <abrestic@chromium.org> Cc: <linux-mips@linux-mips.org> Link: http://lkml.kernel.org/r/1421668289-828-1-git-send-email-qais.yousef@imgtec.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/irqchip/irq-mips-gic.c')
-rw-r--r--drivers/irqchip/irq-mips-gic.c44
1 files changed, 26 insertions, 18 deletions
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 2b0468e3df6a..f3f9873dfb68 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -234,9 +234,9 @@ int gic_get_c0_perfcount_int(void)
234 GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_PERFCTR)); 234 GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_PERFCTR));
235} 235}
236 236
237static unsigned int gic_get_int(void) 237static void gic_handle_shared_int(void)
238{ 238{
239 unsigned int i; 239 unsigned int i, intr, virq;
240 unsigned long *pcpu_mask; 240 unsigned long *pcpu_mask;
241 unsigned long pending_reg, intrmask_reg; 241 unsigned long pending_reg, intrmask_reg;
242 DECLARE_BITMAP(pending, GIC_MAX_INTRS); 242 DECLARE_BITMAP(pending, GIC_MAX_INTRS);
@@ -258,7 +258,16 @@ static unsigned int gic_get_int(void)
258 bitmap_and(pending, pending, intrmask, gic_shared_intrs); 258 bitmap_and(pending, pending, intrmask, gic_shared_intrs);
259 bitmap_and(pending, pending, pcpu_mask, gic_shared_intrs); 259 bitmap_and(pending, pending, pcpu_mask, gic_shared_intrs);
260 260
261 return find_first_bit(pending, gic_shared_intrs); 261 intr = find_first_bit(pending, gic_shared_intrs);
262 while (intr != gic_shared_intrs) {
263 virq = irq_linear_revmap(gic_irq_domain,
264 GIC_SHARED_TO_HWIRQ(intr));
265 do_IRQ(virq);
266
267 /* go to next pending bit */
268 bitmap_clear(pending, intr, 1);
269 intr = find_first_bit(pending, gic_shared_intrs);
270 }
262} 271}
263 272
264static void gic_mask_irq(struct irq_data *d) 273static void gic_mask_irq(struct irq_data *d)
@@ -385,16 +394,26 @@ static struct irq_chip gic_edge_irq_controller = {
385#endif 394#endif
386}; 395};
387 396
388static unsigned int gic_get_local_int(void) 397static void gic_handle_local_int(void)
389{ 398{
390 unsigned long pending, masked; 399 unsigned long pending, masked;
400 unsigned int intr, virq;
391 401
392 pending = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_PEND)); 402 pending = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_PEND));
393 masked = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_MASK)); 403 masked = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_MASK));
394 404
395 bitmap_and(&pending, &pending, &masked, GIC_NUM_LOCAL_INTRS); 405 bitmap_and(&pending, &pending, &masked, GIC_NUM_LOCAL_INTRS);
396 406
397 return find_first_bit(&pending, GIC_NUM_LOCAL_INTRS); 407 intr = find_first_bit(&pending, GIC_NUM_LOCAL_INTRS);
408 while (intr != GIC_NUM_LOCAL_INTRS) {
409 virq = irq_linear_revmap(gic_irq_domain,
410 GIC_LOCAL_TO_HWIRQ(intr));
411 do_IRQ(virq);
412
413 /* go to next pending bit */
414 bitmap_clear(&pending, intr, 1);
415 intr = find_first_bit(&pending, GIC_NUM_LOCAL_INTRS);
416 }
398} 417}
399 418
400static void gic_mask_local_irq(struct irq_data *d) 419static void gic_mask_local_irq(struct irq_data *d)
@@ -453,19 +472,8 @@ static struct irq_chip gic_all_vpes_local_irq_controller = {
453 472
454static void __gic_irq_dispatch(void) 473static void __gic_irq_dispatch(void)
455{ 474{
456 unsigned int intr, virq; 475 gic_handle_local_int();
457 476 gic_handle_shared_int();
458 while ((intr = gic_get_local_int()) != GIC_NUM_LOCAL_INTRS) {
459 virq = irq_linear_revmap(gic_irq_domain,
460 GIC_LOCAL_TO_HWIRQ(intr));
461 do_IRQ(virq);
462 }
463
464 while ((intr = gic_get_int()) != gic_shared_intrs) {
465 virq = irq_linear_revmap(gic_irq_domain,
466 GIC_SHARED_TO_HWIRQ(intr));
467 do_IRQ(virq);
468 }
469} 477}
470 478
471static void gic_irq_dispatch(unsigned int irq, struct irq_desc *desc) 479static void gic_irq_dispatch(unsigned int irq, struct irq_desc *desc)