diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-01-04 14:23:56 -0500 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-01-12 12:00:07 -0500 |
commit | a96d627abaac899e8bfaf18fd0578b228c9c752f (patch) | |
tree | 0ea927e4a1acb8f5a11c29642b960309c732c3a9 | |
parent | 8605c6844fb9bdf55471bb87c3ac62d44eb34e04 (diff) | |
download | op-kernel-dev-a96d627abaac899e8bfaf18fd0578b228c9c752f.zip op-kernel-dev-a96d627abaac899e8bfaf18fd0578b228c9c752f.tar.gz |
pci: Introduce __pci_reset_function_locked to be used when holding device_lock.
The use case of this is when a driver wants to call FLR when a device
is attached to it using the SysFS "bind" or "unbind" functionality.
The call chain when a user does "bind" looks as so:
echo "0000:01.07.0" > /sys/bus/pci/drivers/XXXX/bind
and ends up calling:
driver_bind:
device_lock(dev); <=== TAKES LOCK
XXXX_probe:
.. pci_enable_device()
...__pci_reset_function(), which calls
pci_dev_reset(dev, 0):
if (!0) {
device_lock(dev) <==== DEADLOCK
The __pci_reset_function_locked function allows the the drivers
'probe' function to call the "pci_reset_function" while still holding
the driver mutex lock.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r-- | drivers/pci/pci.c | 25 | ||||
-rw-r--r-- | include/linux/pci.h | 1 |
2 files changed, 26 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 97fff78..192be5d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3163,6 +3163,31 @@ int __pci_reset_function(struct pci_dev *dev) EXPORT_SYMBOL_GPL(__pci_reset_function); /** + * __pci_reset_function_locked - reset a PCI device function while holding + * the @dev mutex lock. + * @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. + * + * The device function is presumed to be unused and the caller is holding + * the device mutex lock when this function is called. + * Resetting the device will make the contents of PCI configuration space + * random, so any caller of this must be prepared to reinitialise the + * device including MSI, bus mastering, BARs, decoding IO and memory spaces, + * etc. + * + * 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) +{ + return pci_dev_reset(dev, 1); +} +EXPORT_SYMBOL_GPL(__pci_reset_function_locked); + +/** * pci_probe_reset_function - check whether the device can be safely reset * @dev: PCI device to reset * diff --git a/include/linux/pci.h b/include/linux/pci.h index a16b1df..65c2d8a 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -817,6 +817,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq); int pcie_get_mps(struct pci_dev *dev); int pcie_set_mps(struct pci_dev *dev, int mps); int __pci_reset_function(struct pci_dev *dev); +int __pci_reset_function_locked(struct pci_dev *dev); int pci_reset_function(struct pci_dev *dev); void pci_update_resource(struct pci_dev *dev, int resno); int __must_check pci_assign_resource(struct pci_dev *dev, int i); |