Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

cxl/pci: Move CXL driver's RCH error handling into core/ras_rch.c

Restricted CXL Host (RCH) protocol error handling uses a procedure distinct
from the CXL Virtual Hierarchy (VH) handling. This is because of the
differences in the RCH and VH topologies. Improve the maintainability and
add ability to enable/disable RCH handling.

Move and combine the RCH handling code into a single block conditionally
compiled with the CONFIG_CXL_RCH_RAS kernel config.

Signed-off-by: Terry Bowman <terry.bowman@amd.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Link: https://patch.msgid.link/20260114182055.46029-9-terry.bowman@amd.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>

authored by

Terry Bowman and committed by
Dave Jiang
0ff60f2e d18f1b7b

+126 -123
+1
drivers/cxl/core/Makefile
··· 20 20 cxl_core-$(CONFIG_CXL_FEATURES) += features.o 21 21 cxl_core-$(CONFIG_CXL_EDAC_MEM_FEATURES) += edac.o 22 22 cxl_core-$(CONFIG_CXL_RAS) += ras.o 23 + cxl_core-$(CONFIG_CXL_RAS) += ras_rch.o
+3 -8
drivers/cxl/core/core.h
··· 149 149 void cxl_ras_exit(void); 150 150 bool cxl_handle_ras(struct cxl_dev_state *cxlds, void __iomem *ras_base); 151 151 void cxl_handle_cor_ras(struct cxl_dev_state *cxlds, void __iomem *ras_base); 152 + void cxl_dport_map_rch_aer(struct cxl_dport *dport); 153 + void cxl_disable_rch_root_ints(struct cxl_dport *dport); 154 + void cxl_handle_rdport_errors(struct cxl_dev_state *cxlds); 152 155 #else 153 156 static inline int cxl_ras_init(void) 154 157 { ··· 167 164 return false; 168 165 } 169 166 static inline void cxl_handle_cor_ras(struct cxl_dev_state *cxlds, void __iomem *ras_base) { } 170 - #endif /* CONFIG_CXL_RAS */ 171 - 172 - /* Restricted CXL Host specific RAS functions */ 173 - #ifdef CONFIG_CXL_RAS 174 - void cxl_dport_map_rch_aer(struct cxl_dport *dport); 175 - void cxl_disable_rch_root_ints(struct cxl_dport *dport); 176 - void cxl_handle_rdport_errors(struct cxl_dev_state *cxlds); 177 - #else 178 167 static inline void cxl_dport_map_rch_aer(struct cxl_dport *dport) { } 179 168 static inline void cxl_disable_rch_root_ints(struct cxl_dport *dport) { } 180 169 static inline void cxl_handle_rdport_errors(struct cxl_dev_state *cxlds) { }
-115
drivers/cxl/core/pci.c
··· 632 632 } 633 633 EXPORT_SYMBOL_NS_GPL(read_cdat_data, "CXL"); 634 634 635 - #ifdef CONFIG_CXL_RAS 636 - void cxl_dport_map_rch_aer(struct cxl_dport *dport) 637 - { 638 - resource_size_t aer_phys; 639 - struct device *host; 640 - u16 aer_cap; 641 - 642 - aer_cap = cxl_rcrb_to_aer(dport->dport_dev, dport->rcrb.base); 643 - if (aer_cap) { 644 - host = dport->reg_map.host; 645 - aer_phys = aer_cap + dport->rcrb.base; 646 - dport->regs.dport_aer = devm_cxl_iomap_block(host, aer_phys, 647 - sizeof(struct aer_capability_regs)); 648 - } 649 - } 650 - 651 - void cxl_disable_rch_root_ints(struct cxl_dport *dport) 652 - { 653 - void __iomem *aer_base = dport->regs.dport_aer; 654 - u32 aer_cmd_mask, aer_cmd; 655 - 656 - if (!aer_base) 657 - return; 658 - 659 - /* 660 - * Disable RCH root port command interrupts. 661 - * CXL 3.0 12.2.1.1 - RCH Downstream Port-detected Errors 662 - * 663 - * This sequence may not be necessary. CXL spec states disabling 664 - * the root cmd register's interrupts is required. But, PCI spec 665 - * shows these are disabled by default on reset. 666 - */ 667 - aer_cmd_mask = (PCI_ERR_ROOT_CMD_COR_EN | 668 - PCI_ERR_ROOT_CMD_NONFATAL_EN | 669 - PCI_ERR_ROOT_CMD_FATAL_EN); 670 - aer_cmd = readl(aer_base + PCI_ERR_ROOT_COMMAND); 671 - aer_cmd &= ~aer_cmd_mask; 672 - writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND); 673 - } 674 - 675 - /* 676 - * Copy the AER capability registers using 32 bit read accesses. 677 - * This is necessary because RCRB AER capability is MMIO mapped. Clear the 678 - * status after copying. 679 - * 680 - * @aer_base: base address of AER capability block in RCRB 681 - * @aer_regs: destination for copying AER capability 682 - */ 683 - static bool cxl_rch_get_aer_info(void __iomem *aer_base, 684 - struct aer_capability_regs *aer_regs) 685 - { 686 - int read_cnt = sizeof(struct aer_capability_regs) / sizeof(u32); 687 - u32 *aer_regs_buf = (u32 *)aer_regs; 688 - int n; 689 - 690 - if (!aer_base) 691 - return false; 692 - 693 - /* Use readl() to guarantee 32-bit accesses */ 694 - for (n = 0; n < read_cnt; n++) 695 - aer_regs_buf[n] = readl(aer_base + n * sizeof(u32)); 696 - 697 - writel(aer_regs->uncor_status, aer_base + PCI_ERR_UNCOR_STATUS); 698 - writel(aer_regs->cor_status, aer_base + PCI_ERR_COR_STATUS); 699 - 700 - return true; 701 - } 702 - 703 - /* Get AER severity. Return false if there is no error. */ 704 - static bool cxl_rch_get_aer_severity(struct aer_capability_regs *aer_regs, 705 - int *severity) 706 - { 707 - if (aer_regs->uncor_status & ~aer_regs->uncor_mask) { 708 - if (aer_regs->uncor_status & PCI_ERR_ROOT_FATAL_RCV) 709 - *severity = AER_FATAL; 710 - else 711 - *severity = AER_NONFATAL; 712 - return true; 713 - } 714 - 715 - if (aer_regs->cor_status & ~aer_regs->cor_mask) { 716 - *severity = AER_CORRECTABLE; 717 - return true; 718 - } 719 - 720 - return false; 721 - } 722 - 723 - void cxl_handle_rdport_errors(struct cxl_dev_state *cxlds) 724 - { 725 - struct pci_dev *pdev = to_pci_dev(cxlds->dev); 726 - struct aer_capability_regs aer_regs; 727 - struct cxl_dport *dport; 728 - int severity; 729 - 730 - struct cxl_port *port __free(put_cxl_port) = 731 - cxl_pci_find_port(pdev, &dport); 732 - if (!port) 733 - return; 734 - 735 - if (!cxl_rch_get_aer_info(dport->regs.dport_aer, &aer_regs)) 736 - return; 737 - 738 - if (!cxl_rch_get_aer_severity(&aer_regs, &severity)) 739 - return; 740 - 741 - pci_print_aer(pdev, severity, &aer_regs); 742 - 743 - if (severity == AER_CORRECTABLE) 744 - cxl_handle_cor_ras(cxlds, dport->regs.ras); 745 - else 746 - cxl_handle_ras(cxlds, dport->regs.ras); 747 - } 748 - #endif 749 - 750 635 static int cxl_flit_size(struct pci_dev *pdev) 751 636 { 752 637 if (cxl_pci_flit_256(pdev))
+121
drivers/cxl/core/ras_rch.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright(c) 2025 AMD Corporation. All rights reserved. */ 3 + 4 + #include <linux/types.h> 5 + #include <linux/aer.h> 6 + #include "cxl.h" 7 + #include "core.h" 8 + #include "cxlmem.h" 9 + 10 + void cxl_dport_map_rch_aer(struct cxl_dport *dport) 11 + { 12 + resource_size_t aer_phys; 13 + struct device *host; 14 + u16 aer_cap; 15 + 16 + aer_cap = cxl_rcrb_to_aer(dport->dport_dev, dport->rcrb.base); 17 + if (aer_cap) { 18 + host = dport->reg_map.host; 19 + aer_phys = aer_cap + dport->rcrb.base; 20 + dport->regs.dport_aer = 21 + devm_cxl_iomap_block(host, aer_phys, 22 + sizeof(struct aer_capability_regs)); 23 + } 24 + } 25 + 26 + void cxl_disable_rch_root_ints(struct cxl_dport *dport) 27 + { 28 + void __iomem *aer_base = dport->regs.dport_aer; 29 + u32 aer_cmd_mask, aer_cmd; 30 + 31 + if (!aer_base) 32 + return; 33 + 34 + /* 35 + * Disable RCH root port command interrupts. 36 + * CXL 3.0 12.2.1.1 - RCH Downstream Port-detected Errors 37 + * 38 + * This sequence may not be necessary. CXL spec states disabling 39 + * the root cmd register's interrupts is required. But, PCI spec 40 + * shows these are disabled by default on reset. 41 + */ 42 + aer_cmd_mask = (PCI_ERR_ROOT_CMD_COR_EN | 43 + PCI_ERR_ROOT_CMD_NONFATAL_EN | 44 + PCI_ERR_ROOT_CMD_FATAL_EN); 45 + aer_cmd = readl(aer_base + PCI_ERR_ROOT_COMMAND); 46 + aer_cmd &= ~aer_cmd_mask; 47 + writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND); 48 + } 49 + 50 + /* 51 + * Copy the AER capability registers using 32 bit read accesses. 52 + * This is necessary because RCRB AER capability is MMIO mapped. Clear the 53 + * status after copying. 54 + * 55 + * @aer_base: base address of AER capability block in RCRB 56 + * @aer_regs: destination for copying AER capability 57 + */ 58 + static bool cxl_rch_get_aer_info(void __iomem *aer_base, 59 + struct aer_capability_regs *aer_regs) 60 + { 61 + int read_cnt = sizeof(struct aer_capability_regs) / sizeof(u32); 62 + u32 *aer_regs_buf = (u32 *)aer_regs; 63 + int n; 64 + 65 + if (!aer_base) 66 + return false; 67 + 68 + /* Use readl() to guarantee 32-bit accesses */ 69 + for (n = 0; n < read_cnt; n++) 70 + aer_regs_buf[n] = readl(aer_base + n * sizeof(u32)); 71 + 72 + writel(aer_regs->uncor_status, aer_base + PCI_ERR_UNCOR_STATUS); 73 + writel(aer_regs->cor_status, aer_base + PCI_ERR_COR_STATUS); 74 + 75 + return true; 76 + } 77 + 78 + /* Get AER severity. Return false if there is no error. */ 79 + static bool cxl_rch_get_aer_severity(struct aer_capability_regs *aer_regs, 80 + int *severity) 81 + { 82 + if (aer_regs->uncor_status & ~aer_regs->uncor_mask) { 83 + if (aer_regs->uncor_status & PCI_ERR_ROOT_FATAL_RCV) 84 + *severity = AER_FATAL; 85 + else 86 + *severity = AER_NONFATAL; 87 + return true; 88 + } 89 + 90 + if (aer_regs->cor_status & ~aer_regs->cor_mask) { 91 + *severity = AER_CORRECTABLE; 92 + return true; 93 + } 94 + 95 + return false; 96 + } 97 + 98 + void cxl_handle_rdport_errors(struct cxl_dev_state *cxlds) 99 + { 100 + struct pci_dev *pdev = to_pci_dev(cxlds->dev); 101 + struct aer_capability_regs aer_regs; 102 + struct cxl_dport *dport; 103 + int severity; 104 + 105 + struct cxl_port *port __free(put_cxl_port) = 106 + cxl_pci_find_port(pdev, &dport); 107 + if (!port) 108 + return; 109 + 110 + if (!cxl_rch_get_aer_info(dport->regs.dport_aer, &aer_regs)) 111 + return; 112 + 113 + if (!cxl_rch_get_aer_severity(&aer_regs, &severity)) 114 + return; 115 + 116 + pci_print_aer(pdev, severity, &aer_regs); 117 + if (severity == AER_CORRECTABLE) 118 + cxl_handle_cor_ras(cxlds, dport->regs.ras); 119 + else 120 + cxl_handle_ras(cxlds, dport->regs.ras); 121 + }
+1
tools/testing/cxl/Kbuild
··· 63 63 cxl_core-$(CONFIG_CXL_FEATURES) += $(CXL_CORE_SRC)/features.o 64 64 cxl_core-$(CONFIG_CXL_EDAC_MEM_FEATURES) += $(CXL_CORE_SRC)/edac.o 65 65 cxl_core-$(CONFIG_CXL_RAS) += $(CXL_CORE_SRC)/ras.o 66 + cxl_core-$(CONFIG_CXL_RAS) += $(CXL_CORE_SRC)/ras_rch.o 66 67 cxl_core-y += config_check.o 67 68 cxl_core-y += cxl_core_test.o 68 69 cxl_core-y += cxl_core_exports.o