Skip to content

Commit 1d4b89f

Browse files
notazlinvjw
authored andcommitted
wl1251: add runtime PM support for SDIO
Add runtime PM support, similar to how it's done for wl1271. This allows to power down the card when the driver is loaded but network is not in use. Cc: Ohad Ben-Cohen <[email protected]> Signed-off-by: Grazvydas Ignotas <[email protected]> Acked-by: Kalle Valo <[email protected]> Signed-off-by: John W. Linville <[email protected]>
1 parent cb7bbc7 commit 1d4b89f

File tree

1 file changed

+61
-3
lines changed
  • drivers/net/wireless/wl1251

1 file changed

+61
-3
lines changed

drivers/net/wireless/wl1251/sdio.c

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <linux/platform_device.h>
2727
#include <linux/wl12xx.h>
2828
#include <linux/irq.h>
29+
#include <linux/pm_runtime.h>
2930

3031
#include "wl1251.h"
3132

@@ -173,10 +174,40 @@ static void wl1251_disable_line_irq(struct wl1251 *wl)
173174

174175
static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable)
175176
{
176-
if (wl->set_power)
177-
wl->set_power(enable);
177+
struct sdio_func *func = wl_to_func(wl);
178+
int ret;
178179

179-
return 0;
180+
if (enable) {
181+
/*
182+
* Power is controlled by runtime PM, but we still call board
183+
* callback in case it wants to do any additional setup,
184+
* for example enabling clock buffer for the module.
185+
*/
186+
if (wl->set_power)
187+
wl->set_power(true);
188+
189+
ret = pm_runtime_get_sync(&func->dev);
190+
if (ret < 0)
191+
goto out;
192+
193+
sdio_claim_host(func);
194+
sdio_enable_func(func);
195+
sdio_release_host(func);
196+
} else {
197+
sdio_claim_host(func);
198+
sdio_disable_func(func);
199+
sdio_release_host(func);
200+
201+
ret = pm_runtime_put_sync(&func->dev);
202+
if (ret < 0)
203+
goto out;
204+
205+
if (wl->set_power)
206+
wl->set_power(false);
207+
}
208+
209+
out:
210+
return ret;
180211
}
181212

182213
static struct wl1251_if_operations wl1251_sdio_ops = {
@@ -277,6 +308,10 @@ static int wl1251_sdio_probe(struct sdio_func *func,
277308
goto out_free_irq;
278309

279310
sdio_set_drvdata(func, wl);
311+
312+
/* Tell PM core that we don't need the card to be powered now */
313+
pm_runtime_put_noidle(&func->dev);
314+
280315
return ret;
281316

282317
out_free_irq:
@@ -298,6 +333,9 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func)
298333
struct wl1251 *wl = sdio_get_drvdata(func);
299334
struct wl1251_sdio *wl_sdio = wl->if_priv;
300335

336+
/* Undo decrement done above in wl1251_probe */
337+
pm_runtime_get_noresume(&func->dev);
338+
301339
if (wl->irq)
302340
free_irq(wl->irq, wl);
303341
kfree(wl_sdio);
@@ -309,11 +347,31 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func)
309347
sdio_release_host(func);
310348
}
311349

350+
static int wl1251_suspend(struct device *dev)
351+
{
352+
/*
353+
* Tell MMC/SDIO core it's OK to power down the card
354+
* (if it isn't already), but not to remove it completely.
355+
*/
356+
return 0;
357+
}
358+
359+
static int wl1251_resume(struct device *dev)
360+
{
361+
return 0;
362+
}
363+
364+
static const struct dev_pm_ops wl1251_sdio_pm_ops = {
365+
.suspend = wl1251_suspend,
366+
.resume = wl1251_resume,
367+
};
368+
312369
static struct sdio_driver wl1251_sdio_driver = {
313370
.name = "wl1251_sdio",
314371
.id_table = wl1251_devices,
315372
.probe = wl1251_sdio_probe,
316373
.remove = __devexit_p(wl1251_sdio_remove),
374+
.drv.pm = &wl1251_sdio_pm_ops,
317375
};
318376

319377
static int __init wl1251_sdio_init(void)

0 commit comments

Comments
 (0)