Re: [PATCH v3] genirq: avoid long loops in handle_edge_irq

From: Wei Gong
Date: Thu Oct 19 2023 - 03:02:48 EST


O Fri, Oct 13, 2023 at 10:44:36AM +0200, Thomas Gleixner wrote:
> On Thu, Oct 12 2023 at 21:39, Wei Gong wrote:
> > O Mon, Oct 09, 2023 at 04:32:10PM +0200, Thomas Gleixner wrote:
> >> Now $COND is not true due to the affinity change and the edge handler
> >> returns. As a consequence nothing acks the device and no further
> >> interrupts are sent by the device.
> >>
> >> That might not be true for your case, but that's a generic function and the
> >> zoo of hardware which uses that is massive.
> >>
> >> So no, we are not taking a risk here.
> >>
> >> Thanks,
> >>
> >> tglx
> >>
> >>
> > By maintaining the original loop exit condition, if a mask mismatch is
> > detected within the loop, we will not perform the unmask_irq operation.
> > Instead, we will wait until the loop exits before executing unmask_irq.
> > Could this approach potentially solve the issue of lost interrupts?
>
> How so exactly?
>
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 8f8f1d62f..b846659ce 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -823,7 +823,9 @@ void handle_edge_irq(struct irq_desc *desc)
*/
if (unlikely(desc->istate & IRQS_PENDING)) {
if (!irqd_irq_disabled(&desc->irq_data) &&
- irqd_irq_masked(&desc->irq_data))
+ irqd_irq_masked(&desc->irq_data) &&
+ cpumask_test_cpu(smp_processor_id(),
+ irq_data_get_effective_affinity_mask(&desc->irq_data)))
unmask_irq(desc);
}

@@ -832,6 +834,10 @@ void handle_edge_irq(struct irq_desc *desc)
} while ((desc->istate & IRQS_PENDING) &&
!irqd_irq_disabled(&desc->irq_data));

+if (!irqd_irq_disabled(&desc->irq_data) &&
+ irqd_irq_masked(&desc->irq_data))
+ unmask_irq(desc);
+
out_unlock:
raw_spin_unlock(&desc->lock);
}