aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOhad Ben-Cohen <ohad@wizery.com>2010-10-02 07:54:11 -0400
committerChris Ball <cjb@laptop.org>2010-10-23 09:11:18 -0400
commit40bba0c1ca83a370f749c8bc9afda71cf79ebd91 (patch)
tree1d2725b031284717468b22b90df59d5939506187
parent81968561bd69536c82be7ee654b04c68cd3e1746 (diff)
mmc: sdio: enable runtime PM for SDIO functions
Enable runtime PM for SDIO functions. SDIO functions are initialized with a disabled runtime PM state, and are set active (and their usage count is incremented) only before potential drivers are probed. SDIO function drivers that support runtime PM should call pm_runtime_put_noidle() in their probe routine, and pm_runtime_get_noresume() in their remove routine (very similarly to PCI drivers). In case a matching driver does not support runtime PM, power will always be kept high (since the usage count is positive). Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com> Tested-by: Luciano Coelho <luciano.coelho@nokia.com> Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r--drivers/mmc/core/sdio.c5
-rw-r--r--drivers/mmc/core/sdio_bus.c38
2 files changed, 40 insertions, 3 deletions
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 0dbd6fe66660..85561dde4c9d 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -734,6 +734,11 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
734 err = sdio_init_func(host->card, i + 1); 734 err = sdio_init_func(host->card, i + 1);
735 if (err) 735 if (err)
736 goto remove; 736 goto remove;
737
738 /*
739 * Enable Runtime PM for this func
740 */
741 pm_runtime_enable(&card->sdio_func[i]->dev);
737 } 742 }
738 743
739 mmc_release_host(host); 744 mmc_release_host(host);
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 256a968774a0..36374834fcff 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -126,21 +126,46 @@ static int sdio_bus_probe(struct device *dev)
126 if (!id) 126 if (!id)
127 return -ENODEV; 127 return -ENODEV;
128 128
129 /* Unbound SDIO functions are always suspended.
130 * During probe, the function is set active and the usage count
131 * is incremented. If the driver supports runtime PM,
132 * it should call pm_runtime_put_noidle() in its probe routine and
133 * pm_runtime_get_noresume() in its remove routine.
134 */
135 ret = pm_runtime_get_sync(dev);
136 if (ret < 0)
137 goto out;
138
129 /* Set the default block size so the driver is sure it's something 139 /* Set the default block size so the driver is sure it's something
130 * sensible. */ 140 * sensible. */
131 sdio_claim_host(func); 141 sdio_claim_host(func);
132 ret = sdio_set_block_size(func, 0); 142 ret = sdio_set_block_size(func, 0);
133 sdio_release_host(func); 143 sdio_release_host(func);
134 if (ret) 144 if (ret)
135 return ret; 145 goto disable_runtimepm;
146
147 ret = drv->probe(func, id);
148 if (ret)
149 goto disable_runtimepm;
136 150
137 return drv->probe(func, id); 151 return 0;
152
153disable_runtimepm:
154 pm_runtime_put_noidle(dev);
155out:
156 return ret;
138} 157}
139 158
140static int sdio_bus_remove(struct device *dev) 159static int sdio_bus_remove(struct device *dev)
141{ 160{
142 struct sdio_driver *drv = to_sdio_driver(dev->driver); 161 struct sdio_driver *drv = to_sdio_driver(dev->driver);
143 struct sdio_func *func = dev_to_sdio_func(dev); 162 struct sdio_func *func = dev_to_sdio_func(dev);
163 int ret;
164
165 /* Make sure card is powered before invoking ->remove() */
166 ret = pm_runtime_get_sync(dev);
167 if (ret < 0)
168 goto out;
144 169
145 drv->remove(func); 170 drv->remove(func);
146 171
@@ -152,7 +177,14 @@ static int sdio_bus_remove(struct device *dev)
152 sdio_release_host(func); 177 sdio_release_host(func);
153 } 178 }
154 179
155 return 0; 180 /* First, undo the increment made directly above */
181 pm_runtime_put_noidle(dev);
182
183 /* Then undo the runtime PM settings in sdio_bus_probe() */
184 pm_runtime_put_noidle(dev);
185
186out:
187 return ret;
156} 188}
157 189
158#ifdef CONFIG_PM_RUNTIME 190#ifdef CONFIG_PM_RUNTIME