diff options
| -rw-r--r-- | drivers/vfio/vfio.c | 24 | ||||
| -rw-r--r-- | include/linux/vfio.h | 2 |
2 files changed, 24 insertions, 2 deletions
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 13e0f39d91e0..4cde85501444 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c | |||
| @@ -710,6 +710,7 @@ void *vfio_del_group_dev(struct device *dev) | |||
| 710 | struct vfio_group *group = device->group; | 710 | struct vfio_group *group = device->group; |
| 711 | void *device_data = device->device_data; | 711 | void *device_data = device->device_data; |
| 712 | struct vfio_unbound_dev *unbound; | 712 | struct vfio_unbound_dev *unbound; |
| 713 | unsigned int i = 0; | ||
| 713 | 714 | ||
| 714 | /* | 715 | /* |
| 715 | * The group exists so long as we have a device reference. Get | 716 | * The group exists so long as we have a device reference. Get |
| @@ -737,8 +738,27 @@ void *vfio_del_group_dev(struct device *dev) | |||
| 737 | 738 | ||
| 738 | vfio_device_put(device); | 739 | vfio_device_put(device); |
| 739 | 740 | ||
| 740 | /* TODO send a signal to encourage this to be released */ | 741 | /* |
| 741 | wait_event(vfio.release_q, !vfio_dev_present(group, dev)); | 742 | * If the device is still present in the group after the above |
| 743 | * 'put', then it is in use and we need to request it from the | ||
| 744 | * bus driver. The driver may in turn need to request the | ||
| 745 | * device from the user. We send the request on an arbitrary | ||
| 746 | * interval with counter to allow the driver to take escalating | ||
| 747 | * measures to release the device if it has the ability to do so. | ||
| 748 | */ | ||
| 749 | do { | ||
| 750 | device = vfio_group_get_device(group, dev); | ||
| 751 | if (!device) | ||
| 752 | break; | ||
| 753 | |||
| 754 | if (device->ops->request) | ||
| 755 | device->ops->request(device_data, i++); | ||
| 756 | |||
| 757 | vfio_device_put(device); | ||
| 758 | |||
| 759 | } while (wait_event_interruptible_timeout(vfio.release_q, | ||
| 760 | !vfio_dev_present(group, dev), | ||
| 761 | HZ * 10) <= 0); | ||
| 742 | 762 | ||
| 743 | vfio_group_put(group); | 763 | vfio_group_put(group); |
| 744 | 764 | ||
diff --git a/include/linux/vfio.h b/include/linux/vfio.h index d3204115f15d..2d67b8998fd8 100644 --- a/include/linux/vfio.h +++ b/include/linux/vfio.h | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | * @ioctl: Perform ioctl(2) on device file descriptor, supporting VFIO_DEVICE_* | 26 | * @ioctl: Perform ioctl(2) on device file descriptor, supporting VFIO_DEVICE_* |
| 27 | * operations documented below | 27 | * operations documented below |
| 28 | * @mmap: Perform mmap(2) on a region of the device file descriptor | 28 | * @mmap: Perform mmap(2) on a region of the device file descriptor |
| 29 | * @request: Request for the bus driver to release the device | ||
| 29 | */ | 30 | */ |
| 30 | struct vfio_device_ops { | 31 | struct vfio_device_ops { |
| 31 | char *name; | 32 | char *name; |
| @@ -38,6 +39,7 @@ struct vfio_device_ops { | |||
| 38 | long (*ioctl)(void *device_data, unsigned int cmd, | 39 | long (*ioctl)(void *device_data, unsigned int cmd, |
| 39 | unsigned long arg); | 40 | unsigned long arg); |
| 40 | int (*mmap)(void *device_data, struct vm_area_struct *vma); | 41 | int (*mmap)(void *device_data, struct vm_area_struct *vma); |
| 42 | void (*request)(void *device_data, unsigned int count); | ||
| 41 | }; | 43 | }; |
| 42 | 44 | ||
| 43 | extern int vfio_add_group_dev(struct device *dev, | 45 | extern int vfio_add_group_dev(struct device *dev, |
