cxl: Allow initialization on timebase sync failures
authorFrederic Barrat <fbarrat@linux.vnet.ibm.com>
Mon, 21 Mar 2016 19:32:48 +0000 (14:32 -0500)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 22 Apr 2016 11:45:44 +0000 (21:45 +1000)
Failure to synchronize the PSL timebase currently prevents the
initialization of the cxl card, thus rendering the card useless. This
is too extreme for a feature which is rarely used, if at all. No
hardware AFUs or software is currently using PSL timebase.

This patch still tries to synchronize the PSL timebase when the card
is initialized, but ignores the error if it can't. Instead, it reports
a status via /sys.

Signed-off-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
Acked-by: Ian Munsie <imunsie@au1.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Documentation/ABI/testing/sysfs-class-cxl
drivers/misc/cxl/cxl.h
drivers/misc/cxl/guest.c
drivers/misc/cxl/pci.c
drivers/misc/cxl/sysfs.c

index 7fd737eed38acd7f794daea91d9561a435a67e00..4ba0a2a61926251edf33e5f94a4eff45028d44a8 100644 (file)
@@ -233,3 +233,11 @@ Description:       read/write
                0 = don't trust, the image may be different (default)
                1 = trust that the image will not change.
 Users:         https://github.com/ibm-capi/libcxl
+
+What:           /sys/class/cxl/<card>/psl_timebase_synced
+Date:           March 2016
+Contact:        linuxppc-dev@lists.ozlabs.org
+Description:    read only
+                Returns 1 if the psl timebase register is synchronized
+                with the core timebase register, 0 otherwise.
+Users:          https://github.com/ibm-capi/libcxl
index 38e21cf7806ed59d6c925edd3e34f5c519d6a510..dfdbfb02508961e10fac9f2779025777f0046a6e 100644 (file)
@@ -579,6 +579,7 @@ struct cxl {
        bool perst_loads_image;
        bool perst_select_user;
        bool perst_same_image;
+       bool psl_timebase_synced;
 };
 
 int cxl_pci_alloc_one_irq(struct cxl *adapter);
index 8213372de2b7217e73d1b884bfa1f07a78d7e83a..a83acf9f8cd98aa77da41cb4dd1e11a8f11c298c 100644 (file)
@@ -1101,6 +1101,12 @@ struct cxl *cxl_guest_init_adapter(struct device_node *np, struct platform_devic
        adapter->dev.release = release_adapter;
        dev_set_drvdata(&pdev->dev, adapter);
 
+       /*
+        * Hypervisor controls PSL timebase initialization (p1 register).
+        * On FW840, PSL is initialized.
+        */
+       adapter->psl_timebase_synced = true;
+
        if ((rc = cxl_of_read_adapter_handle(adapter, np)))
                goto err1;
 
index 94fd3f71f838955b8eda14ac9a726683a85d4606..c6d5cf5e3793b60045a2bfa92b3ad0f9ca144ade 100644 (file)
@@ -394,22 +394,24 @@ static int init_implementation_adapter_regs(struct cxl *adapter, struct pci_dev
 #define TBSYNC_CNT(n) (((u64)n & 0x7) << (63-6))
 #define _2048_250MHZ_CYCLES 1
 
-static int cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev)
+static void cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev)
 {
        u64 psl_tb;
        int delta;
        unsigned int retry = 0;
        struct device_node *np;
 
+       adapter->psl_timebase_synced = false;
+
        if (!(np = pnv_pci_get_phb_node(dev)))
-               return -ENODEV;
+               return;
 
        /* Do not fail when CAPP timebase sync is not supported by OPAL */
        of_node_get(np);
        if (! of_get_property(np, "ibm,capp-timebase-sync", NULL)) {
                of_node_put(np);
-               pr_err("PSL: Timebase sync: OPAL support missing\n");
-               return 0;
+               dev_info(&dev->dev, "PSL timebase inactive: OPAL support missing\n");
+               return;
        }
        of_node_put(np);
 
@@ -428,8 +430,8 @@ static int cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev)
        do {
                msleep(1);
                if (retry++ > 5) {
-                       pr_err("PSL: Timebase sync: giving up!\n");
-                       return -EIO;
+                       dev_info(&dev->dev, "PSL timebase can't synchronize\n");
+                       return;
                }
                psl_tb = cxl_p1_read(adapter, CXL_PSL_Timebase);
                delta = mftb() - psl_tb;
@@ -437,7 +439,8 @@ static int cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev)
                        delta = -delta;
        } while (tb_to_ns(delta) > 16000);
 
-       return 0;
+       adapter->psl_timebase_synced = true;
+       return;
 }
 
 static int init_implementation_afu_regs(struct cxl_afu *afu)
@@ -1183,8 +1186,8 @@ static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev)
        if ((rc = pnv_phb_to_cxl_mode(dev, OPAL_PHB_CAPI_MODE_SNOOP_ON)))
                goto err;
 
-       if ((rc = cxl_setup_psl_timebase(adapter, dev)))
-               goto err;
+       /* Ignore error, adapter init is not dependant on timebase sync */
+       cxl_setup_psl_timebase(adapter, dev);
 
        if ((rc = cxl_native_register_psl_err_irq(adapter)))
                goto err;
index 25913c08794cc29e24c19102e737f94426522e06..b043c20f158f122d11bbf5dc765ae957ebf9155d 100644 (file)
@@ -57,6 +57,15 @@ static ssize_t image_loaded_show(struct device *device,
        return scnprintf(buf, PAGE_SIZE, "factory\n");
 }
 
+static ssize_t psl_timebase_synced_show(struct device *device,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct cxl *adapter = to_cxl_adapter(device);
+
+       return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->psl_timebase_synced);
+}
+
 static ssize_t reset_adapter_store(struct device *device,
                                   struct device_attribute *attr,
                                   const char *buf, size_t count)
@@ -142,6 +151,7 @@ static struct device_attribute adapter_attrs[] = {
        __ATTR_RO(psl_revision),
        __ATTR_RO(base_image),
        __ATTR_RO(image_loaded),
+       __ATTR_RO(psl_timebase_synced),
        __ATTR_RW(load_image_on_perst),
        __ATTR_RW(perst_reloads_same_image),
        __ATTR(reset, S_IWUSR, NULL, reset_adapter_store),