aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl1251
diff options
context:
space:
mode:
authorGrazvydas Ignotas <notasas@gmail.com>2010-11-08 08:29:36 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-15 13:27:01 -0500
commit1d4b89f2970f9ea0902d0a3bc1090f3c770b5080 (patch)
treecfbe5fa103644ceec167a57696c3b9a1e8df5c11 /drivers/net/wireless/wl1251
parentcb7bbc7a5535ab2333915b83391e1d846a0914df (diff)
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 <ohad@wizery.com> Signed-off-by: Grazvydas Ignotas <notasas@gmail.com> Acked-by: Kalle Valo <kvalo@adurom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/wl1251')
-rw-r--r--drivers/net/wireless/wl1251/sdio.c64
1 files changed, 61 insertions, 3 deletions
diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c
index 02851901677e..f3e185efe124 100644
--- a/drivers/net/wireless/wl1251/sdio.c
+++ b/drivers/net/wireless/wl1251/sdio.c
@@ -26,6 +26,7 @@
26#include <linux/platform_device.h> 26#include <linux/platform_device.h>
27#include <linux/wl12xx.h> 27#include <linux/wl12xx.h>
28#include <linux/irq.h> 28#include <linux/irq.h>
29#include <linux/pm_runtime.h>
29 30
30#include "wl1251.h" 31#include "wl1251.h"
31 32
@@ -173,10 +174,40 @@ static void wl1251_disable_line_irq(struct wl1251 *wl)
173 174
174static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable) 175static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable)
175{ 176{
176 if (wl->set_power) 177 struct sdio_func *func = wl_to_func(wl);
177 wl->set_power(enable); 178 int ret;
178 179
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
209out:
210 return ret;
180} 211}
181 212
182static struct wl1251_if_operations wl1251_sdio_ops = { 213static struct wl1251_if_operations wl1251_sdio_ops = {
@@ -277,6 +308,10 @@ static int wl1251_sdio_probe(struct sdio_func *func,
277 goto out_free_irq; 308 goto out_free_irq;
278 309
279 sdio_set_drvdata(func, wl); 310 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
280 return ret; 315 return ret;
281 316
282out_free_irq: 317out_free_irq:
@@ -298,6 +333,9 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func)
298 struct wl1251 *wl = sdio_get_drvdata(func); 333 struct wl1251 *wl = sdio_get_drvdata(func);
299 struct wl1251_sdio *wl_sdio = wl->if_priv; 334 struct wl1251_sdio *wl_sdio = wl->if_priv;
300 335
336 /* Undo decrement done above in wl1251_probe */
337 pm_runtime_get_noresume(&func->dev);
338
301 if (wl->irq) 339 if (wl->irq)
302 free_irq(wl->irq, wl); 340 free_irq(wl->irq, wl);
303 kfree(wl_sdio); 341 kfree(wl_sdio);
@@ -309,11 +347,31 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func)
309 sdio_release_host(func); 347 sdio_release_host(func);
310} 348}
311 349
350static 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
359static int wl1251_resume(struct device *dev)
360{
361 return 0;
362}
363
364static const struct dev_pm_ops wl1251_sdio_pm_ops = {
365 .suspend = wl1251_suspend,
366 .resume = wl1251_resume,
367};
368
312static struct sdio_driver wl1251_sdio_driver = { 369static struct sdio_driver wl1251_sdio_driver = {
313 .name = "wl1251_sdio", 370 .name = "wl1251_sdio",
314 .id_table = wl1251_devices, 371 .id_table = wl1251_devices,
315 .probe = wl1251_sdio_probe, 372 .probe = wl1251_sdio_probe,
316 .remove = __devexit_p(wl1251_sdio_remove), 373 .remove = __devexit_p(wl1251_sdio_remove),
374 .drv.pm = &wl1251_sdio_pm_ops,
317}; 375};
318 376
319static int __init wl1251_sdio_init(void) 377static int __init wl1251_sdio_init(void)