diff mbox series

[v1,2/2] PCI: PM: Resume bus after putting the bridge into D0 entirely

Message ID 1807986.atdPhlSkOF@kreacher (mailing list archive)
State Superseded
Delegated to: Bjorn Helgaas
Headers show
Series : PCI: PM: Improvements related to D3cold -> D0 transitions | expand

Commit Message

Rafael J. Wysocki April 4, 2022, 3:42 p.m. UTC
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

It is rather counter-intuitive to attempt to resume devices on a bus
segment before completing a transition of their parent bridge into
D0, so do that when the transition is complete.

This matters especially when the transition in question is not
successful, in which case it doesn't make sense to even try to
resume the child devices at all.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/pci.c |   21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

Comments

Mika Westerberg April 5, 2022, 9:54 a.m. UTC | #1
On Mon, Apr 04, 2022 at 05:42:27PM +0200, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> It is rather counter-intuitive to attempt to resume devices on a bus
> segment before completing a transition of their parent bridge into
> D0, so do that when the transition is complete.
> 
> This matters especially when the transition in question is not
> successful, in which case it doesn't make sense to even try to
> resume the child devices at all.

Good point.

> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
diff mbox series

Patch

Index: linux-pm/drivers/pci/pci.c
===================================================================
--- linux-pm.orig/drivers/pci/pci.c
+++ linux-pm/drivers/pci/pci.c
@@ -1310,15 +1310,24 @@  static int pci_dev_wait(struct pci_dev *
 int pci_power_up(struct pci_dev *dev)
 {
 	pci_power_t old_state = dev->current_state;
+	int ret;
 
 	pci_platform_power_transition(dev, PCI_D0);
+	/*
+	 * For transitions from D3hot or deeper (including unknown), force
+	 * PCI_PM_CTRL register write, D3*->D0 transition delay and BARS
+	 * restoration.
+	 */
+	if (old_state >= PCI_D3hot)
+		dev->current_state = PCI_D3hot;
 
+	ret = pci_raw_set_power_state(dev, PCI_D0);
 	/*
 	 * Mandatory power management transition delays are handled in
 	 * pci_pm_resume_noirq() and pci_pm_runtime_resume() of the
 	 * corresponding bridge.
 	 */
-	if (dev->runtime_d3cold) {
+	if (!ret && dev->runtime_d3cold) {
 		/*
 		 * When powering on a bridge from D3cold, the whole hierarchy
 		 * may be powered on into D0uninitialized state, resume them to
@@ -1327,15 +1336,7 @@  int pci_power_up(struct pci_dev *dev)
 		pci_resume_bus(dev->subordinate);
 	}
 
-	/*
-	 * For transitions from D3hot or deeper and initial power-up, force
-	 * PCI_PM_CTRL register write, D3*->D0 transition delay and BARS
-	 * restoration.
-	 */
-	if (old_state >= PCI_D3hot)
-		dev->current_state = PCI_D3hot;
-
-	return pci_raw_set_power_state(dev, PCI_D0);
+	return ret;
 }
 
 /**