diff options
author | Scott Anderson <saa@android.com> | 2012-02-13 14:22:46 -0800 |
---|---|---|
committer | Mike J. Chen <mjchen@google.com> | 2012-03-03 17:29:37 -0800 |
commit | 5bc4f1f181cf9057cd22290b3af818c15076cbf3 (patch) | |
tree | 2a8818ba382fb300bb1c29c288ccdba21c6e619a | |
parent | e47602dc85802446f53204e30974e045c8ad99fb (diff) | |
download | uboot-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.c | 35 |
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; + } } } } |