summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>2025-09-18 00:54:01 +0300
committerMiquel Raynal <miquel.raynal@bootlin.com>2025-09-29 17:53:08 +0200
commit010dc7f2dd6a0078ade3f88f627ed5fbf45ceb94 (patch)
tree531e65d48d1547534716e7073fa3830c39d687d5
parent004f8ea0d9917398aabff7388b3bf62a84a4088b (diff)
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 <mikhail.kshevetskiy@iopsys.eu> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
-rw-r--r--drivers/mtd/nand/spi/core.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 58ec85c98ab8..f92133b8e1a6 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -430,8 +430,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)
@@ -899,10 +907,19 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from,
old_stats = mtd->ecc_stats;
- 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);
+ }
if (ops->stats) {
ops->stats->uncorrectable_errors +=