[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.