aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core/sd.c
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2013-10-10 08:20:05 -0400
committerChris Ball <cjb@laptop.org>2013-10-30 20:28:42 -0400
commit0cb403a227774f60f6f52137ca3618805498c4e6 (patch)
tree2d78049251a16d39fee319a8486649af293b4ba6 /drivers/mmc/core/sd.c
parent0cc81a8c6442e43618ff245948bfaa14fdf7938b (diff)
mmc: core: Improve runtime PM support during suspend/resume for sd/mmc
The card device is considered as in-active after it has been suspended. To prevent any further runtime PM requests in suspend state, we then disable runtime PM. After the card device has been resumed, we shall consider it as active, like we also do after a probe sequence. When resumed, we can safely enable runtime PM again. This will make sure the PM core can request the card device to go to in-active state after a resume has been completed. Previously we had to wait for new pm_runtime_get->pm_runtime_put cycle to be executed. Additionally, once a resume has been carried out, update the last busy mark. At the moment this will have no effect but if the PM core will respect autosuspend enabled devices, when it directly triggers a runtime_suspend from a runtime_idle, it will mean the card device will be scheduled for a delayed runtime_suspend instead of done immediately. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/core/sd.c')
-rw-r--r--drivers/mmc/core/sd.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 7b2854009e39..447fa8e9f322 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -13,6 +13,7 @@
13#include <linux/err.h> 13#include <linux/err.h>
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <linux/stat.h> 15#include <linux/stat.h>
16#include <linux/pm_runtime.h>
16 17
17#include <linux/mmc/host.h> 18#include <linux/mmc/host.h>
18#include <linux/mmc/card.h> 19#include <linux/mmc/card.h>
@@ -1067,10 +1068,7 @@ static void mmc_sd_detect(struct mmc_host *host)
1067 } 1068 }
1068} 1069}
1069 1070
1070/* 1071static int _mmc_sd_suspend(struct mmc_host *host)
1071 * Suspend callback from host.
1072 */
1073static int mmc_sd_suspend(struct mmc_host *host)
1074{ 1072{
1075 int err = 0; 1073 int err = 0;
1076 1074
@@ -1096,12 +1094,26 @@ out:
1096} 1094}
1097 1095
1098/* 1096/*
1099 * Resume callback from host. 1097 * Callback for suspend
1100 * 1098 */
1099static int mmc_sd_suspend(struct mmc_host *host)
1100{
1101 int err;
1102
1103 err = _mmc_sd_suspend(host);
1104 if (!err) {
1105 pm_runtime_disable(&host->card->dev);
1106 pm_runtime_set_suspended(&host->card->dev);
1107 }
1108
1109 return err;
1110}
1111
1112/*
1101 * This function tries to determine if the same card is still present 1113 * This function tries to determine if the same card is still present
1102 * and, if so, restore all state to it. 1114 * and, if so, restore all state to it.
1103 */ 1115 */
1104static int mmc_sd_resume(struct mmc_host *host) 1116static int _mmc_sd_resume(struct mmc_host *host)
1105{ 1117{
1106 int err = 0; 1118 int err = 0;
1107 1119
@@ -1123,6 +1135,21 @@ out:
1123} 1135}
1124 1136
1125/* 1137/*
1138 * Callback for resume
1139 */
1140static int mmc_sd_resume(struct mmc_host *host)
1141{
1142 int err;
1143
1144 err = _mmc_sd_resume(host);
1145 pm_runtime_set_active(&host->card->dev);
1146 pm_runtime_mark_last_busy(&host->card->dev);
1147 pm_runtime_enable(&host->card->dev);
1148
1149 return err;
1150}
1151
1152/*
1126 * Callback for runtime_suspend. 1153 * Callback for runtime_suspend.
1127 */ 1154 */
1128static int mmc_sd_runtime_suspend(struct mmc_host *host) 1155static int mmc_sd_runtime_suspend(struct mmc_host *host)
@@ -1132,7 +1159,7 @@ static int mmc_sd_runtime_suspend(struct mmc_host *host)
1132 if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) 1159 if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
1133 return 0; 1160 return 0;
1134 1161
1135 err = mmc_sd_suspend(host); 1162 err = _mmc_sd_suspend(host);
1136 if (err) 1163 if (err)
1137 pr_err("%s: error %d doing aggessive suspend\n", 1164 pr_err("%s: error %d doing aggessive suspend\n",
1138 mmc_hostname(host), err); 1165 mmc_hostname(host), err);
@@ -1150,7 +1177,7 @@ static int mmc_sd_runtime_resume(struct mmc_host *host)
1150 if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) 1177 if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
1151 return 0; 1178 return 0;
1152 1179
1153 err = mmc_sd_resume(host); 1180 err = _mmc_sd_resume(host);
1154 if (err) 1181 if (err)
1155 pr_err("%s: error %d doing aggessive resume\n", 1182 pr_err("%s: error %d doing aggessive resume\n",
1156 mmc_hostname(host), err); 1183 mmc_hostname(host), err);