diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-31 20:53:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-31 20:53:38 -0400 |
commit | 3df765fc65354b73cdbba1a862a69dec79934633 (patch) | |
tree | 4cf2cb641c01a82ebd9ead05c772783196226432 | |
parent | 19788a900803138a4c7c997eb5e9c27f9d17667e (diff) | |
parent | d24cdbfd28b7e0ffecb1e281d73e73c03a57f734 (diff) |
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
-rw-r--r-- | drivers/vfio/pci/vfio_pci.c | 23 | ||||
-rw-r--r-- | drivers/vfio/vfio.c | 37 |
2 files changed, 31 insertions, 29 deletions
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index c5179e269df6..cef6002acbd4 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c | |||
@@ -137,8 +137,27 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev) | |||
137 | */ | 137 | */ |
138 | pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE); | 138 | pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE); |
139 | 139 | ||
140 | if (vdev->reset_works) | 140 | /* |
141 | __pci_reset_function(pdev); | 141 | * Careful, device_lock may already be held. This is the case if |
142 | * a driver unbind is blocked. Try to get the locks ourselves to | ||
143 | * prevent a deadlock. | ||
144 | */ | ||
145 | if (vdev->reset_works) { | ||
146 | bool reset_done = false; | ||
147 | |||
148 | if (pci_cfg_access_trylock(pdev)) { | ||
149 | if (device_trylock(&pdev->dev)) { | ||
150 | __pci_reset_function_locked(pdev); | ||
151 | reset_done = true; | ||
152 | device_unlock(&pdev->dev); | ||
153 | } | ||
154 | pci_cfg_access_unlock(pdev); | ||
155 | } | ||
156 | |||
157 | if (!reset_done) | ||
158 | pr_warn("%s: Unable to acquire locks for reset of %s\n", | ||
159 | __func__, dev_name(&pdev->dev)); | ||
160 | } | ||
142 | 161 | ||
143 | pci_restore_state(pdev); | 162 | pci_restore_state(pdev); |
144 | } | 163 | } |
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index c488da5db7c7..842f4507883e 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c | |||
@@ -494,27 +494,6 @@ static int vfio_group_nb_add_dev(struct vfio_group *group, struct device *dev) | |||
494 | return 0; | 494 | return 0; |
495 | } | 495 | } |
496 | 496 | ||
497 | static int vfio_group_nb_del_dev(struct vfio_group *group, struct device *dev) | ||
498 | { | ||
499 | struct vfio_device *device; | ||
500 | |||
501 | /* | ||
502 | * Expect to fall out here. If a device was in use, it would | ||
503 | * have been bound to a vfio sub-driver, which would have blocked | ||
504 | * in .remove at vfio_del_group_dev. Sanity check that we no | ||
505 | * longer track the device, so it's safe to remove. | ||
506 | */ | ||
507 | device = vfio_group_get_device(group, dev); | ||
508 | if (likely(!device)) | ||
509 | return 0; | ||
510 | |||
511 | WARN("Device %s removed from live group %d!\n", dev_name(dev), | ||
512 | iommu_group_id(group->iommu_group)); | ||
513 | |||
514 | vfio_device_put(device); | ||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | static int vfio_group_nb_verify(struct vfio_group *group, struct device *dev) | 497 | static int vfio_group_nb_verify(struct vfio_group *group, struct device *dev) |
519 | { | 498 | { |
520 | /* We don't care what happens when the group isn't in use */ | 499 | /* 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, | |||
531 | struct device *dev = data; | 510 | struct device *dev = data; |
532 | 511 | ||
533 | /* | 512 | /* |
534 | * Need to go through a group_lock lookup to get a reference or | 513 | * Need to go through a group_lock lookup to get a reference or we |
535 | * we risk racing a group being removed. Leave a WARN_ON for | 514 | * risk racing a group being removed. Ignore spurious notifies. |
536 | * debuging, but if the group no longer exists, a spurious notify | ||
537 | * is harmless. | ||
538 | */ | 515 | */ |
539 | group = vfio_group_try_get(group); | 516 | group = vfio_group_try_get(group); |
540 | if (WARN_ON(!group)) | 517 | if (!group) |
541 | return NOTIFY_OK; | 518 | return NOTIFY_OK; |
542 | 519 | ||
543 | switch (action) { | 520 | switch (action) { |
@@ -545,7 +522,13 @@ static int vfio_iommu_group_notifier(struct notifier_block *nb, | |||
545 | vfio_group_nb_add_dev(group, dev); | 522 | vfio_group_nb_add_dev(group, dev); |
546 | break; | 523 | break; |
547 | case IOMMU_GROUP_NOTIFY_DEL_DEVICE: | 524 | case IOMMU_GROUP_NOTIFY_DEL_DEVICE: |
548 | vfio_group_nb_del_dev(group, dev); | 525 | /* |
526 | * Nothing to do here. If the device is in use, then the | ||
527 | * vfio sub-driver should block the remove callback until | ||
528 | * it is unused. If the device is unused or attached to a | ||
529 | * stub driver, then it should be released and we don't | ||
530 | * care that it will be going away. | ||
531 | */ | ||
549 | break; | 532 | break; |
550 | case IOMMU_GROUP_NOTIFY_BIND_DRIVER: | 533 | case IOMMU_GROUP_NOTIFY_BIND_DRIVER: |
551 | pr_debug("%s: Device %s, group %d binding to driver\n", | 534 | pr_debug("%s: Device %s, group %d binding to driver\n", |