vfio: misc fixes around overreacting to bus notifier events and a locking fix for a corner case blocked remove.

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.13 (GNU/Linux)
 
 iQIcBAABAgAGBQJR+AppAAoJECObm247sIsimnoQAJf2pQjh47ai+Wv5ezN8hSZy
 rg56lhg3RMOHjTjLrKbPfjMLbLxD7rwlRZwu8RHVlhnz4ICEKy4DG0ZpeJ6j06TZ
 AMa4F/rlTysF1ZebzSAnB/Agkss8OFXVUJshA62UE3IzsjyAQzXrwOn3nyAXsgCV
 JTUAAewOV3DivTP2d8V3rDh/rS64eXp4cKf5z8iyPnOfiBzCbSxWcz2SmHVOh1nX
 rMXIM8zvKLhKH0lzC+xm88/lC6rUKwJrnAHVR6TR+OJsnrqB14SDsfjg6wt4JP/4
 e0NGD7YO9GHh20TjnIjF1VnUu2hG/Y7bpAuRhlterVDjDyKBhVIxIImF8GEMl+NB
 f9aNEx4KgotTr9lQFp96ixVsN/y/B9Slv35LGPZIcf014iWpG6pdV59xIXVC3Fsr
 oMyV9R7jaGoQ49k9wgxRG0eVXREFykKIAPW7dqijc6XrcZzyGcF/nBGaRLuCstcR
 VskjNMndQlnEBJVqiarFVHdsDr7Qo01oqIaSnAtappZNAMpPladeY/ebikbzDUKY
 VmrBqQjgDHhUoOws791IQaB8I0Ya31wCml7mHC2IfgJ2ZzzXS5Grlq3KjTW0zkTv
 1cD7eB9tMQAvqDdZISUAdb73f1vGpBthDjFdO+UudtXkM8rPww5ShqovTeLWYdta
 2d+5MVdbqMIyNxo7rK8t
 =yYAu
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2013-07-31 17:53:38 -07:00
commit 3df765fc65
2 changed files with 31 additions and 29 deletions

View File

@ -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);
}

View File

@ -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",