[PATCH v10 07/15] platform-msi: Introduce platform_device_msi_rewrite()
From: Pranjal Shrivastava <praan@google.com>
Date: 2026-09-08 17:17:32
Also in:
driver-core, linux-iommu
Subsystem:
driver core, kobjects, debugfs and sysfs, the rest · Maintainers:
Greg Kroah-Hartman, "Rafael J. Wysocki", Danilo Krummrich, Linus Torvalds
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@nvidia.com> Signed-off-by: Pranjal Shrivastava <praan@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