[PATCH linux dev-5.7 2/2] fsi: scom: Handle FSI2PIB timeout

Joel Stanley joel at jms.id.au
Wed Jul 29 21:52:44 AEST 2020


When the scom engine indicates a FSI2PIB timeout we can recover by
writing any value to the reset register.

On a machine capable of doing SCOMs, the 0x30000 address will fail and
cause subsequent accesses to fail:

 $ pdbg -p0 -b kernel getscom 0xf000f
 p0: 0x00000000000f000f = 0x120da04900800000 (/proc0/pib)
 $ pdbg -p0 -b kernel getscom 0x30000
 p0: 0x0000000000030000 failed (/proc0/pib)
 $ pdbg -p0 -b kernel getscom 0xf000f
 p0: 0x00000000000f000f failed (/proc0/pib)

After this patch, the kernel will detect and clear the error, allowing
subsequent accesses to succeed:

 $ pdbg -p0 -b kernel getscom 0xf000f
 p0: 0x00000000000f000f = 0x120da04900800000 (/proc0/pib)
 $ pdbg -p0 -b kernel getscom 0x30000
 p0: 0x0000000000030000 failed (/proc0/pib)
 $ pdbg -p0 -b kernel getscom 0xf000f
 p0: 0x00000000000f000f = 0x120da04900800000 (/proc0/pib)

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 drivers/fsi/fsi-scom.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/fsi/fsi-scom.c b/drivers/fsi/fsi-scom.c
index 55f30abd20b2..dc6db25a6a8a 100644
--- a/drivers/fsi/fsi-scom.c
+++ b/drivers/fsi/fsi-scom.c
@@ -38,6 +38,15 @@
 #define SCOM_STATUS_PIB_RESP_MASK	0x00007000
 #define SCOM_STATUS_PIB_RESP_SHIFT	12
 
+/* Values the SCOM_STATUS_PIB_RESP_MASK can take */
+#define SCOM_PIB_ERR_XSCOM_BLOCKED	0x00004000
+#define SCOM_PIB_ERR_CHIPLET_OFFLINE	0x00002000
+#define SCOM_PIB_ERR_PARTIAL_GOOD	0x00006000
+#define SCOM_PIB_ERR_INVALID_ADDR	0x00001000
+#define SCOM_PIB_ERR_CLOCK		0x00005000
+#define SCOM_PIB_ERR_HANDSHAKE		0x00003000
+#define SCOM_PIB_ERR_TIMEOUT		0x00007000
+
 #define SCOM_STATUS_ANY_ERR		(SCOM_STATUS_PROTECTION | \
 					 SCOM_STATUS_PARITY |	  \
 					 SCOM_STATUS_PIB_ABORT | \
@@ -249,9 +258,19 @@ static int handle_fsi2pib_status(struct scom_device *scom, uint32_t status)
 				 sizeof(uint32_t));
 		return -EIO;
 	}
+
+	if (status & SCOM_PIB_ERR_TIMEOUT) {
+		dev_dbg(&scom->dev, "PIB timeout, recovering\n");
+		fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG,
+				 &dummy, sizeof(uint32_t));
+		/* Return -EBUSY to force a retry */
+		return -EBUSY;
+	}
+
 	/* Return -EBUSY on PIB abort to force a retry */
 	if (status & SCOM_STATUS_PIB_ABORT)
 		return -EBUSY;
+
 	return 0;
 }
 
-- 
2.27.0



More information about the openbmc mailing list