This patch extends timeout to 2s and sets minimal interval time for checking op_cond stuck problem. Signed-off-by: Huijin Park <huijin.park@xxxxxxxxxxx> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index d63d1c735335..ccad6379d183 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -21,6 +21,7 @@ #define MMC_BKOPS_TIMEOUT_MS (120 * 1000) /* 120s */ #define MMC_SANITIZE_TIMEOUT_MS (240 * 1000) /* 240s */ +#define MMC_OP_COND_TIMEOUT_MS ( 2 * 1000) /* 2s */ static const u8 tuning_blk_pattern_4bit[] = { 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc, @@ -179,6 +180,47 @@ int mmc_go_idle(struct mmc_host *host) return err; } +static int ____mmc_poll_for_busy(struct mmc_host *host, unsigned int udelay_min, + unsigned int timeout_ms, + int (*busy_cb)(void *cb_data, bool *busy), + void *cb_data) +{ + int err; + unsigned long timeout; + unsigned int udelay = udelay_min, udelay_max = 32768; + bool expired = false; + bool busy = false; + + timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1; + do { + /* + * Due to the possibility of being preempted while polling, + * check the expiration time first. + */ + expired = time_after(jiffies, timeout); + + err = (*busy_cb)(cb_data, &busy); + if (err) + return err; + + /* Timeout if the device still remains busy. */ + if (expired && busy) { + pr_err("%s: Card stuck being busy! %s\n", + mmc_hostname(host), __func__); + return -ETIMEDOUT; + } + + /* Throttle the polling rate to avoid hogging the CPU. */ + if (busy) { + usleep_range(udelay, udelay * 2); + if (udelay < udelay_max) + udelay *= 2; + } + } while (busy); + + return 0; +} + static int __mmc_send_op_cond_cb(void *cb_data, bool *busy) { struct mmc_op_cond_busy_data *data = cb_data; @@ -232,7 +274,8 @@ int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) cmd.arg = mmc_host_is_spi(host) ? 0 : ocr; cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; - err = __mmc_poll_for_busy(host, 1000, &__mmc_send_op_cond_cb, &cb_data); + err = ____mmc_poll_for_busy(host, 1000, MMC_OP_COND_TIMEOUT_MS, + &__mmc_send_op_cond_cb, &cb_data); if (err) return err; -- 2.17.1