summaryrefslogtreecommitdiff
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2023-08-29 11:03:49 -0500
committerBjorn Helgaas <bhelgaas@google.com>2023-08-29 11:03:49 -0500
commit95cddeae54b0ad962a8c1857b788b239556dec89 (patch)
treea7886b2c26f737f4486c4dc9a406ed525276d61b /drivers/pci/pci.c
parent8b524514e49670d3ab81c7dca18fdc55d82631d4 (diff)
parent5694ba13b004eea683c6d4faeb6d6e7a9636bda0 (diff)
Merge branch 'pci/pm'
- Only read PCI_PM_CTRL register when available, to avoid reading the wrong register and corrupting dev->current_state (Feiyang Chen) * pci/pm: PCI/PM: Only read PCI_PM_CTRL register when available
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index f7315b13bb82..702fe577089b 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1226,6 +1226,10 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
*
* On success, return 0 or 1, depending on whether or not it is necessary to
* restore the device's BARs subsequently (1 is returned in that case).
+ *
+ * On failure, return a negative error code. Always return failure if @dev
+ * lacks a Power Management Capability, even if the platform was able to
+ * put the device in D0 via non-PCI means.
*/
int pci_power_up(struct pci_dev *dev)
{
@@ -1242,9 +1246,6 @@ int pci_power_up(struct pci_dev *dev)
else
dev->current_state = state;
- if (state == PCI_D0)
- return 0;
-
return -EIO;
}
@@ -1302,8 +1303,12 @@ static int pci_set_full_power_state(struct pci_dev *dev)
int ret;
ret = pci_power_up(dev);
- if (ret < 0)
+ if (ret < 0) {
+ if (dev->current_state == PCI_D0)
+ return 0;
+
return ret;
+ }
pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
dev->current_state = pmcsr & PCI_PM_CTRL_STATE_MASK;