Commit e009a7e8 authored by Frederic Barrat's avatar Frederic Barrat Committed by Michael Ellerman

cxl: Allow initialization on timebase sync failures

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: default avatarFrederic Barrat <fbarrat@linux.vnet.ibm.com>
Acked-by: default avatarIan Munsie <imunsie@au1.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent bb62bad6
...@@ -233,3 +233,11 @@ Description: read/write ...@@ -233,3 +233,11 @@ Description: read/write
0 = don't trust, the image may be different (default) 0 = don't trust, the image may be different (default)
1 = trust that the image will not change. 1 = trust that the image will not change.
Users: https://github.com/ibm-capi/libcxl 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
...@@ -579,6 +579,7 @@ struct cxl { ...@@ -579,6 +579,7 @@ struct cxl {
bool perst_loads_image; bool perst_loads_image;
bool perst_select_user; bool perst_select_user;
bool perst_same_image; bool perst_same_image;
bool psl_timebase_synced;
}; };
int cxl_pci_alloc_one_irq(struct cxl *adapter); int cxl_pci_alloc_one_irq(struct cxl *adapter);
......
...@@ -1101,6 +1101,12 @@ struct cxl *cxl_guest_init_adapter(struct device_node *np, struct platform_devic ...@@ -1101,6 +1101,12 @@ struct cxl *cxl_guest_init_adapter(struct device_node *np, struct platform_devic
adapter->dev.release = release_adapter; adapter->dev.release = release_adapter;
dev_set_drvdata(&pdev->dev, 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))) if ((rc = cxl_of_read_adapter_handle(adapter, np)))
goto err1; goto err1;
......
...@@ -394,22 +394,24 @@ static int init_implementation_adapter_regs(struct cxl *adapter, struct pci_dev ...@@ -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 TBSYNC_CNT(n) (((u64)n & 0x7) << (63-6))
#define _2048_250MHZ_CYCLES 1 #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; u64 psl_tb;
int delta; int delta;
unsigned int retry = 0; unsigned int retry = 0;
struct device_node *np; struct device_node *np;
adapter->psl_timebase_synced = false;
if (!(np = pnv_pci_get_phb_node(dev))) if (!(np = pnv_pci_get_phb_node(dev)))
return -ENODEV; return;
/* Do not fail when CAPP timebase sync is not supported by OPAL */ /* Do not fail when CAPP timebase sync is not supported by OPAL */
of_node_get(np); of_node_get(np);
if (! of_get_property(np, "ibm,capp-timebase-sync", NULL)) { if (! of_get_property(np, "ibm,capp-timebase-sync", NULL)) {
of_node_put(np); of_node_put(np);
pr_err("PSL: Timebase sync: OPAL support missing\n"); dev_info(&dev->dev, "PSL timebase inactive: OPAL support missing\n");
return 0; return;
} }
of_node_put(np); of_node_put(np);
...@@ -428,8 +430,8 @@ static int cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev) ...@@ -428,8 +430,8 @@ static int cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev)
do { do {
msleep(1); msleep(1);
if (retry++ > 5) { if (retry++ > 5) {
pr_err("PSL: Timebase sync: giving up!\n"); dev_info(&dev->dev, "PSL timebase can't synchronize\n");
return -EIO; return;
} }
psl_tb = cxl_p1_read(adapter, CXL_PSL_Timebase); psl_tb = cxl_p1_read(adapter, CXL_PSL_Timebase);
delta = mftb() - psl_tb; delta = mftb() - psl_tb;
...@@ -437,7 +439,8 @@ static int cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev) ...@@ -437,7 +439,8 @@ static int cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev)
delta = -delta; delta = -delta;
} while (tb_to_ns(delta) > 16000); } while (tb_to_ns(delta) > 16000);
return 0; adapter->psl_timebase_synced = true;
return;
} }
static int init_implementation_afu_regs(struct cxl_afu *afu) 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) ...@@ -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))) if ((rc = pnv_phb_to_cxl_mode(dev, OPAL_PHB_CAPI_MODE_SNOOP_ON)))
goto err; goto err;
if ((rc = cxl_setup_psl_timebase(adapter, dev))) /* Ignore error, adapter init is not dependant on timebase sync */
goto err; cxl_setup_psl_timebase(adapter, dev);
if ((rc = cxl_native_register_psl_err_irq(adapter))) if ((rc = cxl_native_register_psl_err_irq(adapter)))
goto err; goto err;
......
...@@ -57,6 +57,15 @@ static ssize_t image_loaded_show(struct device *device, ...@@ -57,6 +57,15 @@ static ssize_t image_loaded_show(struct device *device,
return scnprintf(buf, PAGE_SIZE, "factory\n"); 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, static ssize_t reset_adapter_store(struct device *device,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -142,6 +151,7 @@ static struct device_attribute adapter_attrs[] = { ...@@ -142,6 +151,7 @@ static struct device_attribute adapter_attrs[] = {
__ATTR_RO(psl_revision), __ATTR_RO(psl_revision),
__ATTR_RO(base_image), __ATTR_RO(base_image),
__ATTR_RO(image_loaded), __ATTR_RO(image_loaded),
__ATTR_RO(psl_timebase_synced),
__ATTR_RW(load_image_on_perst), __ATTR_RW(load_image_on_perst),
__ATTR_RW(perst_reloads_same_image), __ATTR_RW(perst_reloads_same_image),
__ATTR(reset, S_IWUSR, NULL, reset_adapter_store), __ATTR(reset, S_IWUSR, NULL, reset_adapter_store),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment