Add reset_loads_image and reset_image_select to sysfs.

reset_image_select identifies which image will be loaded to the card on the
next PERST.  Valid entries are: "user" and "factory".

reset_loads_image defines functionality on a PERST.  Value of 0 means PERST
will not cause image load.  A power cycle is required to load the image.  Value
of 1 means PERST will cause image load.

sysfs updates the cxl struct in the driver then calls cxl_update_image_control
to write the vals in the VSEC.

Signed-off-by: Ryan Grimm <gr...@linux.vnet.ibm.com>
---
 Documentation/ABI/testing/sysfs-class-cxl | 15 ++++++++
 drivers/misc/cxl/cxl.h                    |  1 +
 drivers/misc/cxl/pci.c                    | 35 ++++++++++++++++++
 drivers/misc/cxl/sysfs.c                  | 60 +++++++++++++++++++++++++++++++
 4 files changed, 111 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-cxl 
b/Documentation/ABI/testing/sysfs-class-cxl
index 554405e..134cfaf 100644
--- a/Documentation/ABI/testing/sysfs-class-cxl
+++ b/Documentation/ABI/testing/sysfs-class-cxl
@@ -127,3 +127,18 @@ Contact:        linuxppc-dev@lists.ozlabs.org
 Description:    read only
                 Will return "user" or "factory" depending on the image loaded
                 onto the card.
+
+What:           /sys/class/cxl/<card>/reset_image_select
+Date:           December 2014
+Contact:        linuxppc-dev@lists.ozlabs.org
+Description:    read/write
+                Identifies which image will be loaded to the card on the next
+                PERST.  Valid entries are: "user" and "factory".
+
+What:           /sys/class/cxl/<card>/reset_loads_image
+Date:           December 2014
+Contact:        linuxppc-dev@lists.ozlabs.org
+Description:    read/write
+                Value of 0 means PERST will not cause image load.  A power
+                cycle is required to load the image.  Value of 1 means PERST
+                will cause image load.
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index 0df0438..518c4c6 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -488,6 +488,7 @@ void cxl_release_one_irq(struct cxl *adapter, int hwirq);
 int cxl_alloc_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter, 
unsigned int num);
 void cxl_release_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter);
 int cxl_setup_irq(struct cxl *adapter, unsigned int hwirq, unsigned int virq);
+int cxl_update_image_control(struct cxl *adapter);
 
 /* common == phyp + powernv */
 struct cxl_process_element_common {
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
index f801c28..26cacc1 100644
--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -362,6 +362,41 @@ int cxl_setup_irq(struct cxl *adapter, unsigned int hwirq,
        return pnv_cxl_ioda_msi_setup(dev, hwirq, virq);
 }
 
+int cxl_update_image_control(struct cxl *adapter)
+{
+       struct pci_dev *dev = to_pci_dev(adapter->dev.parent);
+       int rc;
+       int vsec;
+       u8 image_state;
+
+       if (!(vsec = find_cxl_vsec(dev))) {
+               dev_err(&dev->dev, "ABORTING: CXL VSEC not found!\n");
+               return -ENODEV;
+       }
+
+       if ((rc = CXL_READ_VSEC_IMAGE_STATE(dev, vsec, &image_state))) {
+               dev_err(&dev->dev, "failed to read image state: %i\n", rc);
+               return rc;
+       }
+
+       if (adapter->perst_loads_image)
+               image_state |= CXL_VSEC_PERST_LOADS_IMAGE;
+       else
+               image_state &= ~CXL_VSEC_PERST_LOADS_IMAGE;
+
+       if (adapter->perst_select_user)
+               image_state |= CXL_VSEC_PERST_SELECT_USER;
+       else
+               image_state &= ~CXL_VSEC_PERST_SELECT_USER;
+
+       if ((rc = CXL_WRITE_VSEC_IMAGE_STATE(dev, vsec, image_state))) {
+               dev_err(&dev->dev, "failed to update image control: %i\n", rc);
+               return rc;
+       }
+
+       return 0;
+}
+
 int cxl_alloc_one_irq(struct cxl *adapter)
 {
        struct pci_dev *dev = to_pci_dev(adapter->dev.parent);
diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c
index 461bdbd..06f554b 100644
--- a/drivers/misc/cxl/sysfs.c
+++ b/drivers/misc/cxl/sysfs.c
@@ -56,11 +56,71 @@ static ssize_t image_loaded_show(struct device *device,
        return scnprintf(buf, PAGE_SIZE, "factory\n");
 }
 
+static ssize_t reset_loads_image_show(struct device *device,
+                                struct device_attribute *attr,
+                                char *buf)
+{
+       struct cxl *adapter = to_cxl_adapter(device);
+       return sprintf(buf, "%d\n", adapter->perst_loads_image);
+}
+
+static ssize_t reset_loads_image_store(struct device *device,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+       struct cxl *adapter = to_cxl_adapter(device);
+       unsigned long val;
+       int rc;
+
+        if (kstrtoul(buf, 0, &val) < 0)
+                return -EINVAL;
+
+        adapter->perst_loads_image = !!val;
+       if ((rc = cxl_update_image_control(adapter)))
+               return rc;
+
+       return count;
+}
+
+static ssize_t reset_image_select_show(struct device *device,
+                                struct device_attribute *attr,
+                                char *buf)
+{
+       struct cxl *adapter = to_cxl_adapter(device);
+
+       if (adapter->perst_select_user)
+               return scnprintf(buf, PAGE_SIZE, "user\n");
+
+       return scnprintf(buf, PAGE_SIZE, "factory\n");
+}
+
+static ssize_t reset_image_select_store(struct device *device,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+       struct cxl *adapter = to_cxl_adapter(device);
+       int rc;
+
+       if (!strncmp(buf, "user", 4))
+               adapter->perst_select_user = true;
+       else if (!strncmp(buf, "factory", 7))
+               adapter->perst_select_user = false;
+       else
+                return -EINVAL;
+
+       if ((rc = cxl_update_image_control(adapter)))
+               return rc;
+
+       return count;
+}
+
 static struct device_attribute adapter_attrs[] = {
        __ATTR_RO(caia_version),
        __ATTR_RO(psl_revision),
        __ATTR_RO(base_image),
        __ATTR_RO(image_loaded),
+       __ATTR_RW(reset_loads_image),
+       __ATTR_RW(reset_image_select),
 };
 
 
-- 
1.9.1

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to