Re: [PATCH v18 12/13] PCI/CXL: Mask/Unmask CXL protocol errors
From: Jonathan Cameron <jic23@kernel.org>
Date: 2026-07-21 00:10:44
Also in:
linux-acpi, linux-cxl, linux-doc, linux-pci, lkml
On Fri, 17 Jul 2026 17:27:05 -0500 Terry Bowman [off-list ref] wrote:
CXL protocol errors are not enabled for all CXL devices after boot. They must be enabled in order to process CXL protocol errors. Provide matching teardown helpers so the masks are restored when a CXL Port or dport goes away. Add pci_aer_mask_internal_errors() as the symmetric counterpart to pci_aer_unmask_internal_errors() and export both for the cxl_core module. Introduce cxl_unmask_proto_interrupts() and cxl_mask_proto_interrupts() in cxl_core to wrap the PCI helpers with the dev_is_pci() and pcie_aer_is_native() gating CXL needs. Both helpers tolerate a NULL or non-PCI @dev so callers do not have to special-case it. Wire cxl_unmask_proto_interrupts() into the success path of cxl_dport_map_ras() and devm_cxl_port_ras_setup() so the unmask only runs when the RAS register block was actually mapped. Pair each unmask with a devm_add_action_or_reset() registration of cxl_mask_proto_irqs() scoped to the host device so the mask is restored when devres is released. This applies to dports, Endpoints, Upstream Switch Ports, Downstream Switch Ports, and Root Ports. Remove the dev_is_pci(dport->dport_dev) guard in devm_cxl_dport_rch_ras_setup(). On RCH systems dport->dport_dev is the pci_host_bridge device, which is not on pci_bus_type, so this guard caused the function to return early on real hardware without mapping dport RAS or AER registers. The caller already gates on dport->rch, which is sufficient to exclude cxl_test mock devices. Co-developed-by: Dan Williams <djbw@kernel.org> Signed-off-by: Dan Williams <djbw@kernel.org> Signed-off-by: Terry Bowman <redacted>
One minor thing inline and maybe take another spin at a more concise patch description Either way on both of them. Reviewed-by: Jonathan Cameron <redacted> ...
quoted hunk ↗ jump to hunk
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c index 0bd23a65e7ebc..be6dc2cbd4491 100644 --- a/drivers/pci/pcie/aer.c +++ b/drivers/pci/pcie/aer.c@@ -1143,12 +1143,32 @@ void pci_aer_unmask_internal_errors(struct pci_dev *dev) mask &= ~PCI_ERR_COR_INTERNAL; pci_write_config_dword(dev, aer + PCI_ERR_COR_MASK, mask); } +EXPORT_SYMBOL_FOR_MODULES(pci_aer_unmask_internal_errors, "cxl_core"); -/* - * Internal errors are too device-specific to enable generally, however for CXL - * their behavior is standardized for conveying CXL protocol errors. +/** + * pci_aer_mask_internal_errors - mask internal errors + * @dev: pointer to the pci_dev data structure + * + * Mask internal errors in the Uncorrectable and Correctable Error + * Mask registers. + * + * Note: AER must be enabled and supported by the device which must be + * checked in advance, e.g. with pcie_aer_is_native(). */ -EXPORT_SYMBOL_FOR_MODULES(pci_aer_unmask_internal_errors, "cxl_core"); +void pci_aer_mask_internal_errors(struct pci_dev *dev) +{ + int aer = dev->aer_cap; + u32 mask; + + pci_read_config_dword(dev, aer + PCI_ERR_UNCOR_MASK, &mask); + mask |= PCI_ERR_UNC_INTN; + pci_write_config_dword(dev, aer + PCI_ERR_UNCOR_MASK, mask);
Could do pci_clear_and_set_config_dword(dev, aer + PCI_ERR_UNCOR_MASK, 0, PCI_ERR_COR_INTERNAL); or something along those lines. Maybe it is worth wrapping that in some helpers to make it a bit more regmap like in that it could have set and clear only variants.
+ + pci_read_config_dword(dev, aer + PCI_ERR_COR_MASK, &mask); + mask |= PCI_ERR_COR_INTERNAL; + pci_write_config_dword(dev, aer + PCI_ERR_COR_MASK, mask); +} +EXPORT_SYMBOL_FOR_MODULES(pci_aer_mask_internal_errors, "cxl_core");