Skip to content

Commit c7ee7c8

Browse files
committed
mtd: rawnand: Fix and simplify again the continuous read derivations
We need to avoid the first page if we don't read it entirely. We need to avoid the last page if we don't read it entirely. While rather simple, this logic has been failed in the previous fix. This time I wrote about 30 unit tests locally to check each possible condition, hopefully I covered them all. Reported-by: Christophe Kerello <[email protected]> Closes: https://lore.kernel.org/linux-mtd/20240221175327.42f7076d@xps-13/T/#m399bacb10db8f58f6b1f0149a1df867ec086bb0a Suggested-by: Christophe Kerello <[email protected]> Fixes: 828f6df ("mtd: rawnand: Clarify conditions to enable continuous reads") Cc: [email protected] Signed-off-by: Miquel Raynal <[email protected]> Tested-by: Christophe Kerello <[email protected]> Link: https://lore.kernel.org/linux-mtd/[email protected]
1 parent c9692eb commit c7ee7c8

File tree

1 file changed

+20
-14
lines changed

1 file changed

+20
-14
lines changed

drivers/mtd/nand/raw/nand_base.c

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3466,30 +3466,36 @@ static void rawnand_enable_cont_reads(struct nand_chip *chip, unsigned int page,
34663466
u32 readlen, int col)
34673467
{
34683468
struct mtd_info *mtd = nand_to_mtd(chip);
3469-
unsigned int end_page, end_col;
3469+
unsigned int first_page, last_page;
34703470

34713471
chip->cont_read.ongoing = false;
34723472

34733473
if (!chip->controller->supported_op.cont_read)
34743474
return;
34753475

3476-
end_page = DIV_ROUND_UP(col + readlen, mtd->writesize);
3477-
end_col = (col + readlen) % mtd->writesize;
3476+
/*
3477+
* Don't bother making any calculations if the length is too small.
3478+
* Side effect: avoids possible integer underflows below.
3479+
*/
3480+
if (readlen < (2 * mtd->writesize))
3481+
return;
34783482

3483+
/* Derive the page where continuous read should start (the first full page read) */
3484+
first_page = page;
34793485
if (col)
3480-
page++;
3481-
3482-
if (end_col && end_page)
3483-
end_page--;
3486+
first_page++;
34843487

3485-
if (page + 1 > end_page)
3486-
return;
3487-
3488-
chip->cont_read.first_page = page;
3489-
chip->cont_read.last_page = end_page;
3490-
chip->cont_read.ongoing = true;
3488+
/* Derive the page where continuous read should stop (the last full page read) */
3489+
last_page = page + ((col + readlen) / mtd->writesize) - 1;
34913490

3492-
rawnand_cap_cont_reads(chip);
3491+
/* Configure and enable continuous read when suitable */
3492+
if (first_page < last_page) {
3493+
chip->cont_read.first_page = first_page;
3494+
chip->cont_read.last_page = last_page;
3495+
chip->cont_read.ongoing = true;
3496+
/* May reset the ongoing flag */
3497+
rawnand_cap_cont_reads(chip);
3498+
}
34933499
}
34943500

34953501
static void rawnand_cont_read_skip_first_page(struct nand_chip *chip, unsigned int page)

0 commit comments

Comments
 (0)