diff options
Diffstat (limited to 'drivers/mmc/core/core.c')
-rw-r--r-- | drivers/mmc/core/core.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 06c42cfb7c34..bccfd1858b08 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -42,6 +42,9 @@ #include "sd_ops.h" #include "sdio_ops.h" +/* If the device is not responding */ +#define MMC_CORE_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ + /* * Background operations can take a long time, depending on the housekeeping * operations the card has to perform. @@ -1631,6 +1634,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, { struct mmc_command cmd = {0}; unsigned int qty = 0; + unsigned long timeout; int err; /* @@ -1708,6 +1712,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, if (mmc_host_is_spi(card->host)) goto out; + timeout = jiffies + msecs_to_jiffies(MMC_CORE_TIMEOUT_MS); do { memset(&cmd, 0, sizeof(struct mmc_command)); cmd.opcode = MMC_SEND_STATUS; @@ -1721,8 +1726,19 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, err = -EIO; goto out; } + + /* Timeout if the device never becomes ready for data and + * never leaves the program state. + */ + if (time_after(jiffies, timeout)) { + pr_err("%s: Card stuck in programming state! %s\n", + mmc_hostname(card->host), __func__); + err = -EIO; + goto out; + } + } while (!(cmd.resp[0] & R1_READY_FOR_DATA) || - R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG); + (R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG)); out: return err; } |