aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2017-08-01 21:11:02 -0400
committerBjorn Helgaas <bhelgaas@google.com>2017-08-01 21:11:02 -0400
commita477b9cd37aa81a490dfa3265b7ff4f2c5a92463 (patch)
tree267e7a1f7da0e629dc7f8b5829f0afced68c41cf
parent16f73eb02d7e1765ccab3d2018e0bd98eb93d973 (diff)
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: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> [bhelgaas: folded in fix for conflict with 52354b9d1f46 ("PCI: Remove __pci_dev_reset() and pci_dev_reset()")] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Cc: stable@vger.kernel.org # 4.11: 52354b9d1f46: PCI: Remove __pci_dev_reset() and pci_dev_reset() Cc: stable@vger.kernel.org # 4.11
-rw-r--r--drivers/pci/pci.c35
-rw-r--r--include/linux/pci.h1
2 files changed, 36 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index af0cc3456dc1..b4b7eab29400 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4260,6 +4260,41 @@ int pci_reset_function(struct pci_dev *dev)
4260EXPORT_SYMBOL_GPL(pci_reset_function); 4260EXPORT_SYMBOL_GPL(pci_reset_function);
4261 4261
4262/** 4262/**
4263 * pci_reset_function_locked - quiesce and reset a PCI device function
4264 * @dev: PCI device to reset
4265 *
4266 * Some devices allow an individual function to be reset without affecting
4267 * other functions in the same device. The PCI device must be responsive
4268 * to PCI config space in order to use this function.
4269 *
4270 * This function does not just reset the PCI portion of a device, but
4271 * clears all the state associated with the device. This function differs
4272 * from __pci_reset_function() in that it saves and restores device state
4273 * over the reset. It also differs from pci_reset_function() in that it
4274 * requires the PCI device lock to be held.
4275 *
4276 * Returns 0 if the device function was successfully reset or negative if the
4277 * device doesn't support resetting a single function.
4278 */
4279int pci_reset_function_locked(struct pci_dev *dev)
4280{
4281 int rc;
4282
4283 rc = pci_probe_reset_function(dev);
4284 if (rc)
4285 return rc;
4286
4287 pci_dev_save_and_disable(dev);
4288
4289 rc = __pci_reset_function_locked(dev);
4290
4291 pci_dev_restore(dev);
4292
4293 return rc;
4294}
4295EXPORT_SYMBOL_GPL(pci_reset_function_locked);
4296
4297/**
4263 * pci_try_reset_function - quiesce and reset a PCI device function 4298 * pci_try_reset_function - quiesce and reset a PCI device function
4264 * @dev: PCI device to reset 4299 * @dev: PCI device to reset
4265 * 4300 *
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 4869e66dd659..a75c13673852 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1067,6 +1067,7 @@ void pcie_flr(struct pci_dev *dev);
1067int __pci_reset_function(struct pci_dev *dev); 1067int __pci_reset_function(struct pci_dev *dev);
1068int __pci_reset_function_locked(struct pci_dev *dev); 1068int __pci_reset_function_locked(struct pci_dev *dev);
1069int pci_reset_function(struct pci_dev *dev); 1069int pci_reset_function(struct pci_dev *dev);
1070int pci_reset_function_locked(struct pci_dev *dev);
1070int pci_try_reset_function(struct pci_dev *dev); 1071int pci_try_reset_function(struct pci_dev *dev);
1071int pci_probe_reset_slot(struct pci_slot *slot); 1072int pci_probe_reset_slot(struct pci_slot *slot);
1072int pci_reset_slot(struct pci_slot *slot); 1073int pci_reset_slot(struct pci_slot *slot);