[PATCH v4 09/21] iommu/riscv: Refresh platform MSI domain before IR setup
Andrew Jones <[email protected]>
| Newsgroups | org.infradead.lists.linux-riscv,dev.linux.lists.iommu,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Platform devices receive their MSI domain when they are created. On RISC-V, the IMSIC is itself a platform device, so consumer devices may be created before the IMSIC driver registers its MSI domain. fw_devlink delays consumer driver probing but does not refresh dev->msi.domain, leaving it NULL when the IOMMU probe_device callback runs. Refresh the OF or ACPI platform MSI domain before creating the per-device interrupt-remapping domain. Leave PCI devices alone because PCI establishes their MSI domain during device setup. This mirrors the workaround currently used by other RISC-V platform MSI consumers. A proposed driver-core change would perform the refresh from platform_dma_configure(), but until that is merged the local refresh avoids silently skipping interrupt-remapping setup. Signed-off-by: Andrew Jones <[email protected]> --- drivers/iommu/riscv/iommu-ir.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/riscv/iommu-ir.c b/drivers/iommu/riscv/iommu-ir.c index 0aab0efeb70e..3e08249015cd 100644 --- a/drivers/iommu/riscv/iommu-ir.c +++ b/drivers/iommu/riscv/iommu-ir.c @@ -4,8 +4,11 @@ * * Copyright (c) 2026 Qualcomm Technologies, Inc. */ +#include <linux/acpi.h> #include <linux/cleanup.h> #include <linux/msi.h> +#include <linux/of_irq.h> +#include <linux/platform_device.h> #include <linux/slab.h> #include "iommu.h" @@ -53,14 +56,35 @@ static const struct msi_parent_ops riscv_iommu_ir_msi_parent_ops = { .init_dev_msi_info = msi_parent_init_dev_msi_info, }; +static void riscv_iommu_ir_refresh_msi_domain(struct device *dev) +{ + struct fwnode_handle *fwnode = dev_fwnode(dev); + struct irq_domain *irqdomain; + + if (dev_get_msi_domain(dev) || !dev_is_platform(dev)) + return; + + if (is_of_node(fwnode)) { + of_msi_configure(dev, to_of_node(fwnode)); + } else if (is_acpi_device_node(fwnode)) { + fwnode = imsic_acpi_get_fwnode(dev); + irqdomain = irq_find_matching_fwnode(fwnode, DOMAIN_BUS_PLATFORM_MSI); + if (irqdomain) + dev_set_msi_domain(dev, irqdomain); + } +} + struct irq_domain *riscv_iommu_ir_irq_domain_create(struct device *dev, struct riscv_iommu_info *info) { - struct irq_domain *irqparent = dev_get_msi_domain(dev); + struct irq_domain *irqparent; char *fwname __free(kfree) = NULL; struct irq_domain *irqdomain; struct fwnode_handle *fn; + riscv_iommu_ir_refresh_msi_domain(dev); + irqparent = dev_get_msi_domain(dev); + if (!irqparent) return NULL; -- 2.43.0 _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv