Commit a477b9cd authored by Marc Zyngier's avatar Marc Zyngier Committed by Bjorn Helgaas

PCI: Add pci_reset_function_locked()

The implementation of PCI workarounds may require that the device is reset
from its probe function.  This implies that the PCI device lock is already
held, and makes calling pci_reset_function() impossible (since it will
itself try to take that lock).

Add pci_reset_function_locked(), which is the equivalent of
pci_reset_function(), except that it requires the PCI device lock to be
already held by the caller.
Tested-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
[bhelgaas: folded in fix for conflict with 52354b9d ("PCI: Remove
__pci_dev_reset() and pci_dev_reset()")]
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Cc: stable@vger.kernel.org	# 4.11: 52354b9d: PCI: Remove __pci_dev_reset() and pci_dev_reset()
Cc: stable@vger.kernel.org	# 4.11
parent 16f73eb0
...@@ -4259,6 +4259,41 @@ int pci_reset_function(struct pci_dev *dev) ...@@ -4259,6 +4259,41 @@ int pci_reset_function(struct pci_dev *dev)
} }
EXPORT_SYMBOL_GPL(pci_reset_function); EXPORT_SYMBOL_GPL(pci_reset_function);
/**
* pci_reset_function_locked - quiesce and reset a PCI device function
* @dev: PCI device to reset
*
* Some devices allow an individual function to be reset without affecting
* other functions in the same device. The PCI device must be responsive
* to PCI config space in order to use this function.
*
* This function does not just reset the PCI portion of a device, but
* clears all the state associated with the device. This function differs
* from __pci_reset_function() in that it saves and restores device state
* over the reset. It also differs from pci_reset_function() in that it
* requires the PCI device lock to be held.
*
* Returns 0 if the device function was successfully reset or negative if the
* device doesn't support resetting a single function.
*/
int pci_reset_function_locked(struct pci_dev *dev)
{
int rc;
rc = pci_probe_reset_function(dev);
if (rc)
return rc;
pci_dev_save_and_disable(dev);
rc = __pci_reset_function_locked(dev);
pci_dev_restore(dev);
return rc;
}
EXPORT_SYMBOL_GPL(pci_reset_function_locked);
/** /**
* pci_try_reset_function - quiesce and reset a PCI device function * pci_try_reset_function - quiesce and reset a PCI device function
* @dev: PCI device to reset * @dev: PCI device to reset
......
...@@ -1067,6 +1067,7 @@ void pcie_flr(struct pci_dev *dev); ...@@ -1067,6 +1067,7 @@ void pcie_flr(struct pci_dev *dev);
int __pci_reset_function(struct pci_dev *dev); int __pci_reset_function(struct pci_dev *dev);
int __pci_reset_function_locked(struct pci_dev *dev); int __pci_reset_function_locked(struct pci_dev *dev);
int pci_reset_function(struct pci_dev *dev); int pci_reset_function(struct pci_dev *dev);
int pci_reset_function_locked(struct pci_dev *dev);
int pci_try_reset_function(struct pci_dev *dev); int pci_try_reset_function(struct pci_dev *dev);
int pci_probe_reset_slot(struct pci_slot *slot); int pci_probe_reset_slot(struct pci_slot *slot);
int pci_reset_slot(struct pci_slot *slot); int pci_reset_slot(struct pci_slot *slot);
......
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