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

Commit da2265f4 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mmc: sd: reduce the bus speed in case of multiple CRC errors in SDR104" into msm-4.9

parents c707d1f4 af6a03e6
Loading
Loading
Loading
Loading
+57 −1
Original line number Diff line number Diff line
@@ -2200,6 +2200,17 @@ static int mmc_blk_err_check(struct mmc_card *card,
	int need_retune = card->host->need_retune;
	int ecc_err = 0, gen_err = 0;

	if (card->host->sdr104_wa && mmc_card_sd(card) &&
	    (card->host->ios.timing == MMC_TIMING_UHS_SDR104) &&
	    !card->sdr104_blocked &&
	    (brq->data.error == -EILSEQ ||
	     brq->data.error == -EIO ||
	     brq->data.error == -ETIMEDOUT ||
	     brq->cmd.error == -EILSEQ ||
	     brq->cmd.error == -EIO ||
	     brq->cmd.error == -ETIMEDOUT))
		card->err_in_sdr104 = true;

	/*
	 * sbc.error indicates a problem with the set block count
	 * command.  No data will have been transferred.
@@ -3640,6 +3651,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
	struct mmc_async_req *areq;
	const u8 packed_nr = 2;
	u8 reqs = 0;
	bool reset = false;
#ifdef CONFIG_MMC_SIMULATE_MAX_SPEED
	unsigned long waitfor = jiffies;
#endif
@@ -3685,6 +3697,26 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
		type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE;
		mmc_queue_bounce_post(mq_rq);

		if (card->err_in_sdr104) {
			/*
			 * Data CRC/timeout errors will manifest as CMD/DATA
			 * ERR. But we'd like to retry these too.
			 * Moreover, no harm done if this fails too for multiple
			 * times, we anyway reduce the bus-speed and retry the
			 * same request.
			 * If that fails too, we don't override this status.
			 */
			if (status == MMC_BLK_ABORT ||
			    status == MMC_BLK_CMD_ERR ||
			    status == MMC_BLK_DATA_ERR ||
			    status == MMC_BLK_RETRY)
				/* reset on all of these errors and retry */
				reset = true;

			status = MMC_BLK_RETRY;
			card->err_in_sdr104 = false;
		}

		switch (status) {
		case MMC_BLK_SUCCESS:
		case MMC_BLK_PARTIAL:
@@ -3725,8 +3757,32 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
			break;
		case MMC_BLK_RETRY:
			retune_retry_done = brq->retune_retry_done;
			if (retry++ < MMC_BLK_MAX_RETRIES)
			if (retry++ < MMC_BLK_MAX_RETRIES) {
				break;
			} else if (reset) {
				reset = false;
				/*
				 * If we exhaust all the retries due to
				 * CRC/timeout errors in SDR140 mode with UHS SD
				 * cards, re-configure the card in SDR50
				 * bus-speed mode.
				 * All subsequent re-init of this card will be
				 * in SDR50 mode, unless it is removed and
				 * re-inserted. When new UHS SD cards are
				 * inserted, it may start at SDR104 mode if
				 * supported by the card.
				 */
				pr_err("%s: blocked SDR104, lower the bus-speed (SDR50 / DDR50)\n",
					req->rq_disk->disk_name);
				mmc_host_clear_sdr104(card->host);
				mmc_suspend_clk_scaling(card->host);
				mmc_blk_reset(md, card->host, type);
				/* SDR104 mode is blocked from now on */
				card->sdr104_blocked = true;
				/* retry 5 times again */
				retry = 0;
				break;
			}
			/* Fall through */
		case MMC_BLK_ABORT:
			if (!mmc_blk_reset(md, card->host, type) &&
+4 −0
Original line number Diff line number Diff line
@@ -4175,6 +4175,10 @@ 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;
		}
		pr_debug("%s: card remove detected\n", mmc_hostname(host));
	}

+0 −1
Original line number Diff line number Diff line
@@ -80,7 +80,6 @@ void mmc_init_context_info(struct mmc_host *host);

extern bool mmc_can_scale_clk(struct mmc_host *host);
extern int mmc_init_clk_scaling(struct mmc_host *host);
extern int mmc_suspend_clk_scaling(struct mmc_host *host);
extern int mmc_resume_clk_scaling(struct mmc_host *host);
extern int mmc_exit_clk_scaling(struct mmc_host *host);
extern unsigned long mmc_get_max_frequency(struct mmc_host *host);
+2 −0
Original line number Diff line number Diff line
@@ -1313,6 +1313,8 @@ static int _mmc_sd_resume(struct mmc_host *host)
#endif
	mmc_card_clr_suspended(host->card);

	if (host->card->sdr104_blocked)
		goto out;
	err = mmc_resume_clk_scaling(host);
	if (err) {
		pr_err("%s: %s: fail to resume clock scaling (%d)\n",
+2 −0
Original line number Diff line number Diff line
@@ -439,6 +439,8 @@ struct mmc_card {
	u8 *cached_ext_csd;
	bool cmdq_init;
	struct mmc_bkops_info bkops;
	bool err_in_sdr104;
	bool sdr104_blocked;
};

/*
Loading