On Wed, Nov 3, 2010 at 6:13 PM, Grazvydas Ignotas <notasas@xxxxxxxxx> wrote: > 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 <ohad@xxxxxxxxxx> > Signed-off-by: Grazvydas Ignotas <notasas@xxxxxxxxx> > --- > drivers/net/wireless/wl1251/sdio.c | 62 ++++++++++++++++++++++++++++++++++-- > 1 files changed, 59 insertions(+), 3 deletions(-) > > diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c > index 0285190..0a5db21 100644 > --- a/drivers/net/wireless/wl1251/sdio.c > +++ b/drivers/net/wireless/wl1251/sdio.c > @@ -26,6 +26,7 @@ > #include <linux/platform_device.h> > #include <linux/wl12xx.h> > #include <linux/irq.h> > +#include <linux/pm_runtime.h> > > #include "wl1251.h" > > @@ -173,10 +174,36 @@ static void wl1251_disable_line_irq(struct wl1251 *wl) > > static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable) > { > - if (wl->set_power) > - wl->set_power(enable); > + struct sdio_func *func = wl_to_func(wl); > + int ret; > > - return 0; > + if (enable) { > + /* Power up the card */ > + if (wl->set_power) > + wl->set_power(true); Why do you still need that ->set_power() handler ? > + > + ret = pm_runtime_get_sync(&func->dev); This call should do all the power-related work for you (assuming you have a fixed regulator in place). > + if (ret < 0) > + goto out; > + > + sdio_claim_host(func); > + sdio_enable_func(func); > + sdio_release_host(func); > + } else { > + sdio_claim_host(func); > + sdio_disable_func(func); > + sdio_release_host(func); > + > + ret = pm_runtime_put_sync(&func->dev); > + if (ret < 0) > + goto out; > + > + if (wl->set_power) > + wl->set_power(false); > + } > + > +out: > + return ret; > } > > static struct wl1251_if_operations wl1251_sdio_ops = { > @@ -277,6 +304,10 @@ static int wl1251_sdio_probe(struct sdio_func *func, > goto out_free_irq; > > sdio_set_drvdata(func, wl); > + > + /* Tell PM core that we don't need the card to be powered now */ > + pm_runtime_put_noidle(&func->dev); > + > return ret; > > out_free_irq: > @@ -298,6 +329,9 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func) > struct wl1251 *wl = sdio_get_drvdata(func); > struct wl1251_sdio *wl_sdio = wl->if_priv; > > + /* Undo decrement done above in wl1271_probe */ > + pm_runtime_get_noresume(&func->dev); > + > if (wl->irq) > free_irq(wl->irq, wl); > kfree(wl_sdio); > @@ -309,11 +343,33 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func) > sdio_release_host(func); > } > > +static int wl1251_suspend(struct device *dev) > +{ > + /* > + * Tell MMC/SDIO core it's OK to power down the card > + * (if it isn't already), but not to remove it completely > + */ > + return 0; > +} > + > +static int wl1251_resume(struct device *dev) > +{ > + return 0; > +} > + > +static const struct dev_pm_ops wl1251_sdio_pm_ops = { > + .suspend = wl1251_suspend, > + .resume = wl1251_resume, > +}; > + > static struct sdio_driver wl1251_sdio_driver = { > .name = "wl1251_sdio", > .id_table = wl1251_devices, > .probe = wl1251_sdio_probe, > .remove = __devexit_p(wl1251_sdio_remove), > + .drv = { > + .pm = &wl1251_sdio_pm_ops, > + }, > }; > > static int __init wl1251_sdio_init(void) > -- > 1.6.3.3 > > -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html