Skip to content

Commit 62fa19d

Browse files
Ryan Grimmmpe
authored andcommitted
cxl: Add ability to reset the card
Adds reset to sysfs which will PERST the card. If load_image_on_perst is set to "user" or "factory", the PERST will cause that image to be loaded. load_image_on_perst is set to "user" for production. "none" could be used for debugging. The PSL trace arrays are preserved which then can be read through debugfs. PERST also triggers CAPP recovery. An HMI comes in, which is handled by EEH. EEH unbinds the driver, calls into Sapphire to reinitialize the PHB, then rebinds the driver. Signed-off-by: Ryan Grimm <[email protected]> Acked-by: Ian Munsie <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 1212aa1 commit 62fa19d

File tree

4 files changed

+63
-0
lines changed

4 files changed

+63
-0
lines changed

Documentation/ABI/testing/sysfs-class-cxl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,10 @@ Description: read/write
146146
user or factory image to be loaded.
147147
Default is to reload on PERST whichever image the card has
148148
loaded.
149+
150+
What: /sys/class/cxl/<card>/reset
151+
Date: October 2014
152+
153+
Description: write only
154+
Writing 1 will issue a PERST to card which may cause the card
155+
to reload the FPGA depending on load_image_on_perst.

drivers/misc/cxl/cxl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,7 @@ int cxl_alloc_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter, unsig
489489
void cxl_release_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter);
490490
int cxl_setup_irq(struct cxl *adapter, unsigned int hwirq, unsigned int virq);
491491
int cxl_update_image_control(struct cxl *adapter);
492+
int cxl_reset(struct cxl *adapter);
492493

493494
/* common == phyp + powernv */
494495
struct cxl_process_element_common {

drivers/misc/cxl/pci.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <asm/msi_bitmap.h>
2222
#include <asm/pci-bridge.h> /* for struct pci_controller */
2323
#include <asm/pnv-pci.h>
24+
#include <asm/io.h>
2425

2526
#include "cxl.h"
2627

@@ -741,6 +742,42 @@ static void cxl_remove_afu(struct cxl_afu *afu)
741742
device_unregister(&afu->dev);
742743
}
743744

745+
int cxl_reset(struct cxl *adapter)
746+
{
747+
struct pci_dev *dev = to_pci_dev(adapter->dev.parent);
748+
int rc;
749+
int i;
750+
u32 val;
751+
752+
dev_info(&dev->dev, "CXL reset\n");
753+
754+
for (i = 0; i < adapter->slices; i++)
755+
cxl_remove_afu(adapter->afu[i]);
756+
757+
/* pcie_warm_reset requests a fundamental pci reset which includes a
758+
* PERST assert/deassert. PERST triggers a loading of the image
759+
* if "user" or "factory" is selected in sysfs */
760+
if ((rc = pci_set_pcie_reset_state(dev, pcie_warm_reset))) {
761+
dev_err(&dev->dev, "cxl: pcie_warm_reset failed\n");
762+
return rc;
763+
}
764+
765+
/* the PERST done above fences the PHB. So, reset depends on EEH
766+
* to unbind the driver, tell Sapphire to reinit the PHB, and rebind
767+
* the driver. Do an mmio read explictly to ensure EEH notices the
768+
* fenced PHB. Retry for a few seconds before giving up. */
769+
i = 0;
770+
while (((val = mmio_read32be(adapter->p1_mmio)) != 0xffffffff) &&
771+
(i < 5)) {
772+
msleep(500);
773+
i++;
774+
}
775+
776+
if (val != 0xffffffff)
777+
dev_err(&dev->dev, "cxl: PERST failed to trigger EEH\n");
778+
779+
return rc;
780+
}
744781

745782
static int cxl_map_adapter_regs(struct cxl *adapter, struct pci_dev *dev)
746783
{

drivers/misc/cxl/sysfs.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,23 @@ static ssize_t image_loaded_show(struct device *device,
5656
return scnprintf(buf, PAGE_SIZE, "factory\n");
5757
}
5858

59+
static ssize_t reset_adapter_store(struct device *device,
60+
struct device_attribute *attr,
61+
const char *buf, size_t count)
62+
{
63+
struct cxl *adapter = to_cxl_adapter(device);
64+
int rc;
65+
int val;
66+
67+
rc = sscanf(buf, "%i", &val);
68+
if ((rc != 1) || (val != 1))
69+
return -EINVAL;
70+
71+
if ((rc = cxl_reset(adapter)))
72+
return rc;
73+
return count;
74+
}
75+
5976
static ssize_t load_image_on_perst_show(struct device *device,
6077
struct device_attribute *attr,
6178
char *buf)
@@ -100,6 +117,7 @@ static struct device_attribute adapter_attrs[] = {
100117
__ATTR_RO(base_image),
101118
__ATTR_RO(image_loaded),
102119
__ATTR_RW(load_image_on_perst),
120+
__ATTR(reset, S_IWUSR, NULL, reset_adapter_store),
103121
};
104122

105123

0 commit comments

Comments
 (0)