Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6514fbef authored by Can Guo's avatar Can Guo
Browse files

mmc: core: extend SDR104 workaround for other paths



UHS-I SD cards support SDR104 mode which runs the SD card interface
clock upto 208 MHz. But we may see repeated CRC errors in SDR104
with some SDCC controllers. If this happens, commit <aafc430b36f3>
("mmc: sd: reduce the bus speed in case of multiple CRC errors") would
reinit the card to lower speed (SDR50) hoping that CRC error
rate would reduce at lower clock speed (100MHz for SDR50). As the error
may happen for any cmd, this change tries to fix several other paths -
clock scaling, mmc_rescan, non-data commands error path. This change
was backed out from msm-4.9 because SDM845 is unable to detect mmc card
remove by reading cd_gpio. Now it is safe to be merged in once again
because mmc card detect is fixed.

Change-Id: I87505cdc8614ff0c41ad345b2c181603d0235983
Signed-off-by: default avatarSahitya Tummala <stummala@codeaurora.org>
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: default avatarVeerabhadrarao Badiganti <vbadigan@codeaurora.org>
Signed-off-by: default avatarCan Guo <cang@codeaurora.org>
parent d94ffceb
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -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;

	/*
+48 −10
Original line number Diff line number Diff line
@@ -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)
{
@@ -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);

@@ -4257,12 +4289,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;
+1 −0
Original line number Diff line number Diff line
@@ -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