Commit a96d627a authored by Konrad Rzeszutek Wilk's avatar Konrad Rzeszutek Wilk

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: default avatarKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
parent 8605c684
...@@ -3162,6 +3162,31 @@ int __pci_reset_function(struct pci_dev *dev) ...@@ -3162,6 +3162,31 @@ int __pci_reset_function(struct pci_dev *dev)
} }
EXPORT_SYMBOL_GPL(__pci_reset_function); 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 * pci_probe_reset_function - check whether the device can be safely reset
* @dev: PCI device to reset * @dev: PCI device to reset
......
...@@ -817,6 +817,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq); ...@@ -817,6 +817,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq);
int pcie_get_mps(struct pci_dev *dev); int pcie_get_mps(struct pci_dev *dev);
int pcie_set_mps(struct pci_dev *dev, int mps); int pcie_set_mps(struct pci_dev *dev, int mps);
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(struct pci_dev *dev); int pci_reset_function(struct pci_dev *dev);
void pci_update_resource(struct pci_dev *dev, int resno); void pci_update_resource(struct pci_dev *dev, int resno);
int __must_check pci_assign_resource(struct pci_dev *dev, int i); int __must_check pci_assign_resource(struct pci_dev *dev, int i);
......
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