[irqchip: irq/irqchip-next] irqchip/gic-v3: Convert to handle_strict_flow_irq()

irqchip-bot for Valentin Schneider
2021-08-12T15:13:10Z

The following commit has been merged into the irq/irqchip-next branch of irqchip:

Commit-ID: 3359fcab48b0467497883863e2e5538605c51c4a
Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms/3359fcab48b0467497883863e2e5538605c51c4a
Author: Valentin Schneider <valentin.schneider@arm.com>
AuthorDate: Tue, 29 Jun 2021 13:50:10 +01:00
Committer: Marc Zyngier <maz@kernel.org>
CommitterDate: Thu, 12 Aug 2021 15:48:21 +01:00

irqchip/gic-v3: Convert to handle_strict_flow_irq()

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@arm.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20210629125010.458872-14-valentin.schneider@arm.com
---
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 cdffffc..00bbb4d 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.
@@ -697,9 +695,11 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
gic_arch_enable_irqs();
}

- 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)) {
@@ -1310,6 +1310,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,
@@ -1322,7 +1323,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,
@@ -1346,7 +1349,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;
@@ -1355,7 +1360,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;