aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Anderson <saa@android.com>2012-02-13 14:22:46 -0800
committerMike J. Chen <mjchen@google.com>2012-03-03 17:29:37 -0800
commit5bc4f1f181cf9057cd22290b3af818c15076cbf3 (patch)
tree2a8818ba382fb300bb1c29c288ccdba21c6e619a
parente47602dc85802446f53204e30974e045c8ad99fb (diff)
downloaduboot-5bc4f1f181cf9057cd22290b3af818c15076cbf3.tar.gz
ARMV7: OMAP: MMC: Relax erase timeouts and cleanup
We have occasionally seen erase timeout errors. Sometimes erases of 1M blocks will take around 6 seconds instead of the typical less than 1 second. I believe this is due to the MMC doing housekeeping. To try to prevent this from happening, the following changes have been made: 1) The base timeout for an erase used to be 5X the retry time. This change increases that to 10X. 2) Only a warning is printed when the timeout is first hit. The timeout is then doubled and if it is hit again, TIMEOUT will be returned and an error printed. In addition, several other minor changes were made: 1) The code used to add 1 ms per 1000 blocks to the timeout. This was changed to 1 ms to 1024 blocks to allow the compiler to optimize it to a shift instead of a divide. In addition, the comment was cleaned up (mainly to remove the inaccurate "1000 ms per 1 million blocks"). 2) Removed the "erasing %lu blocks" printf. Higher levels can print out advisory information if wanted. This matches the other hardware dependent MMC drivers I looked at. Change-Id: I9a03b93dc4adf3b6a4df34a1a2b592f6cad53a87 Signed-off-by: Scott Anderson <saa@android.com>
-rw-r--r--drivers/mmc/omap_hsmmc.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 496111731..fbac289a5 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -376,23 +376,36 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
}
}
- /* if this is an erase, wait for it to complete.
- * Add additional time to the timeout based on number
- * of blocks being erased. Add 1 second per
- * 1000 blocks for now (1000 ms per 1 million blocks).
+ /* If this is an erase, wait for it to complete. Add a fixed
+ * additional time to the timeout to allow the device to manage its
+ * blocks (10X normal retry) plus add an additional time based on
+ * number of blocks being erased (1 ms per 1024 blocks). In
+ * addition, when that time expires, only a warning is printed and
+ * an error will not be returned until double the time has passed.
+ * Callers should try to avoid erasing very large numbers of blocks
+ * at once to prevent timeouts so long that users can't tell if
+ * progress is being made.
*/
if (cmd->cmdidx == MMC_CMD_ERASE) {
- ulong timeout_ms = MAX_RETRY_MS * 5;
+ ulong timeout_ms = MAX_RETRY_MS * 10;
ulong erase_blk_cnt = last_end_value - last_start_value + 1;
- timeout_ms += DIV_ROUND_UP(erase_blk_cnt, 1000);
- printf("%s: erasing %lu blocks, timeout = %lu seconds\n",
- __func__, erase_blk_cnt, timeout_ms / 1000);
+ int warned = 0;
+ timeout_ms += DIV_ROUND_UP(erase_blk_cnt, 1024);
start = get_timer(0);
while ((readl(&mmc_base->pstate) & DATI_MASK) == DATI_CMDDIS) {
if (get_timer(0) - start > timeout_ms) {
- printf("%s: timedout waiting for cmddis"
- " after command!\n", __func__);
- return TIMEOUT;
+ printf("%s: %s erasing blocks %u to %u, "
+ "timeout = %lu seconds\n",
+ __func__,
+ warned ? "Timed out" : "Warning",
+ last_start_value, last_end_value,
+ timeout_ms / 1000);
+ if (warned) {
+ return TIMEOUT;
+ } else {
+ warned = 1;
+ timeout_ms *= 2;
+ }
}
}
}