Skip to content

Commit

Permalink
genirq: Sanitize state handling in check_irq_resend()
Browse files Browse the repository at this point in the history
The code sets IRQS_REPLAY unconditionally whether the resend happens or
not. That doesn't have bad side effects right now, but inconsistent state
is always a latent source of problems.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Marc Zyngier <maz@kernel.org>
Link: https://lkml.kernel.org/r/20200306130623.882129117@linutronix.de
  • Loading branch information
Thomas Gleixner committed Mar 8, 2020
1 parent 1f85b1f commit da90921
Showing 1 changed file with 14 additions and 8 deletions.
22 changes: 14 additions & 8 deletions kernel/irq/resend.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ static int irq_sw_resend(struct irq_desc *desc)
*/
int check_irq_resend(struct irq_desc *desc)
{
int err = 0;

/*
* We do not resend level type interrupts. Level type interrupts
* are resent by hardware when they are still active. Clear the
Expand All @@ -106,13 +108,17 @@ int check_irq_resend(struct irq_desc *desc)
if (desc->istate & IRQS_REPLAY)
return -EBUSY;

if (desc->istate & IRQS_PENDING) {
desc->istate &= ~IRQS_PENDING;
desc->istate |= IRQS_REPLAY;
if (!(desc->istate & IRQS_PENDING))
return 0;

if (!desc->irq_data.chip->irq_retrigger ||
!desc->irq_data.chip->irq_retrigger(&desc->irq_data))
return irq_sw_resend(desc);
}
return 0;
desc->istate &= ~IRQS_PENDING;

if (!desc->irq_data.chip->irq_retrigger ||
!desc->irq_data.chip->irq_retrigger(&desc->irq_data))
err = irq_sw_resend(desc);

/* If the retrigger was successfull, mark it with the REPLAY bit */
if (!err)
desc->istate |= IRQS_REPLAY;
return err;
}

0 comments on commit da90921

Please sign in to comment.