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