[RFC PATCH 10/10] irqchip/gic-v3: Convert to handle_strict_flow_irq()
From: Valentin Schneider
Date: Thu Apr 08 2021 - 11:44:23 EST
Now that the proper infrastructure is in place, convert the irq-gic-v3 chip
to use handle_strict_flow_irq() along with IRQCHIP_AUTOMASKS_FLOW.
For EOImode=1, the Priority Drop is moved from gic_handle_irq() into
chip->irq_ack(). This effectively pushes the EOIR write down into
->handle_irq(), but doesn't change its ordering wrt the irqaction
handling.
The EOImode=1 irqchip also gains IRQCHIP_EOI_THREADED, which allows the
->irq_eoi() call to be deferred to the tail of ONESHOT IRQ threads. This
means a threaded ONESHOT IRQ can now be handled entirely without a single
chip->irq_mask() call.
Despite not having an Active state, LPIs are made to use
handle_strict_flow_irq() as well. This lets them re-use
gic_eoimode1_chip.irq_ack() as Priority Drop, rather than special-case them
in gic_handle_irq().
EOImode=0 handling remains unchanged.
Signed-off-by: Valentin Schneider <valentin.schneider@xxxxxxx>
---
drivers/irqchip/irq-gic-v3.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 242a8fc5ec86..da73398117a7 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -626,8 +626,6 @@ static inline void gic_handle_nmi(u32 irqnr, struct pt_regs *regs)
if (irqs_enabled)
nmi_enter();
- if (static_branch_likely(&supports_deactivate_key))
- gic_write_eoir(irqnr);
/*
* Leave the PSR.I bit set to prevent other NMIs to be
* received while handling this one.
@@ -663,9 +661,11 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
if ((irqnr >= 1020 && irqnr <= 1023))
return;
- if (static_branch_likely(&supports_deactivate_key))
- gic_write_eoir(irqnr);
- else
+ /*
+ * eoimode1 will give us an isb in handle_domain_irq(), before
+ * handle_irq_event().
+ */
+ if (!static_branch_likely(&supports_deactivate_key))
isb();
if (handle_domain_irq(gic_data.domain, irqnr, regs)) {
@@ -1276,6 +1276,7 @@ static struct irq_chip gic_eoimode1_chip = {
.name = "GICv3",
.irq_mask = gic_eoimode1_mask_irq,
.irq_unmask = gic_unmask_irq,
+ .irq_ack = gic_eoi_irq,
.irq_eoi = gic_eoimode1_eoi_irq,
.irq_set_type = gic_set_type,
.irq_set_affinity = gic_set_affinity,
@@ -1288,7 +1289,9 @@ static struct irq_chip gic_eoimode1_chip = {
.ipi_send_mask = gic_ipi_send_mask,
.flags = IRQCHIP_SET_TYPE_MASKED |
IRQCHIP_SKIP_SET_WAKE |
- IRQCHIP_MASK_ON_SUSPEND,
+ IRQCHIP_MASK_ON_SUSPEND |
+ IRQCHIP_AUTOMASKS_FLOW |
+ IRQCHIP_EOI_THREADED,
};
static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
@@ -1312,7 +1315,9 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
case SPI_RANGE:
case ESPI_RANGE:
irq_domain_set_info(d, irq, hw, chip, d->host_data,
- handle_fasteoi_irq, NULL, NULL);
+ static_branch_likely(&supports_deactivate_key) ?
+ handle_strict_flow_irq : handle_fasteoi_irq,
+ NULL, NULL);
irq_set_probe(irq);
irqd_set_single_target(irqd);
break;
@@ -1321,7 +1326,9 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
if (!gic_dist_supports_lpis())
return -EPERM;
irq_domain_set_info(d, irq, hw, chip, d->host_data,
- handle_fasteoi_irq, NULL, NULL);
+ static_branch_likely(&supports_deactivate_key) ?
+ handle_strict_flow_irq : handle_fasteoi_irq,
+ NULL, NULL);
break;
default:
--
2.25.1