[PATCH v4 09/21] iommu/riscv: Refresh platform MSI domain before IR setup

Andrew Jones andrew.jones at oss.qualcomm.com
Thu Aug 20 14:41:38 PDT 2026


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 <andrew.jones at oss.qualcomm.com>
---
 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




More information about the linux-riscv mailing list