From: Joakim Tjernlund Date: Thu, 1 Mar 2018 13:39:41 +0000 (+0100) Subject: mtd: cfi: cmdset_0002: Do not allow read/write to suspend erase block. X-Git-Tag: v3.16.60~157 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7d0d52c00355397972742d3c00f37669f81c4b42;p=thirdparty%2Fkernel%2Fstable.git mtd: cfi: cmdset_0002: Do not allow read/write to suspend erase block. commit 7b70eb14392a7cf505f9b358d06c33b5af73d1e7 upstream. 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. Taken from cfi_cmdset_0001 driver. Signed-off-by: Joakim Tjernlund Reviewed-by: Richard Weinberger Signed-off-by: Boris Brezillon Signed-off-by: Ben Hutchings --- diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index e21fde9d4d7e2..573d843a73a91 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -780,9 +780,10 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)))) goto sleep; - /* We could check to see if we're trying to access the sector - * that is currently being erased. However, no user will try - * anything like that so we just wait for the timeout. */ + /* 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 */ /* It's harmless to issue the Erase-Suspend and Erase-Resume @@ -1926,6 +1927,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) chip->state = FL_ERASING; chip->erase_suspended = 0; chip->in_progress_block_addr = adr; + chip->in_progress_block_mask = ~(map->size - 1); INVALIDATE_CACHE_UDELAY(map, chip, adr, map->size, @@ -2015,6 +2017,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, chip->state = FL_ERASING; chip->erase_suspended = 0; chip->in_progress_block_addr = adr; + chip->in_progress_block_mask = ~(len - 1); INVALIDATE_CACHE_UDELAY(map, chip, adr, len,