[PATCH v2] spi: cadence-quadspi: fix incorrect supports_op() return value

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

 



Since the conversion to spi-mem, the driver advertised support for
various operations that cqspi_set_protocol() was never expected to handle
correctly - in particuar all non-DTR operations with command or address
buswidth > 1. For DTR, all operations except for 8-8-8 would fail, as
cqspi_set_protocol() returns -EINVAL.

In non-DTR mode, this resulted in data corruption for SPI-NOR flashes that
support such operations. As a minimal fix that can be backported to stable
kernels, simply disallow the unsupported operations again to avoid this
issue.

Fixes: a314f6367787 ("mtd: spi-nor: Convert cadence-quadspi to use spi-mem framework")
Signed-off-by: Matthias Schiffer <matthias.schiffer@xxxxxxxxxxxxxxx>
---

As discussed, here's the minimal fix to disallow the accidentally enabled
1-X-X and X-X-X operations again. As a bonus, I also added proper handling
for non-8-8-8 DTR ops to cqspi_supports_mem_op() to avoid -EINVAL in
cqspi_set_protocol() for these ops.

The patch is based on spi for-5.18 now. It will unfortunately not
cherry-pick cleanly to 5.10 and 5.15, but I can take care of submitting a
backport patch once this is in Linus's tree.

I also have patches for 5.19/next that add proper support for 1-X-X and
X-X-X (without DTR for now, as I haven't tested DTR), which remove most
of the code of cqspi_set_protocol(). I will submit the follow-up patches
once this fix patch is accepted.


 drivers/spi/spi-cadence-quadspi.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
index b0c9f62ccefb..c898321d4e94 100644
--- a/drivers/spi/spi-cadence-quadspi.c
+++ b/drivers/spi/spi-cadence-quadspi.c
@@ -1437,9 +1437,24 @@ static bool cqspi_supports_mem_op(struct spi_mem *mem,
 	all_false = !op->cmd.dtr && !op->addr.dtr && !op->dummy.dtr &&
 		    !op->data.dtr;
 
-	/* Mixed DTR modes not supported. */
-	if (!(all_true || all_false))
+	if (all_true) {
+		/* Right now we only support 8-8-8 DTR mode. */
+		if (op->cmd.nbytes && op->cmd.buswidth != 8)
+			return false;
+		if (op->addr.nbytes && op->addr.buswidth != 8)
+			return false;
+		if (op->data.nbytes && op->data.buswidth != 8)
+			return false;
+	} else if (all_false) {
+		/* Only 1-1-X ops are supported without DTR */
+		if (op->cmd.nbytes && op->cmd.buswidth > 1)
+			return false;
+		if (op->addr.nbytes && op->addr.buswidth > 1)
+			return false;
+	} else {
+		/* Mixed DTR modes are not supported. */
 		return false;
+	}
 
 	return spi_mem_default_supports_op(mem, op);
 }
-- 
2.25.1




[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