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

Commit 874c1642 authored by Ram Prakash Gupta's avatar Ram Prakash Gupta
Browse files

mmc: core: Add retry mechanism for MMC resume failure



Enhance the error handling/recovery path during eMMC resume by
adding retry mechanism and by adding additional error messages
to failure cases. This may help some of the bad parts which fail
to resume sporadically.

Change-Id: I71848f8239bdad7ff17a00140f2ff39ae68e2ba2
Signed-off-by: default avatarSahitya Tummala <stummala@codeaurora.org>
Signed-off-by: default avatarMaya Erez <merez@codeaurora.org>
Signed-off-by: default avatarVenkat Gopalakrishnan <venkatg@codeaurora.org>
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: default avatarRam Prakash Gupta <rampraka@codeaurora.org>
parent 96621034
Loading
Loading
Loading
Loading
+77 −15
Original line number Diff line number Diff line
@@ -660,6 +660,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)

static int mmc_read_ext_csd(struct mmc_card *card)
{
	struct mmc_host *host = card->host;
	u8 *ext_csd;
	int err;

@@ -668,6 +669,8 @@ static int mmc_read_ext_csd(struct mmc_card *card)

	err = mmc_get_ext_csd(card, &ext_csd);
	if (err) {
		pr_err("%s: %s: mmc_get_ext_csd() fails %d\n",
			mmc_hostname(host), __func__, err);
		/* If the host or the card can't do the switch,
		 * fail more gracefully. */
		if ((err != -EINVAL)
@@ -1870,8 +1873,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,

	/* The extra bit indicates that we support high capacity */
	err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr);
	if (err)
	if (err) {
		pr_err("%s: %s: mmc_send_op_cond() fails %d\n",
				mmc_hostname(host), __func__, err);
		goto err;
	}

	/*
	 * For SPI, enable CRC as appropriate.
@@ -1886,12 +1892,17 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
	 * Fetch CID from card.
	 */
	err = mmc_send_cid(host, cid);
	if (err)
	if (err) {
		pr_err("%s: %s: mmc_send_cid() fails %d\n",
				mmc_hostname(host), __func__, err);
		goto err;
	}

	if (oldcard) {
		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
			err = -ENOENT;
			pr_err("%s: %s: CID memcmp failed %d\n",
					mmc_hostname(host), __func__, err);
			goto err;
		}

@@ -1903,6 +1914,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
		card = mmc_alloc_card(host, &mmc_type);
		if (IS_ERR(card)) {
			err = PTR_ERR(card);
			pr_err("%s: %s: no memory to allocate for card %d\n",
					mmc_hostname(host), __func__, err);
			goto err;
		}

@@ -1925,8 +1938,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_set_relative_addr(card);
		if (err)
		if (err) {
			pr_err("%s: %s: mmc_set_relative_addr() fails %d\n",
					mmc_hostname(host), __func__, err);
			goto free_card;
		}

		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
	}
@@ -1936,16 +1952,25 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
		 * Fetch CSD from card.
		 */
		err = mmc_send_csd(card, card->raw_csd);
		if (err)
		if (err) {
			pr_err("%s: %s: mmc_send_csd() fails %d\n",
					mmc_hostname(host), __func__, err);
			goto free_card;
		}

		err = mmc_decode_csd(card);
		if (err)
		if (err) {
			pr_err("%s: %s: mmc_decode_csd() fails %d\n",
					mmc_hostname(host), __func__, err);
			goto free_card;
		}
		err = mmc_decode_cid(card);
		if (err)
		if (err) {
			pr_err("%s: %s: mmc_decode_cid() fails %d\n",
					mmc_hostname(host), __func__, err);
			goto free_card;
		}
	}

	/*
	 * handling only for cards supporting DSR and hosts requesting
@@ -1959,15 +1984,21 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_select_card(card);
		if (err)
		if (err) {
			pr_err("%s: %s: mmc_select_card() fails %d\n",
					mmc_hostname(host), __func__, err);
			goto free_card;
		}
	}

	if (!oldcard) {
		/* Read extended CSD. */
		err = mmc_read_ext_csd(card);
		if (err)
		if (err) {
			pr_err("%s: %s: mmc_read_ext_csd() fails %d\n",
					mmc_hostname(host), __func__, err);
			goto free_card;
		}

		/*
		 * If doing byte addressing, check if required to do sector
@@ -1988,8 +2019,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
				 EXT_CSD_ERASE_GROUP_DEF, 1,
				 card->ext_csd.generic_cmd6_time);

		if (err && err != -EBADMSG)
		if (err && err != -EBADMSG) {
			pr_err("%s: %s: mmc_switch() for ERASE_GRP_DEF fails %d\n",
					mmc_hostname(host), __func__, err);
			goto free_card;
		}

		if (err) {
			err = 0;
@@ -2036,8 +2070,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
				 EXT_CSD_POWER_OFF_NOTIFICATION,
				 EXT_CSD_POWER_ON,
				 card->ext_csd.generic_cmd6_time);
		if (err && err != -EBADMSG)
		if (err && err != -EBADMSG) {
			pr_err("%s: %s: mmc_switch() for POWER_ON PON fails %d\n",
					mmc_hostname(host), __func__, err);
			goto free_card;
		}

		/*
		 * The err can be -EBADMSG or 0,
@@ -2051,8 +2088,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
	 * Select timing interface
	 */
	err = mmc_select_timing(card);
	if (err)
	if (err) {
		pr_err("%s: %s: mmc_select_timing() fails %d\n",
				mmc_hostname(host), __func__, err);
		goto free_card;
	}

	if (mmc_card_hs200(card)) {
		err = mmc_hs200_tuning(card);
@@ -2094,8 +2134,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
				EXT_CSD_HPI_MGMT, 1,
				card->ext_csd.generic_cmd6_time);
		if (err && err != -EBADMSG)
		if (err && err != -EBADMSG) {
			pr_err("%s: %s: mmc_switch() for HPI_MGMT fails %d\n",
					mmc_hostname(host), __func__, err);
			goto free_card;
		}
		if (err) {
			pr_warn("%s: Enabling HPI failed\n",
				mmc_hostname(card->host));
@@ -2115,8 +2158,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
				EXT_CSD_CACHE_CTRL, 1,
				card->ext_csd.generic_cmd6_time);
		if (err && err != -EBADMSG)
		if (err && err != -EBADMSG) {
			pr_err("%s: %s: mmc_switch() for CACHE_CTRL fails %d\n",
					mmc_hostname(host), __func__, err);
			goto free_card;
		}

		/*
		 * Only if no error, cache is turned on successfully.
@@ -2181,8 +2227,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
	return 0;

free_card:
	if (!oldcard)
	if (!oldcard) {
		host->card = NULL;
		mmc_remove_card(card);
	}
err:
	return err;
}
@@ -2411,6 +2459,7 @@ static int mmc_suspend(struct mmc_host *host)
static int _mmc_resume(struct mmc_host *host)
{
	int err = 0;
	int retries = 3;

	mmc_claim_host(host);

@@ -2421,7 +2470,20 @@ static int _mmc_resume(struct mmc_host *host)

	mmc_log_string(host, "Enter\n");
	mmc_power_up(host, host->card->ocr);
	while (retries) {
		err = mmc_init_card(host, host->card->ocr, host->card);
		if (err) {
			pr_err("%s: MMC card re-init failed rc = %d (retries = %d)\n",
					mmc_hostname(host), err, retries);
			retries--;
			mmc_power_off(host);
			usleep_range(5000, 5500);
			mmc_power_up(host, host->card->ocr);
			mmc_select_voltage(host, host->card->ocr);
			continue;
		}
		break;
	}
	mmc_card_clr_suspended(host->card);

	mmc_log_string(host, "Exit err %d\n", err);