All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC][PATCH 1/3] PCI: Clear saved_state after the state has been restored
       [not found] <200909070102.21056.rjw@sisk.pl>
@ 2009-09-06 23:03 ` Rafael J. Wysocki
  2009-09-06 23:04 ` [RFC][PATCH 2/3] PCI PM: Return error codes from pci_pm_resume() Rafael J. Wysocki
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Rafael J. Wysocki @ 2009-09-06 23:03 UTC (permalink / raw)
  To: linux-pci; +Cc: pm list, Jesse Barnes

From: Rafael J. Wysocki <rjw@sisk.pl>

Some PCI devices fail if their standard configuration registers are
restored twice in a row.  Prevent this from happening by making
pci_restore_state() clear the saved_state flag of the device right
after the device's standard configuration registers have been
populated with the previously saved values.

Simplify PCI PM callbacks by removing the direct clearing of
state_saved from them, as it shouldn't be necessary any more.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
 drivers/pci/pci-driver.c |    9 ---------
 drivers/pci/pci.c        |    3 +++
 drivers/pci/probe.c      |    3 +++
 3 files changed, 6 insertions(+), 9 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
@@ -417,8 +417,6 @@ static int pci_legacy_suspend(struct dev
 	struct pci_dev * pci_dev = to_pci_dev(dev);
 	struct pci_driver * drv = pci_dev->driver;
 
-	pci_dev->state_saved = false;
-
 	if (drv && drv->suspend) {
 		pci_power_t prev = pci_dev->current_state;
 		int error;
@@ -514,7 +512,6 @@ static int pci_restore_standard_config(s
 static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev)
 {
 	pci_restore_standard_config(pci_dev);
-	pci_dev->state_saved = false;
 	pci_fixup_device(pci_fixup_resume_early, pci_dev);
 }
 
@@ -580,8 +577,6 @@ static int pci_pm_suspend(struct device 
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_suspend(dev, PMSG_SUSPEND);
 
-	pci_dev->state_saved = false;
-
 	if (!pm) {
 		pci_pm_default_suspend(pci_dev);
 		goto Fixup;
@@ -716,8 +711,6 @@ static int pci_pm_freeze(struct device *
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_suspend(dev, PMSG_FREEZE);
 
-	pci_dev->state_saved = false;
-
 	if (!pm) {
 		pci_pm_default_suspend(pci_dev);
 		return 0;
@@ -804,8 +797,6 @@ static int pci_pm_poweroff(struct device
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_suspend(dev, PMSG_HIBERNATE);
 
-	pci_dev->state_saved = false;
-
 	if (!pm) {
 		pci_pm_default_suspend(pci_dev);
 		goto Fixup;
Index: linux-2.6/drivers/pci/pci.c
===================================================================
--- linux-2.6.orig/drivers/pci/pci.c
+++ linux-2.6/drivers/pci/pci.c
@@ -852,6 +852,7 @@ pci_restore_state(struct pci_dev *dev)
 
 	if (!dev->state_saved)
 		return 0;
+
 	/* PCI Express register must be restored first */
 	pci_restore_pcie_state(dev);
 
@@ -873,6 +874,8 @@ pci_restore_state(struct pci_dev *dev)
 	pci_restore_msi_state(dev);
 	pci_restore_iov_state(dev);
 
+	dev->state_saved = false;
+
 	return 0;
 }
 
Index: linux-2.6/drivers/pci/probe.c
===================================================================
--- linux-2.6.orig/drivers/pci/probe.c
+++ linux-2.6/drivers/pci/probe.c
@@ -1009,6 +1009,9 @@ void pci_device_add(struct pci_dev *dev,
 	/* Fix up broken headers */
 	pci_fixup_device(pci_fixup_header, dev);
 
+	/* Clear the state_saved flag. */
+	dev->state_saved = false;
+
 	/* Initialize various capabilities */
 	pci_init_capabilities(dev);
 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC][PATCH 2/3] PCI PM: Return error codes from pci_pm_resume()
       [not found] <200909070102.21056.rjw@sisk.pl>
  2009-09-06 23:03 ` [RFC][PATCH 1/3] PCI: Clear saved_state after the state has been restored Rafael J. Wysocki
@ 2009-09-06 23:04 ` Rafael J. Wysocki
  2009-09-06 23:05 ` [RFC][PATCH 3/3] PCI PM: Run-time callbacks for PCI bus type Rafael J. Wysocki
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Rafael J. Wysocki @ 2009-09-06 23:04 UTC (permalink / raw)
  To: linux-pci; +Cc: pm list, Jesse Barnes

From: Rafael J. Wysocki <rjw@sisk.pl>

Currently pci_pm_resume() always returns 0, which makes the error
variable defined in there a bit pointless.  Make pci_pm_resume()
return error codes from drivers' callbacks.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
 drivers/pci/pci-driver.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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
@@ -689,7 +689,7 @@ static int pci_pm_resume(struct device *
 		pci_pm_reenable_device(pci_dev);
 	}
 
-	return 0;
+	return error;
 }
 
 #else /* !CONFIG_SUSPEND */

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC][PATCH 3/3] PCI PM: Run-time callbacks for PCI bus type
       [not found] <200909070102.21056.rjw@sisk.pl>
  2009-09-06 23:03 ` [RFC][PATCH 1/3] PCI: Clear saved_state after the state has been restored Rafael J. Wysocki
  2009-09-06 23:04 ` [RFC][PATCH 2/3] PCI PM: Return error codes from pci_pm_resume() Rafael J. Wysocki
@ 2009-09-06 23:05 ` Rafael J. Wysocki
       [not found] ` <200909070105.25835.rjw@sisk.pl>
       [not found] ` <200909070103.20731.rjw@sisk.pl>
  4 siblings, 0 replies; 6+ messages in thread
From: Rafael J. Wysocki @ 2009-09-06 23:05 UTC (permalink / raw)
  To: linux-pci; +Cc: pm list, Jesse Barnes

From: Rafael J. Wysocki <rjw@sisk.pl>

Introduce run-time PM callbacks for the PCI bus type.  Make the new
callbacks work in analogy with the existing system sleep PM
callbacks, so that the drivers already converted to struct dev_pm_ops
can use their suspend and resume routines for run-time PM without
modifications.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
 drivers/pci/pci-driver.c |   96 ++++++++++++++++++++++++++++++++++++++++++++---
 kernel/power/Kconfig     |    5 ++
 2 files changed, 96 insertions(+), 5 deletions(-)

Index: linux-2.6/kernel/power/Kconfig
===================================================================
--- linux-2.6.orig/kernel/power/Kconfig
+++ linux-2.6/kernel/power/Kconfig
@@ -236,3 +236,8 @@ config PM_RUNTIME
 	  and the bus type drivers of the buses the devices are on are
 	  responsible for the actual handling of the autosuspend requests and
 	  wake-up events.
+
+config PM_OPERATIONS
+	bool
+	depends on PM_SLEEP || PM_RUNTIME
+	default y
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
@@ -509,7 +509,7 @@ static int pci_restore_standard_config(s
 	return pci_restore_state(pci_dev);
 }
 
-static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev)
+static void pci_pm_default_resume_early(struct pci_dev *pci_dev)
 {
 	pci_restore_standard_config(pci_dev);
 	pci_fixup_device(pci_fixup_resume_early, pci_dev);
@@ -653,7 +653,7 @@ static int pci_pm_resume_noirq(struct de
 	struct device_driver *drv = dev->driver;
 	int error = 0;
 
-	pci_pm_default_resume_noirq(pci_dev);
+	pci_pm_default_resume_early(pci_dev);
 
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_resume_early(dev);
@@ -849,7 +849,7 @@ static int pci_pm_restore_noirq(struct d
 	struct device_driver *drv = dev->driver;
 	int error = 0;
 
-	pci_pm_default_resume_noirq(pci_dev);
+	pci_pm_default_resume_early(pci_dev);
 
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_resume_early(dev);
@@ -901,6 +901,89 @@ static int pci_pm_restore(struct device 
 
 #endif /* !CONFIG_HIBERNATION */
 
+#endif /* !CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM_RUNTIME
+
+static int pci_pm_runtime_suspend(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	pci_power_t prev = pci_dev->current_state;
+	int error;
+
+	if (!pm || !pm->runtime_suspend)
+		return -ENOSYS;
+
+	error = pm->runtime_suspend(dev);
+	suspend_report_result(pm->runtime_suspend, error);
+	if (error)
+		return error;
+
+	pci_fixup_device(pci_fixup_suspend, pci_dev);
+
+	if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
+	    && pci_dev->current_state != PCI_UNKNOWN) {
+		WARN_ONCE(pci_dev->current_state != prev,
+			"PCI PM: State of device not saved by %pF\n",
+			pm->runtime_suspend);
+		return 0;
+	}
+
+	if (!pci_dev->state_saved) {
+		pci_save_state(pci_dev);
+		if (!pci_is_bridge(pci_dev))
+			pci_prepare_to_sleep(pci_dev);
+	}
+
+	pci_pm_set_unknown_state(pci_dev);
+
+	return 0;
+}
+
+static int pci_pm_runtime_resume(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	int error;
+
+	if (!pm || !pm->runtime_resume)
+		return -ENOSYS;
+
+	pci_pm_default_resume_early(pci_dev);
+	pci_pm_default_resume(pci_dev);
+
+	return pm->runtime_resume(dev);
+}
+
+static int pci_pm_runtime_idle(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (!pm)
+		return -ENOSYS;
+
+	if (pm->runtime_idle) {
+		int ret = pm->runtime_idle(dev);
+		if (ret)
+			return ret;
+	}
+
+	pm_runtime_suspend(dev);
+
+	return 0;
+}
+
+#else /* !CONFIG_PM_RUNTIME */
+
+#define pci_pm_runtime_suspend	NULL
+#define pci_pm_runtime_resume	NULL
+#define pci_pm_runtime_idle	NULL
+
+#endif /* !CONFIG_PM_RUNTIME */
+
+#ifdef COMFIG_PM_OPERATIONS
+
 const struct dev_pm_ops pci_dev_pm_ops = {
 	.prepare = pci_pm_prepare,
 	.complete = pci_pm_complete,
@@ -916,15 +999,18 @@ const struct dev_pm_ops pci_dev_pm_ops =
 	.thaw_noirq = pci_pm_thaw_noirq,
 	.poweroff_noirq = pci_pm_poweroff_noirq,
 	.restore_noirq = pci_pm_restore_noirq,
+	.runtime_suspend = pci_pm_runtime_suspend,
+	.runtime_resume = pci_pm_runtime_resume,
+	.runtime_idle = pci_pm_runtime_idle,
 };
 
 #define PCI_PM_OPS_PTR	(&pci_dev_pm_ops)
 
-#else /* !CONFIG_PM_SLEEP */
+#else /* !COMFIG_PM_OPERATIONS */
 
 #define PCI_PM_OPS_PTR	NULL
 
-#endif /* !CONFIG_PM_SLEEP */
+#endif /* !COMFIG_PM_OPERATIONS */
 
 /**
  * __pci_register_driver - register a new pci driver

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC][PATCH 3/3] PCI PM: Run-time callbacks for PCI bus type
       [not found] ` <200909070105.25835.rjw@sisk.pl>
@ 2009-09-07  1:56   ` Alan Stern
  2009-09-07 23:22   ` [RFC][PATCH 3/3 update] " Rafael J. Wysocki
  1 sibling, 0 replies; 6+ messages in thread
From: Alan Stern @ 2009-09-07  1:56 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: linux-pci, pm list, Jesse Barnes

On Mon, 7 Sep 2009, Rafael J. Wysocki wrote:

> From: Rafael J. Wysocki <rjw@sisk.pl>
> 
> Introduce run-time PM callbacks for the PCI bus type.  Make the new
> callbacks work in analogy with the existing system sleep PM
> callbacks, so that the drivers already converted to struct dev_pm_ops
> can use their suspend and resume routines for run-time PM without
> modifications.

Do you want to arrange things so that PCI devices with no driver will 
get runtime-suspended by default?

Alan Stern

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC][PATCH 3/3 update] PCI PM: Run-time callbacks for PCI bus type
       [not found] ` <200909070105.25835.rjw@sisk.pl>
  2009-09-07  1:56   ` Alan Stern
@ 2009-09-07 23:22   ` Rafael J. Wysocki
  1 sibling, 0 replies; 6+ messages in thread
From: Rafael J. Wysocki @ 2009-09-07 23:22 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-pci, Jesse Barnes

From: Rafael J. Wysocki <rjw@sisk.pl>
Subject: PCI PM: Run-time callbacks for PCI bus type

Introduce run-time PM callbacks for the PCI bus type.  Make the new
callbacks work in analogy with the existing system sleep PM
callbacks, so that the drivers already converted to struct dev_pm_ops
can use their suspend and resume routines for run-time PM without
modifications.

Not-yet-signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
Fixed compilation.

One thing is still missing from here.  Namely, when the device is being
suspended, it generally is necessary to set up the device's GPE to wake it up
and the bus type callback should take care of that (analogously, the resume
callback should switch the GPE back to the "inactive" state).

Thanks,
Rafael

---
 drivers/pci/pci-driver.c |   96 ++++++++++++++++++++++++++++++++++++++++++++---
 kernel/power/Kconfig     |    5 ++
 2 files changed, 96 insertions(+), 5 deletions(-)

Index: linux-2.6/kernel/power/Kconfig
===================================================================
--- linux-2.6.orig/kernel/power/Kconfig
+++ linux-2.6/kernel/power/Kconfig
@@ -236,3 +236,8 @@ config PM_RUNTIME
 	  and the bus type drivers of the buses the devices are on are
 	  responsible for the actual handling of the autosuspend requests and
 	  wake-up events.
+
+config PM_OPERATIONS
+	bool
+	depends on PM_SLEEP || PM_RUNTIME
+	default y
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
@@ -17,6 +17,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/cpu.h>
+#include <linux/pm_runtime.h>
 #include "pci.h"
 
 /*
@@ -509,7 +510,7 @@ static int pci_restore_standard_config(s
 	return pci_restore_state(pci_dev);
 }
 
-static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev)
+static void pci_pm_default_resume_early(struct pci_dev *pci_dev)
 {
 	pci_restore_standard_config(pci_dev);
 	pci_fixup_device(pci_fixup_resume_early, pci_dev);
@@ -653,7 +654,7 @@ static int pci_pm_resume_noirq(struct de
 	struct device_driver *drv = dev->driver;
 	int error = 0;
 
-	pci_pm_default_resume_noirq(pci_dev);
+	pci_pm_default_resume_early(pci_dev);
 
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_resume_early(dev);
@@ -851,7 +852,7 @@ static int pci_pm_restore_noirq(struct d
 	struct device_driver *drv = dev->driver;
 	int error = 0;
 
-	pci_pm_default_resume_noirq(pci_dev);
+	pci_pm_default_resume_early(pci_dev);
 
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_resume_early(dev);
@@ -903,6 +904,88 @@ static int pci_pm_restore(struct device 
 
 #endif /* !CONFIG_HIBERNATION */
 
+#endif /* !CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM_RUNTIME
+
+static int pci_pm_runtime_suspend(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	pci_power_t prev = pci_dev->current_state;
+	int error;
+
+	if (!pm || !pm->runtime_suspend)
+		return -ENOSYS;
+
+	error = pm->runtime_suspend(dev);
+	suspend_report_result(pm->runtime_suspend, error);
+	if (error)
+		return error;
+
+	pci_fixup_device(pci_fixup_suspend, pci_dev);
+
+	if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
+	    && pci_dev->current_state != PCI_UNKNOWN) {
+		WARN_ONCE(pci_dev->current_state != prev,
+			"PCI PM: State of device not saved by %pF\n",
+			pm->runtime_suspend);
+		return 0;
+	}
+
+	if (!pci_dev->state_saved) {
+		pci_save_state(pci_dev);
+		if (!pci_is_bridge(pci_dev))
+			pci_prepare_to_sleep(pci_dev);
+	}
+
+	pci_pm_set_unknown_state(pci_dev);
+
+	return 0;
+}
+
+static int pci_pm_runtime_resume(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (!pm || !pm->runtime_resume)
+		return -ENOSYS;
+
+	pci_pm_default_resume_early(pci_dev);
+	pci_pm_default_resume(pci_dev);
+
+	return pm->runtime_resume(dev);
+}
+
+static int pci_pm_runtime_idle(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (!pm)
+		return -ENOSYS;
+
+	if (pm->runtime_idle) {
+		int ret = pm->runtime_idle(dev);
+		if (ret)
+			return ret;
+	}
+
+	pm_runtime_suspend(dev);
+
+	return 0;
+}
+
+#else /* !CONFIG_PM_RUNTIME */
+
+#define pci_pm_runtime_suspend	NULL
+#define pci_pm_runtime_resume	NULL
+#define pci_pm_runtime_idle	NULL
+
+#endif /* !CONFIG_PM_RUNTIME */
+
+#ifdef CONFIG_PM_OPERATIONS
+
 const struct dev_pm_ops pci_dev_pm_ops = {
 	.prepare = pci_pm_prepare,
 	.complete = pci_pm_complete,
@@ -918,15 +1001,18 @@ const struct dev_pm_ops pci_dev_pm_ops =
 	.thaw_noirq = pci_pm_thaw_noirq,
 	.poweroff_noirq = pci_pm_poweroff_noirq,
 	.restore_noirq = pci_pm_restore_noirq,
+	.runtime_suspend = pci_pm_runtime_suspend,
+	.runtime_resume = pci_pm_runtime_resume,
+	.runtime_idle = pci_pm_runtime_idle,
 };
 
 #define PCI_PM_OPS_PTR	(&pci_dev_pm_ops)
 
-#else /* !CONFIG_PM_SLEEP */
+#else /* !COMFIG_PM_OPERATIONS */
 
 #define PCI_PM_OPS_PTR	NULL
 
-#endif /* !CONFIG_PM_SLEEP */
+#endif /* !COMFIG_PM_OPERATIONS */
 
 /**
  * __pci_register_driver - register a new pci driver

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC][PATCH 1/3 update] PCI: Clear saved_state after the state has been restored
       [not found] ` <200909070103.20731.rjw@sisk.pl>
@ 2009-09-07 23:29   ` Rafael J. Wysocki
  0 siblings, 0 replies; 6+ messages in thread
From: Rafael J. Wysocki @ 2009-09-07 23:29 UTC (permalink / raw)
  To: linux-pm; +Cc: linux-pci, Jesse Barnes

From: Rafael J. Wysocki <rjw@sisk.pl>
Subject: PCI: Clear saved_state after the state has been restored

Some PCI devices fail if their standard configuration registers are
restored twice in a row.  Prevent this from happening by making
pci_restore_state() clear the saved_state flag of the device right
after the device's standard configuration registers have been
populated with the previously saved values.

Simplify PCI PM callbacks by removing the direct clearing of
state_saved from them, as it shouldn't be necessary any more, except
in pci_pm_thaw(), where it has to be cleared to so that the values saved
during the "freeze" phase of hibernation are not used later by mistake.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---

Of course, the state_saved flag has to be cleared in pci_pm_thaw() in case
the driver doesn't restore the state saved in ->freeze() (it doesn't need to do
that).

Thanks,
Rafael

---
 drivers/pci/pci-driver.c |   11 ++---------
 drivers/pci/pci.c        |    3 +++
 drivers/pci/probe.c      |    3 +++
 3 files changed, 8 insertions(+), 9 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
@@ -417,8 +417,6 @@ static int pci_legacy_suspend(struct dev
 	struct pci_dev * pci_dev = to_pci_dev(dev);
 	struct pci_driver * drv = pci_dev->driver;
 
-	pci_dev->state_saved = false;
-
 	if (drv && drv->suspend) {
 		pci_power_t prev = pci_dev->current_state;
 		int error;
@@ -514,7 +512,6 @@ static int pci_restore_standard_config(s
 static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev)
 {
 	pci_restore_standard_config(pci_dev);
-	pci_dev->state_saved = false;
 	pci_fixup_device(pci_fixup_resume_early, pci_dev);
 }
 
@@ -580,8 +577,6 @@ static int pci_pm_suspend(struct device 
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_suspend(dev, PMSG_SUSPEND);
 
-	pci_dev->state_saved = false;
-
 	if (!pm) {
 		pci_pm_default_suspend(pci_dev);
 		goto Fixup;
@@ -716,8 +711,6 @@ static int pci_pm_freeze(struct device *
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_suspend(dev, PMSG_FREEZE);
 
-	pci_dev->state_saved = false;
-
 	if (!pm) {
 		pci_pm_default_suspend(pci_dev);
 		return 0;
@@ -793,6 +786,8 @@ static int pci_pm_thaw(struct device *de
 		pci_pm_reenable_device(pci_dev);
 	}
 
+	pci_dev->state_saved = false;
+
 	return error;
 }
 
@@ -804,8 +799,6 @@ static int pci_pm_poweroff(struct device
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_suspend(dev, PMSG_HIBERNATE);
 
-	pci_dev->state_saved = false;
-
 	if (!pm) {
 		pci_pm_default_suspend(pci_dev);
 		goto Fixup;
Index: linux-2.6/drivers/pci/pci.c
===================================================================
--- linux-2.6.orig/drivers/pci/pci.c
+++ linux-2.6/drivers/pci/pci.c
@@ -852,6 +852,7 @@ pci_restore_state(struct pci_dev *dev)
 
 	if (!dev->state_saved)
 		return 0;
+
 	/* PCI Express register must be restored first */
 	pci_restore_pcie_state(dev);
 
@@ -873,6 +874,8 @@ pci_restore_state(struct pci_dev *dev)
 	pci_restore_msi_state(dev);
 	pci_restore_iov_state(dev);
 
+	dev->state_saved = false;
+
 	return 0;
 }
 
Index: linux-2.6/drivers/pci/probe.c
===================================================================
--- linux-2.6.orig/drivers/pci/probe.c
+++ linux-2.6/drivers/pci/probe.c
@@ -1009,6 +1009,9 @@ void pci_device_add(struct pci_dev *dev,
 	/* Fix up broken headers */
 	pci_fixup_device(pci_fixup_header, dev);
 
+	/* Clear the state_saved flag. */
+	dev->state_saved = false;
+
 	/* Initialize various capabilities */
 	pci_init_capabilities(dev);
 

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2009-09-07 23:29 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <200909070102.21056.rjw@sisk.pl>
2009-09-06 23:03 ` [RFC][PATCH 1/3] PCI: Clear saved_state after the state has been restored Rafael J. Wysocki
2009-09-06 23:04 ` [RFC][PATCH 2/3] PCI PM: Return error codes from pci_pm_resume() Rafael J. Wysocki
2009-09-06 23:05 ` [RFC][PATCH 3/3] PCI PM: Run-time callbacks for PCI bus type Rafael J. Wysocki
     [not found] ` <200909070105.25835.rjw@sisk.pl>
2009-09-07  1:56   ` Alan Stern
2009-09-07 23:22   ` [RFC][PATCH 3/3 update] " Rafael J. Wysocki
     [not found] ` <200909070103.20731.rjw@sisk.pl>
2009-09-07 23:29   ` [RFC][PATCH 1/3 update] PCI: Clear saved_state after the state has been restored Rafael J. Wysocki

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.