Commit 45144d42 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

PCI: PM: Fix pci_power_up()

There is an arbitrary difference between the system resume and
runtime resume code paths for PCI devices regarding the delay to
apply when switching the devices from D3cold to D0.

Namely, pci_restore_standard_config() used in the runtime resume
code path calls pci_set_power_state() which in turn invokes
__pci_start_power_transition() to power up the device through the
platform firmware and that function applies the transition delay
(as per PCI Express Base Specification Revision 2.0, Section 6.6.1).
However, pci_pm_default_resume_early() used in the system resume
code path calls pci_power_up() which doesn't apply the delay at
all and that causes issues to occur during resume from
suspend-to-idle on some systems where the delay is required.

Since there is no reason for that difference to exist, modify
pci_power_up() to follow pci_set_power_state() more closely and
invoke __pci_start_power_transition() from there to call the
platform firmware to power up the device (in case that's necessary).

Fixes: db288c9c ("PCI / PM: restore the original behavior of pci_set_power_state()")
Reported-by: default avatarDaniel Drake <drake@endlessm.com>
Tested-by: default avatarDaniel Drake <drake@endlessm.com>
Link: https://lore.kernel.org/linux-pm/CAD8Lp44TYxrMgPLkHCqF9hv6smEurMXvmmvmtyFhZ6Q4SE+dig@mail.gmail.com/T/#m21be74af263c6a34f36e0fc5c77c5449d9406925Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Cc: 3.10+ <stable@vger.kernel.org> # 3.10+
parent 4f5cafb5
...@@ -958,19 +958,6 @@ void pci_refresh_power_state(struct pci_dev *dev) ...@@ -958,19 +958,6 @@ void pci_refresh_power_state(struct pci_dev *dev)
pci_update_current_state(dev, dev->current_state); pci_update_current_state(dev, dev->current_state);
} }
/**
* pci_power_up - Put the given device into D0 forcibly
* @dev: PCI device to power up
*/
void pci_power_up(struct pci_dev *dev)
{
if (platform_pci_power_manageable(dev))
platform_pci_set_power_state(dev, PCI_D0);
pci_raw_set_power_state(dev, PCI_D0);
pci_update_current_state(dev, PCI_D0);
}
/** /**
* pci_platform_power_transition - Use platform to change device power state * pci_platform_power_transition - Use platform to change device power state
* @dev: PCI device to handle. * @dev: PCI device to handle.
...@@ -1153,6 +1140,17 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) ...@@ -1153,6 +1140,17 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
} }
EXPORT_SYMBOL(pci_set_power_state); EXPORT_SYMBOL(pci_set_power_state);
/**
* pci_power_up - Put the given device into D0 forcibly
* @dev: PCI device to power up
*/
void pci_power_up(struct pci_dev *dev)
{
__pci_start_power_transition(dev, PCI_D0);
pci_raw_set_power_state(dev, PCI_D0);
pci_update_current_state(dev, PCI_D0);
}
/** /**
* pci_choose_state - Choose the power state of a PCI device * pci_choose_state - Choose the power state of a PCI device
* @dev: PCI device to be suspended * @dev: PCI device to be suspended
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment