From patchwork Mon Nov 8 13:29:36 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grazvydas Ignotas X-Patchwork-Id: 308312 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oA8DUBvS004485 for ; Mon, 8 Nov 2010 13:30:11 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754347Ab0KHNaJ (ORCPT ); Mon, 8 Nov 2010 08:30:09 -0500 Received: from mail-fx0-f46.google.com ([209.85.161.46]:38062 "EHLO mail-fx0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754266Ab0KHNaH (ORCPT ); Mon, 8 Nov 2010 08:30:07 -0500 Received: by fxm16 with SMTP id 16so3971185fxm.19 for ; Mon, 08 Nov 2010 05:30:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:subject:date :message-id:x-mailer; bh=sMX1XHtAYQqvIk2j5um/VBBnYxqArv5RTfXg+42MSTo=; b=L7jQ4W0PsXx/144ay//SzpxyVAZlvB0rc4famFZdwtkcA2JEulIeexWNPguSdMzJr3 Iy5Yf1RhWqA24T8Xxy2K+yZk7EBgX9EcAHk81KVIobyLEA4DVPwF49Mw9GrtRUQnMzeG +N/N18gC8IS/FjjbWw3wSkK4xEJrWwnSvW9B4= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; b=IbYoOHAmiYPYekNSVoVg0xD0sJ1TyMW8Wx8KnzKAYM3/jSxCy8WtkJH/4ciJnOKWyc 7Ks2lF5IRciALAhpWHSwPQ0qnoYvdm5xwhqhaHdsRFCvxKqyTY2fChZZj2J5+08ILh3m P8XvYxN7x/Z4xmmitpg9Lo/PLju7gbJ2cPRQM= Received: by 10.223.83.144 with SMTP id f16mr3722885fal.118.1289223006278; Mon, 08 Nov 2010 05:30:06 -0800 (PST) Received: from localhost.localdomain (ip-88-119-226-136.static.b4net.lt [88.119.226.136]) by mx.google.com with ESMTPS id 16sm2110117fal.0.2010.11.08.05.30.04 (version=TLSv1/SSLv3 cipher=RC4-MD5); Mon, 08 Nov 2010 05:30:04 -0800 (PST) From: Grazvydas Ignotas To: linux-wireless@vger.kernel.org Cc: Kalle Valo , "John W. Linville" , Grazvydas Ignotas , Ohad Ben-Cohen Subject: [PATCHv2 2/3] wl1251: add runtime PM support for SDIO Date: Mon, 8 Nov 2010 15:29:36 +0200 Message-Id: <1289222976-19793-1-git-send-email-notasas@gmail.com> X-Mailer: git-send-email 1.6.3.3 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Mon, 08 Nov 2010 13:30:11 +0000 (UTC) diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c index 0285190..f3e185e 100644 --- a/drivers/net/wireless/wl1251/sdio.c +++ b/drivers/net/wireless/wl1251/sdio.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "wl1251.h" @@ -173,10 +174,40 @@ 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 is controlled by runtime PM, but we still call board + * callback in case it wants to do any additional setup, + * for example enabling clock buffer for the module. + */ + if (wl->set_power) + wl->set_power(true); + + ret = pm_runtime_get_sync(&func->dev); + 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 +308,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 +333,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 wl1251_probe */ + pm_runtime_get_noresume(&func->dev); + if (wl->irq) free_irq(wl->irq, wl); kfree(wl_sdio); @@ -309,11 +347,31 @@ 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)