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

Commit d3049504 authored by Adrian Hunter's avatar Adrian Hunter Committed by Chris Ball
Browse files

mmc: allow upper layers to know immediately if card has been removed



Add a function mmc_detect_card_removed() which upper layers can use to
determine immediately if a card has been removed. This function should
be called after an I/O request fails so that all queued I/O requests
can be errored out immediately instead of waiting for the card device
to be removed.

Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Acked-by: default avatarSujit Reddy Thumma <sthumma@codeaurora.org>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 482fce99
Loading
Loading
Loading
Loading
+48 −3
Original line number Diff line number Diff line
@@ -140,7 +140,7 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
			cmd->retries = 0;
	}

	if (err && cmd->retries) {
	if (err && cmd->retries && !mmc_card_removed(host->card)) {
		/*
		 * Request starter must handle retries - see
		 * mmc_wait_for_req_done().
@@ -247,6 +247,11 @@ static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
{
	init_completion(&mrq->completion);
	mrq->done = mmc_wait_done;
	if (mmc_card_removed(host->card)) {
		mrq->cmd->error = -ENOMEDIUM;
		complete(&mrq->completion);
		return;
	}
	mmc_start_request(host, mrq);
}

@@ -259,7 +264,8 @@ static void mmc_wait_for_req_done(struct mmc_host *host,
		wait_for_completion(&mrq->completion);

		cmd = mrq->cmd;
		if (!cmd->error || !cmd->retries)
		if (!cmd->error || !cmd->retries ||
		    mmc_card_removed(host->card))
			break;

		pr_debug("%s: req failed (CMD%u): %d, retrying...\n",
@@ -1456,7 +1462,7 @@ void mmc_detect_change(struct mmc_host *host, unsigned long delay)
	WARN_ON(host->removed);
	spin_unlock_irqrestore(&host->lock, flags);
#endif

	host->detect_change = 1;
	mmc_schedule_delayed_work(&host->detect, delay);
}

@@ -2049,6 +2055,43 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
	return -EIO;
}

int _mmc_detect_card_removed(struct mmc_host *host)
{
	int ret;

	if ((host->caps & MMC_CAP_NONREMOVABLE) || !host->bus_ops->alive)
		return 0;

	if (!host->card || mmc_card_removed(host->card))
		return 1;

	ret = host->bus_ops->alive(host);
	if (ret) {
		mmc_card_set_removed(host->card);
		pr_debug("%s: card remove detected\n", mmc_hostname(host));
	}

	return ret;
}

int mmc_detect_card_removed(struct mmc_host *host)
{
	struct mmc_card *card = host->card;

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

	host->detect_change = 0;

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

void mmc_rescan(struct work_struct *work)
{
	static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
@@ -2069,6 +2112,8 @@ void mmc_rescan(struct work_struct *work)
	    && !(host->caps & MMC_CAP_NONREMOVABLE))
		host->bus_ops->detect(host);

	host->detect_change = 0;

	/*
	 * Let mmc_bus_put() free the bus/bus_ops if we've found that
	 * the card is no longer present.
+3 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ struct mmc_bus_ops {
	int (*resume)(struct mmc_host *);
	int (*power_save)(struct mmc_host *);
	int (*power_restore)(struct mmc_host *);
	int (*alive)(struct mmc_host *);
};

void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
@@ -59,6 +60,8 @@ void mmc_rescan(struct work_struct *work);
void mmc_start_host(struct mmc_host *host);
void mmc_stop_host(struct mmc_host *host);

int _mmc_detect_card_removed(struct mmc_host *host);

int mmc_attach_mmc(struct mmc_host *host);
int mmc_attach_sd(struct mmc_host *host);
int mmc_attach_sdio(struct mmc_host *host);
+11 −1
Original line number Diff line number Diff line
@@ -1104,6 +1104,14 @@ static void mmc_remove(struct mmc_host *host)
	host->card = NULL;
}

/*
 * Card detection - card is alive.
 */
static int mmc_alive(struct mmc_host *host)
{
	return mmc_send_status(host->card, NULL);
}

/*
 * Card detection callback from host.
 */
@@ -1119,7 +1127,7 @@ static void mmc_detect(struct mmc_host *host)
	/*
	 * Just check if our card has been removed.
	 */
	err = mmc_send_status(host->card, NULL);
	err = _mmc_detect_card_removed(host);

	mmc_release_host(host);

@@ -1224,6 +1232,7 @@ static const struct mmc_bus_ops mmc_ops = {
	.suspend = NULL,
	.resume = NULL,
	.power_restore = mmc_power_restore,
	.alive = mmc_alive,
};

static const struct mmc_bus_ops mmc_ops_unsafe = {
@@ -1234,6 +1243,7 @@ static const struct mmc_bus_ops mmc_ops_unsafe = {
	.suspend = mmc_suspend,
	.resume = mmc_resume,
	.power_restore = mmc_power_restore,
	.alive = mmc_alive,
};

static void mmc_attach_bus_ops(struct mmc_host *host)
+11 −1
Original line number Diff line number Diff line
@@ -1018,6 +1018,14 @@ static void mmc_sd_remove(struct mmc_host *host)
	host->card = NULL;
}

/*
 * Card detection - card is alive.
 */
static int mmc_sd_alive(struct mmc_host *host)
{
	return mmc_send_status(host->card, NULL);
}

/*
 * Card detection callback from host.
 */
@@ -1033,7 +1041,7 @@ static void mmc_sd_detect(struct mmc_host *host)
	/*
	 * Just check if our card has been removed.
	 */
	err = mmc_send_status(host->card, NULL);
	err = _mmc_detect_card_removed(host);

	mmc_release_host(host);

@@ -1102,6 +1110,7 @@ static const struct mmc_bus_ops mmc_sd_ops = {
	.suspend = NULL,
	.resume = NULL,
	.power_restore = mmc_sd_power_restore,
	.alive = mmc_sd_alive,
};

static const struct mmc_bus_ops mmc_sd_ops_unsafe = {
@@ -1110,6 +1119,7 @@ static const struct mmc_bus_ops mmc_sd_ops_unsafe = {
	.suspend = mmc_sd_suspend,
	.resume = mmc_sd_resume,
	.power_restore = mmc_sd_power_restore,
	.alive = mmc_sd_alive,
};

static void mmc_sd_attach_bus_ops(struct mmc_host *host)
+10 −1
Original line number Diff line number Diff line
@@ -819,6 +819,14 @@ static void mmc_sdio_remove(struct mmc_host *host)
	host->card = NULL;
}

/*
 * Card detection - card is alive.
 */
static int mmc_sdio_alive(struct mmc_host *host)
{
	return mmc_select_card(host->card);
}

/*
 * Card detection callback from host.
 */
@@ -841,7 +849,7 @@ static void mmc_sdio_detect(struct mmc_host *host)
	/*
	 * Just check if our card has been removed.
	 */
	err = mmc_select_card(host->card);
	err = _mmc_detect_card_removed(host);

	mmc_release_host(host);

@@ -1019,6 +1027,7 @@ static const struct mmc_bus_ops mmc_sdio_ops = {
	.suspend = mmc_sdio_suspend,
	.resume = mmc_sdio_resume,
	.power_restore = mmc_sdio_power_restore,
	.alive = mmc_sdio_alive,
};


Loading