mirror of
https://github.com/fail0verflow/switch-linux.git
synced 2025-05-04 02:34:21 -04:00
mtd: fix hang-up in cfi erase and read contention
cfi erase command hangs up when erase and read contention occurs. If read runs at the same address as erase operation, read issues Erase-Suspend via get_chip() and the erase goes into sleep in wait queue. But in this case, read operation exits by time-out without waking it up. I think the other variants (0001, 0020 and lpddr) have the same problem too. Tested and verified the patch only on CFI-0002 flash, though. Signed-off-by: Tadashi Abe <tabe@mvista.com> Acked-by: Joakim Tjernlund <joakim.tjernlund@transmode.se> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
parent
52534f2dba
commit
100f2341e3
4 changed files with 6 additions and 15 deletions
|
@ -812,12 +812,9 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (time_after(jiffies, timeo)) {
|
if (time_after(jiffies, timeo)) {
|
||||||
/* Urgh. Resume and pretend we weren't here. */
|
/* Urgh. Resume and pretend we weren't here.
|
||||||
map_write(map, CMD(0xd0), adr);
|
* Make sure we're in 'read status' mode if it had finished */
|
||||||
/* Make sure we're in 'read status' mode if it had finished */
|
put_chip(map, chip, adr);
|
||||||
map_write(map, CMD(0x70), adr);
|
|
||||||
chip->state = FL_ERASING;
|
|
||||||
chip->oldstate = FL_READY;
|
|
||||||
printk(KERN_ERR "%s: Chip not ready after erase "
|
printk(KERN_ERR "%s: Chip not ready after erase "
|
||||||
"suspended: status = 0x%lx\n", map->name, status.x[0]);
|
"suspended: status = 0x%lx\n", map->name, status.x[0]);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
|
@ -711,9 +711,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
|
||||||
* there was an error (so leave the erase
|
* there was an error (so leave the erase
|
||||||
* routine to recover from it) or we trying to
|
* routine to recover from it) or we trying to
|
||||||
* use the erase-in-progress sector. */
|
* use the erase-in-progress sector. */
|
||||||
map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr);
|
put_chip(map, chip, adr);
|
||||||
chip->state = FL_ERASING;
|
|
||||||
chip->oldstate = FL_READY;
|
|
||||||
printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__);
|
printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
|
@ -296,6 +296,7 @@ static inline int do_read_onechip(struct map_info *map, struct flchip *chip, lof
|
||||||
/* make sure we're in 'read status' mode */
|
/* make sure we're in 'read status' mode */
|
||||||
map_write(map, CMD(0x70), cmd_addr);
|
map_write(map, CMD(0x70), cmd_addr);
|
||||||
chip->state = FL_ERASING;
|
chip->state = FL_ERASING;
|
||||||
|
wake_up(&chip->wq);
|
||||||
mutex_unlock(&chip->mutex);
|
mutex_unlock(&chip->mutex);
|
||||||
printk(KERN_ERR "Chip not ready after erase "
|
printk(KERN_ERR "Chip not ready after erase "
|
||||||
"suspended: status = 0x%lx\n", status.x[0]);
|
"suspended: status = 0x%lx\n", status.x[0]);
|
||||||
|
|
|
@ -313,12 +313,7 @@ static int chip_ready(struct map_info *map, struct flchip *chip, int mode)
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/* Oops. something got wrong. */
|
/* Oops. something got wrong. */
|
||||||
/* Resume and pretend we weren't here. */
|
/* Resume and pretend we weren't here. */
|
||||||
map_write(map, CMD(LPDDR_RESUME),
|
put_chip(map, chip);
|
||||||
map->pfow_base + PFOW_COMMAND_CODE);
|
|
||||||
map_write(map, CMD(LPDDR_START_EXECUTION),
|
|
||||||
map->pfow_base + PFOW_COMMAND_EXECUTE);
|
|
||||||
chip->state = FL_ERASING;
|
|
||||||
chip->oldstate = FL_READY;
|
|
||||||
printk(KERN_ERR "%s: suspend operation failed."
|
printk(KERN_ERR "%s: suspend operation failed."
|
||||||
"State may be wrong \n", map->name);
|
"State may be wrong \n", map->name);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
Loading…
Add table
Reference in a new issue