Commit 94d89efb authored by Jorg Schummer's avatar Jorg Schummer Committed by Pierre Ossman

mmc: mmc_rescan detects card change in one run

With this patch, mmc_rescan can detect the removal of an mmc card and
the insertion of (possibly another) card in the same run. This means
that a card change can be detected without having to call
mmc_detect_change multiple times.

This change generalises the core such that it can be easily used by
hosts which provide a mechanism to detect only the presence of a card
reader cover, which has to be taken off in order to insert a card. Other
hosts ("card detect" or "MMC_CAP_NEEDS_POLL") each receive an event when
a card is removed and when a card is inserted, so it is sufficient for
them if mmc_rescan handles only one event at a time. "Cover detect"
hosts, however, only receive events about the cover status. This means
that between 2 subsequent events, both a card removal and a card
insertion can occur. In this case, the pre-patch version of mmc_rescan
would only detect the removal of the previous card but not the insertion
of the new card.
Signed-off-by: default avatarJorg Schummer <ext-jorg.2.schummer@nokia.com>
Signed-off-by: default avatarPierre Ossman <pierre@ossman.eu>
parent f3ad1165
...@@ -855,61 +855,72 @@ void mmc_rescan(struct work_struct *work) ...@@ -855,61 +855,72 @@ void mmc_rescan(struct work_struct *work)
mmc_bus_get(host); mmc_bus_get(host);
if (host->bus_ops == NULL) { /* if there is a card registered, check whether it is still present */
/* if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead)
* Only we can add a new handler, so it's safe to host->bus_ops->detect(host);
* release the lock here.
*/ mmc_bus_put(host);
mmc_bus_get(host);
/* if there still is a card present, stop here */
if (host->bus_ops != NULL) {
mmc_bus_put(host); mmc_bus_put(host);
goto out;
}
if (host->ops->get_cd && host->ops->get_cd(host) == 0) /* detect a newly inserted card */
goto out;
mmc_claim_host(host); /*
* Only we can add a new handler, so it's safe to
* release the lock here.
*/
mmc_bus_put(host);
mmc_power_up(host); if (host->ops->get_cd && host->ops->get_cd(host) == 0)
mmc_go_idle(host); goto out;
mmc_send_if_cond(host, host->ocr_avail); mmc_claim_host(host);
/* mmc_power_up(host);
* First we search for SDIO... mmc_go_idle(host);
*/
err = mmc_send_io_op_cond(host, 0, &ocr);
if (!err) {
if (mmc_attach_sdio(host, ocr))
mmc_power_off(host);
goto out;
}
/* mmc_send_if_cond(host, host->ocr_avail);
* ...then normal SD...
*/
err = mmc_send_app_op_cond(host, 0, &ocr);
if (!err) {
if (mmc_attach_sd(host, ocr))
mmc_power_off(host);
goto out;
}
/* /*
* ...and finally MMC. * First we search for SDIO...
*/ */
err = mmc_send_op_cond(host, 0, &ocr); err = mmc_send_io_op_cond(host, 0, &ocr);
if (!err) { if (!err) {
if (mmc_attach_mmc(host, ocr)) if (mmc_attach_sdio(host, ocr))
mmc_power_off(host); mmc_power_off(host);
goto out; goto out;
} }
mmc_release_host(host); /*
mmc_power_off(host); * ...then normal SD...
} else { */
if (host->bus_ops->detect && !host->bus_dead) err = mmc_send_app_op_cond(host, 0, &ocr);
host->bus_ops->detect(host); if (!err) {
if (mmc_attach_sd(host, ocr))
mmc_power_off(host);
goto out;
}
mmc_bus_put(host); /*
* ...and finally MMC.
*/
err = mmc_send_op_cond(host, 0, &ocr);
if (!err) {
if (mmc_attach_mmc(host, ocr))
mmc_power_off(host);
goto out;
} }
mmc_release_host(host);
mmc_power_off(host);
out: out:
if (host->caps & MMC_CAP_NEEDS_POLL) if (host->caps & MMC_CAP_NEEDS_POLL)
mmc_schedule_delayed_work(&host->detect, HZ); mmc_schedule_delayed_work(&host->detect, HZ);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment