Commit da90921a authored by Thomas Gleixner's avatar Thomas Gleixner

genirq: Sanitize state handling in check_irq_resend()

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: default avatarThomas Gleixner <tglx@linutronix.de>
Acked-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lkml.kernel.org/r/20200306130623.882129117@linutronix.de
parent 1f85b1f5
...@@ -93,6 +93,8 @@ static int irq_sw_resend(struct irq_desc *desc) ...@@ -93,6 +93,8 @@ static int irq_sw_resend(struct irq_desc *desc)
*/ */
int check_irq_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 * We do not resend level type interrupts. Level type interrupts
* are resent by hardware when they are still active. Clear the * are resent by hardware when they are still active. Clear the
...@@ -106,13 +108,17 @@ int check_irq_resend(struct irq_desc *desc) ...@@ -106,13 +108,17 @@ int check_irq_resend(struct irq_desc *desc)
if (desc->istate & IRQS_REPLAY) if (desc->istate & IRQS_REPLAY)
return -EBUSY; return -EBUSY;
if (desc->istate & IRQS_PENDING) { if (!(desc->istate & IRQS_PENDING))
desc->istate &= ~IRQS_PENDING; return 0;
desc->istate |= IRQS_REPLAY;
if (!desc->irq_data.chip->irq_retrigger || desc->istate &= ~IRQS_PENDING;
!desc->irq_data.chip->irq_retrigger(&desc->irq_data))
return irq_sw_resend(desc); if (!desc->irq_data.chip->irq_retrigger ||
} !desc->irq_data.chip->irq_retrigger(&desc->irq_data))
return 0; err = irq_sw_resend(desc);
/* If the retrigger was successfull, mark it with the REPLAY bit */
if (!err)
desc->istate |= IRQS_REPLAY;
return err;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment