|
@@ -21,6 +21,7 @@
|
|
|
#include <asm/msi_bitmap.h>
|
|
|
#include <asm/pci-bridge.h> /* for struct pci_controller */
|
|
|
#include <asm/pnv-pci.h>
|
|
|
+#include <asm/io.h>
|
|
|
|
|
|
#include "cxl.h"
|
|
|
|
|
@@ -741,6 +742,42 @@ static void cxl_remove_afu(struct cxl_afu *afu)
|
|
|
device_unregister(&afu->dev);
|
|
|
}
|
|
|
|
|
|
+int cxl_reset(struct cxl *adapter)
|
|
|
+{
|
|
|
+ struct pci_dev *dev = to_pci_dev(adapter->dev.parent);
|
|
|
+ int rc;
|
|
|
+ int i;
|
|
|
+ u32 val;
|
|
|
+
|
|
|
+ dev_info(&dev->dev, "CXL reset\n");
|
|
|
+
|
|
|
+ for (i = 0; i < adapter->slices; i++)
|
|
|
+ cxl_remove_afu(adapter->afu[i]);
|
|
|
+
|
|
|
+ /* pcie_warm_reset requests a fundamental pci reset which includes a
|
|
|
+ * PERST assert/deassert. PERST triggers a loading of the image
|
|
|
+ * if "user" or "factory" is selected in sysfs */
|
|
|
+ if ((rc = pci_set_pcie_reset_state(dev, pcie_warm_reset))) {
|
|
|
+ dev_err(&dev->dev, "cxl: pcie_warm_reset failed\n");
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* the PERST done above fences the PHB. So, reset depends on EEH
|
|
|
+ * to unbind the driver, tell Sapphire to reinit the PHB, and rebind
|
|
|
+ * the driver. Do an mmio read explictly to ensure EEH notices the
|
|
|
+ * fenced PHB. Retry for a few seconds before giving up. */
|
|
|
+ i = 0;
|
|
|
+ while (((val = mmio_read32be(adapter->p1_mmio)) != 0xffffffff) &&
|
|
|
+ (i < 5)) {
|
|
|
+ msleep(500);
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (val != 0xffffffff)
|
|
|
+ dev_err(&dev->dev, "cxl: PERST failed to trigger EEH\n");
|
|
|
+
|
|
|
+ return rc;
|
|
|
+}
|
|
|
|
|
|
static int cxl_map_adapter_regs(struct cxl *adapter, struct pci_dev *dev)
|
|
|
{
|