[PATCH v19 08/14] cxl/ras: Handle RCH correctable and uncorrectable errors in one pass
Terry Bowman <[email protected]> Mon, 3 Aug 2026 17:18:04 -0500
| Newsgroups | org.kernel.vger.linux-acpi,org.kernel.vger.linux-cxl,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci |
|---|---|
| Message-ID | <[email protected]> |
cxl_rch_get_aer_info() reads and clears both the correctable and uncorrectable AER status registers in a single pass. The previous severity decode returned after the first matching class, so when a correctable and an uncorrectable error were logged simultaneously the correctable event was cleared in hardware but never traced or handled. Handle both classes independently: dispatch cxl_handle_cor_ras() when correctable status is set and cxl_do_recovery() when uncorrectable status is set. Remove the now-unused cxl_rch_get_aer_severity() helper and decode the uncorrectable severity inline. Reported-by: Sashiko <[email protected]> Signed-off-by: Terry Bowman <[email protected]> --- Changes in v18 -> v19: - New patch to process correctable and uncorrectable RCH errors in the same call so a co-logged correctable event is not lost. --- drivers/cxl/core/ras_rch.c | 42 ++++++++++++++------------------------ 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/drivers/cxl/core/ras_rch.c b/drivers/cxl/core/ras_rch.c index 41959c0333711..6f95542e2e6a7 100644 --- a/drivers/cxl/core/ras_rch.c +++ b/drivers/cxl/core/ras_rch.c @@ -89,31 +89,10 @@ static bool cxl_rch_get_aer_info(void __iomem *aer_base, return true; } -/* Get AER severity. Return false if there is no error. */ -static bool cxl_rch_get_aer_severity(struct aer_capability_regs *aer_regs, - int *severity) -{ - u32 uncor_status = aer_regs->uncor_status & ~aer_regs->uncor_mask; - - if (uncor_status) { - *severity = (uncor_status & aer_regs->uncor_severity) ? - AER_FATAL : AER_NONFATAL; - return true; - } - - if (aer_regs->cor_status & ~aer_regs->cor_mask) { - *severity = AER_CORRECTABLE; - return true; - } - - return false; -} - void cxl_handle_rdport_errors(struct pci_dev *pdev) { struct aer_capability_regs aer_regs; struct cxl_dport *dport; - int severity; struct cxl_port *port __free(put_cxl_port) = cxl_pci_find_port(pdev, NULL); if (!port) @@ -127,12 +106,21 @@ void cxl_handle_rdport_errors(struct pci_dev *pdev) if (!cxl_rch_get_aer_info(dport->regs.dport_aer, &aer_regs)) return; - if (!cxl_rch_get_aer_severity(&aer_regs, &severity)) - return; + /* + * Handle correctable and uncorrectable errors independently; both + * may be set in the same pass and cxl_rch_get_aer_info() has already + * cleared both status registers. + */ + if (aer_regs.cor_status & ~aer_regs.cor_mask) { + pci_print_aer(pdev, AER_CORRECTABLE, &aer_regs); + cxl_handle_cor_ras(dport->dport_dev, to_ras_base(port, dport)); + } + + if (aer_regs.uncor_status & ~aer_regs.uncor_mask) { + int severity = (aer_regs.uncor_status & aer_regs.uncor_severity) ? + AER_FATAL : AER_NONFATAL; - pci_print_aer(pdev, severity, &aer_regs); - if (severity == AER_CORRECTABLE) - cxl_handle_cor_ras(&pdev->dev, to_ras_base(port, dport)); - else + pci_print_aer(pdev, severity, &aer_regs); cxl_do_recovery(pdev, dport->port, dport); + } } -- 2.34.1