mtd: cfi: cmdset_0001: Do not allow read/write to suspend erase block.

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Tue Apr 24 08:59:06 PDT 2018


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=6510bbc88e3258631831ade49033537081950605
Commit:     6510bbc88e3258631831ade49033537081950605
Parent:     47016b341fc3b3fd4909e058c6fa38f165b53646
Author:     Joakim Tjernlund <joakim.tjernlund at transmode.se>
AuthorDate: Thu Mar 1 14:39:39 2018 +0100
Committer:  Boris Brezillon <boris.brezillon at bootlin.com>
CommitDate: Tue Apr 24 17:41:18 2018 +0200

    mtd: cfi: cmdset_0001: Do not allow read/write to suspend erase block.
    
    Currently it is possible to read and/or write to suspend EB's.
    Writing /dev/mtdX or /dev/mtdblockX from several processes may
    break the flash state machine.
    
    Signed-off-by: Joakim Tjernlund <joakim.tjernlund at infinera.com>
    Cc: <stable at vger.kernel.org>
    Reviewed-by: Richard Weinberger <richard at nod.at>
    Signed-off-by: Boris Brezillon <boris.brezillon at bootlin.com>
---
 drivers/mtd/chips/cfi_cmdset_0001.c | 16 +++++++++++-----
 include/linux/mtd/flashchip.h       |  1 +
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index d4c07b85f18e..8833115fbc11 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -831,21 +831,25 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long
 		     (mode == FL_WRITING && (cfip->SuspendCmdSupport & 1))))
 			goto sleep;
 
+		/* Do not allow suspend iff read/write to EB address */
+		if ((adr & chip->in_progress_block_mask) ==
+		    chip->in_progress_block_addr)
+			goto sleep;
 
 		/* Erase suspend */
-		map_write(map, CMD(0xB0), adr);
+		map_write(map, CMD(0xB0), chip->in_progress_block_addr);
 
 		/* If the flash has finished erasing, then 'erase suspend'
 		 * appears to make some (28F320) flash devices switch to
 		 * 'read' mode.  Make sure that we switch to 'read status'
 		 * mode so we get the right data. --rmk
 		 */
-		map_write(map, CMD(0x70), adr);
+		map_write(map, CMD(0x70), chip->in_progress_block_addr);
 		chip->oldstate = FL_ERASING;
 		chip->state = FL_ERASE_SUSPENDING;
 		chip->erase_suspended = 1;
 		for (;;) {
-			status = map_read(map, adr);
+			status = map_read(map, chip->in_progress_block_addr);
 			if (map_word_andequal(map, status, status_OK, status_OK))
 			        break;
 
@@ -1041,8 +1045,8 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
 		   sending the 0x70 (Read Status) command to an erasing
 		   chip and expecting it to be ignored, that's what we
 		   do. */
-		map_write(map, CMD(0xd0), adr);
-		map_write(map, CMD(0x70), adr);
+		map_write(map, CMD(0xd0), chip->in_progress_block_addr);
+		map_write(map, CMD(0x70), chip->in_progress_block_addr);
 		chip->oldstate = FL_READY;
 		chip->state = FL_ERASING;
 		break;
@@ -1933,6 +1937,8 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
 	map_write(map, CMD(0xD0), adr);
 	chip->state = FL_ERASING;
 	chip->erase_suspended = 0;
+	chip->in_progress_block_addr = adr;
+	chip->in_progress_block_mask = ~(len - 1);
 
 	ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
 				   adr, len,
diff --git a/include/linux/mtd/flashchip.h b/include/linux/mtd/flashchip.h
index b63fa457febd..3529683f691e 100644
--- a/include/linux/mtd/flashchip.h
+++ b/include/linux/mtd/flashchip.h
@@ -85,6 +85,7 @@ struct flchip {
 	unsigned int write_suspended:1;
 	unsigned int erase_suspended:1;
 	unsigned long in_progress_block_addr;
+	unsigned long in_progress_block_mask;
 
 	struct mutex mutex;
 	wait_queue_head_t wq; /* Wait on here when we're waiting for the chip



More information about the linux-mtd-cvs mailing list