]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
irqchip/sifive-plic: Cache the interrupt enable state
authorCharles Mirabile <cmirabil@redhat.com>
Fri, 24 Oct 2025 08:36:42 +0000 (09:36 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Fri, 24 Oct 2025 19:34:32 +0000 (21:34 +0200)
Optimize the PLIC driver by maintaining the interrupt enable state in the
handler's enable_save array during normal operation rather than only during
suspend/resume. This eliminates the need to read enable registers during
suspend and makes the enable state immediately available for other
purposes.

Let __plic_toggle() update both the hardware registers and the cached
enable_save state atomically within the existing enable_lock protection.

That allows to remove the suspend-time enable register reading since
handler::enable_save now always reflects the current state.

[ tglx: Massaged change log ]

Signed-off-by: Charles Mirabile <cmirabil@redhat.com>
Signed-off-by: Lucas Zampieri <lzampier@redhat.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://patch.msgid.link/20251024083647.475239-4-lzampier@redhat.com
drivers/irqchip/irq-sifive-plic.c

index cbd7697bc14819cbe3b77096b26901b605491f75..d518a8b468742123f7fa30dbd2dd831258ad3ac6 100644 (file)
@@ -94,15 +94,22 @@ static DEFINE_PER_CPU(struct plic_handler, plic_handlers);
 
 static int plic_irq_set_type(struct irq_data *d, unsigned int type);
 
-static void __plic_toggle(void __iomem *enable_base, int hwirq, int enable)
+static void __plic_toggle(struct plic_handler *handler, int hwirq, int enable)
 {
-       u32 __iomem *reg = enable_base + (hwirq / 32) * sizeof(u32);
+       u32 __iomem *base = handler->enable_base;
        u32 hwirq_mask = 1 << (hwirq % 32);
+       int group = hwirq / 32;
+       u32 value;
+
+       value = readl(base + group);
 
        if (enable)
-               writel(readl(reg) | hwirq_mask, reg);
+               value |= hwirq_mask;
        else
-               writel(readl(reg) & ~hwirq_mask, reg);
+               value &= ~hwirq_mask;
+
+       handler->enable_save[group] = value;
+       writel(value, base + group);
 }
 
 static void plic_toggle(struct plic_handler *handler, int hwirq, int enable)
@@ -110,7 +117,7 @@ static void plic_toggle(struct plic_handler *handler, int hwirq, int enable)
        unsigned long flags;
 
        raw_spin_lock_irqsave(&handler->enable_lock, flags);
-       __plic_toggle(handler->enable_base, hwirq, enable);
+       __plic_toggle(handler, hwirq, enable);
        raw_spin_unlock_irqrestore(&handler->enable_lock, flags);
 }
 
@@ -247,33 +254,16 @@ static int plic_irq_set_type(struct irq_data *d, unsigned int type)
 
 static int plic_irq_suspend(void)
 {
-       unsigned int i, cpu;
-       unsigned long flags;
-       u32 __iomem *reg;
        struct plic_priv *priv;
 
        priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv;
 
        /* irq ID 0 is reserved */
-       for (i = 1; i < priv->nr_irqs; i++) {
+       for (unsigned int i = 1; i < priv->nr_irqs; i++) {
                __assign_bit(i, priv->prio_save,
                             readl(priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID));
        }
 
-       for_each_present_cpu(cpu) {
-               struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu);
-
-               if (!handler->present)
-                       continue;
-
-               raw_spin_lock_irqsave(&handler->enable_lock, flags);
-               for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) {
-                       reg = handler->enable_base + i * sizeof(u32);
-                       handler->enable_save[i] = readl(reg);
-               }
-               raw_spin_unlock_irqrestore(&handler->enable_lock, flags);
-       }
-
        return 0;
 }