From: Frank Li Frank.Li@nxp.com
[ Upstream commit 9a958e1fd40d6fae8c66385687a00ebd9575a7d2 ]
platform_device_msi_init_and_alloc_irqs() performs two tasks: allocating the MSI domain for a platform device, and allocate a number of MSIs in that domain.
platform_device_msi_free_irqs_all() only frees the MSIs, and leaves the MSI domain alive.
Given that platform_device_msi_init_and_alloc_irqs() is the sole tool a platform device has to allocate platform MSIs, it makes sense for platform_device_msi_free_irqs_all() to teardown the MSI domain at the same time as the MSIs.
This avoids warnings and unexpected behaviours when a driver repeatedly allocates and frees MSIs.
Signed-off-by: Frank Li Frank.Li@nxp.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Acked-by: Marc Zyngier maz@kernel.org Link: https://lore.kernel.org/all/20250414-ep-msi-v18-1-f69b49917464@nxp.com Signed-off-by: Sasha Levin sashal@kernel.org ---
**YES** This commit should be backported to stable kernel trees. ## Analysis: ### Bug Being Fixed: The commit addresses a resource management asymmetry in the platform-MSI subsystem. The issue is that `platform_device_msi_init_and_alloc_irqs()` performs two operations: 1. Creates an MSI domain via `msi_create_device_irq_domain()` 2. Allocates MSIs in that domain via `msi_domain_alloc_irqs_range()` However, `platform_device_msi_free_irqs_all()` only performed one cleanup operation: 1. Freed the MSIs via `msi_domain_free_irqs_all()` 2. **Missing**: Domain cleanup via `msi_remove_device_irq_domain()` ### Code Change Analysis: The fix is minimal and surgical - adding just one line: ```c void platform_device_msi_free_irqs_all(struct device *dev) { msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN); + msi_remove_device_irq_domain(dev, MSI_DEFAULT_DOMAIN); } ``` This creates the missing symmetry between allocation and deallocation operations. ### Supporting Evidence from Kernel Repository: 1. **Related NULL pointer crash**: The UFS driver commit `64506b3d23a3` shows that missing MSI domain cleanup can lead to NULL pointer dereferences when drivers repeatedly allocate/free MSIs, requiring a `Cc: stable@vger.kernel.org # 6.3` tag. 2. **Recent platform-MSI evolution**: The git blame shows the current implementation was added in commit `c88f9110bfbc` (Jan 2024) by Thomas Gleixner, indicating this is relatively new code that needs stabilization. 3. **Consistent pattern**: The PCI MSI code (`drivers/pci/msi/irqdomain.c`) already follows this pattern, calling `msi_remove_device_irq_domain()` in cleanup paths. ### Stable Tree Criteria Assessment: ✅ **Fixes important bug**: Resource leaks and "warnings and unexpected behaviours" when drivers repeatedly allocate/free MSIs ✅ **Small and contained**: Single line addition with clear purpose ✅ **Minimal side effects**: Only adds missing cleanup, no behavioral changes ✅ **No architectural changes**: Simple resource management fix ✅ **Confined to subsystem**: Only affects platform-MSI infrastructure ✅ **Minimal regression risk**: Adding proper cleanup is very low risk ### Comparison to Historical Examples: This is most similar to "Similar Commit #1" (platform-msi resource leak fix) which was marked "Backport Status: YES" and had explicit `Cc: stable@vger.kernel.org`. Both commits: - Fix resource management bugs in platform-MSI - Have minimal, surgical changes - Address issues that affect driver stability - Follow existing patterns in the codebase The asymmetry between allocation and deallocation is a classic bug pattern that stable trees should address to prevent resource leaks and crashes in drivers using platform MSI.
drivers/base/platform-msi.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c index 0e60dd650b5e0..70db08f3ac6fa 100644 --- a/drivers/base/platform-msi.c +++ b/drivers/base/platform-msi.c @@ -95,5 +95,6 @@ EXPORT_SYMBOL_GPL(platform_device_msi_init_and_alloc_irqs); void platform_device_msi_free_irqs_all(struct device *dev) { msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN); + msi_remove_device_irq_domain(dev, MSI_DEFAULT_DOMAIN); } EXPORT_SYMBOL_GPL(platform_device_msi_free_irqs_all);