aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorRyan Grimm <grimm@linux.vnet.ibm.com>2015-01-19 12:52:51 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2015-01-22 01:31:52 -0500
commit62fa19d4b4fd781ad37c9155c6332f28a9e97a2c (patch)
treebd2a354aa2e928e7fd60b347a784e2e0b6d49d3e /drivers/misc
parent1212aa1c8c9ca34642f7737e1edaa96c9ce3d7dd (diff)
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 <grimm@linux.vnet.ibm.com> Acked-by: Ian Munsie <imunsie@au1.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/cxl/cxl.h1
-rw-r--r--drivers/misc/cxl/pci.c37
-rw-r--r--drivers/misc/cxl/sysfs.c18
3 files changed, 56 insertions, 0 deletions
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index 518c4c6e6151..6a6a487464c5 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -489,6 +489,7 @@ int cxl_alloc_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter, unsig
489void cxl_release_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter); 489void cxl_release_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter);
490int cxl_setup_irq(struct cxl *adapter, unsigned int hwirq, unsigned int virq); 490int cxl_setup_irq(struct cxl *adapter, unsigned int hwirq, unsigned int virq);
491int cxl_update_image_control(struct cxl *adapter); 491int cxl_update_image_control(struct cxl *adapter);
492int cxl_reset(struct cxl *adapter);
492 493
493/* common == phyp + powernv */ 494/* common == phyp + powernv */
494struct cxl_process_element_common { 495struct cxl_process_element_common {
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
index a4a4e0217eed..428ea8ba25fc 100644
--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -21,6 +21,7 @@
21#include <asm/msi_bitmap.h> 21#include <asm/msi_bitmap.h>
22#include <asm/pci-bridge.h> /* for struct pci_controller */ 22#include <asm/pci-bridge.h> /* for struct pci_controller */
23#include <asm/pnv-pci.h> 23#include <asm/pnv-pci.h>
24#include <asm/io.h>
24 25
25#include "cxl.h" 26#include "cxl.h"
26 27
@@ -741,6 +742,42 @@ static void cxl_remove_afu(struct cxl_afu *afu)
741 device_unregister(&afu->dev); 742 device_unregister(&afu->dev);
742} 743}
743 744
745int 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}
744 781
745static int cxl_map_adapter_regs(struct cxl *adapter, struct pci_dev *dev) 782static int cxl_map_adapter_regs(struct cxl *adapter, struct pci_dev *dev)
746{ 783{
diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c
index ed4ad461143c..adf1f6d84913 100644
--- a/drivers/misc/cxl/sysfs.c
+++ b/drivers/misc/cxl/sysfs.c
@@ -56,6 +56,23 @@ static ssize_t image_loaded_show(struct device *device,
56 return scnprintf(buf, PAGE_SIZE, "factory\n"); 56 return scnprintf(buf, PAGE_SIZE, "factory\n");
57} 57}
58 58
59static 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
59static ssize_t load_image_on_perst_show(struct device *device, 76static ssize_t load_image_on_perst_show(struct device *device,
60 struct device_attribute *attr, 77 struct device_attribute *attr,
61 char *buf) 78 char *buf)
@@ -100,6 +117,7 @@ static struct device_attribute adapter_attrs[] = {
100 __ATTR_RO(base_image), 117 __ATTR_RO(base_image),
101 __ATTR_RO(image_loaded), 118 __ATTR_RO(image_loaded),
102 __ATTR_RW(load_image_on_perst), 119 __ATTR_RW(load_image_on_perst),
120 __ATTR(reset, S_IWUSR, NULL, reset_adapter_store),
103}; 121};
104 122
105 123