Commit 100f2341e305f98de3aa12fb472771ab029cbda7
Committed by
David Woodhouse
1 parent
52534f2dba
Exists in
master
and in
7 other branches
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; |