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 <[email protected]>
---
 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

Reply via email to