From: Alan Stern <stern@rowland.harvard.edu> To: Pierre Tardy <tardyp@gmail.com> Cc: linux-kernel@vger.kernel.org, <linux-pm@lists.linux-foundation.org>, <linux-mmc@vger.kernel.org>, Pierre Tardy <pierre.tardy@intel.com>, Yunpeng Gao <yunpeng.gao@intel.com> Subject: Re: [linux-pm] [RFC, PATCHv3 1/3] mmc: sdhci-pci: Enable runtime PM support Date: Tue, 1 Mar 2011 14:46:56 -0500 (EST) [thread overview] Message-ID: <Pine.LNX.4.44L0.1103011433110.2034-100000@iolanthe.rowland.org> (raw) In-Reply-To: <1c071e206d0d02e07d3872f20268fba6b101a6b4.1298820826.git.tardyp@gmail.com> On Tue, 1 Mar 2011, Pierre Tardy wrote: > From: Yunpeng Gao <yunpeng.gao@intel.com> > > Follow the kernel runtime PM framework, enable runtime PM support of the > sdhci host controller with pci interface. > > Note that this patch implements runtime_pm but now actually detects > activity. > It relies on higher level (childrens) to do actual waking up > Activity detection is put in a following patch > > This patch also does not enable wakeups, so card insertion will not work > if runtime_pm is activated. > This is also dealt in a following patch > > Original version from: Yunpeng Gao <yunpeng.gao@intel.com> > with modifications by: Pierre Tardy <pierre.tardy@intel.com> > > Signed-off-by: Pierre Tardy <pierre.tardy@intel.com> > --- > drivers/mmc/host/sdhci-pci.c | 120 +++++++++++++++++++++++++++++++++++++++++- > drivers/mmc/host/sdhci.c | 31 +++++++++++ > drivers/mmc/host/sdhci.h | 5 ++ > 3 files changed, 155 insertions(+), 1 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c > index 2f8d468..f167a55 100644 > --- a/drivers/mmc/host/sdhci-pci.c > +++ b/drivers/mmc/host/sdhci-pci.c > @@ -18,6 +18,7 @@ > #include <linux/dma-mapping.h> > #include <linux/slab.h> > #include <linux/device.h> > +#include <linux/pm_runtime.h> > > #include <linux/mmc/host.h> > > @@ -1031,6 +1032,8 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev, > if (ret) > return ret; > > + pm_runtime_set_active(&pdev->dev); This line is redundant. It won't do anything, and the PCI core already does it. > + > slots = PCI_SLOT_INFO_SLOTS(slots) + 1; > dev_dbg(&pdev->dev, "found %d slot(s)\n", slots); > if (slots == 0) > @@ -1086,7 +1089,7 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev, > > chip->slots[i] = slot; > } > - > + pm_runtime_put_noidle(&pdev->dev); > return 0; > > free: > @@ -1114,8 +1117,120 @@ static void __devexit sdhci_pci_remove(struct pci_dev *pdev) > } > > pci_disable_device(pdev); > + pm_runtime_get_noresume(&pdev->dev); > + > +} > + > +#ifdef CONFIG_PM_RUNTIME > + > +static int sdhci_pci_runtime_suspend(struct device *dev) > +{ > + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); > + struct sdhci_pci_chip *chip; > + struct sdhci_pci_slot *slot; > + int i, ret; > + mmc_pm_flag_t pm_flags = 0; > + pm_message_t state; > + > + chip = pci_get_drvdata(pdev); > + if (!chip) > + return 0; > + > + for (i = 0; i < chip->num_slots; i++) { > + slot = chip->slots[i]; > + if (!slot) > + continue; > + > + ret = sdhci_runtime_suspend(slot->host); > + > + if (ret) { > + for (i--; i >= 0; i--) > + sdhci_runtime_resume(chip->slots[i]->host); > + return ret; > + } > + > + pm_flags |= slot->host->mmc->pm_flags; > + } > + > + state.event = PM_EVENT_AUTO_SUSPEND; > + if (chip->fixes && chip->fixes->suspend) { > + ret = chip->fixes->suspend(chip, state); > + if (ret) { > + for (i = chip->num_slots - 1; i >= 0; i--) > + sdhci_runtime_resume(chip->slots[i]->host); > + return ret; > + } > + } You probably should call synchronize_irq() here. Otherwise a delayed IRQ might get delivered after the device has changed to D3. > + > + pci_save_state(pdev); > + if (pm_flags & MMC_PM_KEEP_POWER) { > + if (pm_flags & MMC_PM_WAKE_SDIO_IRQ) > + pci_enable_wake(pdev, PCI_D3hot, 1); > + } else { > + pci_enable_wake(pdev, PCI_D3hot, 0); > + pci_disable_device(pdev); > + } > + pci_set_power_state(pdev, PCI_D3hot); Most of this isn't needed. The PCI core does pci_save_state(), pci_enable_wake(), and pci_set_power_state(). Of course, you might want to override the wakeup setting selected by the core. This is determined by pci_dev_run_wake(), for which you may need to call device_set_run_wake(). > + > + return 0; > } > > +static int sdhci_pci_runtime_resume(struct device *dev) > +{ > + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); > + struct sdhci_pci_chip *chip; > + struct sdhci_pci_slot *slot; > + int i, ret; > + > + chip = pci_get_drvdata(pdev); > + if (!chip) > + return 0; > + > + pci_set_power_state(pdev, PCI_D0); > + pci_restore_state(pdev); The PCI core does pci_set_power_state() and pci_restore_state(). > + ret = pci_enable_device(pdev); > + if (ret) > + return ret; > + > + if (chip->fixes && chip->fixes->resume) { > + ret = chip->fixes->resume(chip); > + if (ret) > + return ret; > + } > + > + for (i = 0; i < chip->num_slots; i++) { > + slot = chip->slots[i]; > + if (!slot) > + continue; > + > + ret = sdhci_runtime_resume(slot->host); > + if (ret) > + return ret; > + } > + > + return 0; > +} > + > +static int sdhci_pci_runtime_idle(struct device *dev) > +{ > + pm_runtime_autosuspend(dev); > + return -EAGAIN; > +} Alan Stern
WARNING: multiple messages have this Message-ID (diff)
From: Alan Stern <stern@rowland.harvard.edu> To: Pierre Tardy <tardyp@gmail.com> Cc: linux-kernel@vger.kernel.org, linux-pm@lists.linux-foundation.org, linux-mmc@vger.kernel.org, Pierre Tardy <pierre.tardy@intel.com>, Yunpeng Gao <yunpeng.gao@intel.com> Subject: Re: [linux-pm] [RFC, PATCHv3 1/3] mmc: sdhci-pci: Enable runtime PM support Date: Tue, 1 Mar 2011 14:46:56 -0500 (EST) [thread overview] Message-ID: <Pine.LNX.4.44L0.1103011433110.2034-100000@iolanthe.rowland.org> (raw) In-Reply-To: <1c071e206d0d02e07d3872f20268fba6b101a6b4.1298820826.git.tardyp@gmail.com> On Tue, 1 Mar 2011, Pierre Tardy wrote: > From: Yunpeng Gao <yunpeng.gao@intel.com> > > Follow the kernel runtime PM framework, enable runtime PM support of the > sdhci host controller with pci interface. > > Note that this patch implements runtime_pm but now actually detects > activity. > It relies on higher level (childrens) to do actual waking up > Activity detection is put in a following patch > > This patch also does not enable wakeups, so card insertion will not work > if runtime_pm is activated. > This is also dealt in a following patch > > Original version from: Yunpeng Gao <yunpeng.gao@intel.com> > with modifications by: Pierre Tardy <pierre.tardy@intel.com> > > Signed-off-by: Pierre Tardy <pierre.tardy@intel.com> > --- > drivers/mmc/host/sdhci-pci.c | 120 +++++++++++++++++++++++++++++++++++++++++- > drivers/mmc/host/sdhci.c | 31 +++++++++++ > drivers/mmc/host/sdhci.h | 5 ++ > 3 files changed, 155 insertions(+), 1 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c > index 2f8d468..f167a55 100644 > --- a/drivers/mmc/host/sdhci-pci.c > +++ b/drivers/mmc/host/sdhci-pci.c > @@ -18,6 +18,7 @@ > #include <linux/dma-mapping.h> > #include <linux/slab.h> > #include <linux/device.h> > +#include <linux/pm_runtime.h> > > #include <linux/mmc/host.h> > > @@ -1031,6 +1032,8 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev, > if (ret) > return ret; > > + pm_runtime_set_active(&pdev->dev); This line is redundant. It won't do anything, and the PCI core already does it. > + > slots = PCI_SLOT_INFO_SLOTS(slots) + 1; > dev_dbg(&pdev->dev, "found %d slot(s)\n", slots); > if (slots == 0) > @@ -1086,7 +1089,7 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev, > > chip->slots[i] = slot; > } > - > + pm_runtime_put_noidle(&pdev->dev); > return 0; > > free: > @@ -1114,8 +1117,120 @@ static void __devexit sdhci_pci_remove(struct pci_dev *pdev) > } > > pci_disable_device(pdev); > + pm_runtime_get_noresume(&pdev->dev); > + > +} > + > +#ifdef CONFIG_PM_RUNTIME > + > +static int sdhci_pci_runtime_suspend(struct device *dev) > +{ > + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); > + struct sdhci_pci_chip *chip; > + struct sdhci_pci_slot *slot; > + int i, ret; > + mmc_pm_flag_t pm_flags = 0; > + pm_message_t state; > + > + chip = pci_get_drvdata(pdev); > + if (!chip) > + return 0; > + > + for (i = 0; i < chip->num_slots; i++) { > + slot = chip->slots[i]; > + if (!slot) > + continue; > + > + ret = sdhci_runtime_suspend(slot->host); > + > + if (ret) { > + for (i--; i >= 0; i--) > + sdhci_runtime_resume(chip->slots[i]->host); > + return ret; > + } > + > + pm_flags |= slot->host->mmc->pm_flags; > + } > + > + state.event = PM_EVENT_AUTO_SUSPEND; > + if (chip->fixes && chip->fixes->suspend) { > + ret = chip->fixes->suspend(chip, state); > + if (ret) { > + for (i = chip->num_slots - 1; i >= 0; i--) > + sdhci_runtime_resume(chip->slots[i]->host); > + return ret; > + } > + } You probably should call synchronize_irq() here. Otherwise a delayed IRQ might get delivered after the device has changed to D3. > + > + pci_save_state(pdev); > + if (pm_flags & MMC_PM_KEEP_POWER) { > + if (pm_flags & MMC_PM_WAKE_SDIO_IRQ) > + pci_enable_wake(pdev, PCI_D3hot, 1); > + } else { > + pci_enable_wake(pdev, PCI_D3hot, 0); > + pci_disable_device(pdev); > + } > + pci_set_power_state(pdev, PCI_D3hot); Most of this isn't needed. The PCI core does pci_save_state(), pci_enable_wake(), and pci_set_power_state(). Of course, you might want to override the wakeup setting selected by the core. This is determined by pci_dev_run_wake(), for which you may need to call device_set_run_wake(). > + > + return 0; > } > > +static int sdhci_pci_runtime_resume(struct device *dev) > +{ > + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); > + struct sdhci_pci_chip *chip; > + struct sdhci_pci_slot *slot; > + int i, ret; > + > + chip = pci_get_drvdata(pdev); > + if (!chip) > + return 0; > + > + pci_set_power_state(pdev, PCI_D0); > + pci_restore_state(pdev); The PCI core does pci_set_power_state() and pci_restore_state(). > + ret = pci_enable_device(pdev); > + if (ret) > + return ret; > + > + if (chip->fixes && chip->fixes->resume) { > + ret = chip->fixes->resume(chip); > + if (ret) > + return ret; > + } > + > + for (i = 0; i < chip->num_slots; i++) { > + slot = chip->slots[i]; > + if (!slot) > + continue; > + > + ret = sdhci_runtime_resume(slot->host); > + if (ret) > + return ret; > + } > + > + return 0; > +} > + > +static int sdhci_pci_runtime_idle(struct device *dev) > +{ > + pm_runtime_autosuspend(dev); > + return -EAGAIN; > +} Alan Stern
next prev parent reply other threads:[~2011-03-01 19:47 UTC|newest] Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top 2011-03-01 18:15 [RFC,PATCHv3 0/3] sdhci runtime_pm implementation Pierre Tardy 2011-03-01 18:15 ` [RFC, PATCHv3 1/3] mmc: sdhci-pci: Enable runtime PM support Pierre Tardy 2011-03-01 18:15 ` [RFC,PATCHv3 " Pierre Tardy 2011-03-01 19:46 ` [RFC, PATCHv3 " Alan Stern 2011-03-01 19:46 ` Alan Stern [this message] 2011-03-01 19:46 ` [linux-pm] " Alan Stern 2011-03-01 18:15 ` [RFC,PATCHv3 2/3] mmc: sdhci: use ios->clock to know when sdhci is idle Pierre Tardy 2011-03-01 18:15 ` [RFC, PATCHv3 " Pierre Tardy 2011-03-01 18:15 ` [RFC,PATCHv3 3/3] mmc: sdhci: handle wake-up from runtime_pm Pierre Tardy 2011-03-01 19:53 ` [RFC, PATCHv3 " Alan Stern 2011-03-01 19:53 ` [linux-pm] " Alan Stern 2011-03-01 19:53 ` Alan Stern 2011-03-01 20:01 ` Pierre Tardy 2011-03-01 20:01 ` [linux-pm] " Pierre Tardy 2011-03-01 20:27 ` Alan Stern 2011-03-01 20:27 ` [linux-pm] " Alan Stern 2011-03-01 20:27 ` Alan Stern 2011-03-01 20:48 ` Pierre Tardy 2011-03-01 20:48 ` [linux-pm] " Pierre Tardy 2011-03-01 18:15 ` Pierre Tardy 2011-03-01 19:33 ` [linux-pm] [RFC,PATCHv3 0/3] sdhci runtime_pm implementation Alan Stern 2011-03-01 19:33 ` Alan Stern 2011-03-01 19:36 ` Pierre Tardy 2011-03-01 19:57 ` Alan Stern 2011-03-01 19:57 ` [linux-pm] " Alan Stern 2011-03-01 19:57 ` Alan Stern 2011-03-01 20:06 ` Pierre Tardy 2011-03-01 20:06 ` [linux-pm] " Pierre Tardy 2011-03-01 20:30 ` Alan Stern 2011-03-01 20:30 ` [linux-pm] " Alan Stern 2011-03-01 20:30 ` Alan Stern 2011-03-01 21:07 ` Rafael J. Wysocki 2011-03-01 21:07 ` [linux-pm] " Rafael J. Wysocki 2011-03-01 23:40 ` Pierre Tardy 2011-03-01 23:40 ` [linux-pm] " Pierre Tardy 2011-03-01 23:49 ` Rafael J. Wysocki 2011-03-02 15:12 ` Alan Stern 2011-03-02 15:12 ` [linux-pm] " Alan Stern 2011-03-02 15:12 ` Alan Stern 2011-03-01 23:49 ` Rafael J. Wysocki 2011-03-01 19:36 ` Pierre Tardy 2011-03-01 19:33 ` Alan Stern
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=Pine.LNX.4.44L0.1103011433110.2034-100000@iolanthe.rowland.org \ --to=stern@rowland.harvard.edu \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-mmc@vger.kernel.org \ --cc=linux-pm@lists.linux-foundation.org \ --cc=pierre.tardy@intel.com \ --cc=tardyp@gmail.com \ --cc=yunpeng.gao@intel.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.