Merge "mmc: core: extend SDR104 workaround for other paths"
This commit is contained in:
commit
c1df3ce04e
4 changed files with 62 additions and 11 deletions
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -456,6 +456,22 @@ out:
|
|||
}
|
||||
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)
|
||||
{
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -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 ||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -1571,8 +1598,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);
|
||||
|
||||
|
|
@ -4264,12 +4296,18 @@ int _mmc_detect_card_removed(struct mmc_host *host)
|
|||
}
|
||||
|
||||
if (ret) {
|
||||
mmc_card_set_removed(host->card);
|
||||
if (host->card->sdr104_blocked) {
|
||||
mmc_host_set_sdr104(host);
|
||||
host->card->sdr104_blocked = false;
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -77,6 +77,15 @@ EXPORT_SYMBOL(mmc_gpio_get_ro);
|
|||
int mmc_gpio_get_cd(struct mmc_host *host)
|
||||
{
|
||||
struct mmc_gpio *ctx = host->slot.handler_priv;
|
||||
int ret;
|
||||
|
||||
if (host->extcon) {
|
||||
ret = extcon_get_state(host->extcon, EXTCON_MECHANICAL);
|
||||
if (ret < 0)
|
||||
dev_err(mmc_dev(host), "%s: Extcon failed to check card state, ret=%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!ctx || !ctx->cd_gpio)
|
||||
return -ENOSYS;
|
||||
|
|
|
|||
|
|
@ -233,6 +233,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…
Reference in a new issue