Skip to content

Commit

Permalink
mtd: fix hang-up in cfi erase and read contention
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Tadashi Abe authored and David Woodhouse committed May 25, 2011
1 parent 52534f2 commit 100f234
Show file tree
Hide file tree
Showing 4 changed files with 6 additions and 15 deletions.
9 changes: 3 additions & 6 deletions drivers/mtd/chips/cfi_cmdset_0001.c
Original file line number Diff line number Diff line change
Expand Up @@ -812,12 +812,9 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long
break;

if (time_after(jiffies, timeo)) {
/* 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 */
map_write(map, CMD(0x70), adr);
chip->state = FL_ERASING;
chip->oldstate = FL_READY;
/* Urgh. Resume and pretend we weren't here.
* Make sure we're in 'read status' mode if it had finished */
put_chip(map, chip, adr);
printk(KERN_ERR "%s: Chip not ready after erase "
"suspended: status = 0x%lx\n", map->name, status.x[0]);
return -EIO;
Expand Down
4 changes: 1 addition & 3 deletions drivers/mtd/chips/cfi_cmdset_0002.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
* routine to recover from it) or we trying to
* use the erase-in-progress sector. */
map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr);
chip->state = FL_ERASING;
chip->oldstate = FL_READY;
put_chip(map, chip, adr);
printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__);
return -EIO;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/mtd/chips/cfi_cmdset_0020.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
map_write(map, CMD(0x70), cmd_addr);
chip->state = FL_ERASING;
wake_up(&chip->wq);
mutex_unlock(&chip->mutex);
printk(KERN_ERR "Chip not ready after erase "
"suspended: status = 0x%lx\n", status.x[0]);
Expand Down
7 changes: 1 addition & 6 deletions drivers/mtd/lpddr/lpddr_cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,12 +313,7 @@ static int chip_ready(struct map_info *map, struct flchip *chip, int mode)
if (ret) {
/* Oops. something got wrong. */
/* Resume and pretend we weren't here. */
map_write(map, CMD(LPDDR_RESUME),
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;
put_chip(map, chip);
printk(KERN_ERR "%s: suspend operation failed."
"State may be wrong \n", map->name);
return -EIO;
Expand Down

0 comments on commit 100f234

Please sign in to comment.