[PATCH v10 07/15] platform-msi: Introduce platform_device_msi_rewrite()

Pranjal Shrivastava praan at google.com
Tue Sep 8 10:17:03 PDT 2026


Platform devices using MSIs often lose their MSI configuration registers
during system suspend or power down. Add platform_device_msi_rewrite()
to re-apply the cached MSI configuration for a given IRQ using the
device-provided write_msi_msg callback.

Suggested-by: Jason Gunthorpe <jgg at nvidia.com>
Signed-off-by: Pranjal Shrivastava <praan at google.com>
---
 drivers/base/platform-msi.c | 37 +++++++++++++++++++++++++++++++++++++
 include/linux/msi.h         |  2 ++
 2 files changed, 39 insertions(+)

diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
index 69eed058eb20..022febf2da93 100644
--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -94,3 +94,40 @@ void platform_device_msi_free_irqs_all(struct device *dev)
 	msi_remove_device_irq_domain(dev, MSI_DEFAULT_DOMAIN);
 }
 EXPORT_SYMBOL_GPL(platform_device_msi_free_irqs_all);
+
+/**
+ * platform_device_msi_rewrite - Rewrite the MSI config for a platform device
+ * @dev:		The device for which to rewrite interrupt
+ * @irq:		The interrupt number to be rewritten.
+ * @write_msi_msg:	Callback to write the interrupt message for @dev
+ *
+ * Rewrites the cached MSI message for a platform device.
+ *
+ * Note: Platform MSI does not automatically cache composed messages. The caller's
+ * @write_msi_msg callback is expected to cache the message (e.g. into desc->msg)
+ * during initial configuration so it can be rewritten on resume.
+ */
+void platform_device_msi_rewrite(struct device *dev, unsigned int irq,
+				 irq_write_msi_msg_t write_msi_msg)
+{
+	struct msi_desc *desc;
+	struct msi_msg msg;
+
+	if (!irq || !write_msi_msg)
+		return;
+
+	desc = irq_get_msi_desc(irq);
+	if (!desc) {
+		dev_err(dev, "Failed to get MSI descriptor for irq %u\n", irq);
+		return;
+	}
+
+	__get_cached_msi_msg(desc, &msg);
+	if (!msg.address_hi && !msg.address_lo) {
+		dev_warn(dev, "No cached MSI message found for irq %u\n", irq);
+		return;
+	}
+
+	write_msi_msg(desc, &msg);
+}
+EXPORT_SYMBOL_GPL(platform_device_msi_rewrite);
diff --git a/include/linux/msi.h b/include/linux/msi.h
index a4613de11960..72b0d36160d9 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -673,6 +673,8 @@ struct msi_domain_info *msi_get_domain_info(struct irq_domain *domain);
 int platform_device_msi_init_and_alloc_irqs(struct device *dev, unsigned int nvec,
 					    irq_write_msi_msg_t write_msi_msg);
 void platform_device_msi_free_irqs_all(struct device *dev);
+void platform_device_msi_rewrite(struct device *dev, unsigned int irq,
+				 irq_write_msi_msg_t write_msi_msg);
 
 bool msi_device_has_isolated_msi(struct device *dev);
 
-- 
2.55.0.979.g7e5102b832-goog




More information about the linux-arm-kernel mailing list