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

Commit f0cc9cf9 authored by Ulf Hansson's avatar Ulf Hansson Committed by Chris Ball
Browse files

mmc: core: Detect card removal on I/O error



To prevent I/O as soon as possible at card removal, a new detect work is
re-scheduled without a delay to let a rescan remove the card device as
soon as possible.

Additionally, MMC_CAP2_DETECT_ON_ERR can now be used to handle "slowly"
removed cards that a scheduled detect work did not detect as removed.
To prevent further I/O requests for these lingering removed cards,
check if card has been removed and then schedule a detect work to
properly remove it.

Signed-off-by: default avatarUlf Hansson <ulf.hansson@stericsson.com>
Reviewed-by: default avatarNamjae Jeon <linkinjeon@gmail.com>
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 885c3e80
Loading
Loading
Loading
Loading
+21 −3
Original line number Original line Diff line number Diff line
@@ -2121,18 +2121,36 @@ int _mmc_detect_card_removed(struct mmc_host *host)
int mmc_detect_card_removed(struct mmc_host *host)
int mmc_detect_card_removed(struct mmc_host *host)
{
{
	struct mmc_card *card = host->card;
	struct mmc_card *card = host->card;
	int ret;


	WARN_ON(!host->claimed);
	WARN_ON(!host->claimed);

	if (!card)
		return 1;

	ret = mmc_card_removed(card);
	/*
	/*
	 * The card will be considered unchanged unless we have been asked to
	 * The card will be considered unchanged unless we have been asked to
	 * detect a change or host requires polling to provide card detection.
	 * detect a change or host requires polling to provide card detection.
	 */
	 */
	if (card && !host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL))
	if (!host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL) &&
		return mmc_card_removed(card);
	    !(host->caps2 & MMC_CAP2_DETECT_ON_ERR))
		return ret;


	host->detect_change = 0;
	host->detect_change = 0;
	if (!ret) {
		ret = _mmc_detect_card_removed(host);
		if (ret && (host->caps2 & MMC_CAP2_DETECT_ON_ERR)) {
			/*
			 * Schedule a detect work as soon as possible to let a
			 * rescan handle the card removal.
			 */
			cancel_delayed_work(&host->detect);
			mmc_detect_change(host, 0);
		}
	}


	return _mmc_detect_card_removed(host);
	return ret;
}
}
EXPORT_SYMBOL(mmc_detect_card_removed);
EXPORT_SYMBOL(mmc_detect_card_removed);


+1 −0
Original line number Original line Diff line number Diff line
@@ -258,6 +258,7 @@ struct mmc_host {
#define MMC_CAP2_HS200		(MMC_CAP2_HS200_1_8V_SDR | \
#define MMC_CAP2_HS200		(MMC_CAP2_HS200_1_8V_SDR | \
				 MMC_CAP2_HS200_1_2V_SDR)
				 MMC_CAP2_HS200_1_2V_SDR)
#define MMC_CAP2_BROKEN_VOLTAGE	(1 << 7)	/* Use the broken voltage */
#define MMC_CAP2_BROKEN_VOLTAGE	(1 << 7)	/* Use the broken voltage */
#define MMC_CAP2_DETECT_ON_ERR	(1 << 8)	/* On I/O err check card removal */


	mmc_pm_flag_t		pm_caps;	/* supported pm features */
	mmc_pm_flag_t		pm_caps;	/* supported pm features */
	unsigned int        power_notify_type;
	unsigned int        power_notify_type;