]> git.ipfire.org Git - thirdparty/kernel/linux.git/commit
genirq/msi: Move prepare() call to per-device allocation
authorMarc Zyngier <maz@kernel.org>
Tue, 13 May 2025 16:31:42 +0000 (17:31 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Wed, 14 May 2025 10:36:41 +0000 (12:36 +0200)
commit1396e89e09f00deb816e5f4a176d71d554922292
tree6d497bd28611de133f993563087d7cc938a9e01b
parent713335b6ee29f0045737a1ddfc685bc6040d4baf
genirq/msi: Move prepare() call to per-device allocation

The current device MSI infrastructure is subtly broken, as it will issue an
.msi_prepare() callback into the MSI controller driver every time it needs
to allocate an MSI. That's pretty wrong, as the contract (or unwarranted
assumption, depending who you ask) between the MSI controller and the core
code is that .msi_prepare() is called exactly once per device.

This leads to some subtle breakage in some MSI controller drivers, as it
gives the impression that there are multiple endpoints sharing a bus
identifier (RID in PCI parlance, DID for GICv3+). It implies that whatever
allocation the ITS driver (for example) has done on behalf of these devices
cannot be undone, as there is no way to track the shared state. This is
particularly bad for wire-MSI devices, for which .msi_prepare() is called
for each input line.

To address this issue, move the call to .msi_prepare() to take place at the
point of irq domain allocation, which is the only place that makes
sense. The msi_alloc_info_t structure is made part of the
msi_domain_template, so that its life-cycle is that of the domain as well.

Finally, the msi_info::alloc_data field is made to point at this allocation
tracking structure, ensuring that it is carried around the block.

This is all pretty straightforward, except for the non-device-MSI
leftovers, which still have to call .msi_prepare() at the old spot. One
day...

Signed-off-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20250513163144.2215824-4-maz@kernel.org
include/linux/msi.h
kernel/irq/msi.c