From dce745009349fc391271c9415d5e242781ddadd7 Mon Sep 17 00:00:00 2001 From: Nam Cao Date: Mon, 21 Jul 2025 08:36:26 +0200 Subject: [PATCH 1/4] PCI/MSI: Delete pci_msi_create_irq_domain() pci_msi_create_irq_domain() is now unused. Delete it. Signed-off-by: Nam Cao Signed-off-by: Thomas Gleixner Acked-by: Bjorn Helgaas --- drivers/pci/msi/irqdomain.c | 90 ------------------------------------- include/linux/msi.h | 3 -- 2 files changed, 93 deletions(-) diff --git a/drivers/pci/msi/irqdomain.c b/drivers/pci/msi/irqdomain.c index ce741ed9dc3f..a329060287b5 100644 --- a/drivers/pci/msi/irqdomain.c +++ b/drivers/pci/msi/irqdomain.c @@ -49,96 +49,6 @@ static void pci_msi_domain_write_msg(struct irq_data *irq_data, struct msi_msg * __pci_write_msi_msg(desc, msg); } -/** - * pci_msi_domain_calc_hwirq - Generate a unique ID for an MSI source - * @desc: Pointer to the MSI descriptor - * - * The ID number is only used within the irqdomain. - */ -static irq_hw_number_t pci_msi_domain_calc_hwirq(struct msi_desc *desc) -{ - struct pci_dev *dev = msi_desc_to_pci_dev(desc); - - return (irq_hw_number_t)desc->msi_index | - pci_dev_id(dev) << 11 | - ((irq_hw_number_t)(pci_domain_nr(dev->bus) & 0xFFFFFFFF)) << 27; -} - -static void pci_msi_domain_set_desc(msi_alloc_info_t *arg, - struct msi_desc *desc) -{ - arg->desc = desc; - arg->hwirq = pci_msi_domain_calc_hwirq(desc); -} - -static struct msi_domain_ops pci_msi_domain_ops_default = { - .set_desc = pci_msi_domain_set_desc, -}; - -static void pci_msi_domain_update_dom_ops(struct msi_domain_info *info) -{ - struct msi_domain_ops *ops = info->ops; - - if (ops == NULL) { - info->ops = &pci_msi_domain_ops_default; - } else { - if (ops->set_desc == NULL) - ops->set_desc = pci_msi_domain_set_desc; - } -} - -static void pci_msi_domain_update_chip_ops(struct msi_domain_info *info) -{ - struct irq_chip *chip = info->chip; - - BUG_ON(!chip); - if (!chip->irq_write_msi_msg) - chip->irq_write_msi_msg = pci_msi_domain_write_msg; - if (!chip->irq_mask) - chip->irq_mask = pci_msi_mask_irq; - if (!chip->irq_unmask) - chip->irq_unmask = pci_msi_unmask_irq; -} - -/** - * pci_msi_create_irq_domain - Create a MSI interrupt domain - * @fwnode: Optional fwnode of the interrupt controller - * @info: MSI domain info - * @parent: Parent irq domain - * - * Updates the domain and chip ops and creates a MSI interrupt domain. - * - * Returns: - * A domain pointer or NULL in case of failure. - */ -struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode, - struct msi_domain_info *info, - struct irq_domain *parent) -{ - if (WARN_ON(info->flags & MSI_FLAG_LEVEL_CAPABLE)) - info->flags &= ~MSI_FLAG_LEVEL_CAPABLE; - - if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) - pci_msi_domain_update_dom_ops(info); - if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) - pci_msi_domain_update_chip_ops(info); - - /* Let the core code free MSI descriptors when freeing interrupts */ - info->flags |= MSI_FLAG_FREE_MSI_DESCS; - - info->flags |= MSI_FLAG_ACTIVATE_EARLY | MSI_FLAG_DEV_SYSFS; - if (IS_ENABLED(CONFIG_GENERIC_IRQ_RESERVATION_MODE)) - info->flags |= MSI_FLAG_MUST_REACTIVATE; - - /* PCI-MSI is oneshot-safe */ - info->chip->flags |= IRQCHIP_ONESHOT_SAFE; - /* Let the core update the bus token */ - info->bus_token = DOMAIN_BUS_PCI_MSI; - - return msi_create_irq_domain(fwnode, info, parent); -} -EXPORT_SYMBOL_GPL(pci_msi_create_irq_domain); - /* * Per device MSI[-X] domain functionality */ diff --git a/include/linux/msi.h b/include/linux/msi.h index d415dd15a0a9..8003e3218c46 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -701,9 +701,6 @@ void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg); void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg); void pci_msi_mask_irq(struct irq_data *data); void pci_msi_unmask_irq(struct irq_data *data); -struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode, - struct msi_domain_info *info, - struct irq_domain *parent); u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev); u32 pci_msi_map_rid_ctlr_node(struct pci_dev *pdev, struct device_node **node); struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev); From ac646f44956edc9aaa406b4a8fef17888a2166af Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 19 Oct 2025 10:40:08 +0200 Subject: [PATCH 2/4] genirq/msi: Slightly simplify msi_domain_alloc() The return value of irq_find_mapping() is only tested, not used for anything else. Replaced it by irq_resolve_mapping() which is internally used by irq_find_mapping() and allows a simple boolean decision. Signed-off-by: Christophe JAILLET Signed-off-by: Thomas Gleixner Link: https://patch.msgid.link/1ce680114cdb8d40b072c54d7f015696a540e5a6.1760863194.git.christophe.jaillet@wanadoo.fr --- kernel/irq/msi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index e7ad99254841..68886881fe10 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -706,7 +706,7 @@ static int msi_domain_alloc(struct irq_domain *domain, unsigned int virq, irq_hw_number_t hwirq = ops->get_hwirq(info, arg); int i, ret; - if (irq_find_mapping(domain, hwirq) > 0) + if (irq_resolve_mapping(domain, hwirq)) return -EEXIST; if (domain->parent) { From 4f32612f6a4e5a9b1344aebf856aa1a1581a426d Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Tue, 21 Oct 2025 14:41:02 +0200 Subject: [PATCH 3/4] PCI: iproc: Implement MSI controller node detection with of_msi_xlate() The functionality implemented in the iproc driver in order to detect an OF MSI controller node is now fully implemented in of_msi_xlate(). Replace the current msi-map/msi-parent parsing code with of_msi_xlate(). Since of_msi_xlate() is also a deviceID mapping API, pass in a fictitious 0 as deviceID - the driver only requires detecting the OF MSI controller node not the deviceID mapping per-se (of_msi_xlate() return value is ignored for the same reason). Signed-off-by: Lorenzo Pieralisi Signed-off-by: Thomas Gleixner Reviewed-by: Frank Li Acked-by: Bjorn Helgaas Link: https://patch.msgid.link/20251021124103.198419-5-lpieralisi@kernel.org --- drivers/pci/controller/pcie-iproc.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c index 22134e95574b..ccf71993ea35 100644 --- a/drivers/pci/controller/pcie-iproc.c +++ b/drivers/pci/controller/pcie-iproc.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -1337,29 +1338,16 @@ static int iproc_pcie_msi_steer(struct iproc_pcie *pcie, static int iproc_pcie_msi_enable(struct iproc_pcie *pcie) { - struct device_node *msi_node; + struct device_node *msi_node = NULL; int ret; /* * Either the "msi-parent" or the "msi-map" phandle needs to exist * for us to obtain the MSI node. */ - - msi_node = of_parse_phandle(pcie->dev->of_node, "msi-parent", 0); - if (!msi_node) { - const __be32 *msi_map = NULL; - int len; - u32 phandle; - - msi_map = of_get_property(pcie->dev->of_node, "msi-map", &len); - if (!msi_map) - return -ENODEV; - - phandle = be32_to_cpup(msi_map + 1); - msi_node = of_find_node_by_phandle(phandle); - if (!msi_node) - return -ENODEV; - } + of_msi_xlate(pcie->dev, &msi_node, 0); + if (!msi_node) + return -ENODEV; /* * Certain revisions of the iProc PCIe controller require additional From 9c1fbc56ca0a98113e75dcc5030103a02eff8897 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Tue, 21 Oct 2025 14:41:03 +0200 Subject: [PATCH 4/4] irqchip/gic-its: Rework platform MSI deviceID detection Current code retrieving platform devices MSI devID in the GIC ITS MSI parent helpers suffers from some minor issues: - It leaks a struct device_node reference - It is duplicated between GICv3 and GICv5 for no good reason - It does not use the OF phandle iterator code that simplifies the msi-parent property parsing Consolidate GIC v3 and v5 deviceID retrieval in a function that addresses the full set of issues in one go by merging GIC v3 and v5 code and converting the msi-parent parsing loop to the more modern OF phandle iterator API, fixing the struct device_node reference leak in the process. Signed-off-by: Lorenzo Pieralisi Signed-off-by: Thomas Gleixner Reviewed-by: Frank Li Reviewed-by: Marc Zyngier Link: https://patch.msgid.link/20251021124103.198419-6-lpieralisi@kernel.org --- drivers/irqchip/irq-gic-its-msi-parent.c | 91 ++++++------------------ 1 file changed, 23 insertions(+), 68 deletions(-) diff --git a/drivers/irqchip/irq-gic-its-msi-parent.c b/drivers/irqchip/irq-gic-its-msi-parent.c index eb1473f1448a..12f45228c867 100644 --- a/drivers/irqchip/irq-gic-its-msi-parent.c +++ b/drivers/irqchip/irq-gic-its-msi-parent.c @@ -142,83 +142,38 @@ static int its_v5_pci_msi_prepare(struct irq_domain *domain, struct device *dev, #define its_v5_pci_msi_prepare NULL #endif /* !CONFIG_PCI_MSI */ -static int of_pmsi_get_dev_id(struct irq_domain *domain, struct device *dev, - u32 *dev_id) +static int of_pmsi_get_msi_info(struct irq_domain *domain, struct device *dev, u32 *dev_id, + phys_addr_t *pa) { - int ret, index = 0; + struct of_phandle_iterator it; + int ret; /* Suck the DeviceID out of the msi-parent property */ - do { - struct of_phandle_args args; + of_for_each_phandle(&it, ret, dev->of_node, "msi-parent", "#msi-cells", -1) { + /* GICv5 ITS domain matches the MSI controller node parent */ + struct device_node *np __free(device_node) = pa ? of_get_parent(it.node) + : of_node_get(it.node); - ret = of_parse_phandle_with_args(dev->of_node, - "msi-parent", "#msi-cells", - index, &args); - if (args.np == irq_domain_get_of_node(domain)) { - if (WARN_ON(args.args_count != 1)) - return -EINVAL; - *dev_id = args.args[0]; - break; - } - index++; - } while (!ret); + if (np == irq_domain_get_of_node(domain)) { + u32 args; - if (ret) { - struct device_node *np = NULL; + if (WARN_ON(of_phandle_iterator_args(&it, &args, 1) != 1)) + ret = -EINVAL; - ret = of_map_id(dev->of_node, dev->id, "msi-map", "msi-map-mask", &np, dev_id); - if (np) - of_node_put(np); - } + if (!ret && pa) + ret = its_translate_frame_address(it.node, pa); - return ret; -} + if (!ret) + *dev_id = args; -static int of_v5_pmsi_get_msi_info(struct irq_domain *domain, struct device *dev, - u32 *dev_id, phys_addr_t *pa) -{ - int ret, index = 0; - /* - * Retrieve the DeviceID and the ITS translate frame node pointer - * out of the msi-parent property. - */ - do { - struct of_phandle_args args; - - ret = of_parse_phandle_with_args(dev->of_node, - "msi-parent", "#msi-cells", - index, &args); - if (ret) - break; - /* - * The IRQ domain fwnode is the msi controller parent - * in GICv5 (where the msi controller nodes are the - * ITS translate frames). - */ - if (args.np->parent == irq_domain_get_of_node(domain)) { - if (WARN_ON(args.args_count != 1)) - return -EINVAL; - *dev_id = args.args[0]; - - ret = its_translate_frame_address(args.np, pa); - if (ret) - return -ENODEV; - break; - } - index++; - } while (!ret); - - if (ret) { - struct device_node *np = NULL; - - ret = of_map_id(dev->of_node, dev->id, "msi-map", "msi-map-mask", &np, dev_id); - if (np) { - ret = its_translate_frame_address(np, pa); - of_node_put(np); + of_node_put(it.node); + return ret; } } - return ret; + struct device_node *msi_ctrl __free(device_node) = NULL; + + return of_map_id(dev->of_node, dev->id, "msi-map", "msi-map-mask", &msi_ctrl, dev_id); } int __weak iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id) @@ -234,7 +189,7 @@ static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev, int ret; if (dev->of_node) - ret = of_pmsi_get_dev_id(domain->parent, dev, &dev_id); + ret = of_pmsi_get_msi_info(domain->parent, dev, &dev_id, NULL); else ret = iort_pmsi_get_dev_id(dev, &dev_id); if (ret) @@ -262,7 +217,7 @@ static int its_v5_pmsi_prepare(struct irq_domain *domain, struct device *dev, if (!dev->of_node) return -ENODEV; - ret = of_v5_pmsi_get_msi_info(domain->parent, dev, &dev_id, &pa); + ret = of_pmsi_get_msi_info(domain->parent, dev, &dev_id, &pa); if (ret) return ret;