Loading drivers/mmc/card/block.c +4 −1 Original line number Diff line number Diff line Loading @@ -1718,6 +1718,8 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, /* We couldn't get a response from the card. Give up. */ if (err) { if (card->err_in_sdr104) return ERR_RETRY; /* Check if the card is removed */ if (mmc_detect_card_removed(card->host)) return ERR_NOMEDIUM; Loading Loading @@ -2208,7 +2210,8 @@ static int mmc_blk_err_check(struct mmc_card *card, brq->data.error == -ETIMEDOUT || brq->cmd.error == -EILSEQ || brq->cmd.error == -EIO || brq->cmd.error == -ETIMEDOUT)) brq->cmd.error == -ETIMEDOUT || brq->sbc.error)) card->err_in_sdr104 = true; /* Loading drivers/mmc/core/core.c +55 −10 Original line number Diff line number Diff line Loading @@ -456,6 +456,22 @@ int mmc_clk_update_freq(struct mmc_host *host, } EXPORT_SYMBOL(mmc_clk_update_freq); void mmc_recovery_fallback_lower_speed(struct mmc_host *host) { if (!host->card) return; if (host->sdr104_wa && mmc_card_sd(host->card) && (host->ios.timing == MMC_TIMING_UHS_SDR104) && !host->card->sdr104_blocked) { pr_err("%s: %s: blocked SDR104, lower the bus-speed (SDR50 / DDR50)\n", mmc_hostname(host), __func__); mmc_host_clear_sdr104(host); mmc_hw_reset(host); host->card->sdr104_blocked = true; } } static int mmc_devfreq_set_target(struct device *dev, unsigned long *freq, u32 devfreq_flags) { Loading Loading @@ -507,6 +523,9 @@ static int mmc_devfreq_set_target(struct device *dev, if (abort) goto out; if (mmc_card_sd(host->card) && host->card->sdr104_blocked) goto rel_host; /* * In case we were able to claim host there is no need to * defer the frequency change. It will be done now Loading @@ -515,15 +534,18 @@ static int mmc_devfreq_set_target(struct device *dev, mmc_host_clk_hold(host); err = mmc_clk_update_freq(host, *freq, clk_scaling->state); if (err && err != -EAGAIN) if (err && err != -EAGAIN) { pr_err("%s: clock scale to %lu failed with error %d\n", mmc_hostname(host), *freq, err); else mmc_recovery_fallback_lower_speed(host); } else { pr_debug("%s: clock change to %lu finished successfully (%s)\n", mmc_hostname(host), *freq, current->comm); } mmc_host_clk_release(host); rel_host: mmc_release_host(host); out: return err; Loading @@ -544,6 +566,9 @@ void mmc_deferred_scaling(struct mmc_host *host) if (!host->clk_scaling.enable) return; if (mmc_card_sd(host->card) && host->card->sdr104_blocked) return; spin_lock_bh(&host->clk_scaling.lock); if (host->clk_scaling.clk_scaling_in_progress || Loading @@ -564,13 +589,15 @@ void mmc_deferred_scaling(struct mmc_host *host) err = mmc_clk_update_freq(host, target_freq, host->clk_scaling.state); if (err && err != -EAGAIN) if (err && err != -EAGAIN) { pr_err("%s: failed on deferred scale clocks (%d)\n", mmc_hostname(host), err); else mmc_recovery_fallback_lower_speed(host); } else { pr_debug("%s: clocks were successfully scaled to %lu (%s)\n", mmc_hostname(host), target_freq, current->comm); } host->clk_scaling.clk_scaling_in_progress = false; atomic_dec(&host->clk_scaling.devfreq_abort); } Loading Loading @@ -1540,8 +1567,13 @@ void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq) } } if (!cmd->error || !cmd->retries || mmc_card_removed(host->card)) mmc_card_removed(host->card)) { if (cmd->error && !cmd->retries && cmd->opcode != MMC_SEND_STATUS && cmd->opcode != MMC_SEND_TUNING_BLOCK) mmc_recovery_fallback_lower_speed(host); break; } mmc_retune_recheck(host); Loading Loading @@ -2368,6 +2400,13 @@ void mmc_ungate_clock(struct mmc_host *host) WARN_ON(host->ios.clock); /* This call will also set host->clk_gated to false */ __mmc_set_clock(host, host->clk_old); /* * We have seen that host controller's clock tuning circuit may * go out of sync if controller clocks are gated. * To workaround this issue, we are triggering retuning of the * tuning circuit after ungating the controller clocks. */ mmc_retune_needed(host); } } Loading Loading @@ -4189,12 +4228,18 @@ int _mmc_detect_card_removed(struct mmc_host *host) } if (ret) { if (host->ops->get_cd && host->ops->get_cd(host)) { mmc_recovery_fallback_lower_speed(host); ret = 0; } else { mmc_card_set_removed(host->card); if (host->card->sdr104_blocked) { mmc_host_set_sdr104(host); host->card->sdr104_blocked = false; } pr_debug("%s: card remove detected\n", mmc_hostname(host)); pr_debug("%s: card remove detected\n", mmc_hostname(host)); } } return ret; Loading include/linux/mmc/core.h +1 −0 Original line number Diff line number Diff line Loading @@ -232,6 +232,7 @@ extern void mmc_cmdq_clk_scaling_start_busy(struct mmc_host *host, bool lock_needed); extern void mmc_cmdq_clk_scaling_stop_busy(struct mmc_host *host, bool lock_needed, bool is_cmdq_dcmd); extern void mmc_recovery_fallback_lower_speed(struct mmc_host *host); /** * mmc_claim_host - exclusively claim a host Loading Loading
drivers/mmc/card/block.c +4 −1 Original line number Diff line number Diff line Loading @@ -1718,6 +1718,8 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, /* We couldn't get a response from the card. Give up. */ if (err) { if (card->err_in_sdr104) return ERR_RETRY; /* Check if the card is removed */ if (mmc_detect_card_removed(card->host)) return ERR_NOMEDIUM; Loading Loading @@ -2208,7 +2210,8 @@ static int mmc_blk_err_check(struct mmc_card *card, brq->data.error == -ETIMEDOUT || brq->cmd.error == -EILSEQ || brq->cmd.error == -EIO || brq->cmd.error == -ETIMEDOUT)) brq->cmd.error == -ETIMEDOUT || brq->sbc.error)) card->err_in_sdr104 = true; /* Loading
drivers/mmc/core/core.c +55 −10 Original line number Diff line number Diff line Loading @@ -456,6 +456,22 @@ int mmc_clk_update_freq(struct mmc_host *host, } EXPORT_SYMBOL(mmc_clk_update_freq); void mmc_recovery_fallback_lower_speed(struct mmc_host *host) { if (!host->card) return; if (host->sdr104_wa && mmc_card_sd(host->card) && (host->ios.timing == MMC_TIMING_UHS_SDR104) && !host->card->sdr104_blocked) { pr_err("%s: %s: blocked SDR104, lower the bus-speed (SDR50 / DDR50)\n", mmc_hostname(host), __func__); mmc_host_clear_sdr104(host); mmc_hw_reset(host); host->card->sdr104_blocked = true; } } static int mmc_devfreq_set_target(struct device *dev, unsigned long *freq, u32 devfreq_flags) { Loading Loading @@ -507,6 +523,9 @@ static int mmc_devfreq_set_target(struct device *dev, if (abort) goto out; if (mmc_card_sd(host->card) && host->card->sdr104_blocked) goto rel_host; /* * In case we were able to claim host there is no need to * defer the frequency change. It will be done now Loading @@ -515,15 +534,18 @@ static int mmc_devfreq_set_target(struct device *dev, mmc_host_clk_hold(host); err = mmc_clk_update_freq(host, *freq, clk_scaling->state); if (err && err != -EAGAIN) if (err && err != -EAGAIN) { pr_err("%s: clock scale to %lu failed with error %d\n", mmc_hostname(host), *freq, err); else mmc_recovery_fallback_lower_speed(host); } else { pr_debug("%s: clock change to %lu finished successfully (%s)\n", mmc_hostname(host), *freq, current->comm); } mmc_host_clk_release(host); rel_host: mmc_release_host(host); out: return err; Loading @@ -544,6 +566,9 @@ void mmc_deferred_scaling(struct mmc_host *host) if (!host->clk_scaling.enable) return; if (mmc_card_sd(host->card) && host->card->sdr104_blocked) return; spin_lock_bh(&host->clk_scaling.lock); if (host->clk_scaling.clk_scaling_in_progress || Loading @@ -564,13 +589,15 @@ void mmc_deferred_scaling(struct mmc_host *host) err = mmc_clk_update_freq(host, target_freq, host->clk_scaling.state); if (err && err != -EAGAIN) if (err && err != -EAGAIN) { pr_err("%s: failed on deferred scale clocks (%d)\n", mmc_hostname(host), err); else mmc_recovery_fallback_lower_speed(host); } else { pr_debug("%s: clocks were successfully scaled to %lu (%s)\n", mmc_hostname(host), target_freq, current->comm); } host->clk_scaling.clk_scaling_in_progress = false; atomic_dec(&host->clk_scaling.devfreq_abort); } Loading Loading @@ -1540,8 +1567,13 @@ void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq) } } if (!cmd->error || !cmd->retries || mmc_card_removed(host->card)) mmc_card_removed(host->card)) { if (cmd->error && !cmd->retries && cmd->opcode != MMC_SEND_STATUS && cmd->opcode != MMC_SEND_TUNING_BLOCK) mmc_recovery_fallback_lower_speed(host); break; } mmc_retune_recheck(host); Loading Loading @@ -2368,6 +2400,13 @@ void mmc_ungate_clock(struct mmc_host *host) WARN_ON(host->ios.clock); /* This call will also set host->clk_gated to false */ __mmc_set_clock(host, host->clk_old); /* * We have seen that host controller's clock tuning circuit may * go out of sync if controller clocks are gated. * To workaround this issue, we are triggering retuning of the * tuning circuit after ungating the controller clocks. */ mmc_retune_needed(host); } } Loading Loading @@ -4189,12 +4228,18 @@ int _mmc_detect_card_removed(struct mmc_host *host) } if (ret) { if (host->ops->get_cd && host->ops->get_cd(host)) { mmc_recovery_fallback_lower_speed(host); ret = 0; } else { mmc_card_set_removed(host->card); if (host->card->sdr104_blocked) { mmc_host_set_sdr104(host); host->card->sdr104_blocked = false; } pr_debug("%s: card remove detected\n", mmc_hostname(host)); pr_debug("%s: card remove detected\n", mmc_hostname(host)); } } return ret; Loading
include/linux/mmc/core.h +1 −0 Original line number Diff line number Diff line Loading @@ -232,6 +232,7 @@ extern void mmc_cmdq_clk_scaling_start_busy(struct mmc_host *host, bool lock_needed); extern void mmc_cmdq_clk_scaling_stop_busy(struct mmc_host *host, bool lock_needed, bool is_cmdq_dcmd); extern void mmc_recovery_fallback_lower_speed(struct mmc_host *host); /** * mmc_claim_host - exclusively claim a host Loading