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>
This commit is contained in:
parent
7c48c56e9b
commit
646fd12784
1 changed files with 5 additions and 2 deletions
|
@ -1504,9 +1504,12 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
|
||||||
int ret, wbufsize, word_gap, words;
|
int ret, wbufsize, word_gap, words;
|
||||||
const struct kvec *vec;
|
const struct kvec *vec;
|
||||||
unsigned long vec_seek;
|
unsigned long vec_seek;
|
||||||
|
unsigned long initial_adr;
|
||||||
|
int initial_len = len;
|
||||||
|
|
||||||
wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
|
wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
|
||||||
adr += chip->start;
|
adr += chip->start;
|
||||||
|
initial_adr = adr;
|
||||||
cmd_adr = adr & ~(wbufsize-1);
|
cmd_adr = adr & ~(wbufsize-1);
|
||||||
|
|
||||||
/* Let's determine this according to the interleave only once */
|
/* 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,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
XIP_INVAL_CACHED_RANGE(map, adr, len);
|
XIP_INVAL_CACHED_RANGE(map, initial_adr, initial_len);
|
||||||
ENABLE_VPP(map);
|
ENABLE_VPP(map);
|
||||||
xip_disable(map, chip, cmd_adr);
|
xip_disable(map, chip, cmd_adr);
|
||||||
|
|
||||||
|
@ -1610,7 +1613,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
|
||||||
chip->state = FL_WRITING;
|
chip->state = FL_WRITING;
|
||||||
|
|
||||||
ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr,
|
ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr,
|
||||||
adr, len,
|
initial_adr, initial_len,
|
||||||
chip->buffer_write_time);
|
chip->buffer_write_time);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
map_write(map, CMD(0x70), cmd_adr);
|
map_write(map, CMD(0x70), cmd_adr);
|
||||||
|
|
Loading…
Reference in a new issue