2.6.37-stable review patch. If anyone has any objections, please let us know.
------------------ From: Joakim Tjernlund <[email protected]> commit ecf3fde07c8dcb92a1bf3fbdfe70905d85cd00e1 upstream. As inval_cache_and_wait_for_operation() drop and reclaim the lock to invalidate the cache, some other thread may suspend the operation before reaching the for(;;) loop. Therefore the loop must start with checking the chip->state before reading status from the chip. Signed-off-by: Joakim Tjernlund <[email protected]> Acked-by: Michael Cashwell <[email protected]> Acked-by: Stefan Bigler <[email protected]> Signed-off-by: Artem Bityutskiy <[email protected]> Signed-off-by: David Woodhouse <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> --- drivers/mtd/chips/cfi_cmdset_0001.c | 43 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 21 deletions(-) --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -1229,10 +1229,32 @@ static int inval_cache_and_wait_for_oper sleep_time = chip_op_time / 2; for (;;) { + if (chip->state != chip_state) { + /* Someone's suspended the operation: sleep */ + DECLARE_WAITQUEUE(wait, current); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + mutex_unlock(&chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + mutex_lock(&chip->mutex); + continue; + } + status = map_read(map, cmd_adr); if (map_word_andequal(map, status, status_OK, status_OK)) break; + if (chip->erase_suspended && chip_state == FL_ERASING) { + /* Erase suspend occured while sleep: reset timeout */ + timeo = reset_timeo; + chip->erase_suspended = 0; + } + if (chip->write_suspended && chip_state == FL_WRITING) { + /* Write suspend occured while sleep: reset timeout */ + timeo = reset_timeo; + chip->write_suspended = 0; + } if (!timeo) { map_write(map, CMD(0x70), cmd_adr); chip->state = FL_STATUS; @@ -1256,27 +1278,6 @@ static int inval_cache_and_wait_for_oper timeo--; } mutex_lock(&chip->mutex); - - while (chip->state != chip_state) { - /* Someone's suspended the operation: sleep */ - DECLARE_WAITQUEUE(wait, current); - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - mutex_unlock(&chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); - mutex_lock(&chip->mutex); - } - if (chip->erase_suspended && chip_state == FL_ERASING) { - /* Erase suspend occured while sleep: reset timeout */ - timeo = reset_timeo; - chip->erase_suspended = 0; - } - if (chip->write_suspended && chip_state == FL_WRITING) { - /* Write suspend occured while sleep: reset timeout */ - timeo = reset_timeo; - chip->write_suspended = 0; - } } /* Done and happy. */ _______________________________________________ stable mailing list [email protected] http://linux.kernel.org/mailman/listinfo/stable
