aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChaotian Jing <chaotian.jing@mediatek.com>2015-11-29 20:27:30 -0500
committerUlf Hansson <ulf.hansson@linaro.org>2015-12-22 05:32:18 -0500
commit3bbb0deea6d5c6d5ed38ae927a5bf9b0cd7c8639 (patch)
treee1af5a6ec3b17d99f86fa42c6c39563b01602197
parent05caee939f8d58d81e962071da85761e1e3a4c73 (diff)
mmc: core: fix __mmc_switch timeout caused by preempt
there is a time window between __mmc_send_status() and time_afer(), on some eMMC chip, the timeout_ms is only 10ms, if this thread was scheduled out during this period, then, even card has already changes to transfer state by the result of CMD13, this part of code also treat it to timeout error. So, need calculate timeout first, then call __mmc_send_status(), if already timeout and card still in programing state, then treat it to the real timeout error. Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/core/mmc_ops.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 1f444269ebbe..2c90635c89af 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -489,6 +489,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
489 unsigned long timeout; 489 unsigned long timeout;
490 u32 status = 0; 490 u32 status = 0;
491 bool use_r1b_resp = use_busy_signal; 491 bool use_r1b_resp = use_busy_signal;
492 bool expired = false;
492 493
493 mmc_retune_hold(host); 494 mmc_retune_hold(host);
494 495
@@ -545,6 +546,12 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
545 timeout = jiffies + msecs_to_jiffies(timeout_ms); 546 timeout = jiffies + msecs_to_jiffies(timeout_ms);
546 do { 547 do {
547 if (send_status) { 548 if (send_status) {
549 /*
550 * Due to the possibility of being preempted after
551 * sending the status command, check the expiration
552 * time first.
553 */
554 expired = time_after(jiffies, timeout);
548 err = __mmc_send_status(card, &status, ignore_crc); 555 err = __mmc_send_status(card, &status, ignore_crc);
549 if (err) 556 if (err)
550 goto out; 557 goto out;
@@ -565,7 +572,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
565 } 572 }
566 573
567 /* Timeout if the device never leaves the program state. */ 574 /* Timeout if the device never leaves the program state. */
568 if (time_after(jiffies, timeout)) { 575 if (expired && R1_CURRENT_STATE(status) == R1_STATE_PRG) {
569 pr_err("%s: Card stuck in programming state! %s\n", 576 pr_err("%s: Card stuck in programming state! %s\n",
570 mmc_hostname(host), __func__); 577 mmc_hostname(host), __func__);
571 err = -ETIMEDOUT; 578 err = -ETIMEDOUT;