Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d24cdbfd authored by Alex Williamson's avatar Alex Williamson
Browse files

vfio-pci: Avoid deadlock on remove



If an attempt is made to unbind a device from vfio-pci while that
device is in use, the request is blocked until the device becomes
unused.  Unfortunately, that unbind path still grabs the device_lock,
which certain things like __pci_reset_function() also want to take.
This means we need to try to acquire the locks ourselves and use the
pre-locked version, __pci_reset_function_locked().

Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent c6401930
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -137,8 +137,27 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev)
	 */
	pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);

	if (vdev->reset_works)
		__pci_reset_function(pdev);
	/*
	 * Careful, device_lock may already be held.  This is the case if
	 * a driver unbind is blocked.  Try to get the locks ourselves to
	 * prevent a deadlock.
	 */
	if (vdev->reset_works) {
		bool reset_done = false;

		if (pci_cfg_access_trylock(pdev)) {
			if (device_trylock(&pdev->dev)) {
				__pci_reset_function_locked(pdev);
				reset_done = true;
				device_unlock(&pdev->dev);
			}
			pci_cfg_access_unlock(pdev);
		}

		if (!reset_done)
			pr_warn("%s: Unable to acquire locks for reset of %s\n",
				__func__, dev_name(&pdev->dev));
	}

	pci_restore_state(pdev);
}