aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
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
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')
-rw-r--r--drivers/mmc/core/mmc.c38
-rw-r--r--drivers/mmc/core/sd.c45
2 files changed, 66 insertions, 17 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index b22eff80a95e..7f5dc26865de 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.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>
@@ -1510,20 +1511,26 @@ out:
1510} 1511}
1511 1512
1512/* 1513/*
1513 * Suspend callback from host. 1514 * Suspend callback
1514 */ 1515 */
1515static int mmc_suspend(struct mmc_host *host) 1516static int mmc_suspend(struct mmc_host *host)
1516{ 1517{
1517 return _mmc_suspend(host, true); 1518 int err;
1519
1520 err = _mmc_suspend(host, true);
1521 if (!err) {
1522 pm_runtime_disable(&host->card->dev);
1523 pm_runtime_set_suspended(&host->card->dev);
1524 }
1525
1526 return err;
1518} 1527}
1519 1528
1520/* 1529/*
1521 * Resume callback from host.
1522 *
1523 * This function tries to determine if the same card is still present 1530 * This function tries to determine if the same card is still present
1524 * and, if so, restore all state to it. 1531 * and, if so, restore all state to it.
1525 */ 1532 */
1526static int mmc_resume(struct mmc_host *host) 1533static int _mmc_resume(struct mmc_host *host)
1527{ 1534{
1528 int err = 0; 1535 int err = 0;
1529 1536
@@ -1557,7 +1564,7 @@ static int mmc_shutdown(struct mmc_host *host)
1557 */ 1564 */
1558 if (mmc_can_poweroff_notify(host->card) && 1565 if (mmc_can_poweroff_notify(host->card) &&
1559 !(host->caps2 & MMC_CAP2_FULL_PWR_CYCLE)) 1566 !(host->caps2 & MMC_CAP2_FULL_PWR_CYCLE))
1560 err = mmc_resume(host); 1567 err = _mmc_resume(host);
1561 1568
1562 if (!err) 1569 if (!err)
1563 err = _mmc_suspend(host, false); 1570 err = _mmc_suspend(host, false);
@@ -1566,6 +1573,21 @@ static int mmc_shutdown(struct mmc_host *host)
1566} 1573}
1567 1574
1568/* 1575/*
1576 * Callback for resume.
1577 */
1578static int mmc_resume(struct mmc_host *host)
1579{
1580 int err;
1581
1582 err = _mmc_resume(host);
1583 pm_runtime_set_active(&host->card->dev);
1584 pm_runtime_mark_last_busy(&host->card->dev);
1585 pm_runtime_enable(&host->card->dev);
1586
1587 return err;
1588}
1589
1590/*
1569 * Callback for runtime_suspend. 1591 * Callback for runtime_suspend.
1570 */ 1592 */
1571static int mmc_runtime_suspend(struct mmc_host *host) 1593static int mmc_runtime_suspend(struct mmc_host *host)
@@ -1575,7 +1597,7 @@ static int mmc_runtime_suspend(struct mmc_host *host)
1575 if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) 1597 if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
1576 return 0; 1598 return 0;
1577 1599
1578 err = mmc_suspend(host); 1600 err = _mmc_suspend(host, true);
1579 if (err) 1601 if (err)
1580 pr_err("%s: error %d doing aggessive suspend\n", 1602 pr_err("%s: error %d doing aggessive suspend\n",
1581 mmc_hostname(host), err); 1603 mmc_hostname(host), err);
@@ -1593,7 +1615,7 @@ static int mmc_runtime_resume(struct mmc_host *host)
1593 if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) 1615 if (!(host->caps & MMC_CAP_AGGRESSIVE_PM))
1594 return 0; 1616 return 0;
1595 1617
1596 err = mmc_resume(host); 1618 err = _mmc_resume(host);
1597 if (err) 1619 if (err)
1598 pr_err("%s: error %d doing aggessive resume\n", 1620 pr_err("%s: error %d doing aggessive resume\n",
1599 mmc_hostname(host), err); 1621 mmc_hostname(host), err);
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);