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

Commit 3bc5f567 authored by Sahitya Tummala's avatar Sahitya Tummala Committed by Matt Wagantall
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: I895068edb487e6a44205e0769342b2ec2c89c876
Signed-off-by: default avatarSahitya Tummala <stummala@codeaurora.org>
[merez@codeaurora.org: fix conflicts due to addition of __mmc_resume
in 3.14 and different bus speed implementation]
Signed-off-by: default avatarMaya Erez <merez@codeaurora.org>
[venkatg@codeaurora.org: Fix args for mmc_power_up and
mmc_select_voltage to use with 3.14 kernel]
Signed-off-by: default avatarVenkat Gopalakrishnan <venkatg@codeaurora.org>
parent 84bac424
Loading
Loading
Loading
Loading
+95 −21
Original line number Diff line number Diff line
@@ -1381,17 +1381,23 @@ 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.
	 */
	if (mmc_host_is_spi(host)) {
		err = mmc_spi_set_crc(host, use_spi_crc);
		if (err)
		if (err) {
			pr_err("%s: %s: mmc_spi_set_crc() fails %d\n",
					mmc_hostname(host), __func__, err);
			goto err;
		}
	}

	/*
	 * Fetch CID from card.
@@ -1400,12 +1406,17 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
		err = mmc_send_cid(host, cid);
	else
		err = mmc_all_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;
		}

@@ -1417,6 +1428,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;
		}

@@ -1433,8 +1446,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);
	}
@@ -1444,16 +1460,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
@@ -1467,9 +1492,12 @@ 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) {
		/*
@@ -1477,12 +1505,18 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
		 */

		err = mmc_get_ext_csd(card, &ext_csd);
		if (err)
		if (err) {
			pr_err("%s: %s: mmc_get_ext_csd() fails %d\n",
					mmc_hostname(host), __func__, err);
			goto free_card;
		}
		card->cached_ext_csd = ext_csd;
		err = mmc_read_ext_csd(card, ext_csd);
		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
		 * addressing.  Handle the case of <2GB cards needing sector
@@ -1509,8 +1543,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;
@@ -1540,8 +1577,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONFIG,
				 card->ext_csd.part_config,
				 card->ext_csd.part_time);
		if (err && err != -EBADMSG)
		if (err && err != -EBADMSG) {
			pr_err("%s: %s: mmc_switch() for PART_CONFIG fails %d\n",
					mmc_hostname(host), __func__, err);
			goto free_card;
		}
		card->part_curr = card->ext_csd.part_config &
				  EXT_CSD_PART_CONFIG_ACC_MASK;
	}
@@ -1554,8 +1594,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,
@@ -1569,8 +1612,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);
@@ -1602,8 +1648,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));
@@ -1620,8 +1669,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.
@@ -1647,8 +1699,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
				EXT_CSD_EXP_EVENTS_CTRL,
				EXT_CSD_PACKED_EVENT_EN,
				card->ext_csd.generic_cmd6_time);
		if (err && err != -EBADMSG)
		if (err && err != -EBADMSG) {
			pr_err("%s: %s: mmc_switch() for EXP_EVENTS_CTRL fails %d\n",
					mmc_hostname(host), __func__, err);
			goto free_card;
		}
		if (err) {
			pr_warn("%s: Enabling packed event failed\n",
				mmc_hostname(card->host));
@@ -1672,18 +1727,22 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
				(card->ext_csd.max_packed_writes + 1) *
				sizeof(*card->wr_pack_stats.packing_events),
				GFP_KERNEL);
			if (!card->wr_pack_stats.packing_events)
			if (!card->wr_pack_stats.packing_events) {
				pr_err("%s: %s: no memory for packing events\n",
						mmc_hostname(host), __func__);
				goto free_card;
			}
		}
	}


	return 0;

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

	BUG_ON(!host);
	BUG_ON(!host->card);
@@ -1914,7 +1974,21 @@ static int _mmc_resume(struct mmc_host *host)
	}

	mmc_power_up(host, host->card->ocr);
	retries = 3;
	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_release_host(host);