diff options
author | Massimo Cirillo <maxcir@gmail.com> | 2008-01-11 05:24:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-01-11 14:44:37 -0500 |
commit | 646fd12784d506180353005f40f90bcf08c84a3e (patch) | |
tree | 69cd72ea6fb51212d439bd3e4237126af2b6ada2 /drivers/mtd/chips | |
parent | 7c48c56e9b5a51263269dd419cc32531db141340 (diff) |
cache invalidation error for buffered write
The bug causes corruptions of data read from flash.
The original code performs cache invalidation from "adr" to "adr + len"
in do_write_buffer(). Since len and adr could be updated in the code
before invalidation - it causes improper setting of cache invalidation
regions.
Signed-off-by: Massimo Cirillo <maxcir@gmail.com>
Signed-off-by: Giuseppe D'Eliseo <giuseppedeliseo@gmail.com>
Acked-by: Nicolas Pitre <nico@cam.org>
Acked-by: Jörn Engel <joern@logfs.org>
Signed-off-by: David Woohouse <dwmw2@infradead.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/mtd/chips')
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0001.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index a9eb1c516247..1707f98c322c 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -1504,9 +1504,12 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1504 | int ret, wbufsize, word_gap, words; | 1504 | int ret, wbufsize, word_gap, words; |
1505 | const struct kvec *vec; | 1505 | const struct kvec *vec; |
1506 | unsigned long vec_seek; | 1506 | unsigned long vec_seek; |
1507 | unsigned long initial_adr; | ||
1508 | int initial_len = len; | ||
1507 | 1509 | ||
1508 | wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; | 1510 | wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; |
1509 | adr += chip->start; | 1511 | adr += chip->start; |
1512 | initial_adr = adr; | ||
1510 | cmd_adr = adr & ~(wbufsize-1); | 1513 | cmd_adr = adr & ~(wbufsize-1); |
1511 | 1514 | ||
1512 | /* Let's determine this according to the interleave only once */ | 1515 | /* Let's determine this according to the interleave only once */ |
@@ -1519,7 +1522,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1519 | return ret; | 1522 | return ret; |
1520 | } | 1523 | } |
1521 | 1524 | ||
1522 | XIP_INVAL_CACHED_RANGE(map, adr, len); | 1525 | XIP_INVAL_CACHED_RANGE(map, initial_adr, initial_len); |
1523 | ENABLE_VPP(map); | 1526 | ENABLE_VPP(map); |
1524 | xip_disable(map, chip, cmd_adr); | 1527 | xip_disable(map, chip, cmd_adr); |
1525 | 1528 | ||
@@ -1610,7 +1613,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1610 | chip->state = FL_WRITING; | 1613 | chip->state = FL_WRITING; |
1611 | 1614 | ||
1612 | ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, | 1615 | ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, |
1613 | adr, len, | 1616 | initial_adr, initial_len, |
1614 | chip->buffer_write_time); | 1617 | chip->buffer_write_time); |
1615 | if (ret) { | 1618 | if (ret) { |
1616 | map_write(map, CMD(0x70), cmd_adr); | 1619 | map_write(map, CMD(0x70), cmd_adr); |