aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJoakim Tjernlund <joakim.tjernlund@transmode.se>2018-03-01 08:39:39 -0500
committerBoris Brezillon <boris.brezillon@bootlin.com>2018-04-24 11:41:18 -0400
commit6510bbc88e3258631831ade49033537081950605 (patch)
tree0d8762148a39f335e76992d0e937bafc657e5b69 /drivers
parent47016b341fc3b3fd4909e058c6fa38f165b53646 (diff)
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@infinera.com> Cc: <stable@vger.kernel.org> Reviewed-by: Richard Weinberger <richard@nod.at> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c16
1 files changed, 11 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
831 (mode == FL_WRITING && (cfip->SuspendCmdSupport & 1)))) 831 (mode == FL_WRITING && (cfip->SuspendCmdSupport & 1))))
832 goto sleep; 832 goto sleep;
833 833
834 /* Do not allow suspend iff read/write to EB address */
835 if ((adr & chip->in_progress_block_mask) ==
836 chip->in_progress_block_addr)
837 goto sleep;
834 838
835 /* Erase suspend */ 839 /* Erase suspend */
836 map_write(map, CMD(0xB0), adr); 840 map_write(map, CMD(0xB0), chip->in_progress_block_addr);
837 841
838 /* If the flash has finished erasing, then 'erase suspend' 842 /* If the flash has finished erasing, then 'erase suspend'
839 * appears to make some (28F320) flash devices switch to 843 * appears to make some (28F320) flash devices switch to
840 * 'read' mode. Make sure that we switch to 'read status' 844 * 'read' mode. Make sure that we switch to 'read status'
841 * mode so we get the right data. --rmk 845 * mode so we get the right data. --rmk
842 */ 846 */
843 map_write(map, CMD(0x70), adr); 847 map_write(map, CMD(0x70), chip->in_progress_block_addr);
844 chip->oldstate = FL_ERASING; 848 chip->oldstate = FL_ERASING;
845 chip->state = FL_ERASE_SUSPENDING; 849 chip->state = FL_ERASE_SUSPENDING;
846 chip->erase_suspended = 1; 850 chip->erase_suspended = 1;
847 for (;;) { 851 for (;;) {
848 status = map_read(map, adr); 852 status = map_read(map, chip->in_progress_block_addr);
849 if (map_word_andequal(map, status, status_OK, status_OK)) 853 if (map_word_andequal(map, status, status_OK, status_OK))
850 break; 854 break;
851 855
@@ -1041,8 +1045,8 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
1041 sending the 0x70 (Read Status) command to an erasing 1045 sending the 0x70 (Read Status) command to an erasing
1042 chip and expecting it to be ignored, that's what we 1046 chip and expecting it to be ignored, that's what we
1043 do. */ 1047 do. */
1044 map_write(map, CMD(0xd0), adr); 1048 map_write(map, CMD(0xd0), chip->in_progress_block_addr);
1045 map_write(map, CMD(0x70), adr); 1049 map_write(map, CMD(0x70), chip->in_progress_block_addr);
1046 chip->oldstate = FL_READY; 1050 chip->oldstate = FL_READY;
1047 chip->state = FL_ERASING; 1051 chip->state = FL_ERASING;
1048 break; 1052 break;
@@ -1933,6 +1937,8 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
1933 map_write(map, CMD(0xD0), adr); 1937 map_write(map, CMD(0xD0), adr);
1934 chip->state = FL_ERASING; 1938 chip->state = FL_ERASING;
1935 chip->erase_suspended = 0; 1939 chip->erase_suspended = 0;
1940 chip->in_progress_block_addr = adr;
1941 chip->in_progress_block_mask = ~(len - 1);
1936 1942
1937 ret = INVAL_CACHE_AND_WAIT(map, chip, adr, 1943 ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
1938 adr, len, 1944 adr, len,