diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-10 16:30:29 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-10 16:30:29 -0800 |
| commit | 3381d7b2b3dd012d366b9ba9339f98d54bea69fd (patch) | |
| tree | 6a0b972da773421b6d3c0df490cbd7130f33dcf4 /drivers/pci/msi | |
| parent | dc855b77719fe452d670cae2cf64da1eb51f16cc (diff) | |
| parent | cb9b6f9d2be6bda1b0117b147df40f982ce06888 (diff) | |
Merge tag 'irq-msi-2026-02-09' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull MSI updates from Thomas Gleixner:
"Updates for the [PCI] MSI subsystem:
- Add interrupt redirection infrastructure
Some PCI controllers use a single demultiplexing interrupt for the
MSI interrupts of subordinate devices.
This prevents setting the interrupt affinity of device interrupts,
which causes device interrupts to be delivered to a single CPU.
That obviously is counterproductive for multi-queue devices and
interrupt balancing.
To work around this limitation the new infrastructure installs a
dummy irq_set_affinity() callback which captures the affinity mask
and picks a redirection target CPU out of the mask.
When the PCI controller demultiplexes the interrupts it invokes a
new handling function in the core, which either runs the interrupt
handler in the context of the target CPU or delegates it to
irq_work on the target CPU.
- Utilize the interrupt redirection mechanism in the PCI DWC host
controller driver.
This allows affinity control for the subordinate device MSI
interrupts instead of being randomly executed on the CPU which runs
the demultiplex handler.
- Replace the binary 64-bit MSI flag with a DMA mask
Some PCI devices have PCI_MSI_FLAGS_64BIT in the MSI capability,
but implement less than 64 address bits. This breaks on platforms
where such a device is assigned an MSI address higher than what's
supported.
With the binary 64-bit flag there is no other choice than disabling
64-bit MSI support which leaves the device disfunctional.
By using a DMA mask the address limit of a device can be described
correctly which provides support for the above scenario.
- Make use of the DMA mask based address limit in the hda/intel and
radeon drivers to enable them on affected platforms
- The usual small cleanups and improvements"
* tag 'irq-msi-2026-02-09' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
ALSA: hda/intel: Make MSI address limit based on the device DMA limit
drm/radeon: Make MSI address limit based on the device DMA limit
PCI/MSI: Check the device specific address mask in msi_verify_entries()
PCI/MSI: Convert the boolean no_64bit_msi flag to a DMA address mask
genirq/redirect: Prevent writing MSI message on affinity change
PCI/MSI: Unmap MSI-X region on error
genirq: Update effective affinity for redirected interrupts
PCI: dwc: Enable MSI affinity support
PCI: dwc: Code cleanup
genirq: Add interrupt redirection infrastructure
genirq/msi: Correct kernel-doc in <linux/msi.h>
Diffstat (limited to 'drivers/pci/msi')
| -rw-r--r-- | drivers/pci/msi/msi.c | 14 | ||||
| -rw-r--r-- | drivers/pci/msi/pcidev_msi.c | 2 |
2 files changed, 10 insertions, 6 deletions
diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c index 34d664139f48..e2412175d7af 100644 --- a/drivers/pci/msi/msi.c +++ b/drivers/pci/msi/msi.c @@ -321,14 +321,16 @@ static int msi_setup_msi_desc(struct pci_dev *dev, int nvec, static int msi_verify_entries(struct pci_dev *dev) { struct msi_desc *entry; + u64 address; - if (!dev->no_64bit_msi) + if (dev->msi_addr_mask == DMA_BIT_MASK(64)) return 0; msi_for_each_desc(entry, &dev->dev, MSI_DESC_ALL) { - if (entry->msg.address_hi) { - pci_err(dev, "arch assigned 64-bit MSI address %#x%08x but device only supports 32 bits\n", - entry->msg.address_hi, entry->msg.address_lo); + address = (u64)entry->msg.address_hi << 32 | entry->msg.address_lo; + if (address & ~dev->msi_addr_mask) { + pci_err(dev, "arch assigned 64-bit MSI address %#llx above device MSI address mask %#llx\n", + address, dev->msi_addr_mask); break; } } @@ -737,7 +739,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, ret = msix_setup_interrupts(dev, entries, nvec, affd); if (ret) - goto out_disable; + goto out_unmap; /* Disable INTX */ pci_intx_for_msi(dev, 0); @@ -758,6 +760,8 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, pcibios_free_irq(dev); return 0; +out_unmap: + iounmap(dev->msix_base); out_disable: dev->msix_enabled = 0; pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE, 0); diff --git a/drivers/pci/msi/pcidev_msi.c b/drivers/pci/msi/pcidev_msi.c index 5520aff53b56..0b0346813092 100644 --- a/drivers/pci/msi/pcidev_msi.c +++ b/drivers/pci/msi/pcidev_msi.c @@ -24,7 +24,7 @@ void pci_msi_init(struct pci_dev *dev) } if (!(ctrl & PCI_MSI_FLAGS_64BIT)) - dev->no_64bit_msi = 1; + dev->msi_addr_mask = DMA_BIT_MASK(32); } void pci_msix_init(struct pci_dev *dev) |
