* [PATCH] PCI/MSI: Skip address mask check for MSI-X entries
@ 2026-11-09 9:24 Yu Yang via B4 Relay
2026-11-09 13:52 ` Thomas Gleixner
2026-11-09 20:11 ` sashiko-bot
0 siblings, 2 replies; 4+ messages in thread
From: Yu Yang via B4 Relay @ 2026-11-09 9:24 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: linux-pci, Thomas Gleixner, Michael Ellerman, Brett Creeley,
Shannon Nelson, linux-kernel, Yu Yang
From: Yu Yang <yuyang@kylinos.cn>
The AHCI controller on Zhaoxin ZX-200 platforms supports only 32-bit
MSI addresses, but its MSI-X capability uses 64-bit message addresses.
pci_msi_init() therefore sets dev->msi_addr_mask to DMA_BIT_MASK(32)
based on the MSI capability.
msi_verify_entries() is shared between the MSI and MSI-X setup paths.
When the irq domain assigns an MSI-X message address above 4GB, the
32-bit mask inherited from the MSI capability causes MSI-X setup to
fail with -EIO:
ahci 0000:09:0f.0: arch assigned 64-bit MSI address 0x8002a030040
above device MSI address mask 0xffffffff.
...
ahci: probe of 0000:09:0f.0 failed with error -22.
MSI-X table entries have a 64-bit message address field, so the 32-bit
limit derived from the MSI capability does not apply to them.
Platforms that use msi_addr_mask to constrain MSI-X allocation, e.g.
powerpc pseries/powernv and ionic on PPC64, already allocate addresses
that satisfy the mask, so the verification is redundant for MSI-X.
Skip the address mask check for MSI-X descriptors.
Fixes: f144d1496b47 ("PCI/MSI: Add device flag indicating that 64-bit MSIs don't work")
Signed-off-by: Yu Yang <yuyang@kylinos.cn>
---
drivers/pci/msi/msi.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c
index 8a0133a6a286..7f34bccc8248 100644
--- a/drivers/pci/msi/msi.c
+++ b/drivers/pci/msi/msi.c
@@ -338,6 +338,13 @@ static int msi_verify_entries(struct pci_dev *dev)
return 0;
msi_for_each_desc(entry, &dev->dev, MSI_DESC_ALL) {
+ /*
+ * MSI-X entries always use a 64-bit address, so the address
+ * limit for MSI capability does not apply for MSI-X.
+ */
+ if (entry->pci.msi_attrib.is_msix)
+ continue;
+
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",
---
base-commit: 996a59519af2ef3d8f47479685616bb2278c6cfa
change-id: 20261109-pci-fix-msix-alloc-failure-cdffedf97e82
Best regards,
--
Yu Yang <yuyang@kylinos.cn>
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH] PCI/MSI: Skip address mask check for MSI-X entries
2026-11-09 9:24 [PATCH] PCI/MSI: Skip address mask check for MSI-X entries Yu Yang via B4 Relay
@ 2026-11-09 13:52 ` Thomas Gleixner
2026-11-12 1:35 ` Yu Yang
2026-11-09 20:11 ` sashiko-bot
1 sibling, 1 reply; 4+ messages in thread
From: Thomas Gleixner @ 2026-11-09 13:52 UTC (permalink / raw)
To: Yu Yang via B4 Relay, Bjorn Helgaas
Cc: linux-pci, Michael Ellerman, Brett Creeley, Shannon Nelson,
linux-kernel, Yu Yang
On Mon, Nov 09 2026 at 17:24, Yu Yang via B4 Relay wrote:
> From: Yu Yang <yuyang@kylinos.cn>
>
> The AHCI controller on Zhaoxin ZX-200 platforms supports only 32-bit
> MSI addresses, but its MSI-X capability uses 64-bit message addresses.
> pci_msi_init() therefore sets dev->msi_addr_mask to DMA_BIT_MASK(32)
> based on the MSI capability.
>
> msi_verify_entries() is shared between the MSI and MSI-X setup paths.
> When the irq domain assigns an MSI-X message address above 4GB, the
> 32-bit mask inherited from the MSI capability causes MSI-X setup to
> fail with -EIO:
>
> ahci 0000:09:0f.0: arch assigned 64-bit MSI address 0x8002a030040
> above device MSI address mask 0xffffffff.
> ...
> ahci: probe of 0000:09:0f.0 failed with error -22.
>
> MSI-X table entries have a 64-bit message address field, so the 32-bit
> limit derived from the MSI capability does not apply to them.
That's just wrong. The limitation is not about the size of the address
field. The limitation is about the ability of the platform/device to
handle DMA to addresses above 4G.
There are devices/platforms out there which have such limitiations.
> Platforms that use msi_addr_mask to constrain MSI-X allocation, e.g.
> powerpc pseries/powernv and ionic on PPC64, already allocate addresses
> that satisfy the mask, so the verification is redundant for MSI-X.
The core cannot rely on random implementation details of drivers and
architecture code. It fails gracefully when the provided address limit
is violated to prevent hard to diagnose subsequent failures.
Coming back to your AHCI controller. That's broken to begin with. Assume
that MSI-X is not supported then MSI setup would fail the same way. You
don't notice because MSI-X is always enabled on x86 platforms.
Something like the uncompiled below should work. You get the idea.
Thanks,
tglx
---
--- a/drivers/pci/msi/msi.c
+++ b/drivers/pci/msi/msi.c
@@ -430,6 +430,9 @@ int __pci_enable_msi_range(struct pci_de
if (!pci_msi_supported(dev, minvec) || dev->current_state != PCI_D0)
return -EINVAL;
+ if (dev->pci_msi_broken)
+ return -ENOTSUPP;
+
/* Check whether driver already requested MSI-X IRQs */
if (dev->msix_enabled) {
pci_info(dev, "can't enable MSI (MSI-X already enabled)\n");
--- a/drivers/pci/msi/pcidev_msi.c
+++ b/drivers/pci/msi/pcidev_msi.c
@@ -23,6 +23,14 @@ void pci_msi_init(struct pci_dev *dev)
ctrl & ~PCI_MSI_FLAGS_ENABLE);
}
+ /*
+ * PCI/MSI support on some devices is broken and would end up
+ * restricting the MSI address mask which in turn breaks MSI-X support
+ * on the device.
+ */
+ if (dev->pci_msi__broken)
+ return;
+
if (!(ctrl & PCI_MSI_FLAGS_64BIT))
dev->msi_addr_mask = DMA_BIT_MASK(32);
}
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -6449,6 +6449,12 @@ static void nvidia_ion_ahci_fixup(struct
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0ab8, nvidia_ion_ahci_fixup);
+static void zhaoxin_ahci_fixup(struct pci_dev *pdev)
+{
+ pdev->pci_msi_broken = 1;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ZHAOZIN, 0x????, zhaoxin_ahci_fixup);
+
static void rom_bar_overlap_defect(struct pci_dev *dev)
{
pci_info(dev, "working around ROM BAR overlap defect\n");
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -515,6 +515,7 @@ struct pci_dev {
unsigned int rom_bar_overlap:1; /* ROM BAR disable broken */
unsigned int rom_attr_enabled:1; /* Display of ROM attribute enabled? */
unsigned int non_mappable_bars:1; /* BARs can't be mapped by CPU or peers */
+ unsigned int pci_msi_broken:1, /* PCI/MSI support broken. PCI/MSI-X still works */
pci_dev_flags_t dev_flags;
atomic_t enable_cnt; /* pci_enable_device has been called */
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] PCI/MSI: Skip address mask check for MSI-X entries
2026-11-09 13:52 ` Thomas Gleixner
@ 2026-11-12 1:35 ` Yu Yang
0 siblings, 0 replies; 4+ messages in thread
From: Yu Yang @ 2026-11-12 1:35 UTC (permalink / raw)
To: Thomas Gleixner, Bjorn Helgaas
Cc: linux-pci, Michael Ellerman, Brett Creeley, Shannon Nelson,
linux-kernel
Hi Thomas,
Thanks for the review and the suggested approach.
> The core cannot rely on random implementation details of drivers and
> architecture code. It fails gracefully when the provided address limit
> is violated to prevent hard to diagnose subsequent failures.
I agree, and I am not proposing to rely on those details. My concern with
the pci_msi_broken approach is that it disables MSI unconditionally,
including on platforms where the MSI allocator returns a 32-bit address
and MSI works fine. ahci_init_irq() uses MSI as the first choice for
single-port controllers and as a fallback for multi-port controllers, so
this would cause a functional regression on such systems (falling back to
MSI-X or INTx instead of MSI).
> Coming back to your AHCI controller. That's broken to begin with. Assume
> that MSI-X is not supported then MSI setup would fail the same way. You
> don't notice because MSI-X is always enabled on x86 platforms.
Understood. The device's MSI capability is 32-bit while its MSI-X
capability uses 64-bit addresses.
Would a device-specific flag meaning "MSI-X supports 64-bit addresses
even though the MSI capability is 32-bit" be acceptable? That would keep
MSI enabled with the existing 32-bit msi_addr_mask, use a 64-bit mask for
MSI-X, and keep the verification in place instead of skipping it. The
quirk would only affect this ZX-200 AHCI device.
Please let me know which direction you and Bjorn prefer. I will also fix
the Fixes: tag as pointed out by the Sashiko review.
Thanks,
Yu
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] PCI/MSI: Skip address mask check for MSI-X entries
2026-11-09 9:24 [PATCH] PCI/MSI: Skip address mask check for MSI-X entries Yu Yang via B4 Relay
2026-11-09 13:52 ` Thomas Gleixner
@ 2026-11-09 20:11 ` sashiko-bot
1 sibling, 0 replies; 4+ messages in thread
From: sashiko-bot @ 2026-11-09 20:11 UTC (permalink / raw)
To: Yu Yang; +Cc: linux-pci
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] PCI/MSI: skipping MSI-X in msi_verify_entries() breaks mask
verification
- [Low] PCI/MSI: wrong commit cited in Fixes trailer for
msi_verify_entries()
--
commit ad679f69e8ee163ac9de4d91832ae0f1a10a2a14
Author: Yu Yang <yuyang@kylinos.cn>
> PCI/MSI: Skip address mask check for MSI-X entries
>
> The AHCI controller on Zhaoxin ZX-200 platforms supports only 32-bit
> MSI addresses, but its MSI-X capability uses 64-bit message addresses.
> pci_msi_init() therefore sets dev->msi_addr_mask to DMA_BIT_MASK(32)
> based on the MSI capability.
>
> msi_verify_entries() is shared between the MSI and MSI-X setup paths.
> When the irq domain assigns an MSI-X message address above 4GB, the
> 32-bit mask inherited from the MSI capability causes MSI-X setup to
> fail with -EIO:
>
> ahci 0000:09:0f.0: arch assigned 64-bit MSI address 0x8002a030040
> above device MSI address mask 0xffffffff.
> ...
> ahci: probe of 0000:09:0f.0 failed with error -22.
>
> MSI-X table entries have a 64-bit message address field, so the 32-bit
> limit derived from the MSI capability does not apply to them.
> Platforms that use msi_addr_mask to constrain MSI-X allocation, e.g.
> powerpc pseries/powernv and ionic on PPC64, already allocate addresses
> that satisfy the mask, so the verification is redundant for MSI-X.
>
> Skip the address mask check for MSI-X descriptors.
>
> Fixes: f144d1496b47 ("PCI/MSI: Add device flag indicating that 64-bit MSIs don't work")
>
> Signed-off-by: Yu Yang <yuyang@kylinos.cn>
[Severity: Low]
Should the Fixes tag reference 2053230af11d ("PCI/MSI: Set device flag
indicating only 32-bit MSI support") instead? Commit f144d1496b47
("PCI/MSI: Add device flag indicating that 64-bit MSIs don't work") only
added the opt-in flag for quirks and drivers; 2053230af11d ("PCI/MSI: Set
device flag indicating only 32-bit MSI support") is what made
pci_msi_init() restrict the device based on PCI_MSI_FLAGS_64BIT in the MSI
capability.
> diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c
> index 8a0133a6a2863..7f34bccc8248b 100644
> --- a/drivers/pci/msi/msi.c
> +++ b/drivers/pci/msi/msi.c
> @@ -338,6 +338,13 @@ static int msi_verify_entries(struct pci_dev *dev)
> return 0;
>
> msi_for_each_desc(entry, &dev->dev, MSI_DESC_ALL) {
> + /*
> + * MSI-X entries always use a 64-bit address, so the address
> + * limit for MSI capability does not apply for MSI-X.
> + */
> + if (entry->pci.msi_attrib.is_msix)
> + continue;
> +
> 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",
[Severity: Medium]
Does skipping MSI-X descriptors in msi_verify_entries() bypass
dev->msi_addr_mask verification when a driver or quirk explicitly restricts
the device's addressable bits?
Although MSI-X table entries have 64-bit address fields, MSI-X is delivered
as a PCIe Memory Write TLP and is still constrained by the device's DMA
address width. Drivers such as ionic (which only uses MSI-X) and radeon
set dev->msi_addr_mask to their hardware address limit, and on
architectures that do not consult dev->msi_addr_mask during MSI-X doorbell
allocation (such as x86 and arm64), msi_verify_entries() is the only check
preventing an unreachable doorbell address from being programmed.
Because msi_verify_entries() is only called from __msi_capability_init()
(all entries have is_msix == 0) and __msix_setup_interrupts() (all entries
have is_msix == 1), this check also turns the call in
__msix_setup_interrupts() into a no-op loop. Meanwhile, pci_msi_init()
still lowers dev->msi_addr_mask to DMA_BIT_MASK(32) based on the MSI
capability, so powerpc's rtas_prepare_msi_irqs() and
__pnv_pci_ioda_msi_setup() will still force 32-bit MSI-X allocation on
devices with 32-bit MSI and 64-bit MSI-X capabilities.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261109-pci-fix-msix-alloc-failure-v1-1-6370c0b84354@kylinos.cn?part=1
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-12 1:36 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-09 9:24 [PATCH] PCI/MSI: Skip address mask check for MSI-X entries Yu Yang via B4 Relay
2026-11-09 13:52 ` Thomas Gleixner
2026-11-12 1:35 ` Yu Yang
2026-11-09 20:11 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox