Commit 8f4b5895 authored by James Gowans's avatar James Gowans Committed by Marc Zyngier

irqchip/gic-v3-its: Enable RESEND_WHEN_IN_PROGRESS for LPIs

GICv3 LPIs are impacted by an architectural design issue: they do not
have a global active state and as such a given LPI can be delivered to
a new CPU after an affinity change while the previous instance of the
same LPI handler has not yet completed on the original CPU.

If LPIs had an active state, this second LPI would not be delivered
until the first CPU deactivated the initial LPI, just like SPIs.

To solve this issue, use the newly introduced IRQD_RESEND_WHEN_IN_PROGRESS
flag, ensuring that we do not lose an LPI being delivered during that window
by getting the GIC to resend it.

This workaround gets enabled for all LPIs, including the VPE doorbells.
Suggested-by: default avatarMarc Zyngier <maz@kernel.org>
Signed-off-by: default avatarJames Gowans <jgowans@amazon.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Marc Zyngier <maz@kernel.org>
Cc: KarimAllah Raslan <karahmed@amazon.com>
Cc: Yipeng Zou <zouyipeng@huawei.com>
Cc: Zhang Jianhua <chris.zjh@huawei.com>
[maz: massaged commit message]
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20230608120021.3273400-4-jgowans@amazon.com
parent 9c15eeb5
...@@ -3585,6 +3585,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, ...@@ -3585,6 +3585,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
irqd = irq_get_irq_data(virq + i); irqd = irq_get_irq_data(virq + i);
irqd_set_single_target(irqd); irqd_set_single_target(irqd);
irqd_set_affinity_on_activate(irqd); irqd_set_affinity_on_activate(irqd);
irqd_set_resend_when_in_progress(irqd);
pr_debug("ID:%d pID:%d vID:%d\n", pr_debug("ID:%d pID:%d vID:%d\n",
(int)(hwirq + i - its_dev->event_map.lpi_base), (int)(hwirq + i - its_dev->event_map.lpi_base),
(int)(hwirq + i), virq + i); (int)(hwirq + i), virq + i);
...@@ -4523,6 +4524,7 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq ...@@ -4523,6 +4524,7 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
irq_domain_set_hwirq_and_chip(domain, virq + i, i, irq_domain_set_hwirq_and_chip(domain, virq + i, i,
irqchip, vm->vpes[i]); irqchip, vm->vpes[i]);
set_bit(i, bitmap); set_bit(i, bitmap);
irqd_set_resend_when_in_progress(irq_get_irq_data(virq + i));
} }
if (err) { if (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