aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Barrat <fbarrat@linux.vnet.ibm.com>2016-10-03 15:36:02 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2016-10-04 01:16:42 -0400
commitaaa2245ed836824f21f8e42e0ab63b1637d1cb20 (patch)
tree8c330d717ea072f8ec77d35b2304d7d0ea196663
parente2ad477cb26360532da7ee9ffc9631d6c0006a1d (diff)
cxl: Flush PSL cache before resetting the adapter
If the capi link is going down while the PSL owns a dirty cache line, any access from the host for that data could lead to an Uncorrectable Error. So when resetting the capi adapter through sysfs, make sure the PSL cache is flushed. It won't help if there are any active Process Elements on the card, as the cache would likely get new dirty cache lines immediately, but if resetting an idle adapter, it should avoid any bad surprises from data left over from terminated Process Elements. Signed-off-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com> Reviewed-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com> Acked-by: Ian Munsie <imunsie@au1.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--drivers/misc/cxl/cxl.h6
-rw-r--r--drivers/misc/cxl/native.c31
-rw-r--r--drivers/misc/cxl/pci.c3
3 files changed, 39 insertions, 1 deletions
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index 344a0ff8f8c7..01d372aba131 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -162,7 +162,10 @@ static const cxl_p2n_reg_t CXL_PSL_WED_An = {0x0A0};
162#define CXL_PSL_SPAP_V 0x0000000000000001ULL 162#define CXL_PSL_SPAP_V 0x0000000000000001ULL
163 163
164/****** CXL_PSL_Control ****************************************************/ 164/****** CXL_PSL_Control ****************************************************/
165#define CXL_PSL_Control_tb 0x0000000000000001ULL 165#define CXL_PSL_Control_tb (0x1ull << (63-63))
166#define CXL_PSL_Control_Fr (0x1ull << (63-31))
167#define CXL_PSL_Control_Fs_MASK (0x3ull << (63-29))
168#define CXL_PSL_Control_Fs_Complete (0x3ull << (63-29))
166 169
167/****** CXL_PSL_DLCNTL *****************************************************/ 170/****** CXL_PSL_DLCNTL *****************************************************/
168#define CXL_PSL_DLCNTL_D (0x1ull << (63-28)) 171#define CXL_PSL_DLCNTL_D (0x1ull << (63-28))
@@ -854,6 +857,7 @@ int cxl_register_one_irq(struct cxl *adapter, irq_handler_t handler,
854int cxl_check_error(struct cxl_afu *afu); 857int cxl_check_error(struct cxl_afu *afu);
855int cxl_afu_slbia(struct cxl_afu *afu); 858int cxl_afu_slbia(struct cxl_afu *afu);
856int cxl_tlb_slb_invalidate(struct cxl *adapter); 859int cxl_tlb_slb_invalidate(struct cxl *adapter);
860int cxl_data_cache_flush(struct cxl *adapter);
857int cxl_afu_disable(struct cxl_afu *afu); 861int cxl_afu_disable(struct cxl_afu *afu);
858int cxl_psl_purge(struct cxl_afu *afu); 862int cxl_psl_purge(struct cxl_afu *afu);
859 863
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c
index e606fdc4bc9c..a217a74ccc98 100644
--- a/drivers/misc/cxl/native.c
+++ b/drivers/misc/cxl/native.c
@@ -290,6 +290,37 @@ int cxl_tlb_slb_invalidate(struct cxl *adapter)
290 return 0; 290 return 0;
291} 291}
292 292
293int cxl_data_cache_flush(struct cxl *adapter)
294{
295 u64 reg;
296 unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT);
297
298 pr_devel("Flushing data cache\n");
299
300 reg = cxl_p1_read(adapter, CXL_PSL_Control);
301 reg |= CXL_PSL_Control_Fr;
302 cxl_p1_write(adapter, CXL_PSL_Control, reg);
303
304 reg = cxl_p1_read(adapter, CXL_PSL_Control);
305 while ((reg & CXL_PSL_Control_Fs_MASK) != CXL_PSL_Control_Fs_Complete) {
306 if (time_after_eq(jiffies, timeout)) {
307 dev_warn(&adapter->dev, "WARNING: cache flush timed out!\n");
308 return -EBUSY;
309 }
310
311 if (!cxl_ops->link_ok(adapter, NULL)) {
312 dev_warn(&adapter->dev, "WARNING: link down when flushing cache\n");
313 return -EIO;
314 }
315 cpu_relax();
316 reg = cxl_p1_read(adapter, CXL_PSL_Control);
317 }
318
319 reg &= ~CXL_PSL_Control_Fr;
320 cxl_p1_write(adapter, CXL_PSL_Control, reg);
321 return 0;
322}
323
293static int cxl_write_sstp(struct cxl_afu *afu, u64 sstp0, u64 sstp1) 324static int cxl_write_sstp(struct cxl_afu *afu, u64 sstp0, u64 sstp1)
294{ 325{
295 int rc; 326 int rc;
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
index cd922a80bf97..7afad8477ad5 100644
--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -1239,6 +1239,9 @@ int cxl_pci_reset(struct cxl *adapter)
1239 1239
1240 dev_info(&dev->dev, "CXL reset\n"); 1240 dev_info(&dev->dev, "CXL reset\n");
1241 1241
1242 /* the adapter is about to be reset, so ignore errors */
1243 cxl_data_cache_flush(adapter);
1244
1242 /* pcie_warm_reset requests a fundamental pci reset which includes a 1245 /* pcie_warm_reset requests a fundamental pci reset which includes a
1243 * PERST assert/deassert. PERST triggers a loading of the image 1246 * PERST assert/deassert. PERST triggers a loading of the image
1244 * if "user" or "factory" is selected in sysfs */ 1247 * if "user" or "factory" is selected in sysfs */