]> www.infradead.org Git - users/hch/misc.git/commitdiff
powerpc/xive: Untangle xive from child interrupt controller drivers
authorNam Cao <namcao@linutronix.de>
Mon, 11 Aug 2025 09:28:54 +0000 (11:28 +0200)
committerMadhavan Srinivasan <maddy@linux.ibm.com>
Sat, 6 Sep 2025 12:03:18 +0000 (17:33 +0530)
xive-specific data is stored in handler_data. This creates a mess, as xive
has to rely on child interrupt controller drivers to clean up this data, as
was done by 9a014f45688 ("powerpc/pseries/pci: Add a msi_free() handler to
clear XIVE data").

Instead, store xive-specific data in chip_data and untangle the child
drivers.

Signed-off-by: Nam Cao <namcao@linutronix.de>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/83968073022a4cc211dcbd0faccd20ec05e58c3e.1754903590.git.namcao@linutronix.de
arch/powerpc/include/asm/xive.h
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/pseries/msi.c
arch/powerpc/sysdev/xive/common.c

index 92930b0b5d0e17bcd7ec834fc1ce0c03c66b0a4e..efb0f5effcc6943cbd331880cf70d7d3796d2521 100644 (file)
@@ -111,7 +111,6 @@ void xive_native_free_vp_block(u32 vp_base);
 int xive_native_populate_irq_data(u32 hw_irq,
                                  struct xive_irq_data *data);
 void xive_cleanup_irq_data(struct xive_irq_data *xd);
-void xive_irq_free_data(unsigned int virq);
 void xive_native_free_irq(u32 irq);
 int xive_native_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq);
 
index 0166bf39ce1e52dfaa554d6637ca2f0fe079c981..1c730e6b7283ebcd40575b5011c050c2a3116629 100644 (file)
@@ -37,7 +37,6 @@
 #include <asm/firmware.h>
 #include <asm/pnv-pci.h>
 #include <asm/mmzone.h>
-#include <asm/xive.h>
 
 #include "powernv.h"
 #include "pci.h"
@@ -1707,23 +1706,6 @@ static int __pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
        return 0;
 }
 
-/*
- * The msi_free() op is called before irq_domain_free_irqs_top() when
- * the handler data is still available. Use that to clear the XIVE
- * controller.
- */
-static void pnv_msi_ops_msi_free(struct irq_domain *domain,
-                                struct msi_domain_info *info,
-                                unsigned int irq)
-{
-       if (xive_enabled())
-               xive_irq_free_data(irq);
-}
-
-static struct msi_domain_ops pnv_pci_msi_domain_ops = {
-       .msi_free       = pnv_msi_ops_msi_free,
-};
-
 static void pnv_msi_shutdown(struct irq_data *d)
 {
        d = d->parent_data;
@@ -1754,7 +1736,6 @@ static struct irq_chip pnv_pci_msi_irq_chip = {
 static struct msi_domain_info pnv_msi_domain_info = {
        .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
                  MSI_FLAG_MULTI_PCI_MSI  | MSI_FLAG_PCI_MSIX),
-       .ops   = &pnv_pci_msi_domain_ops,
        .chip  = &pnv_pci_msi_irq_chip,
 };
 
@@ -1870,7 +1851,7 @@ static void pnv_irq_domain_free(struct irq_domain *domain, unsigned int virq,
                 virq, d->hwirq, nr_irqs);
 
        msi_bitmap_free_hwirqs(&phb->msi_bmp, d->hwirq, nr_irqs);
-       /* XIVE domain is cleared through ->msi_free() */
+       irq_domain_free_irqs_parent(domain, virq, nr_irqs);
 }
 
 static const struct irq_domain_ops pnv_irq_domain_ops = {
index 9dc294de631f1d617be18e66f165e69c07943d0a..e5cf061c519ee5749d927f6a7106a1d997011619 100644 (file)
@@ -15,7 +15,6 @@
 #include <asm/hw_irq.h>
 #include <asm/ppc-pci.h>
 #include <asm/machdep.h>
-#include <asm/xive.h>
 
 #include "pseries.h"
 
@@ -436,19 +435,6 @@ static int pseries_msi_ops_prepare(struct irq_domain *domain, struct device *dev
        return rtas_prepare_msi_irqs(pdev, nvec, type, arg);
 }
 
-/*
- * ->msi_free() is called before irq_domain_free_irqs_top() when the
- * handler data is still available. Use that to clear the XIVE
- * controller data.
- */
-static void pseries_msi_ops_msi_free(struct irq_domain *domain,
-                                    struct msi_domain_info *info,
-                                    unsigned int irq)
-{
-       if (xive_enabled())
-               xive_irq_free_data(irq);
-}
-
 /*
  * RTAS can not disable one MSI at a time. It's all or nothing. Do it
  * at the end after all IRQs have been freed.
@@ -463,7 +449,6 @@ static void pseries_msi_post_free(struct irq_domain *domain, struct device *dev)
 
 static struct msi_domain_ops pseries_pci_msi_domain_ops = {
        .msi_prepare    = pseries_msi_ops_prepare,
-       .msi_free       = pseries_msi_ops_msi_free,
        .msi_post_free  = pseries_msi_post_free,
 };
 
@@ -604,8 +589,7 @@ static void pseries_irq_domain_free(struct irq_domain *domain, unsigned int virq
        struct pci_controller *phb = irq_data_get_irq_chip_data(d);
 
        pr_debug("%s bridge %pOF %d #%d\n", __func__, phb->dn, virq, nr_irqs);
-
-       /* XIVE domain data is cleared through ->msi_free() */
+       irq_domain_free_irqs_parent(domain, virq, nr_irqs);
 }
 
 static const struct irq_domain_ops pseries_irq_domain_ops = {
index f10592405024794cbee5853bd336fe0dd6e0c0f9..625361a15424e5aff258b36d5d792bd402e1ab00 100644 (file)
@@ -317,7 +317,7 @@ int xmon_xive_get_irq_config(u32 hw_irq, struct irq_data *d)
        if (d) {
                char buffer[128];
 
-               xive_irq_data_dump(irq_data_get_irq_handler_data(d),
+               xive_irq_data_dump(irq_data_get_irq_chip_data(d),
                                   buffer, sizeof(buffer));
                xmon_printf("%s", buffer);
        }
@@ -437,7 +437,7 @@ static void xive_do_source_eoi(struct xive_irq_data *xd)
 /* irq_chip eoi callback, called with irq descriptor lock held */
 static void xive_irq_eoi(struct irq_data *d)
 {
-       struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
+       struct xive_irq_data *xd = irq_data_get_irq_chip_data(d);
        struct xive_cpu *xc = __this_cpu_read(xive_cpu);
 
        DBG_VERBOSE("eoi_irq: irq=%d [0x%lx] pending=%02x\n",
@@ -595,7 +595,7 @@ static int xive_pick_irq_target(struct irq_data *d,
                                const struct cpumask *affinity)
 {
        static unsigned int fuzz;
-       struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
+       struct xive_irq_data *xd = irq_data_get_irq_chip_data(d);
        cpumask_var_t mask;
        int cpu = -1;
 
@@ -628,7 +628,7 @@ static int xive_pick_irq_target(struct irq_data *d,
 
 static unsigned int xive_irq_startup(struct irq_data *d)
 {
-       struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
+       struct xive_irq_data *xd = irq_data_get_irq_chip_data(d);
        unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
        int target, rc;
 
@@ -673,7 +673,7 @@ static unsigned int xive_irq_startup(struct irq_data *d)
 /* called with irq descriptor lock held */
 static void xive_irq_shutdown(struct irq_data *d)
 {
-       struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
+       struct xive_irq_data *xd = irq_data_get_irq_chip_data(d);
        unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
 
        pr_debug("%s: irq %d [0x%x] data @%p\n", __func__, d->irq, hw_irq, d);
@@ -698,7 +698,7 @@ static void xive_irq_shutdown(struct irq_data *d)
 
 static void xive_irq_unmask(struct irq_data *d)
 {
-       struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
+       struct xive_irq_data *xd = irq_data_get_irq_chip_data(d);
 
        pr_debug("%s: irq %d data @%p\n", __func__, d->irq, xd);
 
@@ -707,7 +707,7 @@ static void xive_irq_unmask(struct irq_data *d)
 
 static void xive_irq_mask(struct irq_data *d)
 {
-       struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
+       struct xive_irq_data *xd = irq_data_get_irq_chip_data(d);
 
        pr_debug("%s: irq %d data @%p\n", __func__, d->irq, xd);
 
@@ -718,7 +718,7 @@ static int xive_irq_set_affinity(struct irq_data *d,
                                 const struct cpumask *cpumask,
                                 bool force)
 {
-       struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
+       struct xive_irq_data *xd = irq_data_get_irq_chip_data(d);
        unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
        u32 target, old_target;
        int rc = 0;
@@ -776,7 +776,7 @@ static int xive_irq_set_affinity(struct irq_data *d,
 
 static int xive_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-       struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
+       struct xive_irq_data *xd = irq_data_get_irq_chip_data(d);
 
        /*
         * We only support these. This has really no effect other than setting
@@ -815,7 +815,7 @@ static int xive_irq_set_type(struct irq_data *d, unsigned int flow_type)
 
 static int xive_irq_retrigger(struct irq_data *d)
 {
-       struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
+       struct xive_irq_data *xd = irq_data_get_irq_chip_data(d);
 
        /* This should be only for MSIs */
        if (WARN_ON(xd->flags & XIVE_IRQ_FLAG_LSI))
@@ -837,7 +837,7 @@ static int xive_irq_retrigger(struct irq_data *d)
  */
 static int xive_irq_set_vcpu_affinity(struct irq_data *d, void *state)
 {
-       struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
+       struct xive_irq_data *xd = irq_data_get_irq_chip_data(d);
        unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
        int rc;
        u8 pq;
@@ -951,7 +951,7 @@ static int xive_irq_set_vcpu_affinity(struct irq_data *d, void *state)
 static int xive_get_irqchip_state(struct irq_data *data,
                                  enum irqchip_irq_state which, bool *state)
 {
-       struct xive_irq_data *xd = irq_data_get_irq_handler_data(data);
+       struct xive_irq_data *xd = irq_data_get_irq_chip_data(data);
        u8 pq;
 
        switch (which) {
@@ -1011,21 +1011,20 @@ void xive_cleanup_irq_data(struct xive_irq_data *xd)
 }
 EXPORT_SYMBOL_GPL(xive_cleanup_irq_data);
 
-static int xive_irq_alloc_data(unsigned int virq, irq_hw_number_t hw)
+static struct xive_irq_data *xive_irq_alloc_data(unsigned int virq, irq_hw_number_t hw)
 {
        struct xive_irq_data *xd;
        int rc;
 
        xd = kzalloc(sizeof(struct xive_irq_data), GFP_KERNEL);
        if (!xd)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
        rc = xive_ops->populate_irq_data(hw, xd);
        if (rc) {
                kfree(xd);
-               return rc;
+               return ERR_PTR(rc);
        }
        xd->target = XIVE_INVALID_TARGET;
-       irq_set_handler_data(virq, xd);
 
        /*
         * Turn OFF by default the interrupt being mapped. A side
@@ -1036,20 +1035,19 @@ static int xive_irq_alloc_data(unsigned int virq, irq_hw_number_t hw)
         */
        xive_esb_read(xd, XIVE_ESB_SET_PQ_01);
 
-       return 0;
+       return xd;
 }
 
-void xive_irq_free_data(unsigned int virq)
+static void xive_irq_free_data(unsigned int virq)
 {
-       struct xive_irq_data *xd = irq_get_handler_data(virq);
+       struct xive_irq_data *xd = irq_get_chip_data(virq);
 
        if (!xd)
                return;
-       irq_set_handler_data(virq, NULL);
+       irq_set_chip_data(virq, NULL);
        xive_cleanup_irq_data(xd);
        kfree(xd);
 }
-EXPORT_SYMBOL_GPL(xive_irq_free_data);
 
 #ifdef CONFIG_SMP
 
@@ -1286,7 +1284,7 @@ void __init xive_smp_probe(void)
 static int xive_irq_domain_map(struct irq_domain *h, unsigned int virq,
                               irq_hw_number_t hw)
 {
-       int rc;
+       struct xive_irq_data *xd;
 
        /*
         * Mark interrupts as edge sensitive by default so that resend
@@ -1294,11 +1292,12 @@ static int xive_irq_domain_map(struct irq_domain *h, unsigned int virq,
         */
        irq_clear_status_flags(virq, IRQ_LEVEL);
 
-       rc = xive_irq_alloc_data(virq, hw);
-       if (rc)
-               return rc;
+       xd = xive_irq_alloc_data(virq, hw);
+       if (IS_ERR(xd))
+               return PTR_ERR(xd);
 
        irq_set_chip_and_handler(virq, &xive_irq_chip, handle_fasteoi_irq);
+       irq_set_chip_data(virq, xd);
 
        return 0;
 }
@@ -1366,7 +1365,7 @@ static void xive_irq_domain_debug_show(struct seq_file *m, struct irq_domain *d,
        seq_printf(m, "%*sXIVE:\n", ind, "");
        ind++;
 
-       xd = irq_data_get_irq_handler_data(irqd);
+       xd = irq_data_get_irq_chip_data(irqd);
        if (!xd) {
                seq_printf(m, "%*snot assigned\n", ind, "");
                return;
@@ -1403,6 +1402,7 @@ static int xive_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
                                 unsigned int nr_irqs, void *arg)
 {
        struct irq_fwspec *fwspec = arg;
+       struct xive_irq_data *xd;
        irq_hw_number_t hwirq;
        unsigned int type = IRQ_TYPE_NONE;
        int i, rc;
@@ -1423,12 +1423,11 @@ static int xive_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
                irq_clear_status_flags(virq, IRQ_LEVEL);
 
                /* allocates and sets handler data */
-               rc = xive_irq_alloc_data(virq + i, hwirq + i);
-               if (rc)
-                       return rc;
+               xd = xive_irq_alloc_data(virq + i, hwirq + i);
+               if (IS_ERR(xd))
+                       return PTR_ERR(xd);
 
-               irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
-                                             &xive_irq_chip, domain->host_data);
+               irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, &xive_irq_chip, xd);
                irq_set_handler(virq + i, handle_fasteoi_irq);
        }
 
@@ -1764,7 +1763,7 @@ static void xive_debug_show_irq(struct seq_file *m, struct irq_data *d)
        seq_printf(m, "IRQ 0x%08x : target=0x%x prio=%02x lirq=0x%x ",
                   hw_irq, target, prio, lirq);
 
-       xive_irq_data_dump(irq_data_get_irq_handler_data(d), buffer, sizeof(buffer));
+       xive_irq_data_dump(irq_data_get_irq_chip_data(d), buffer, sizeof(buffer));
        seq_puts(m, buffer);
        seq_puts(m, "\n");
 }