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

Commit 17febdf7 authored by Sahitya Tummala's avatar Sahitya Tummala
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>
parent b97d19d1
Loading
Loading
Loading
Loading
+96 −21
Original line number Diff line number Diff line
@@ -1366,17 +1366,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.
@@ -1385,12 +1391,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;
		}

@@ -1402,6 +1413,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;
		}

@@ -1417,8 +1430,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);
	}
@@ -1428,25 +1444,37 @@ 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;
		}
	}

	/*
	 * Select card, as all following commands rely on that.
	 */
	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) {
		/*
@@ -1454,12 +1482,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
@@ -1486,8 +1520,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;
@@ -1517,8 +1554,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;
	}
@@ -1533,8 +1573,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,
@@ -1548,8 +1591,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
	 * Activate highest bus speed mode supported by both host and card.
	 */
	err = mmc_select_bus_speed(card, ext_csd);
	if (err)
	if (err) {
		pr_err("%s: %s: mmc_select_bus_speed() fails %d\n",
					mmc_hostname(host), __func__, err);
		goto free_card;
	}

	/*
	 * Enable HPI feature (if supported)
@@ -1558,8 +1604,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_warning("%s: Enabling HPI failed\n",
				   mmc_hostname(card->host));
@@ -1579,8 +1628,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.
@@ -1607,8 +1659,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));
@@ -1632,9 +1687,12 @@ 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;
			}
		}

		if (card->ext_csd.bkops_en) {
			INIT_DELAYED_WORK(&card->bkops_info.dw,
@@ -1658,9 +1716,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
	return 0;

free_card:
	if (!oldcard) {
		host->card = NULL;
	if (!oldcard)
		mmc_remove_card(card);
	}
err:
	return err;
}
@@ -1816,12 +1875,28 @@ out:
static int mmc_resume(struct mmc_host *host)
{
	int err;
	int retries;

	BUG_ON(!host);
	BUG_ON(!host->card);

	mmc_claim_host(host);
	retries = 3;
	while (retries) {
		err = mmc_init_card(host, host->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);
			mmc_select_voltage(host, host->ocr);
			continue;
		}
		break;
	}
	mmc_release_host(host);

	/*