Commit 100f2341e305f98de3aa12fb472771ab029cbda7

Authored by Tadashi Abe
Committed by David Woodhouse
1 parent 52534f2dba

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>

Showing 4 changed files with 6 additions and 15 deletions Side-by-side Diff

drivers/mtd/chips/cfi_cmdset_0001.c
... ... @@ -812,12 +812,9 @@
812 812 break;
813 813  
814 814 if (time_after(jiffies, timeo)) {
815   - /* Urgh. Resume and pretend we weren't here. */
816   - map_write(map, CMD(0xd0), adr);
817   - /* Make sure we're in 'read status' mode if it had finished */
818   - map_write(map, CMD(0x70), adr);
819   - chip->state = FL_ERASING;
820   - chip->oldstate = FL_READY;
  815 + /* Urgh. Resume and pretend we weren't here.
  816 + * Make sure we're in 'read status' mode if it had finished */
  817 + put_chip(map, chip, adr);
821 818 printk(KERN_ERR "%s: Chip not ready after erase "
822 819 "suspended: status = 0x%lx\n", map->name, status.x[0]);
823 820 return -EIO;
drivers/mtd/chips/cfi_cmdset_0002.c
... ... @@ -711,9 +711,7 @@
711 711 * there was an error (so leave the erase
712 712 * routine to recover from it) or we trying to
713 713 * use the erase-in-progress sector. */
714   - map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr);
715   - chip->state = FL_ERASING;
716   - chip->oldstate = FL_READY;
  714 + put_chip(map, chip, adr);
717 715 printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__);
718 716 return -EIO;
719 717 }
drivers/mtd/chips/cfi_cmdset_0020.c
... ... @@ -296,6 +296,7 @@
296 296 /* make sure we're in 'read status' mode */
297 297 map_write(map, CMD(0x70), cmd_addr);
298 298 chip->state = FL_ERASING;
  299 + wake_up(&chip->wq);
299 300 mutex_unlock(&chip->mutex);
300 301 printk(KERN_ERR "Chip not ready after erase "
301 302 "suspended: status = 0x%lx\n", status.x[0]);
drivers/mtd/lpddr/lpddr_cmds.c
... ... @@ -313,12 +313,7 @@
313 313 if (ret) {
314 314 /* Oops. something got wrong. */
315 315 /* Resume and pretend we weren't here. */
316   - map_write(map, CMD(LPDDR_RESUME),
317   - map->pfow_base + PFOW_COMMAND_CODE);
318   - map_write(map, CMD(LPDDR_START_EXECUTION),
319   - map->pfow_base + PFOW_COMMAND_EXECUTE);
320   - chip->state = FL_ERASING;
321   - chip->oldstate = FL_READY;
  316 + put_chip(map, chip);
322 317 printk(KERN_ERR "%s: suspend operation failed."
323 318 "State may be wrong \n", map->name);
324 319 return -EIO;