Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1697573 > unrolled thread

[PATCH] vfio/pci: Use pci_try_reset_function() on initial open

Started byAlex Williamson <alex.williamson@redhat.com>
First post2017-07-26 23:30 +0200
Last post2017-07-26 23:30 +0200
Articles 1 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCH] vfio/pci: Use pci_try_reset_function() on initial open Alex Williamson <alex.williamson@redhat.com> - 2017-07-26 23:30 +0200

#1697573 — [PATCH] vfio/pci: Use pci_try_reset_function() on initial open

FromAlex Williamson <alex.williamson@redhat.com>
Date2017-07-26 23:30 +0200
Subject[PATCH] vfio/pci: Use pci_try_reset_function() on initial open
Message-ID<u7C2v-5CF-27@gated-at.bofh.it>
Device lock bites again; if a device .remove() callback races a user
calling ioctl(VFIO_GROUP_GET_DEVICE_FD), the unbind request will hold
the device lock, but the user ioctl may have already taken a vfio_device
reference.  In the case of a PCI device, the initial open will attempt
to reset the device, which again attempts to get the device lock,
resulting in deadlock.  Use the trylock PCI reset interface and return
error on the open path if reset fails due to lock contention.

Link: https://lkml.org/lkml/2017/7/25/381
Reported-by: Wen Congyang <wencongyang2@huawei.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
 drivers/vfio/pci/vfio_pci.c |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 063c1ce6fa42..f041b1a6cf66 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -226,7 +226,14 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
 	if (ret)
 		return ret;
 
-	vdev->reset_works = (pci_reset_function(pdev) == 0);
+	/* If reset fails because of the device lock, fail this path entirely */
+	ret = pci_try_reset_function(pdev);
+	if (ret == -EAGAIN) {
+		pci_disable_device(pdev);
+		return ret;
+	}
+
+	vdev->reset_works = !ret;
 	pci_save_state(pdev);
 	vdev->pci_saved_state = pci_store_saved_state(pdev);
 	if (!vdev->pci_saved_state)

[toc] | [standalone]


Back to top | Article view | linux.kernel


csiph-web