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

Commit 3df765fc authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'vfio-v3.11-rc4' of git://github.com/awilliam/linux-vfio

Pull vfio fixes from Alex Williamson:
 "misc fixes around overreacting to bus notifier events and a locking
  fix for a corner case blocked remove"

* tag 'vfio-v3.11-rc4' of git://github.com/awilliam/linux-vfio:
  vfio-pci: Avoid deadlock on remove
  vfio: Ignore sprurious notifies
  vfio: Don't overreact to DEL_DEVICE
parents 19788a90 d24cdbfd
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);
}
+10 −27
Original line number Diff line number Diff line
@@ -494,27 +494,6 @@ static int vfio_group_nb_add_dev(struct vfio_group *group, struct device *dev)
	return 0;
}

static int vfio_group_nb_del_dev(struct vfio_group *group, struct device *dev)
{
	struct vfio_device *device;

	/*
	 * Expect to fall out here.  If a device was in use, it would
	 * have been bound to a vfio sub-driver, which would have blocked
	 * in .remove at vfio_del_group_dev.  Sanity check that we no
	 * longer track the device, so it's safe to remove.
	 */
	device = vfio_group_get_device(group, dev);
	if (likely(!device))
		return 0;

	WARN("Device %s removed from live group %d!\n", dev_name(dev),
	     iommu_group_id(group->iommu_group));

	vfio_device_put(device);
	return 0;
}

static int vfio_group_nb_verify(struct vfio_group *group, struct device *dev)
{
	/* We don't care what happens when the group isn't in use */
@@ -531,13 +510,11 @@ static int vfio_iommu_group_notifier(struct notifier_block *nb,
	struct device *dev = data;

	/*
	 * Need to go through a group_lock lookup to get a reference or
	 * we risk racing a group being removed.  Leave a WARN_ON for
	 * debuging, but if the group no longer exists, a spurious notify
	 * is harmless.
	 * Need to go through a group_lock lookup to get a reference or we
	 * risk racing a group being removed.  Ignore spurious notifies.
	 */
	group = vfio_group_try_get(group);
	if (WARN_ON(!group))
	if (!group)
		return NOTIFY_OK;

	switch (action) {
@@ -545,7 +522,13 @@ static int vfio_iommu_group_notifier(struct notifier_block *nb,
		vfio_group_nb_add_dev(group, dev);
		break;
	case IOMMU_GROUP_NOTIFY_DEL_DEVICE:
		vfio_group_nb_del_dev(group, dev);
		/*
		 * Nothing to do here.  If the device is in use, then the
		 * vfio sub-driver should block the remove callback until
		 * it is unused.  If the device is unused or attached to a
		 * stub driver, then it should be released and we don't
		 * care that it will be going away.
		 */
		break;
	case IOMMU_GROUP_NOTIFY_BIND_DRIVER:
		pr_debug("%s: Device %s, group %d binding to driver\n",