diff options
author | Jorg Schummer <ext-jorg.2.schummer@nokia.com> | 2009-03-31 10:51:21 -0400 |
---|---|---|
committer | Pierre Ossman <pierre@ossman.eu> | 2009-06-13 16:42:56 -0400 |
commit | 94d89efb2c347a82a08a61dbac8565b1087c3259 (patch) | |
tree | 78e4cfaec79e4ae6346635d859f4d1501dd7e0e7 /drivers | |
parent | f3ad116588151b3371ae4e092290e4f48e62b8bb (diff) |
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: Jorg Schummer <ext-jorg.2.schummer@nokia.com>
Signed-off-by: Pierre Ossman <pierre@ossman.eu>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/core/core.c | 99 |
1 files changed, 55 insertions, 44 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 264911732756..23fb2c39d9ed 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -855,61 +855,72 @@ void mmc_rescan(struct work_struct *work) | |||
855 | 855 | ||
856 | mmc_bus_get(host); | 856 | mmc_bus_get(host); |
857 | 857 | ||
858 | if (host->bus_ops == NULL) { | 858 | /* if there is a card registered, check whether it is still present */ |
859 | /* | 859 | if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead) |
860 | * Only we can add a new handler, so it's safe to | 860 | host->bus_ops->detect(host); |
861 | * release the lock here. | 861 | |
862 | */ | 862 | mmc_bus_put(host); |
863 | |||
864 | |||
865 | mmc_bus_get(host); | ||
866 | |||
867 | /* if there still is a card present, stop here */ | ||
868 | if (host->bus_ops != NULL) { | ||
863 | mmc_bus_put(host); | 869 | mmc_bus_put(host); |
870 | goto out; | ||
871 | } | ||
864 | 872 | ||
865 | if (host->ops->get_cd && host->ops->get_cd(host) == 0) | 873 | /* detect a newly inserted card */ |
866 | goto out; | ||
867 | 874 | ||
868 | mmc_claim_host(host); | 875 | /* |
876 | * Only we can add a new handler, so it's safe to | ||
877 | * release the lock here. | ||
878 | */ | ||
879 | mmc_bus_put(host); | ||
869 | 880 | ||
870 | mmc_power_up(host); | 881 | if (host->ops->get_cd && host->ops->get_cd(host) == 0) |
871 | mmc_go_idle(host); | 882 | goto out; |
872 | 883 | ||
873 | mmc_send_if_cond(host, host->ocr_avail); | 884 | mmc_claim_host(host); |
874 | 885 | ||
875 | /* | 886 | mmc_power_up(host); |
876 | * First we search for SDIO... | 887 | mmc_go_idle(host); |
877 | */ | ||
878 | err = mmc_send_io_op_cond(host, 0, &ocr); | ||
879 | if (!err) { | ||
880 | if (mmc_attach_sdio(host, ocr)) | ||
881 | mmc_power_off(host); | ||
882 | goto out; | ||
883 | } | ||
884 | 888 | ||
885 | /* | 889 | mmc_send_if_cond(host, host->ocr_avail); |
886 | * ...then normal SD... | ||
887 | */ | ||
888 | err = mmc_send_app_op_cond(host, 0, &ocr); | ||
889 | if (!err) { | ||
890 | if (mmc_attach_sd(host, ocr)) | ||
891 | mmc_power_off(host); | ||
892 | goto out; | ||
893 | } | ||
894 | 890 | ||
895 | /* | 891 | /* |
896 | * ...and finally MMC. | 892 | * First we search for SDIO... |
897 | */ | 893 | */ |
898 | err = mmc_send_op_cond(host, 0, &ocr); | 894 | err = mmc_send_io_op_cond(host, 0, &ocr); |
899 | if (!err) { | 895 | if (!err) { |
900 | if (mmc_attach_mmc(host, ocr)) | 896 | if (mmc_attach_sdio(host, ocr)) |
901 | mmc_power_off(host); | 897 | mmc_power_off(host); |
902 | goto out; | 898 | goto out; |
903 | } | 899 | } |
904 | 900 | ||
905 | mmc_release_host(host); | 901 | /* |
906 | mmc_power_off(host); | 902 | * ...then normal SD... |
907 | } else { | 903 | */ |
908 | if (host->bus_ops->detect && !host->bus_dead) | 904 | err = mmc_send_app_op_cond(host, 0, &ocr); |
909 | host->bus_ops->detect(host); | 905 | if (!err) { |
906 | if (mmc_attach_sd(host, ocr)) | ||
907 | mmc_power_off(host); | ||
908 | goto out; | ||
909 | } | ||
910 | 910 | ||
911 | mmc_bus_put(host); | 911 | /* |
912 | * ...and finally MMC. | ||
913 | */ | ||
914 | err = mmc_send_op_cond(host, 0, &ocr); | ||
915 | if (!err) { | ||
916 | if (mmc_attach_mmc(host, ocr)) | ||
917 | mmc_power_off(host); | ||
918 | goto out; | ||
912 | } | 919 | } |
920 | |||
921 | mmc_release_host(host); | ||
922 | mmc_power_off(host); | ||
923 | |||
913 | out: | 924 | out: |
914 | if (host->caps & MMC_CAP_NEEDS_POLL) | 925 | if (host->caps & MMC_CAP_NEEDS_POLL) |
915 | mmc_schedule_delayed_work(&host->detect, HZ); | 926 | mmc_schedule_delayed_work(&host->detect, HZ); |