diff options
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 92 |
1 files changed, 26 insertions, 66 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 77960fe9d9f3..80da4841c7d2 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4349,7 +4349,7 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) * Returns true if the device advertises support for PCIe function level * resets. */ -static bool pcie_has_flr(struct pci_dev *dev) +bool pcie_has_flr(struct pci_dev *dev) { u32 cap; @@ -4359,6 +4359,7 @@ static bool pcie_has_flr(struct pci_dev *dev) pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap); return cap & PCI_EXP_DEVCAP_FLR; } +EXPORT_SYMBOL_GPL(pcie_has_flr); /** * pcie_flr - initiate a PCIe function level reset @@ -4534,19 +4535,18 @@ void __weak pcibios_reset_secondary_bus(struct pci_dev *dev) } /** - * pci_reset_bridge_secondary_bus - Reset the secondary bus on a PCI bridge. + * pci_bridge_secondary_bus_reset - Reset the secondary bus on a PCI bridge. * @dev: Bridge device * * Use the bridge control register to assert reset on the secondary bus. * Devices on the secondary bus are left in power-on state. */ -int pci_reset_bridge_secondary_bus(struct pci_dev *dev) +int pci_bridge_secondary_bus_reset(struct pci_dev *dev) { pcibios_reset_secondary_bus(dev); return pci_dev_wait(dev, "bus reset", PCIE_RESET_READY_POLL_MS); } -EXPORT_SYMBOL_GPL(pci_reset_bridge_secondary_bus); static int pci_parent_bus_reset(struct pci_dev *dev, int probe) { @@ -4563,9 +4563,7 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe) if (probe) return 0; - pci_reset_bridge_secondary_bus(dev->bus->self); - - return 0; + return pci_bridge_secondary_bus_reset(dev->bus->self); } static int pci_reset_hotplug_slot(struct hotplug_slot *hotplug, int probe) @@ -5097,7 +5095,7 @@ int pci_probe_reset_slot(struct pci_slot *slot) EXPORT_SYMBOL_GPL(pci_probe_reset_slot); /** - * pci_reset_slot - reset a PCI slot + * __pci_reset_slot - Try to reset a PCI slot * @slot: PCI slot to reset * * A PCI bus may host multiple slots, each slot may support a reset mechanism @@ -5109,33 +5107,9 @@ EXPORT_SYMBOL_GPL(pci_probe_reset_slot); * through this function. PCI config space of all devices in the slot and * behind the slot is saved before and restored after reset. * - * Return 0 on success, non-zero on error. - */ -int pci_reset_slot(struct pci_slot *slot) -{ - int rc; - - rc = pci_slot_reset(slot, 1); - if (rc) - return rc; - - pci_slot_save_and_disable(slot); - - rc = pci_slot_reset(slot, 0); - - pci_slot_restore(slot); - - return rc; -} -EXPORT_SYMBOL_GPL(pci_reset_slot); - -/** - * pci_try_reset_slot - Try to reset a PCI slot - * @slot: PCI slot to reset - * * Same as above except return -EAGAIN if the slot cannot be locked */ -int pci_try_reset_slot(struct pci_slot *slot) +static int __pci_reset_slot(struct pci_slot *slot) { int rc; @@ -5156,10 +5130,11 @@ int pci_try_reset_slot(struct pci_slot *slot) return rc; } -EXPORT_SYMBOL_GPL(pci_try_reset_slot); static int pci_bus_reset(struct pci_bus *bus, int probe) { + int ret; + if (!bus->self || !pci_bus_resetable(bus)) return -ENOTTY; @@ -5170,11 +5145,11 @@ static int pci_bus_reset(struct pci_bus *bus, int probe) might_sleep(); - pci_reset_bridge_secondary_bus(bus->self); + ret = pci_bridge_secondary_bus_reset(bus->self); pci_bus_unlock(bus); - return 0; + return ret; } /** @@ -5190,15 +5165,12 @@ int pci_probe_reset_bus(struct pci_bus *bus) EXPORT_SYMBOL_GPL(pci_probe_reset_bus); /** - * pci_reset_bus - reset a PCI bus + * __pci_reset_bus - Try to reset a PCI bus * @bus: top level PCI bus to reset * - * Do a bus reset on the given bus and any subordinate buses, saving - * and restoring state of all devices. - * - * Return 0 on success, non-zero on error. + * Same as above except return -EAGAIN if the bus cannot be locked */ -int pci_reset_bus(struct pci_bus *bus) +static int __pci_reset_bus(struct pci_bus *bus) { int rc; @@ -5208,42 +5180,30 @@ int pci_reset_bus(struct pci_bus *bus) pci_bus_save_and_disable(bus); - rc = pci_bus_reset(bus, 0); + if (pci_bus_trylock(bus)) { + might_sleep(); + rc = pci_bridge_secondary_bus_reset(bus->self); + pci_bus_unlock(bus); + } else + rc = -EAGAIN; pci_bus_restore(bus); return rc; } -EXPORT_SYMBOL_GPL(pci_reset_bus); /** - * pci_try_reset_bus - Try to reset a PCI bus - * @bus: top level PCI bus to reset + * pci_reset_bus - Try to reset a PCI bus + * @pdev: top level PCI device to reset via slot/bus * * Same as above except return -EAGAIN if the bus cannot be locked */ -int pci_try_reset_bus(struct pci_bus *bus) +int pci_reset_bus(struct pci_dev *pdev) { - int rc; - - rc = pci_bus_reset(bus, 1); - if (rc) - return rc; - - pci_bus_save_and_disable(bus); - - if (pci_bus_trylock(bus)) { - might_sleep(); - pci_reset_bridge_secondary_bus(bus->self); - pci_bus_unlock(bus); - } else - rc = -EAGAIN; - - pci_bus_restore(bus); - - return rc; + return pci_probe_reset_slot(pdev->slot) ? + __pci_reset_slot(pdev->slot) : __pci_reset_bus(pdev->bus); } -EXPORT_SYMBOL_GPL(pci_try_reset_bus); +EXPORT_SYMBOL_GPL(pci_reset_bus); /** * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count |