Merge branch 'for-6.3/cxl' into cxl/next
authorDan Williams <dan.j.williams@intel.com>
Tue, 7 Feb 2023 19:12:24 +0000 (11:12 -0800)
committerDan Williams <dan.j.williams@intel.com>
Tue, 7 Feb 2023 19:12:24 +0000 (11:12 -0800)
Merge the general CXL updates with fixes targeting v6.2-rc for v6.3.
Resolve a conflict with the fix and move of cxl_report_and_clear() from
pci.c to core/pci.c.

1  2 
drivers/cxl/acpi.c
drivers/cxl/core/pci.c
drivers/cxl/core/region.c

Simple merge
index 57764e9cd19d27d4a15a0ed8da4c52f0ade0e3fc,1d1492440287c9762829d3a603d35663a42c1e81..184ead6a2796d2c58dd41c9ab65bbe54836d39b5
@@@ -622,3 -623,114 +623,117 @@@ void read_cdat_data(struct cxl_port *po
        }
  }
  EXPORT_SYMBOL_NS_GPL(read_cdat_data, CXL);
 -              addr = cxlds->regs.ras + CXL_RAS_CAP_CONTROL_OFFSET;
 -              fe = BIT(FIELD_GET(CXL_RAS_CAP_CONTROL_FE_MASK, readl(addr)));
+ void cxl_cor_error_detected(struct pci_dev *pdev)
+ {
+       struct cxl_dev_state *cxlds = pci_get_drvdata(pdev);
+       struct cxl_memdev *cxlmd = cxlds->cxlmd;
+       struct device *dev = &cxlmd->dev;
+       void __iomem *addr;
+       u32 status;
+       if (!cxlds->regs.ras)
+               return;
+       addr = cxlds->regs.ras + CXL_RAS_CORRECTABLE_STATUS_OFFSET;
+       status = readl(addr);
+       if (status & CXL_RAS_CORRECTABLE_STATUS_MASK) {
+               writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
+               trace_cxl_aer_correctable_error(dev, status);
+       }
+ }
+ EXPORT_SYMBOL_NS_GPL(cxl_cor_error_detected, CXL);
+ /* CXL spec rev3.0 8.2.4.16.1 */
+ static void header_log_copy(struct cxl_dev_state *cxlds, u32 *log)
+ {
+       void __iomem *addr;
+       u32 *log_addr;
+       int i, log_u32_size = CXL_HEADERLOG_SIZE / sizeof(u32);
+       addr = cxlds->regs.ras + CXL_RAS_HEADER_LOG_OFFSET;
+       log_addr = log;
+       for (i = 0; i < log_u32_size; i++) {
+               *log_addr = readl(addr);
+               log_addr++;
+               addr += sizeof(u32);
+       }
+ }
+ /*
+  * Log the state of the RAS status registers and prepare them to log the
+  * next error status. Return 1 if reset needed.
+  */
+ static bool cxl_report_and_clear(struct cxl_dev_state *cxlds)
+ {
+       struct cxl_memdev *cxlmd = cxlds->cxlmd;
+       struct device *dev = &cxlmd->dev;
+       u32 hl[CXL_HEADERLOG_SIZE_U32];
+       void __iomem *addr;
+       u32 status;
+       u32 fe;
+       if (!cxlds->regs.ras)
+               return false;
+       addr = cxlds->regs.ras + CXL_RAS_UNCORRECTABLE_STATUS_OFFSET;
+       status = readl(addr);
+       if (!(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK))
+               return false;
+       /* If multiple errors, log header points to first error from ctrl reg */
+       if (hweight32(status) > 1) {
++              void __iomem *rcc_addr =
++                      cxlds->regs.ras + CXL_RAS_CAP_CONTROL_OFFSET;
++
++              fe = BIT(FIELD_GET(CXL_RAS_CAP_CONTROL_FE_MASK,
++                                 readl(rcc_addr)));
+       } else {
+               fe = status;
+       }
+       header_log_copy(cxlds, hl);
+       trace_cxl_aer_uncorrectable_error(dev, status, fe, hl);
+       writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
+       return true;
+ }
+ pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
+                                   pci_channel_state_t state)
+ {
+       struct cxl_dev_state *cxlds = pci_get_drvdata(pdev);
+       struct cxl_memdev *cxlmd = cxlds->cxlmd;
+       struct device *dev = &cxlmd->dev;
+       bool ue;
+       /*
+        * A frozen channel indicates an impending reset which is fatal to
+        * CXL.mem operation, and will likely crash the system. On the off
+        * chance the situation is recoverable dump the status of the RAS
+        * capability registers and bounce the active state of the memdev.
+        */
+       ue = cxl_report_and_clear(cxlds);
+       switch (state) {
+       case pci_channel_io_normal:
+               if (ue) {
+                       device_release_driver(dev);
+                       return PCI_ERS_RESULT_NEED_RESET;
+               }
+               return PCI_ERS_RESULT_CAN_RECOVER;
+       case pci_channel_io_frozen:
+               dev_warn(&pdev->dev,
+                        "%s: frozen state error detected, disable CXL.mem\n",
+                        dev_name(dev));
+               device_release_driver(dev);
+               return PCI_ERS_RESULT_NEED_RESET;
+       case pci_channel_io_perm_failure:
+               dev_warn(&pdev->dev,
+                        "failure state error detected, request disconnect\n");
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+       return PCI_ERS_RESULT_NEED_RESET;
+ }
+ EXPORT_SYMBOL_NS_GPL(cxl_error_detected, CXL);
Simple merge