From patchwork Mon Nov 1 09:02:00 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ohad Ben Cohen X-Patchwork-Id: 294192 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 oA1912NL011259 for ; Mon, 1 Nov 2010 09:02:22 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755000Ab0KAJCW (ORCPT ); Mon, 1 Nov 2010 05:02:22 -0400 Received: from mail-iw0-f174.google.com ([209.85.214.174]:35790 "EHLO mail-iw0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753649Ab0KAJCV (ORCPT ); Mon, 1 Nov 2010 05:02:21 -0400 Received: by iwn10 with SMTP id 10so6804601iwn.19 for ; Mon, 01 Nov 2010 02:02:20 -0700 (PDT) Received: by 10.231.33.129 with SMTP id h1mr6946569ibd.158.1288602140842; Mon, 01 Nov 2010 02:02:20 -0700 (PDT) MIME-Version: 1.0 Received: by 10.231.190.149 with HTTP; Mon, 1 Nov 2010 02:02:00 -0700 (PDT) X-Originating-IP: [93.172.188.124] In-Reply-To: <4CCE74DB.8000206@arndnet.de> References: <4CCDA454.708@arndnet.de> <4CCDE4EB.7060001@arndnet.de> <4CCE74DB.8000206@arndnet.de> From: Ohad Ben-Cohen Date: Mon, 1 Nov 2010 11:02:00 +0200 Message-ID: Subject: Re: regression: b43-sdio: probe of mmc0:0001:1 failed with error -16 To: Arnd Hannemann Cc: "linux-mmc@vger.kernel.org" , "linux-wireless@vger.kernel.org" , linux-kernel@vger.kernel.org Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@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, 01 Nov 2010 09:02:23 +0000 (UTC) From 6b5691bdd8184cc0876d209c69d38844ea10f678 Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Mon, 1 Nov 2010 09:41:44 +0200 Subject: [PATCH] mmc: add MMC_CAP_RUNTIME_PM Some board/card/host configurations are not capable of powering off/on on the card during runtime. To support such configurations, and to allow smoother transition to runtime PM behavior, MMC_CAP_RUNTIME_PM is added, so hosts need to explicitly indicate that it's OK to power off their cards after boot. This will prevent sdio_bus_probe() from failing to power on the card when the driver is loaded on such setups. Signed-off-by: Ohad Ben-Cohen --- drivers/mmc/core/sdio.c | 37 +++++++++++++++++++++++-------------- drivers/mmc/core/sdio_bus.c | 33 ++++++++++++++++++++++----------- include/linux/mmc/host.h | 1 + 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 6a9ad40..373d56d 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -547,9 +547,11 @@ static void mmc_sdio_detect(struct mmc_host *host) BUG_ON(!host->card); /* Make sure card is powered before detecting it */ - err = pm_runtime_get_sync(&host->card->dev); - if (err < 0) - goto out; + if (host->caps & MMC_CAP_RUNTIME_PM) { + err = pm_runtime_get_sync(&host->card->dev); + if (err < 0) + goto out; + } mmc_claim_host(host); @@ -570,7 +572,8 @@ out: } /* Tell PM core that we're done */ - pm_runtime_put(&host->card->dev); + if (host->caps & MMC_CAP_RUNTIME_PM) + pm_runtime_put(&host->card->dev); } /* @@ -720,16 +723,21 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) card = host->card; /* - * Let runtime PM core know our card is active + * Enable runtime PM only if supported by host+card+board */ - err = pm_runtime_set_active(&card->dev); - if (err) - goto remove; + if (host->caps & MMC_CAP_RUNTIME_PM) { + /* + * Let runtime PM core know our card is active + */ + err = pm_runtime_set_active(&card->dev); + if (err) + goto remove; - /* - * Enable runtime PM for this card - */ - pm_runtime_enable(&card->dev); + /* + * Enable runtime PM for this card + */ + pm_runtime_enable(&card->dev); + } /* * The number of functions on the card is encoded inside @@ -747,9 +755,10 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) goto remove; /* - * Enable Runtime PM for this func + * Enable Runtime PM for this func (if supported) */ - pm_runtime_enable(&card->sdio_func[i]->dev); + if (host->caps & MMC_CAP_RUNTIME_PM) + pm_runtime_enable(&card->sdio_func[i]->dev); } mmc_release_host(host); diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 2716c7a..f3ce21b 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -17,6 +17,7 @@ #include #include +#include #include #include "sdio_cis.h" @@ -132,9 +133,11 @@ static int sdio_bus_probe(struct device *dev) * it should call pm_runtime_put_noidle() in its probe routine and * pm_runtime_get_noresume() in its remove routine. */ - ret = pm_runtime_get_sync(dev); - if (ret < 0) - goto out; + if (func->card->host->caps & MMC_CAP_RUNTIME_PM) { + ret = pm_runtime_get_sync(dev); + if (ret < 0) + goto out; + } /* Set the default block size so the driver is sure it's something * sensible. */ @@ -151,7 +154,8 @@ static int sdio_bus_probe(struct device *dev) return 0; disable_runtimepm: - pm_runtime_put_noidle(dev); + if (func->card->host->caps & MMC_CAP_RUNTIME_PM) + pm_runtime_put_noidle(dev); out: return ret; } @@ -160,12 +164,14 @@ static int sdio_bus_remove(struct device *dev) { struct sdio_driver *drv = to_sdio_driver(dev->driver); struct sdio_func *func = dev_to_sdio_func(dev); - int ret; + int ret = 0; /* Make sure card is powered before invoking ->remove() */ - ret = pm_runtime_get_sync(dev); - if (ret < 0) - goto out; + if (func->card->host->caps & MMC_CAP_RUNTIME_PM) { + ret = pm_runtime_get_sync(dev); + if (ret < 0) + goto out; + } drv->remove(func); @@ -178,10 +184,12 @@ static int sdio_bus_remove(struct device *dev) } /* First, undo the increment made directly above */ - pm_runtime_put_noidle(dev); + if (func->card->host->caps & MMC_CAP_RUNTIME_PM) + pm_runtime_put_noidle(dev); /* Then undo the runtime PM settings in sdio_bus_probe() */ - pm_runtime_put_noidle(dev); + if (func->card->host->caps & MMC_CAP_RUNTIME_PM) + pm_runtime_put_noidle(dev); out: return ret; @@ -191,6 +199,8 @@ out: static int sdio_bus_pm_prepare(struct device *dev) { + struct sdio_func *func = dev_to_sdio_func(dev); + /* * Resume an SDIO device which was suspended at run time at this * point, in order to allow standard SDIO suspend/resume paths @@ -212,7 +222,8 @@ static int sdio_bus_pm_prepare(struct device *dev) * since there is little point in failing system suspend if a * device can't be resumed. */ - pm_runtime_resume(dev); + if (func->card->host->caps & MMC_CAP_RUNTIME_PM) + pm_runtime_resume(dev); return 0; } diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index c3ffad8..e5eee0e 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -167,6 +167,7 @@ struct mmc_host { /* DDR mode at 1.8V */ #define MMC_CAP_1_2V_DDR (1 << 12) /* can support */ /* DDR mode at 1.2V */ +#define MMC_CAP_RUNTIME_PM (1 << 13) /* Can power off/on in runtime */ mmc_pm_flag_t pm_caps; /* supported pm features */ -- 1.7.0.4