diff options
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 72 |
1 files changed, 39 insertions, 33 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 60230da957e0..59c01d68c6d5 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; } @@ -1290,7 +1291,7 @@ end: * * Call pci_power_up() to put @dev into D0, read from its PCI_PM_CTRL register * to confirm the state change, restore its BARs if they might be lost and - * reconfigure ASPM in acordance with the new power state. + * reconfigure ASPM in accordance with the new power state. * * If pci_restore_state() is going to be called right after a power state change * to D0, it is more efficient to use pci_power_up() directly instead of this @@ -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; @@ -1681,7 +1686,7 @@ int pci_save_state(struct pci_dev *dev) /* XXX: 100% dword access ok here? */ for (i = 0; i < 16; i++) { pci_read_config_dword(dev, i * 4, &dev->saved_config_space[i]); - pci_dbg(dev, "saving config space at offset %#x (reading %#x)\n", + pci_dbg(dev, "save config %#04x: %#010x\n", i * 4, dev->saved_config_space[i]); } dev->state_saved = true; @@ -1712,7 +1717,7 @@ static void pci_restore_config_dword(struct pci_dev *pdev, int offset, return; for (;;) { - pci_dbg(pdev, "restoring config space at offset %#x (was %#x, writing %#x)\n", + pci_dbg(pdev, "restore config %#04x: %#010x -> %#010x\n", offset, val, saved_val); pci_write_config_dword(pdev, offset, saved_val); if (retry-- <= 0) @@ -2415,10 +2420,13 @@ static void pci_pme_list_scan(struct work_struct *work) mutex_lock(&pci_pme_list_mutex); list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) { - if (pme_dev->dev->pme_poll) { - struct pci_dev *bridge; + struct pci_dev *pdev = pme_dev->dev; + + if (pdev->pme_poll) { + struct pci_dev *bridge = pdev->bus->self; + struct device *dev = &pdev->dev; + int pm_status; - bridge = pme_dev->dev->bus->self; /* * If bridge is in low power state, the * configuration space of subordinate devices @@ -2426,14 +2434,20 @@ static void pci_pme_list_scan(struct work_struct *work) */ if (bridge && bridge->current_state != PCI_D0) continue; + /* - * If the device is in D3cold it should not be - * polled either. + * If the device is in a low power state it + * should not be polled either. */ - if (pme_dev->dev->current_state == PCI_D3cold) + pm_status = pm_runtime_get_if_active(dev, true); + if (!pm_status) continue; - pci_pme_wakeup(pme_dev->dev, NULL); + if (pdev->current_state != PCI_D3cold) + pci_pme_wakeup(pdev, NULL); + + if (pm_status > 0) + pm_runtime_put(dev); } else { list_del(&pme_dev->list); kfree(pme_dev); @@ -4191,16 +4205,12 @@ int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr, phys_addr_t pci_pio_to_address(unsigned long pio) { - phys_addr_t address = (phys_addr_t)OF_BAD_ADDR; - #ifdef PCI_IOBASE - if (pio >= MMIO_UPPER_LIMIT) - return address; - - address = logic_pio_to_hwaddr(pio); + if (pio < MMIO_UPPER_LIMIT) + return logic_pio_to_hwaddr(pio); #endif - return address; + return (phys_addr_t) OF_BAD_ADDR; } EXPORT_SYMBOL_GPL(pci_pio_to_address); @@ -4927,7 +4937,6 @@ static int pcie_wait_for_link_status(struct pci_dev *pdev, int pcie_retrain_link(struct pci_dev *pdev, bool use_lt) { int rc; - u16 lnkctl; /* * Ensure the updated LNKCTL parameters are used during link @@ -4939,17 +4948,14 @@ int pcie_retrain_link(struct pci_dev *pdev, bool use_lt) if (rc) return rc; - pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnkctl); - lnkctl |= PCI_EXP_LNKCTL_RL; - pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnkctl); + pcie_capability_set_word(pdev, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_RL); if (pdev->clear_retrain_link) { /* * Due to an erratum in some devices the Retrain Link bit * needs to be cleared again manually to allow the link * training to succeed. */ - lnkctl &= ~PCI_EXP_LNKCTL_RL; - pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnkctl); + pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_RL); } return pcie_wait_for_link_status(pdev, use_lt, !use_lt); @@ -5631,7 +5637,7 @@ int pci_try_reset_function(struct pci_dev *dev) EXPORT_SYMBOL_GPL(pci_try_reset_function); /* Do any devices on or below this bus prevent a bus reset? */ -static bool pci_bus_resetable(struct pci_bus *bus) +static bool pci_bus_resettable(struct pci_bus *bus) { struct pci_dev *dev; @@ -5641,7 +5647,7 @@ static bool pci_bus_resetable(struct pci_bus *bus) list_for_each_entry(dev, &bus->devices, bus_list) { if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || - (dev->subordinate && !pci_bus_resetable(dev->subordinate))) + (dev->subordinate && !pci_bus_resettable(dev->subordinate))) return false; } @@ -5699,7 +5705,7 @@ unlock: } /* Do any devices on or below this slot prevent a bus reset? */ -static bool pci_slot_resetable(struct pci_slot *slot) +static bool pci_slot_resettable(struct pci_slot *slot) { struct pci_dev *dev; @@ -5711,7 +5717,7 @@ static bool pci_slot_resetable(struct pci_slot *slot) if (!dev->slot || dev->slot != slot) continue; if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || - (dev->subordinate && !pci_bus_resetable(dev->subordinate))) + (dev->subordinate && !pci_bus_resettable(dev->subordinate))) return false; } @@ -5847,7 +5853,7 @@ static int pci_slot_reset(struct pci_slot *slot, bool probe) { int rc; - if (!slot || !pci_slot_resetable(slot)) + if (!slot || !pci_slot_resettable(slot)) return -ENOTTY; if (!probe) @@ -5914,7 +5920,7 @@ static int pci_bus_reset(struct pci_bus *bus, bool probe) { int ret; - if (!bus->self || !pci_bus_resetable(bus)) + if (!bus->self || !pci_bus_resettable(bus)) return -ENOTTY; if (probe) |