[PATCH v4 09/21] iommu/riscv: Refresh platform MSI domain before IR setup
From: Andrew Jones
Date: Thu Aug 20 2026 - 17:48:51 EST
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@xxxxxxxxxxxxxxxx>
---
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