aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Korolev <akorolev@infradead.org>2008-07-16 10:28:56 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2008-07-25 09:48:42 -0400
commit998453fbf2e0709bf65ac419718ad284401b2b4f (patch)
treea2295f4755e329215a9420916d6a69ce8d9f4444
parent55679df30dfa37886cd9e22d8dea0e6974a552df (diff)
[MTD] [NOR] Fix -ETIMEO errors in CFI driver
Existing CFI driver has problems with excessive writes during erase. If CFI driver does many writes during one erase cycle we may face the messages with -ETIMEO error on erase operation. It may cause the following data corruption and kernel panics. The reason of the issue is related to specifics of suspend operation: if we write to flash during erase, suspend operation will cost some time to erase procedure (for P30 it could be significant). In current version of cfi driver the problem of many suspends is partially workarounded by adding some time reserv to any operation (8xerase_time) but if we have many writes during one erase the problem appears. This patch detects the suspend and resets timer if suspend occured. It has been well verified on different chips. No problems were found. Could you please include the patch as it is simple and fixes bad issue. Signed-off-by: Alexey Korolev <akorolev@infradead.org> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 324ff82a3cd9..5f1b472137a0 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -1149,7 +1149,7 @@ static int inval_cache_and_wait_for_operation(
1149 struct cfi_private *cfi = map->fldrv_priv; 1149 struct cfi_private *cfi = map->fldrv_priv;
1150 map_word status, status_OK = CMD(0x80); 1150 map_word status, status_OK = CMD(0x80);
1151 int chip_state = chip->state; 1151 int chip_state = chip->state;
1152 unsigned int timeo, sleep_time; 1152 unsigned int timeo, sleep_time, reset_timeo;
1153 1153
1154 spin_unlock(chip->mutex); 1154 spin_unlock(chip->mutex);
1155 if (inval_len) 1155 if (inval_len)
@@ -1160,6 +1160,7 @@ static int inval_cache_and_wait_for_operation(
1160 timeo = chip_op_time * 8; 1160 timeo = chip_op_time * 8;
1161 if (!timeo) 1161 if (!timeo)
1162 timeo = 500000; 1162 timeo = 500000;
1163 reset_timeo = timeo;
1163 sleep_time = chip_op_time / 2; 1164 sleep_time = chip_op_time / 2;
1164 1165
1165 for (;;) { 1166 for (;;) {
@@ -1201,6 +1202,12 @@ static int inval_cache_and_wait_for_operation(
1201 remove_wait_queue(&chip->wq, &wait); 1202 remove_wait_queue(&chip->wq, &wait);
1202 spin_lock(chip->mutex); 1203 spin_lock(chip->mutex);
1203 } 1204 }
1205 if (chip->erase_suspended || chip->write_suspended) {
1206 /* Suspend has occured while sleep: reset timeout */
1207 timeo = reset_timeo;
1208 chip->erase_suspended = 0;
1209 chip->write_suspended = 0;
1210 }
1204 } 1211 }
1205 1212
1206 /* Done and happy. */ 1213 /* Done and happy. */