diff options
author | Dan Williams <dan.j.williams@intel.com> | 2023-02-14 15:06:08 -0800 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2023-02-14 15:06:08 -0800 |
commit | 5a6fe61facdb7f830895712b31fb39f544ffc165 (patch) | |
tree | 5a276223390d2304152b5512bef5bfd2b5ba4ecf /drivers/cxl/pci.c | |
parent | ee817acaa01d5c56e5fef396bea05c869b7e9351 (diff) | |
parent | 248529edc86f8d7d390a15a86bd1904951311665 (diff) |
Merge branch 'for-6.3/cxl' into cxl/next
Pick up the AER unmasking patches for v6.3.
Diffstat (limited to 'drivers/cxl/pci.c')
-rw-r--r-- | drivers/cxl/pci.c | 70 |
1 files changed, 62 insertions, 8 deletions
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c index 4cf9a2191602..60b23624d167 100644 --- a/drivers/cxl/pci.c +++ b/drivers/cxl/pci.c @@ -412,9 +412,65 @@ static bool is_cxl_restricted(struct pci_dev *pdev) return pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END; } -static void disable_aer(void *pdev) +/* + * CXL v3.0 6.2.3 Table 6-4 + * The table indicates that if PCIe Flit Mode is set, then CXL is in 256B flits + * mode, otherwise it's 68B flits mode. + */ +static bool cxl_pci_flit_256(struct pci_dev *pdev) { - pci_disable_pcie_error_reporting(pdev); + u16 lnksta2; + + pcie_capability_read_word(pdev, PCI_EXP_LNKSTA2, &lnksta2); + return lnksta2 & PCI_EXP_LNKSTA2_FLIT; +} + +static int cxl_pci_ras_unmask(struct pci_dev *pdev) +{ + struct pci_host_bridge *host_bridge = pci_find_host_bridge(pdev->bus); + struct cxl_dev_state *cxlds = pci_get_drvdata(pdev); + void __iomem *addr; + u32 orig_val, val, mask; + u16 cap; + int rc; + + if (!cxlds->regs.ras) { + dev_dbg(&pdev->dev, "No RAS registers.\n"); + return 0; + } + + /* BIOS has CXL error control */ + if (!host_bridge->native_cxl_error) + return -ENXIO; + + rc = pcie_capability_read_word(pdev, PCI_EXP_DEVCTL, &cap); + if (rc) + return rc; + + if (cap & PCI_EXP_DEVCTL_URRE) { + addr = cxlds->regs.ras + CXL_RAS_UNCORRECTABLE_MASK_OFFSET; + orig_val = readl(addr); + + mask = CXL_RAS_UNCORRECTABLE_MASK_MASK; + if (!cxl_pci_flit_256(pdev)) + mask &= ~CXL_RAS_UNCORRECTABLE_MASK_F256B_MASK; + val = orig_val & ~mask; + writel(val, addr); + dev_dbg(&pdev->dev, + "Uncorrectable RAS Errors Mask: %#x -> %#x\n", + orig_val, val); + } + + if (cap & PCI_EXP_DEVCTL_CERE) { + addr = cxlds->regs.ras + CXL_RAS_CORRECTABLE_MASK_OFFSET; + orig_val = readl(addr); + val = orig_val & ~CXL_RAS_CORRECTABLE_MASK_MASK; + writel(val, addr); + dev_dbg(&pdev->dev, "Correctable RAS Errors Mask: %#x -> %#x\n", + orig_val, val); + } + + return 0; } static void free_event_buf(void *buf) @@ -733,12 +789,10 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (rc) return rc; - if (cxlds->regs.ras) { - pci_enable_pcie_error_reporting(pdev); - rc = devm_add_action_or_reset(&pdev->dev, disable_aer, pdev); - if (rc) - return rc; - } + rc = cxl_pci_ras_unmask(pdev); + if (rc) + dev_dbg(&pdev->dev, "No RAS reporting unmasked\n"); + pci_save_state(pdev); return rc; |