diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 95d40fd263698c..bed4d7fe8b9cca 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -399,10 +399,16 @@ void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq) struct mmc_command *cmd; while (1) { - wait_for_completion(&mrq->completion); + if (!host->rescan_disable) + wait_for_completion(&mrq->completion); cmd = mrq->cmd; + if (host->rescan_disable) { + cmd->error = -ENOENT; + break; + } + if (!cmd->error || !cmd->retries || mmc_card_removed(host->card)) break; @@ -619,6 +625,11 @@ EXPORT_SYMBOL(mmc_is_req_done); */ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) { + if (host->rescan_disable) { + mrq->cmd->error = -ENOENT; + return; + } + __mmc_start_req(host, mrq); if (!mrq->cap_cmd_during_tfr) @@ -2265,6 +2276,8 @@ void mmc_rescan(struct work_struct *work) for (i = 0; i < ARRAY_SIZE(freqs); i++) { unsigned int freq = freqs[i]; + if (host->rescan_disable) + return; if (freq > host->f_max) { if (i + 1 < ARRAY_SIZE(freqs)) continue; diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 3b3adbddf6641e..7db55752a671d9 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -512,6 +512,9 @@ int __mmc_poll_for_busy(struct mmc_host *host, unsigned int period_us, timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1; do { + if (host->rescan_disable) + return -ENOENT; + /* * Due to the possibility of being preempted while polling, * check the expiration time first. diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 4b19b8a16b0968..0954d43e41365b 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -673,6 +673,10 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, ocr |= R4_18V_PRESENT; try_again: + if (host->rescan_disable) { + err = -ENOENT; + goto remove; + } if (!retries) { pr_warn("%s: Skipping voltage switch\n", mmc_hostname(host)); ocr &= ~R4_18V_PRESENT; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9bb360efe5b857..64c44a74cb5966 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1490,6 +1490,8 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq) { + if (!mrq) + return false; return (!(host->flags & SDHCI_DEVICE_DEAD) && ((mrq->cmd && mrq->cmd->error) || (mrq->sbc && mrq->sbc->error) || @@ -1629,6 +1631,7 @@ static void sdhci_finish_data(struct sdhci_host *host) static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) { + const unsigned long default_timeout_secs = 5; int flags; u32 mask; unsigned long timeout; @@ -1704,10 +1707,10 @@ static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) timeout = jiffies; if (host->data_timeout) timeout += nsecs_to_jiffies(host->data_timeout); - else if (!cmd->data && cmd->busy_timeout > 9000) + else if (!cmd->data && cmd->busy_timeout > (default_timeout_secs - 1) * 1000) timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; else - timeout += 10 * HZ; + timeout += default_timeout_secs * HZ; sdhci_mod_timer(host, cmd->mrq, timeout); if (host->use_external_dma)