From e55069fab47407e85171c66ac018456306a5923b Mon Sep 17 00:00:00 2001 From: Mikhail Kshevetskiy Date: Tue, 30 Sep 2025 03:21:09 +0300 Subject: [PATCH] mtd: spinand: repeat reading in regular mode if continuous reading fails Continuous reading may result in multiple flash pages reading in one operation. Unfortunately, not all spinand controllers support such large reading. They will read less data. Unfortunately, the operation can't be continued. In this case: * disable continuous reading on this (not good enough) spi controller * repeat reading in regular mode. Signed-off-by: Mikhail Kshevetskiy Signed-off-by: Michael Trimarchi --- drivers/mtd/nand/spi/core.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 68a03ddee8b..0c435059546 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -427,8 +427,16 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand, * Dirmap accesses are allowed to toggle the CS. * Toggling the CS during a continuous read is forbidden. */ - if (nbytes && req->continuous) - return -EIO; + if (nbytes && req->continuous) { + /* + * Spi controller with broken support of continuous + * reading was detected. Disable future use of + * continuous reading and return -EAGAIN to retry + * reading within regular mode. + */ + spinand->cont_read_possible = false; + return -EAGAIN; + } } if (req->datalen) @@ -890,6 +898,7 @@ static bool spinand_use_cont_read(struct mtd_info *mtd, loff_t from, static int spinand_mtd_read(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) { + struct spinand_device *spinand = mtd_to_spinand(mtd); unsigned int max_bitflips = 0; int ret; @@ -897,10 +906,19 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from, mutex_lock(&spinand->lock); #endif - if (spinand_use_cont_read(mtd, from, ops)) + if (spinand_use_cont_read(mtd, from, ops)) { ret = spinand_mtd_continuous_page_read(mtd, from, ops, &max_bitflips); - else + if (ret == -EAGAIN && !spinand->cont_read_possible) { + /* + * Spi controller with broken support of continuous + * reading was detected (see spinand_read_from_cache_op()), + * repeat reading in regular mode. + */ + ret = spinand_mtd_regular_page_read(mtd, from, ops, &max_bitflips); + } + } else { ret = spinand_mtd_regular_page_read(mtd, from, ops, &max_bitflips); + } #ifndef __UBOOT__ mutex_unlock(&spinand->lock); -- 2.47.3