aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2013-06-10 11:03:37 -0400
committerChris Ball <cjb@laptop.org>2013-06-27 12:39:15 -0400
commit810caddba42a54fe5db4e2664757a9a334ba359c (patch)
tree12bd0ddf6a95e42bbc5f0438337b5492710760d6 /drivers/mmc/core
parent58a8a4a1a5da4694a3a069de5e0a8c15995e7b5f (diff)
mmc: core: Validate suspend prerequisites for SDIO at SUSPEND_PREPARE
This patch moves the validation for all the suspend prerequisites to be done at SUSPEND_PREPARE notification. Previously in the SDIO case parts of the validation was done from mmc_suspend_host. This patch invents a new pre_suspend bus_ops callback and implements it for SDIO. Returning an error code from it, will mean at SUSPEND_PREPARE notification, the card will be removed before proceeding with the suspend sequence. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Tested-by: Jaehoon Chung <jh80.chung@samsung.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r--drivers/mmc/core/core.c25
-rw-r--r--drivers/mmc/core/core.h1
-rw-r--r--drivers/mmc/core/sdio.c27
3 files changed, 32 insertions, 21 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index d2ee2829b313..7a8a42d3a039 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2628,22 +2628,6 @@ int mmc_suspend_host(struct mmc_host *host)
2628 if (host->bus_ops && !host->bus_dead) { 2628 if (host->bus_ops && !host->bus_dead) {
2629 if (host->bus_ops->suspend) 2629 if (host->bus_ops->suspend)
2630 err = host->bus_ops->suspend(host); 2630 err = host->bus_ops->suspend(host);
2631
2632 if (err == -ENOSYS || !host->bus_ops->resume) {
2633 /*
2634 * We simply "remove" the card in this case.
2635 * It will be redetected on resume. (Calling
2636 * bus_ops->remove() with a claimed host can
2637 * deadlock.)
2638 */
2639 host->bus_ops->remove(host);
2640 mmc_claim_host(host);
2641 mmc_detach_bus(host);
2642 mmc_power_off(host);
2643 mmc_release_host(host);
2644 host->pm_flags = 0;
2645 err = 0;
2646 }
2647 } 2631 }
2648 mmc_bus_put(host); 2632 mmc_bus_put(host);
2649 2633
@@ -2706,6 +2690,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
2706 struct mmc_host *host = container_of( 2690 struct mmc_host *host = container_of(
2707 notify_block, struct mmc_host, pm_notify); 2691 notify_block, struct mmc_host, pm_notify);
2708 unsigned long flags; 2692 unsigned long flags;
2693 int err = 0;
2709 2694
2710 switch (mode) { 2695 switch (mode) {
2711 case PM_HIBERNATION_PREPARE: 2696 case PM_HIBERNATION_PREPARE:
@@ -2715,7 +2700,13 @@ int mmc_pm_notify(struct notifier_block *notify_block,
2715 spin_unlock_irqrestore(&host->lock, flags); 2700 spin_unlock_irqrestore(&host->lock, flags);
2716 cancel_delayed_work_sync(&host->detect); 2701 cancel_delayed_work_sync(&host->detect);
2717 2702
2718 if (!host->bus_ops || host->bus_ops->suspend) 2703 if (!host->bus_ops)
2704 break;
2705
2706 /* Validate prerequisites for suspend */
2707 if (host->bus_ops->pre_suspend)
2708 err = host->bus_ops->pre_suspend(host);
2709 if (!err && host->bus_ops->suspend)
2719 break; 2710 break;
2720 2711
2721 /* Calling bus_ops->remove() with a claimed host can deadlock */ 2712 /* Calling bus_ops->remove() with a claimed host can deadlock */
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 52a3650307af..79f37cfc373b 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -18,6 +18,7 @@
18struct mmc_bus_ops { 18struct mmc_bus_ops {
19 void (*remove)(struct mmc_host *); 19 void (*remove)(struct mmc_host *);
20 void (*detect)(struct mmc_host *); 20 void (*detect)(struct mmc_host *);
21 int (*pre_suspend)(struct mmc_host *);
21 int (*suspend)(struct mmc_host *); 22 int (*suspend)(struct mmc_host *);
22 int (*resume)(struct mmc_host *); 23 int (*resume)(struct mmc_host *);
23 int (*runtime_suspend)(struct mmc_host *); 24 int (*runtime_suspend)(struct mmc_host *);
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 1fbbd1bc55ec..be8cca8d3024 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -910,11 +910,11 @@ out:
910} 910}
911 911
912/* 912/*
913 * SDIO suspend. We need to suspend all functions separately. 913 * SDIO pre_suspend. We need to suspend all functions separately.
914 * Therefore all registered functions must have drivers with suspend 914 * Therefore all registered functions must have drivers with suspend
915 * and resume methods. Failing that we simply remove the whole card. 915 * and resume methods. Failing that we simply remove the whole card.
916 */ 916 */
917static int mmc_sdio_suspend(struct mmc_host *host) 917static int mmc_sdio_pre_suspend(struct mmc_host *host)
918{ 918{
919 int i, err = 0; 919 int i, err = 0;
920 920
@@ -925,8 +925,26 @@ static int mmc_sdio_suspend(struct mmc_host *host)
925 if (!pmops || !pmops->suspend || !pmops->resume) { 925 if (!pmops || !pmops->suspend || !pmops->resume) {
926 /* force removal of entire card in that case */ 926 /* force removal of entire card in that case */
927 err = -ENOSYS; 927 err = -ENOSYS;
928 } else 928 break;
929 err = pmops->suspend(&func->dev); 929 }
930 }
931 }
932
933 return err;
934}
935
936/*
937 * SDIO suspend. Suspend all functions separately.
938 */
939static int mmc_sdio_suspend(struct mmc_host *host)
940{
941 int i, err = 0;
942
943 for (i = 0; i < host->card->sdio_funcs; i++) {
944 struct sdio_func *func = host->card->sdio_func[i];
945 if (func && sdio_func_present(func) && func->dev.driver) {
946 const struct dev_pm_ops *pmops = func->dev.driver->pm;
947 err = pmops->suspend(&func->dev);
930 if (err) 948 if (err)
931 break; 949 break;
932 } 950 }
@@ -1076,6 +1094,7 @@ static int mmc_sdio_runtime_resume(struct mmc_host *host)
1076static const struct mmc_bus_ops mmc_sdio_ops = { 1094static const struct mmc_bus_ops mmc_sdio_ops = {
1077 .remove = mmc_sdio_remove, 1095 .remove = mmc_sdio_remove,
1078 .detect = mmc_sdio_detect, 1096 .detect = mmc_sdio_detect,
1097 .pre_suspend = mmc_sdio_pre_suspend,
1079 .suspend = mmc_sdio_suspend, 1098 .suspend = mmc_sdio_suspend,
1080 .resume = mmc_sdio_resume, 1099 .resume = mmc_sdio_resume,
1081 .runtime_suspend = mmc_sdio_runtime_suspend, 1100 .runtime_suspend = mmc_sdio_runtime_suspend,