[PATCH 3/5] spi: zynqmp-gqspi: Abort operations on timeout

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When an operation times out, we leave the device (and driver) in an
inconsistent state. This generally results in all subsequent operations
timing out. Attempt to address this by resetting/reinitializing the
device when we have a timeout. This tends to be fairly robust.

Signed-off-by: Sean Anderson <sean.anderson@xxxxxxxxx>
---

 drivers/spi/spi-zynqmp-gqspi.c | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
index 7d138f45b692..cf47466ec982 100644
--- a/drivers/spi/spi-zynqmp-gqspi.c
+++ b/drivers/spi/spi-zynqmp-gqspi.c
@@ -1057,6 +1057,21 @@ static unsigned long zynqmp_qspi_timeout(struct zynqmp_qspi *xqspi, u8 bits,
 	return msecs_to_jiffies(timeout + 100);
 }
 
+
+static int zynqmp_qspi_wait(struct zynqmp_qspi *xqspi, unsigned long timeout)
+{
+	int ret;
+
+	ret = wait_for_completion_timeout(&xqspi->data_completion, timeout);
+	if (ret)
+		return 0;
+	dev_err(xqspi->dev, "Operation timed out\n");
+
+	/* Attempt to recover as best we can */
+	zynqmp_qspi_init_hw(xqspi);
+	return -ETIMEDOUT;
+}
+
 /**
  * zynqmp_qspi_exec_op() - Initiates the QSPI transfer
  * @mem: The SPI memory
@@ -1104,11 +1119,9 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem,
 				   GQSPI_IER_TXNOT_FULL_MASK);
 		timeout = zynqmp_qspi_timeout(xqspi, op->cmd.buswidth,
 					      op->cmd.nbytes);
-		if (!wait_for_completion_timeout(&xqspi->data_completion,
-						 timeout)) {
-			err = -ETIMEDOUT;
+		err = zynqmp_qspi_wait(xqspi, timeout);
+		if (err)
 			goto return_err;
-		}
 	}
 
 	if (op->addr.nbytes) {
@@ -1133,11 +1146,9 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem,
 				   GQSPI_IER_TXNOT_FULL_MASK);
 		timeout = zynqmp_qspi_timeout(xqspi, op->addr.buswidth,
 					      op->addr.nbytes);
-		if (!wait_for_completion_timeout(&xqspi->data_completion,
-						 timeout)) {
-			err = -ETIMEDOUT;
+		err = zynqmp_qspi_wait(xqspi, timeout);
+		if (err)
 			goto return_err;
-		}
 	}
 
 	if (op->dummy.nbytes) {
@@ -1204,8 +1215,7 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem,
 		}
 		timeout = zynqmp_qspi_timeout(xqspi, op->data.buswidth,
 					      op->data.nbytes);
-		if (!wait_for_completion_timeout(&xqspi->data_completion, timeout))
-			err = -ETIMEDOUT;
+		err = zynqmp_qspi_wait(xqspi, timeout);
 	}
 
 return_err:
-- 
2.35.1.1320.gc452695387.dirty





[Index of Archives]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux