]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
mtd: rawnand: Ensure all continuous terms are always in sync
authorMiquel Raynal <miquel.raynal@bootlin.com>
Fri, 23 Feb 2024 11:55:45 +0000 (12:55 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 3 Apr 2024 13:11:28 +0000 (15:11 +0200)
[ Upstream commit 6fb075fca63c3486612986eeff84ed4179644038 ]

While crossing a LUN boundary, it is probably safer (and clearer) to
keep all members of the continuous read structure aligned, including the
pause page (which is the last page of the lun or the last page of the
continuous read). Once these members properly in sync, we can use the
rawnand_cap_cont_reads() helper everywhere to "prepare" the next
continuous read if there is one.

Fixes: bbcd80f53a5e ("mtd: rawnand: Prevent crossing LUN boundaries during sequential reads")
Cc: stable@vger.kernel.org
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20240223115545.354541-4-miquel.raynal@bootlin.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/mtd/nand/raw/nand_base.c

index af37c2dea76b699faa7ff79d37a19e4603bb8cf3..dc8f3551c9a91d560a40afcbe12aa067dbe806c4 100644 (file)
@@ -1228,6 +1228,15 @@ static void rawnand_cap_cont_reads(struct nand_chip *chip)
                chip->cont_read.pause_page = rawnand_last_page_of_lun(ppl, first_lun);
        else
                chip->cont_read.pause_page = chip->cont_read.last_page;
+
+       if (chip->cont_read.first_page == chip->cont_read.pause_page) {
+               chip->cont_read.first_page++;
+               chip->cont_read.pause_page = min(chip->cont_read.last_page,
+                                                rawnand_last_page_of_lun(ppl, first_lun + 1));
+       }
+
+       if (chip->cont_read.first_page >= chip->cont_read.last_page)
+               chip->cont_read.ongoing = false;
 }
 
 static int nand_lp_exec_cont_read_page_op(struct nand_chip *chip, unsigned int page,
@@ -1294,12 +1303,11 @@ static int nand_lp_exec_cont_read_page_op(struct nand_chip *chip, unsigned int p
        if (!chip->cont_read.ongoing)
                return 0;
 
-       if (page == chip->cont_read.pause_page &&
-           page != chip->cont_read.last_page) {
-               chip->cont_read.first_page = chip->cont_read.pause_page + 1;
-               rawnand_cap_cont_reads(chip);
-       } else if (page == chip->cont_read.last_page) {
+       if (page == chip->cont_read.last_page) {
                chip->cont_read.ongoing = false;
+       } else if (page == chip->cont_read.pause_page) {
+               chip->cont_read.first_page++;
+               rawnand_cap_cont_reads(chip);
        }
 
        return 0;
@@ -3504,10 +3512,7 @@ static void rawnand_cont_read_skip_first_page(struct nand_chip *chip, unsigned i
                return;
 
        chip->cont_read.first_page++;
-       if (chip->cont_read.first_page == chip->cont_read.pause_page)
-               chip->cont_read.first_page++;
-       if (chip->cont_read.first_page >= chip->cont_read.last_page)
-               chip->cont_read.ongoing = false;
+       rawnand_cap_cont_reads(chip);
 }
 
 /**