irqchip/irq-brcmstb-l2: Avoid saving mask on shutdown
authorFlorian Fainelli <florian.fainelli@broadcom.com>
Wed, 24 Apr 2024 17:57:32 +0000 (10:57 -0700)
committerThomas Gleixner <tglx@linutronix.de>
Wed, 24 Apr 2024 19:11:48 +0000 (21:11 +0200)
The interrupt controller shutdown path does not need to save the mask of
enabled interrupts because the next state the system is going to be in is
akin to a cold boot, or a kexec'd kernel. Saving the mask only makes sense
if the software state needs to preserve the hardware state across a system
suspend/resume cycle.

As an optimization, and given that there are systems with dozens of such
interrupt controller, save a "slow" memory mapped I/O read in the shutdown
path where no saving/restoring is required.

Reported-by: Tim Ross <tim.ross@broadcom.com>
Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20240424175732.1526531-1-florian.fainelli@broadcom.com
drivers/irqchip/irq-brcmstb-l2.c

index 2b0b3175cea068eb571d8ec5f82a4d45a01e5719..c988886917f73910a81403057f325430e98f751c 100644 (file)
@@ -118,7 +118,7 @@ out:
        chained_irq_exit(chip, desc);
 }
 
-static void brcmstb_l2_intc_suspend(struct irq_data *d)
+static void __brcmstb_l2_intc_suspend(struct irq_data *d, bool save)
 {
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct irq_chip_type *ct = irq_data_get_chip_type(d);
@@ -127,7 +127,8 @@ static void brcmstb_l2_intc_suspend(struct irq_data *d)
 
        irq_gc_lock_irqsave(gc, flags);
        /* Save the current mask */
-       b->saved_mask = irq_reg_readl(gc, ct->regs.mask);
+       if (save)
+               b->saved_mask = irq_reg_readl(gc, ct->regs.mask);
 
        if (b->can_wake) {
                /* Program the wakeup mask */
@@ -137,6 +138,16 @@ static void brcmstb_l2_intc_suspend(struct irq_data *d)
        irq_gc_unlock_irqrestore(gc, flags);
 }
 
+static void brcmstb_l2_intc_shutdown(struct irq_data *d)
+{
+       __brcmstb_l2_intc_suspend(d, false);
+}
+
+static void brcmstb_l2_intc_suspend(struct irq_data *d)
+{
+       __brcmstb_l2_intc_suspend(d, true);
+}
+
 static void brcmstb_l2_intc_resume(struct irq_data *d)
 {
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
@@ -252,7 +263,7 @@ static int __init brcmstb_l2_intc_of_init(struct device_node *np,
 
        ct->chip.irq_suspend = brcmstb_l2_intc_suspend;
        ct->chip.irq_resume = brcmstb_l2_intc_resume;
-       ct->chip.irq_pm_shutdown = brcmstb_l2_intc_suspend;
+       ct->chip.irq_pm_shutdown = brcmstb_l2_intc_shutdown;
 
        if (data->can_wake) {
                /* This IRQ chip can wake the system, set all child interrupts