diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/core/core.c | 36 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 30 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.h | 7 |
3 files changed, 33 insertions, 40 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index a971c4bcc442..3f7a31456eb4 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1658,8 +1658,6 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, struct mmc_command cmd = {}; unsigned int qty = 0, busy_timeout = 0; bool use_r1b_resp = false; - unsigned long timeout; - int loop_udelay=64, udelay_max=32768; int err; mmc_retune_hold(card->host); @@ -1763,38 +1761,8 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) goto out; - timeout = jiffies + msecs_to_jiffies(busy_timeout); - do { - memset(&cmd, 0, sizeof(struct mmc_command)); - cmd.opcode = MMC_SEND_STATUS; - cmd.arg = card->rca << 16; - cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - /* Do not retry else we can't see errors */ - err = mmc_wait_for_cmd(card->host, &cmd, 0); - if (err || R1_STATUS(cmd.resp[0])) { - pr_err("error %d requesting status %#x\n", - err, cmd.resp[0]); - 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; - } - if ((cmd.resp[0] & R1_READY_FOR_DATA) && - R1_CURRENT_STATE(cmd.resp[0]) != R1_STATE_PRG) - break; - - usleep_range(loop_udelay, loop_udelay*2); - if (loop_udelay < udelay_max) - loop_udelay *= 2; - } while (1); + /* Let's poll to find out when the erase operation completes. */ + err = mmc_poll_for_busy(card, busy_timeout, MMC_BUSY_ERASE); out: mmc_retune_release(card->host); diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 4566f43305d5..3f510348b916 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -445,7 +445,7 @@ int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal) } static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err, - bool *busy) + enum mmc_busy_cmd busy_cmd, bool *busy) { struct mmc_host *host = card->host; u32 status = 0; @@ -464,7 +464,17 @@ static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err, if (err) return err; - err = mmc_switch_status_error(card->host, status); + switch (busy_cmd) { + case MMC_BUSY_CMD6: + err = mmc_switch_status_error(card->host, status); + break; + case MMC_BUSY_ERASE: + err = R1_STATUS(status) ? -EIO : 0; + break; + default: + err = -EINVAL; + } + if (err) return err; @@ -472,8 +482,9 @@ static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err, return 0; } -static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, - bool send_status, bool retry_crc_err) +static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, + bool send_status, bool retry_crc_err, + enum mmc_busy_cmd busy_cmd) { struct mmc_host *host = card->host; int err; @@ -500,7 +511,7 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, */ expired = time_after(jiffies, timeout); - err = mmc_busy_status(card, retry_crc_err, &busy); + err = mmc_busy_status(card, retry_crc_err, busy_cmd, &busy); if (err) return err; @@ -522,6 +533,12 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, return 0; } +int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, + enum mmc_busy_cmd busy_cmd) +{ + return __mmc_poll_for_busy(card, timeout_ms, true, false, busy_cmd); +} + /** * __mmc_switch - modify EXT_CSD register * @card: the MMC card associated with the data transfer @@ -591,7 +608,8 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, goto out_tim; /* Let's try to poll to find out when the command is completed. */ - err = mmc_poll_for_busy(card, timeout_ms, send_status, retry_crc_err); + err = __mmc_poll_for_busy(card, timeout_ms, send_status, retry_crc_err, + MMC_BUSY_CMD6); if (err) goto out; diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index de0c509a3a38..8cd05fb583da 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -10,6 +10,11 @@ #include <linux/types.h> +enum mmc_busy_cmd { + MMC_BUSY_CMD6, + MMC_BUSY_ERASE, +}; + struct mmc_host; struct mmc_card; @@ -30,6 +35,8 @@ int mmc_interrupt_hpi(struct mmc_card *card); int mmc_can_ext_csd(struct mmc_card *card); int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd); int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal); +int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, + enum mmc_busy_cmd busy_cmd); int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, unsigned int timeout_ms, unsigned char timing, bool send_status, bool retry_crc_err); |