From d3b057a55c18fb339a95dbe4c81f70fb6a448bd0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 27 Jul 2020 11:11:27 -0400 Subject: [PATCH 2016/2944] genirq: Sanitize state handling in check_irq_resend() task #29600094 commit da90921acc62c71d27729ae211ccfda5370bf75b upstream. Backport summary: for 4.19 kernel ICX PCIe Gen4 support. 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 Acked-by: Marc Zyngier Link: https://lkml.kernel.org/r/20200306130623.882129117@linutronix.de (cherry picked from commit da90921acc62c71d27729ae211ccfda5370bf75b) Signed-off-by: Ethan Zhao Signed-off-by: Artie Ding Acked-by: Caspar Zhang --- kernel/irq/resend.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c index a21fc4e..bef72dc 100644 --- a/kernel/irq/resend.c +++ b/kernel/irq/resend.c @@ -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 @@ -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; } -- 1.8.3.1