diff options
| author | Alex Williamson <alex.williamson@redhat.com> | 2014-08-07 13:12:07 -0400 |
|---|---|---|
| committer | Alex Williamson <alex.williamson@redhat.com> | 2014-08-07 13:12:07 -0400 |
| commit | bc4fba77124e2fe4eb14bcb52875c0b0228deace (patch) | |
| tree | 32c9a964e7e40735ef6e9841f2509053f5e24729 | |
| parent | 61d792562b53c610f9fe917f2bbc22218aa39c22 (diff) | |
vfio-pci: Attempt bus/slot reset on release
Each time a device is released, mark whether a local reset was
successful or whether a bus/slot reset is needed. If a reset is
needed and all of the affected devices are bound to vfio-pci and
unused, allow the reset. This is most useful when the userspace
driver is killed and releases all the devices in an unclean state,
such as when a QEMU VM quits.
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
| -rw-r--r-- | drivers/vfio/pci/vfio_pci.c | 112 | ||||
| -rw-r--r-- | drivers/vfio/pci/vfio_pci_private.h | 1 |
2 files changed, 113 insertions, 0 deletions
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index c9d756b7ee9e..1651c0769b72 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c | |||
| @@ -39,6 +39,8 @@ MODULE_PARM_DESC(nointxmask, | |||
| 39 | 39 | ||
| 40 | static DEFINE_MUTEX(driver_lock); | 40 | static DEFINE_MUTEX(driver_lock); |
| 41 | 41 | ||
| 42 | static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev); | ||
| 43 | |||
| 42 | static int vfio_pci_enable(struct vfio_pci_device *vdev) | 44 | static int vfio_pci_enable(struct vfio_pci_device *vdev) |
| 43 | { | 45 | { |
| 44 | struct pci_dev *pdev = vdev->pdev; | 46 | struct pci_dev *pdev = vdev->pdev; |
| @@ -123,6 +125,8 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev) | |||
| 123 | vdev->barmap[bar] = NULL; | 125 | vdev->barmap[bar] = NULL; |
| 124 | } | 126 | } |
| 125 | 127 | ||
| 128 | vdev->needs_reset = true; | ||
| 129 | |||
| 126 | /* | 130 | /* |
| 127 | * If we have saved state, restore it. If we can reset the device, | 131 | * If we have saved state, restore it. If we can reset the device, |
| 128 | * even better. Resetting with current state seems better than | 132 | * even better. Resetting with current state seems better than |
| @@ -154,11 +158,15 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev) | |||
| 154 | if (ret) | 158 | if (ret) |
| 155 | pr_warn("%s: Failed to reset device %s (%d)\n", | 159 | pr_warn("%s: Failed to reset device %s (%d)\n", |
| 156 | __func__, dev_name(&pdev->dev), ret); | 160 | __func__, dev_name(&pdev->dev), ret); |
| 161 | else | ||
| 162 | vdev->needs_reset = false; | ||
| 157 | } | 163 | } |
| 158 | 164 | ||
| 159 | pci_restore_state(pdev); | 165 | pci_restore_state(pdev); |
| 160 | out: | 166 | out: |
| 161 | pci_disable_device(pdev); | 167 | pci_disable_device(pdev); |
| 168 | |||
| 169 | vfio_pci_try_bus_reset(vdev); | ||
| 162 | } | 170 | } |
| 163 | 171 | ||
| 164 | static void vfio_pci_release(void *device_data) | 172 | static void vfio_pci_release(void *device_data) |
| @@ -923,6 +931,110 @@ static struct pci_driver vfio_pci_driver = { | |||
| 923 | .err_handler = &vfio_err_handlers, | 931 | .err_handler = &vfio_err_handlers, |
| 924 | }; | 932 | }; |
| 925 | 933 | ||
| 934 | /* | ||
| 935 | * Test whether a reset is necessary and possible. We mark devices as | ||
| 936 | * needs_reset when they are released, but don't have a function-local reset | ||
| 937 | * available. If any of these exist in the affected devices, we want to do | ||
| 938 | * a bus/slot reset. We also need all of the affected devices to be unused, | ||
| 939 | * so we abort if any device has a non-zero refcnt. driver_lock prevents a | ||
| 940 | * device from being opened during the scan or unbound from vfio-pci. | ||
| 941 | */ | ||
| 942 | static int vfio_pci_test_bus_reset(struct pci_dev *pdev, void *data) | ||
| 943 | { | ||
| 944 | bool *needs_reset = data; | ||
| 945 | struct pci_driver *pci_drv = ACCESS_ONCE(pdev->driver); | ||
| 946 | int ret = -EBUSY; | ||
| 947 | |||
| 948 | if (pci_drv == &vfio_pci_driver) { | ||
| 949 | struct vfio_device *device; | ||
| 950 | struct vfio_pci_device *vdev; | ||
| 951 | |||
| 952 | device = vfio_device_get_from_dev(&pdev->dev); | ||
| 953 | if (!device) | ||
| 954 | return ret; | ||
| 955 | |||
| 956 | vdev = vfio_device_data(device); | ||
| 957 | if (vdev) { | ||
| 958 | if (vdev->needs_reset) | ||
| 959 | *needs_reset = true; | ||
| 960 | |||
| 961 | if (!vdev->refcnt) | ||
| 962 | ret = 0; | ||
| 963 | } | ||
| 964 | |||
| 965 | vfio_device_put(device); | ||
| 966 | } | ||
| 967 | |||
| 968 | /* | ||
| 969 | * TODO: vfio-core considers groups to be viable even if some devices | ||
| 970 | * are attached to known drivers, like pci-stub or pcieport. We can't | ||
| 971 | * freeze devices from being unbound to those drivers like we can | ||
| 972 | * here though, so it would be racy to test for them. We also can't | ||
| 973 | * use device_lock() to prevent changes as that would interfere with | ||
| 974 | * PCI-core taking device_lock during bus reset. For now, we require | ||
| 975 | * devices to be bound to vfio-pci to get a bus/slot reset on release. | ||
| 976 | */ | ||
| 977 | |||
| 978 | return ret; | ||
| 979 | } | ||
| 980 | |||
| 981 | /* Clear needs_reset on all affected devices after successful bus/slot reset */ | ||
| 982 | static int vfio_pci_clear_needs_reset(struct pci_dev *pdev, void *data) | ||
| 983 | { | ||
| 984 | struct pci_driver *pci_drv = ACCESS_ONCE(pdev->driver); | ||
| 985 | |||
| 986 | if (pci_drv == &vfio_pci_driver) { | ||
| 987 | struct vfio_device *device; | ||
| 988 | struct vfio_pci_device *vdev; | ||
| 989 | |||
| 990 | device = vfio_device_get_from_dev(&pdev->dev); | ||
| 991 | if (!device) | ||
| 992 | return 0; | ||
| 993 | |||
| 994 | vdev = vfio_device_data(device); | ||
| 995 | if (vdev) | ||
| 996 | vdev->needs_reset = false; | ||
| 997 | |||
| 998 | vfio_device_put(device); | ||
| 999 | } | ||
| 1000 | |||
| 1001 | return 0; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | /* | ||
| 1005 | * Attempt to do a bus/slot reset if there are devices affected by a reset for | ||
| 1006 | * this device that are needs_reset and all of the affected devices are unused | ||
| 1007 | * (!refcnt). Callers of this function are required to hold driver_lock such | ||
| 1008 | * that devices can not be unbound from vfio-pci or opened by a user while we | ||
| 1009 | * test for and perform a bus/slot reset. | ||
| 1010 | */ | ||
| 1011 | static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev) | ||
| 1012 | { | ||
| 1013 | bool needs_reset = false, slot = false; | ||
| 1014 | int ret; | ||
| 1015 | |||
| 1016 | if (!pci_probe_reset_slot(vdev->pdev->slot)) | ||
| 1017 | slot = true; | ||
| 1018 | else if (pci_probe_reset_bus(vdev->pdev->bus)) | ||
| 1019 | return; | ||
| 1020 | |||
| 1021 | if (vfio_pci_for_each_slot_or_bus(vdev->pdev, | ||
| 1022 | vfio_pci_test_bus_reset, | ||
| 1023 | &needs_reset, slot) || !needs_reset) | ||
| 1024 | return; | ||
| 1025 | |||
| 1026 | if (slot) | ||
| 1027 | ret = pci_try_reset_slot(vdev->pdev->slot); | ||
| 1028 | else | ||
| 1029 | ret = pci_try_reset_bus(vdev->pdev->bus); | ||
| 1030 | |||
| 1031 | if (ret) | ||
| 1032 | return; | ||
| 1033 | |||
| 1034 | vfio_pci_for_each_slot_or_bus(vdev->pdev, | ||
| 1035 | vfio_pci_clear_needs_reset, NULL, slot); | ||
| 1036 | } | ||
| 1037 | |||
| 926 | static void __exit vfio_pci_cleanup(void) | 1038 | static void __exit vfio_pci_cleanup(void) |
| 927 | { | 1039 | { |
| 928 | pci_unregister_driver(&vfio_pci_driver); | 1040 | pci_unregister_driver(&vfio_pci_driver); |
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h index 31e7a30196ab..671c17a6e6d0 100644 --- a/drivers/vfio/pci/vfio_pci_private.h +++ b/drivers/vfio/pci/vfio_pci_private.h | |||
| @@ -54,6 +54,7 @@ struct vfio_pci_device { | |||
| 54 | bool extended_caps; | 54 | bool extended_caps; |
| 55 | bool bardirty; | 55 | bool bardirty; |
| 56 | bool has_vga; | 56 | bool has_vga; |
| 57 | bool needs_reset; | ||
| 57 | struct pci_saved_state *pci_saved_state; | 58 | struct pci_saved_state *pci_saved_state; |
| 58 | int refcnt; | 59 | int refcnt; |
| 59 | struct eventfd_ctx *err_trigger; | 60 | struct eventfd_ctx *err_trigger; |
