[PATCH 2/2] cxl/core: Skip non-CXL capabilities in MCAP

From: peng.guo

Date: Sun Aug 16 2026 - 05:05:57 EST


From: pguo <peng.guo@xxxxxxxxxxxxxxxx>

When MMPT is enabled, a CXL device may expose both CXL-defined capabilities
and PCIe Management Message Passthrough (MMPT) capabilities in the same
MMIO Capabilities Register Block (MCAP).

The CXL capability parser currently identifies entries using only the
capability ID. Since capability IDs are scoped by Vendor ID, a
PCI-SIG-defined capability may have the same ID as a CXL-defined
capability. This causes non-CXL entries, including MMPT and MMIO Mailbox,
to be interpreted as CXL register blocks.

The MMPT register block may be interpreted as a CXL mailbox. This
causes mailbox initialization to fail with:

cxl_pci 0000:3b:00.0: Mailbox is too small (64b)

Check the MCAP Vendor ID before interpreting an entry as a CXL-defined
capability. This prevents PCI-SIG-defined MMPT capabilities from being
mistaken for CXL mailbox capabilities.

Fixes: 8adaf747c9f0 ("cxl/mem: Find device capabilities")
Suggested-by: Johnny <johnny.li@xxxxxxxxxxxxxxxx>
Signed-off-by: pguo <peng.guo@xxxxxxxxxxxxxxxx>
---
drivers/cxl/core/regs.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
index 93710cf4f0a6..79edb7bac8eb 100644
--- a/drivers/cxl/core/regs.c
+++ b/drivers/cxl/core/regs.c
@@ -134,7 +134,13 @@ void cxl_probe_device_regs(struct device *dev, void __iomem *base,
for (cap = 1; cap <= cap_count; cap++) {
struct cxl_reg_map *rmap;
u32 offset, length;
- u16 cap_id;
+ u16 cap_id, vendor_id;
+
+ vendor_id = FIELD_GET(PCI_MCAP_HDR_VENDOR_ID,
+ readl(base + PCI_MCAP_HDR_BASE(cap) +
+ PCI_MCAP_HDR_REG_4));
+ if (vendor_id != PCI_VENDOR_ID_CXL)
+ continue;

cap_id = FIELD_GET(CXLDEV_CAP_HDR_CAP_ID_MASK,
readl(base + cap * 0x10));
--
2.43.0