Re: -ENOSYS suspend-powerdown regression

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 4 June 2011 11:33, Ohad Ben-Cohen <ohad@xxxxxxxxxx> wrote:
> It means runtime PM is disabled for your device.
>
> Which doesn't make sense, assuming you had MMC_CAP_POWER_OFF_CARD
> configured (if you didn't, you wouldn't end up calling runtime PM api
> at all).
>
> If you post your entire diff, I might be able to spot what's wrong.

Its not really different from what I posted before. Just with some
added printks and a hack to enable POWER_OFF_CARD for sdhci. Attaching
it anyway.

Is it possible that there is confusion as to whether runtime PM is
enabled or disabled for the device because we are so late at this
point in device teardown?

Daniel
commit 2460eee717cbae4e683edeb17ffe448b0c32fd28
Author: Daniel Drake <dsd@xxxxxxxxxx>
Date:   Tue May 31 12:51:39 2011 +0100

    runtime suspend WIP

diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 0d4587b..ddb0ae5 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -452,7 +452,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
 	struct device *parent = NULL;
 	int retval = 0;
 
-	dev_dbg(dev, "%s flags 0x%x\n", __func__, rpmflags);
+	dev_warn(dev, "%s flags 0x%x\n", __func__, rpmflags);
 
  repeat:
 	if (dev->power.runtime_error)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 68091dd..8a59072 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1664,6 +1664,7 @@ int mmc_power_save_host(struct mmc_host *host)
 	int ret = 0;
 
 	mmc_bus_get(host);
+printk("mmc_power_save_host %s\n", mmc_hostname(host));
 
 	if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
 		mmc_bus_put(host);
@@ -1686,6 +1687,7 @@ int mmc_power_restore_host(struct mmc_host *host)
 	int ret;
 
 	mmc_bus_get(host);
+printk("mmc_power_restore_host %s\n", mmc_hostname(host));
 
 	if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
 		mmc_bus_put(host);
@@ -1751,6 +1753,8 @@ int mmc_suspend_host(struct mmc_host *host)
 {
 	int err = 0;
 
+	printk("mmc_suspend_host %s\n", mmc_hostname(host));
+
 	if (host->caps & MMC_CAP_DISABLE)
 		cancel_delayed_work(&host->disable);
 	cancel_delayed_work(&host->detect);
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 4d0c15b..a241176 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -537,11 +537,14 @@ static void mmc_sdio_remove(struct mmc_host *host)
 {
 	int i;
 
+	printk("mmc_sdio_remove %s\n", mmc_hostname(host));
+
 	BUG_ON(!host);
 	BUG_ON(!host->card);
 
 	for (i = 0;i < host->card->sdio_funcs;i++) {
 		if (host->card->sdio_func[i]) {
+			printk("remove func %d\n", i);
 			sdio_remove_func(host->card->sdio_func[i]);
 			host->card->sdio_func[i] = NULL;
 		}
@@ -647,6 +650,8 @@ static int mmc_sdio_resume(struct mmc_host *host)
 	BUG_ON(!host);
 	BUG_ON(!host->card);
 
+printk("mmc_sdio_resume %s\n", mmc_hostname(host));
+
 	/* Basic card reinitialization. */
 	mmc_claim_host(host);
 
@@ -691,15 +696,47 @@ static int mmc_sdio_resume(struct mmc_host *host)
 static int mmc_sdio_power_restore(struct mmc_host *host)
 {
 	int ret;
+	u32 ocr;
 
 	BUG_ON(!host);
 	BUG_ON(!host->card);
 
 	mmc_claim_host(host);
+
+	ret = mmc_send_io_op_cond(host, 0, &ocr);
+	if (ret)
+		goto out;
+
+	if (host->ocr_avail_sdio)
+		host->ocr_avail = host->ocr_avail_sdio;
+
+	/*
+	 * Sanity check the voltages that the card claims to
+	 * support.
+	 */
+	if (ocr & 0x7F) {
+		printk(KERN_WARNING "%s: card claims to support voltages "
+		       "below the defined range. These will be ignored.\n",
+		       mmc_hostname(host));
+		ocr &= ~0x7F;
+	}
+
+	host->ocr = mmc_select_voltage(host, ocr);
+
+	/*
+	 * Can we support the voltage(s) of the card(s)?
+	 */
+	if (!host->ocr) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	ret = mmc_sdio_init_card(host, host->ocr, host->card,
 				mmc_card_keep_power(host));
 	if (!ret && host->sdio_irqs)
 		mmc_signal_sdio_irq(host);
+
+out:
 	mmc_release_host(host);
 
 	return ret;
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index d29b9c3..fe332de 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -166,13 +166,17 @@ static int sdio_bus_remove(struct device *dev)
 	struct sdio_func *func = dev_to_sdio_func(dev);
 	int ret = 0;
 
+dev_warn(dev, "sdio_bus_remove\n");
+
 	/* Make sure card is powered before invoking ->remove() */
 	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
 		ret = pm_runtime_get_sync(dev);
+printk("get_sync %d\n", ret);
 		if (ret < 0)
 			goto out;
 	}
 
+printk("CALL REMOVE\n");
 	drv->remove(func);
 
 	if (func->irq_handler) {
@@ -314,9 +318,11 @@ int sdio_add_func(struct sdio_func *func)
  */
 void sdio_remove_func(struct sdio_func *func)
 {
+	printk("sdio_remove_func\n");
 	if (!sdio_func_present(func))
 		return;
 
+	dev_warn(&func->dev, "do device_del\n");
 	device_del(&func->dev);
 	put_device(&func->dev);
 }
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 58d5436..ce3e2e2 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2488,7 +2488,7 @@ int sdhci_add_host(struct sdhci_host *host)
 	} else
 		mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
 
-	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
+	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23 | MMC_CAP_POWER_OFF_CARD;
 
 	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
 		host->flags |= SDHCI_AUTO_CMD12;
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 224e985..d2b077b 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -946,7 +946,7 @@ static int if_sdio_probe(struct sdio_func *func,
 	unsigned int model;
 	struct if_sdio_packet *packet;
 	struct mmc_host *host = func->card->host;
-
+printk("if_sdio_probe %p\n", &func->dev);
 	lbs_deb_enter(LBS_DEB_SDIO);
 
 	for (i = 0;i < func->card->num_info;i++) {
@@ -1124,6 +1124,7 @@ static int if_sdio_probe(struct sdio_func *func,
 out:
 	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
 
+printk("if_sdio_probe done %d\n", ret);
 	return ret;
 
 err_activate_card:
@@ -1159,6 +1160,8 @@ static void if_sdio_remove(struct sdio_func *func)
 	struct if_sdio_card *card;
 	struct if_sdio_packet *packet;
 
+printk("if_sdio_remove\n");
+dump_stack();
 	lbs_deb_enter(LBS_DEB_SDIO);
 
 	card = sdio_get_drvdata(func);
@@ -1204,6 +1207,7 @@ static void if_sdio_remove(struct sdio_func *func)
 		kfree(card->firmware);
 	kfree(card);
 
+printk("if_sdio_remove done\n");
 	lbs_deb_leave(LBS_DEB_SDIO);
 }
 
@@ -1212,8 +1216,8 @@ static int if_sdio_suspend(struct device *dev)
 	struct sdio_func *func = dev_to_sdio_func(dev);
 	int ret;
 	struct if_sdio_card *card = sdio_get_drvdata(func);
-
 	mmc_pm_flag_t flags = sdio_get_host_pm_caps(func);
+printk("if_sdio_suspend %p\n", dev);
 
 	dev_info(dev, "%s: suspend: PM flags = 0x%x\n",
 		 sdio_func_id(func), flags);
@@ -1249,6 +1253,7 @@ static int if_sdio_resume(struct device *dev)
 	struct if_sdio_card *card = sdio_get_drvdata(func);
 	int ret;
 
+printk("if_sdio_resume %p\n", dev);
 	dev_info(dev, "%s: resume: we're back\n", sdio_func_id(func));
 
 	ret = lbs_resume(card->priv);

[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux