From: Greg Kroah-Hartman <gregkh@suse.de>
To: linux-kernel@vger.kernel.org
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>,
Jesse Barnes <jbarnes@virtuousgeek.org>,
Greg Kroah-Hartman <gregkh@suse.de>
Subject: [PATCH 10/60] PCI: Rework default handling of suspend and resume
Date: Tue, 6 Jan 2009 14:11:29 -0800 [thread overview]
Message-ID: <1231279939-32728-10-git-send-email-gregkh@suse.de> (raw)
In-Reply-To: <20090106221123.GA32689@kroah.com>
From: Rafael J. Wysocki <rjw@sisk.pl>
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>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
drivers/pci/pci-driver.c | 94 +++++++++++++++++++++++++++++++---------------
1 files changed, 63 insertions(+), 31 deletions(-)
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 4042d21..99d867b 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -300,6 +300,14 @@ static void pci_device_shutdown(struct device *dev)
#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(struct pci_dev *pci_dev)
/*
* 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 device *dev)
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 *dev)
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);
@@ -433,6 +449,7 @@ static int pci_pm_suspend(struct device *dev)
static int pci_pm_suspend_noirq(struct device *dev)
{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
int error = 0;
@@ -441,8 +458,10 @@ static int pci_pm_suspend_noirq(struct device *dev)
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;
@@ -452,15 +471,17 @@ static int pci_pm_resume(struct device *dev)
{
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;
@@ -468,6 +489,7 @@ static int pci_pm_resume(struct device *dev)
static int pci_pm_resume_noirq(struct device *dev)
{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
int error = 0;
@@ -476,8 +498,10 @@ static int pci_pm_resume_noirq(struct device *dev)
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;
@@ -504,10 +528,8 @@ static int pci_pm_freeze(struct device *dev)
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);
}
@@ -517,6 +539,7 @@ static int pci_pm_freeze(struct device *dev)
static int pci_pm_freeze_noirq(struct device *dev)
{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
int error = 0;
@@ -525,8 +548,10 @@ static int pci_pm_freeze_noirq(struct device *dev)
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;
@@ -534,14 +559,15 @@ static int pci_pm_freeze_noirq(struct device *dev)
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);
}
@@ -550,13 +576,14 @@ static int pci_pm_thaw(struct device *dev)
static int pci_pm_thaw_noirq(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_noirq)
error = drv->pm->thaw_noirq(dev);
- } else {
+ } else if (pci_has_legacy_pm_support(pci_dev)) {
pci_fixup_device(pci_fixup_resume_early, to_pci_dev(dev));
error = pci_legacy_resume_early(dev);
}
@@ -566,17 +593,18 @@ static int pci_pm_thaw_noirq(struct device *dev)
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);
}
@@ -593,7 +621,7 @@ static int pci_pm_poweroff_noirq(struct device *dev)
error = drv->pm->poweroff_noirq(dev);
suspend_report_result(drv->pm->poweroff_noirq, error);
}
- } else {
+ } else if (pci_has_legacy_pm_support(to_pci_dev(dev))) {
error = pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
}
@@ -604,13 +632,15 @@ static int pci_pm_restore(struct device *dev)
{
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);
@@ -628,8 +658,10 @@ static int pci_pm_restore_noirq(struct device *dev)
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);
--
1.6.0.4
next prev parent reply other threads:[~2009-01-06 22:16 UTC|newest]
Thread overview: 69+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-06 22:11 [GIT PATCH] driver core patches for your 2.6-git tree Greg KH
2009-01-06 22:11 ` [PATCH 01/60] PM: Simplify the new suspend/hibernation framework for devices Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 02/60] Fix misspellings in pm.h macros Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 03/60] driver core: Rearrange struct device for better packing Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 04/60] driver core: Remove completion from struct klist_node Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 05/60] driver core: struct device - replace bus_id with dev_name(), dev_set_name() Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 06/60] sysfs: clarify SYSFS_DEPRECATED help text Greg Kroah-Hartman
2009-01-07 9:21 ` Mikael Pettersson
2009-01-07 19:38 ` Greg KH
2009-01-06 22:11 ` [PATCH 07/60] uevent: don't pass envp_ext[] as format string in kobject_uevent_env() Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 08/60] kobject: return the result of uevent sending by netlink Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 09/60] kernel/ksysfs.c:fix dependence on CONFIG_NET Greg Kroah-Hartman
2009-01-06 22:11 ` Greg Kroah-Hartman [this message]
2009-01-06 22:11 ` [PATCH 11/60] kobject: Make Documentation/kobject.txt a little more coherent Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 12/60] dynamic_printk: reduce one level of indentation Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 13/60] driver core: create a private portion of struct device Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 14/60] driver core: move klist_children into private structure Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 15/60] driver core: move knode_driver " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 16/60] driver core: move knode_bus " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 17/60] Make DEBUG take precedence over DYNAMIC_PRINTK_DEBUG Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 18/60] Driver core: move the bus notifier call points Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 19/60] driver core:fix duplicate removing driver link in __device_release_driver Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 20/60] driver core: add root_device_register() Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 21/60] virtio: do not statically allocate root device Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 22/60] lguest: " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 23/60] s390: remove s390_root_dev_*() Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 24/60] xen: struct device - replace bus_id with dev_name(), dev_set_name() Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 25/60] w1: " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 26/60] video: " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 27/60] tifm: " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 28/60] thermal: " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 29/60] swiotlb: " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 30/60] spi: " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 31/60] SGI: " Greg Kroah-Hartman
2009-01-06 23:03 ` Jack Steiner
2009-01-06 22:11 ` [PATCH 32/60] serial: " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 33/60] power-supply: " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 34/60] pnp: " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 35/60] mwave: " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 36/60] mtd: " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 37/60] mips: " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 38/60] memstick: " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 39/60] macintosh: " Greg Kroah-Hartman
2009-01-06 22:11 ` [PATCH 40/60] pm: " Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 41/60] ISDN: " Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 42/60] infiniband: " Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 43/60] i7300_idle: " Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 44/60] IA64: " Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 45/60] i2o: " Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 46/60] hwmon: " Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 47/60] gpu: " Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 48/60] gpio: " Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 49/60] gadget: " Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 50/60] dmi: " Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 51/60] chris: " Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 52/60] block: " Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 53/60] avr: " Greg Kroah-Hartman
2009-01-07 8:54 ` Haavard Skinnemoen
2009-01-07 19:36 ` Greg KH
2009-01-06 22:12 ` [PATCH 54/60] libata: " Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 55/60] arm: " Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 56/60] UIO: use pci_ioremap_bar() in drivers/uio Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 57/60] UIO: uio_pdrv_genirq: allow custom irq_flags Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 58/60] UIO: Pass information about ioports to userspace (V2) Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 59/60] UIO: Documentation for UIO ioport info handling Greg Kroah-Hartman
2009-01-06 22:12 ` [PATCH 60/60] uio: make uio_info's name and version const Greg Kroah-Hartman
2009-01-06 23:23 ` [GIT PATCH] driver core patches for your 2.6-git tree Hans J. Koch
2009-01-07 0:36 ` Greg KH
2009-01-07 11:33 ` [PATCH 41/60] ISDN: struct device - replace bus_id with dev_name(), dev_set_name() Karsten Keil
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=1231279939-32728-10-git-send-email-gregkh@suse.de \
--to=gregkh@suse.de \
--cc=jbarnes@virtuousgeek.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rjw@sisk.pl \
/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
all inboxes | Powered by JetHome®