From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Takashi Iwai <tiwai@suse.de>, Greg KH <greg@kroah.com>,
LKML <linux-kernel@vger.kernel.org>,
Jesse Barnes <jbarnes@virtuousgeek.org>,
pm list <linux-pm@lists.linux-foundation.org>,
Ingo Molnar <mingo@elte.hu>,
Andrew Morton <akpm@linux-foundation.org>
Subject: [PATCH 1/3] PCI: Rework default handling of suspend and resume
Date: Sat, 6 Dec 2008 15:07:05 +0100 [thread overview]
Message-ID: <200812061507.06474.rjw@sisk.pl> (raw)
In-Reply-To: <200812061505.33815.rjw@sisk.pl>
From: Rafael J. Wysocki <rjw@sisk.pl>
Subject: PCI: Rework default handling of suspend and resume
Rework the handling of suspend and resume of PCI devices which have
no drivers or the drivers of which do not provide any suspend-resume
callbacks in such a way that their standard PCI configuration
registers will be saved and restored with interrupts disabled. This
should prevent such devices, including PCI bridges, from being
resumed too late to be able to function correctly during the resume
of the other PCI devices that may depend on them.
Also, to remove one possible source of future confusion, drop the
default handling of suspend and resume for PCI devices with drivers
providing the 'pm' object introduced by the new suspend-resume
framework (there are no such PCI drivers at the moment).
This patch addresses the regression from 2.6.26 tracked as
http://bugzilla.kernel.org/show_bug.cgi?id=12121 .
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
drivers/pci/pci-driver.c | 90 ++++++++++++++++++++++++++++++-----------------
1 file changed, 59 insertions(+), 31 deletions(-)
Index: linux-2.6/drivers/pci/pci-driver.c
===================================================================
--- linux-2.6.orig/drivers/pci/pci-driver.c
+++ linux-2.6/drivers/pci/pci-driver.c
@@ -300,6 +300,14 @@ static void pci_device_shutdown(struct d
#ifdef CONFIG_PM_SLEEP
+static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
+{
+ struct pci_driver *drv = pci_dev->driver;
+
+ return drv && (drv->suspend || drv->suspend_late || drv->resume
+ || drv->resume_early);
+}
+
/*
* Default "suspend" method for devices that have no driver provided suspend,
* or not even a driver at all.
@@ -317,14 +325,22 @@ static void pci_default_pm_suspend(struc
/*
* Default "resume" method for devices that have no driver provided resume,
- * or not even a driver at all.
+ * or not even a driver at all (first part).
*/
-static int pci_default_pm_resume(struct pci_dev *pci_dev)
+static void pci_default_pm_resume_early(struct pci_dev *pci_dev)
{
- int retval = 0;
-
/* restore the PCI config space */
pci_restore_state(pci_dev);
+}
+
+/*
+ * Default "resume" method for devices that have no driver provided resume,
+ * or not even a driver at all (second part).
+ */
+static int pci_default_pm_resume_late(struct pci_dev *pci_dev)
+{
+ int retval;
+
/* if the device was enabled before suspend, reenable */
retval = pci_reenable_device(pci_dev);
/*
@@ -371,10 +387,12 @@ static int pci_legacy_resume(struct devi
struct pci_dev * pci_dev = to_pci_dev(dev);
struct pci_driver * drv = pci_dev->driver;
- if (drv && drv->resume)
+ if (drv && drv->resume) {
error = drv->resume(pci_dev);
- else
- error = pci_default_pm_resume(pci_dev);
+ } else {
+ pci_default_pm_resume_early(pci_dev);
+ error = pci_default_pm_resume_late(pci_dev);
+ }
return error;
}
@@ -420,10 +438,8 @@ static int pci_pm_suspend(struct device
if (drv->pm->suspend) {
error = drv->pm->suspend(dev);
suspend_report_result(drv->pm->suspend, error);
- } else {
- pci_default_pm_suspend(pci_dev);
}
- } else {
+ } else if (pci_has_legacy_pm_support(pci_dev)) {
error = pci_legacy_suspend(dev, PMSG_SUSPEND);
}
pci_fixup_device(pci_fixup_suspend, pci_dev);
@@ -442,8 +458,10 @@ static int pci_pm_suspend_noirq(struct d
error = drv->pm->suspend_noirq(dev);
suspend_report_result(drv->pm->suspend_noirq, error);
}
- } else {
+ } else if (pci_has_legacy_pm_support(pci_dev)) {
error = pci_legacy_suspend_late(dev, PMSG_SUSPEND);
+ } else {
+ pci_default_pm_suspend(pci_dev);
}
return error;
@@ -453,15 +471,17 @@ static int pci_pm_resume(struct device *
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
- int error;
+ int error = 0;
pci_fixup_device(pci_fixup_resume, pci_dev);
if (drv && drv->pm) {
- error = drv->pm->resume ? drv->pm->resume(dev) :
- pci_default_pm_resume(pci_dev);
- } else {
+ if (drv->pm->resume)
+ error = drv->pm->resume(dev);
+ } else if (pci_has_legacy_pm_support(pci_dev)) {
error = pci_legacy_resume(dev);
+ } else {
+ error = pci_default_pm_resume_late(pci_dev);
}
return error;
@@ -478,8 +498,10 @@ static int pci_pm_resume_noirq(struct de
if (drv && drv->pm) {
if (drv->pm->resume_noirq)
error = drv->pm->resume_noirq(dev);
- } else {
+ } else if (pci_has_legacy_pm_support(pci_dev)) {
error = pci_legacy_resume_early(dev);
+ } else {
+ pci_default_pm_resume_early(pci_dev);
}
return error;
@@ -506,10 +528,8 @@ static int pci_pm_freeze(struct device *
if (drv->pm->freeze) {
error = drv->pm->freeze(dev);
suspend_report_result(drv->pm->freeze, error);
- } else {
- pci_default_pm_suspend(pci_dev);
}
- } else {
+ } else if (pci_has_legacy_pm_support(pci_dev)) {
error = pci_legacy_suspend(dev, PMSG_FREEZE);
pci_fixup_device(pci_fixup_suspend, pci_dev);
}
@@ -528,8 +548,10 @@ static int pci_pm_freeze_noirq(struct de
error = drv->pm->freeze_noirq(dev);
suspend_report_result(drv->pm->freeze_noirq, error);
}
- } else {
+ } else if (pci_has_legacy_pm_support(pci_dev)) {
error = pci_legacy_suspend_late(dev, PMSG_FREEZE);
+ } else {
+ pci_default_pm_suspend(pci_dev);
}
return error;
@@ -537,14 +559,15 @@ static int pci_pm_freeze_noirq(struct de
static int pci_pm_thaw(struct device *dev)
{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
int error = 0;
if (drv && drv->pm) {
if (drv->pm->thaw)
error = drv->pm->thaw(dev);
- } else {
- pci_fixup_device(pci_fixup_resume, to_pci_dev(dev));
+ } else if (pci_has_legacy_pm_support(pci_dev)) {
+ pci_fixup_device(pci_fixup_resume, pci_dev);
error = pci_legacy_resume(dev);
}
@@ -560,7 +583,7 @@ static int pci_pm_thaw_noirq(struct devi
if (drv && drv->pm) {
if (drv->pm->thaw_noirq)
error = drv->pm->thaw_noirq(dev);
- } else {
+ } else if (pci_has_legacy_pm_support(pci_dev)) {
pci_fixup_device(pci_fixup_resume_early, pci_dev);
error = pci_legacy_resume_early(dev);
}
@@ -570,17 +593,18 @@ static int pci_pm_thaw_noirq(struct devi
static int pci_pm_poweroff(struct device *dev)
{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
int error = 0;
- pci_fixup_device(pci_fixup_suspend, to_pci_dev(dev));
+ pci_fixup_device(pci_fixup_suspend, pci_dev);
if (drv && drv->pm) {
if (drv->pm->poweroff) {
error = drv->pm->poweroff(dev);
suspend_report_result(drv->pm->poweroff, error);
}
- } else {
+ } else if (pci_has_legacy_pm_support(pci_dev)) {
error = pci_legacy_suspend(dev, PMSG_HIBERNATE);
}
@@ -598,7 +622,7 @@ static int pci_pm_poweroff_noirq(struct
error = drv->pm->poweroff_noirq(dev);
suspend_report_result(drv->pm->poweroff_noirq, error);
}
- } else {
+ } else if (pci_has_legacy_pm_support(pci_dev)) {
error = pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
}
@@ -609,13 +633,15 @@ static int pci_pm_restore(struct device
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
- int error;
+ int error = 0;
if (drv && drv->pm) {
- error = drv->pm->restore ? drv->pm->restore(dev) :
- pci_default_pm_resume(pci_dev);
- } else {
+ if (drv->pm->restore)
+ error = drv->pm->restore(dev);
+ } else if (pci_has_legacy_pm_support(pci_dev)) {
error = pci_legacy_resume(dev);
+ } else {
+ error = pci_default_pm_resume_late(pci_dev);
}
pci_fixup_device(pci_fixup_resume, pci_dev);
@@ -633,8 +659,10 @@ static int pci_pm_restore_noirq(struct d
if (drv && drv->pm) {
if (drv->pm->restore_noirq)
error = drv->pm->restore_noirq(dev);
- } else {
+ } else if (pci_has_legacy_pm_support(pci_dev)) {
error = pci_legacy_resume_early(dev);
+ } else {
+ pci_default_pm_resume_early(pci_dev);
}
pci_fixup_device(pci_fixup_resume_early, pci_dev);
next prev parent reply other threads:[~2008-12-06 14:07 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <200812020320.31876.rjw@sisk.pl>
2008-12-06 14:05 ` [PATCH 0/3] Fix hibernation regression on Toshiba Portege R500 Rafael J. Wysocki
[not found] ` <200812061505.33815.rjw@sisk.pl>
2008-12-06 14:07 ` Rafael J. Wysocki [this message]
2008-12-06 17:07 ` [PATCH 1/3] PCI: Rework default handling of suspend and resume Linus Torvalds
[not found] ` <alpine.LFD.2.00.0812060855580.3425@nehalem.linux-foundation.org>
2008-12-06 17:22 ` Rafael J. Wysocki
[not found] ` <200812061822.35763.rjw@sisk.pl>
2008-12-06 17:33 ` Linus Torvalds
[not found] ` <alpine.LFD.2.00.0812060930490.3425@nehalem.linux-foundation.org>
2008-12-06 17:43 ` Rafael J. Wysocki
[not found] ` <200812061843.59495.rjw@sisk.pl>
2008-12-06 18:00 ` Linus Torvalds
2008-12-06 21:24 ` Rafael J. Wysocki
2008-12-07 4:44 ` Jesse Barnes
2008-12-07 5:41 ` Greg KH
[not found] ` <20081207054149.GA20415@kroah.com>
2008-12-07 12:47 ` Rafael J. Wysocki
[not found] ` <200812071347.18608.rjw@sisk.pl>
2008-12-07 16:44 ` Linus Torvalds
2008-12-07 17:26 ` Greg KH
[not found] ` <alpine.LFD.2.00.0812070835040.3425@nehalem.linux-foundation.org>
2008-12-07 21:02 ` Rafael J. Wysocki
[not found] ` <20081207172642.GC23744@kroah.com>
2008-12-07 23:34 ` [PATCH 1/3] PCI: Rework default handling of suspend and resume (rebased) Rafael J. Wysocki
2008-12-06 18:30 ` [PATCH 1/3] PCI: Rework default handling of suspend and resume Alan Stern
2008-12-06 21:09 ` Alan Cox
2008-12-06 21:50 ` Rafael J. Wysocki
2008-12-06 14:07 ` [PATCH 2/3] PCI: Suspend and resume PCI Express ports with interrupts disabled Rafael J. Wysocki
2008-12-06 14:09 ` [PATCH 3/3] Sound (HDA Intel): Restore PCI configuration space with interrupts off Rafael J. Wysocki
[not found] ` <200812061508.00277.rjw@sisk.pl>
2008-12-06 17:15 ` [PATCH 2/3] PCI: Suspend and resume PCI Express ports with interrupts disabled Linus Torvalds
[not found] ` <alpine.LFD.2.00.0812060914100.3425@nehalem.linux-foundation.org>
2008-12-06 17:25 ` Rafael J. Wysocki
[not found] ` <200812061825.59914.rjw@sisk.pl>
2008-12-06 17:38 ` Linus Torvalds
[not found] ` <alpine.LFD.2.00.0812060933430.3425@nehalem.linux-foundation.org>
2008-12-06 17:46 ` Rafael J. Wysocki
[not found] ` <200812061846.12167.rjw@sisk.pl>
2008-12-07 2:18 ` Jesse Barnes
[not found] ` <200812061818.55115.jbarnes@virtuousgeek.org>
2008-12-07 12:53 ` Rafael J. Wysocki
2008-12-06 19:30 ` [PATCH 0/3] Fix hibernation regression on Toshiba Portege R500 Frans Pop
[not found] ` <200812061509.08994.rjw@sisk.pl>
2008-12-07 4:45 ` [PATCH 3/3] Sound (HDA Intel): Restore PCI configuration space with interrupts off Jesse Barnes
[not found] ` <200812062045.35689.jbarnes@virtuousgeek.org>
2008-12-07 9:47 ` Takashi Iwai
[not found] ` <s5hbpvoxqnn.wl%tiwai@suse.de>
2008-12-11 7:07 ` Takashi Iwai
[not found] ` <s5htz9bgpgl.wl%tiwai@suse.de>
2008-12-11 20:03 ` Rafael J. Wysocki
[not found] ` <200812112103.17018.rjw@sisk.pl>
2008-12-11 20:27 ` Takashi Iwai
[not found] ` <s5h7i66v4nb.wl%tiwai@suse.de>
2008-12-11 20:38 ` Rafael J. Wysocki
[not found] ` <200812112138.57145.rjw@sisk.pl>
2008-12-12 6:32 ` Takashi Iwai
[not found] <Pine.LNX.4.44L0.0812061324260.13426-100000@netrider.rowland.org>
2008-12-06 21:36 ` [PATCH 1/3] PCI: Rework default handling of suspend and resume Rafael J. Wysocki
2008-12-06 22:24 ` Linus Torvalds
[not found] ` <alpine.LFD.2.00.0812061420190.3425@nehalem.linux-foundation.org>
2008-12-06 23:25 ` Arjan van de Ven
[not found] ` <20081206152545.326c8b67@infradead.org>
2008-12-06 23:35 ` Alan Cox
2008-12-07 6:00 ` Linus Torvalds
[not found] ` <alpine.LFD.2.00.0812062157590.3425@nehalem.linux-foundation.org>
2008-12-07 6:03 ` Linus Torvalds
2008-12-07 9:44 ` Takashi Iwai
[not found] ` <s5hd4g4xqso.wl%tiwai@suse.de>
2008-12-07 12:30 ` Rafael J. Wysocki
[not found] ` <alpine.LFD.2.00.0812062201230.3425@nehalem.linux-foundation.org>
2008-12-07 13:39 ` Rafael J. Wysocki
[not found] ` <200812071439.27712.rjw@sisk.pl>
2008-12-07 16:34 ` Linus Torvalds
2008-12-07 17:18 ` Arjan van de Ven
[not found] ` <alpine.LFD.2.00.0812070824260.3425@nehalem.linux-foundation.org>
2008-12-14 9:28 ` Pavel Machek
2008-12-07 0:02 ` Alan Stern
[not found] <Pine.LNX.4.44L0.0812061858160.16554-100000@netrider.rowland.org>
2008-12-07 13:14 ` Rafael J. Wysocki
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=200812061507.06474.rjw@sisk.pl \
--to=rjw@sisk.pl \
--cc=akpm@linux-foundation.org \
--cc=greg@kroah.com \
--cc=jbarnes@virtuousgeek.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@lists.linux-foundation.org \
--cc=mingo@elte.hu \
--cc=tiwai@suse.de \
--cc=torvalds@linux-foundation.org \
/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: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox