mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 11:41:38 -04:00
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: Adrian Hunter <[email protected]> Acked-by: Sujit Reddy Thumma <[email protected]> Signed-off-by: Chris Ball <[email protected]>
This commit is contained in:
parent
482fce997e
commit
d304950488
8 changed files with 89 additions and 6 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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…
Reference in a new issue