unsigned index, unsigned start,
unsigned count, uint32_t flags, void *data)
{
- int32_t fd = *(int32_t *)data;
-
- if ((index != VFIO_PCI_ERR_IRQ_INDEX) ||
- !(flags & VFIO_IRQ_SET_DATA_TYPE_MASK))
+ if (index != VFIO_PCI_ERR_IRQ_INDEX || start != 0 || count > 1)
return -EINVAL;
/* DATA_NONE/DATA_BOOL enables loopback testing */
if (flags & VFIO_IRQ_SET_DATA_NONE) {
- if (vdev->err_trigger)
- eventfd_signal(vdev->err_trigger, 1);
- return 0;
+ if (vdev->err_trigger) {
+ if (count) {
+ eventfd_signal(vdev->err_trigger, 1);
+ } else {
+ eventfd_ctx_put(vdev->err_trigger);
+ vdev->err_trigger = NULL;
+ }
+ return 0;
+ }
} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
- uint8_t trigger = *(uint8_t *)data;
+ uint8_t trigger;
+
+ if (!count)
+ return -EINVAL;
+
+ trigger = *(uint8_t *)data;
if (trigger && vdev->err_trigger)
eventfd_signal(vdev->err_trigger, 1);
- return 0;
- }
- /* Handle SET_DATA_EVENTFD */
- if (fd == -1) {
- if (vdev->err_trigger)
- eventfd_ctx_put(vdev->err_trigger);
- vdev->err_trigger = NULL;
return 0;
- } else if (fd >= 0) {
- struct eventfd_ctx *efdctx;
- efdctx = eventfd_ctx_fdget(fd);
- if (IS_ERR(efdctx))
- return PTR_ERR(efdctx);
- if (vdev->err_trigger)
- eventfd_ctx_put(vdev->err_trigger);
- vdev->err_trigger = efdctx;
+ } else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+ int32_t fd;
+
+ if (!count)
+ return -EINVAL;
+
+ fd = *(int32_t *)data;
+ if (fd == -1) {
+ if (vdev->err_trigger)
+ eventfd_ctx_put(vdev->err_trigger);
+ vdev->err_trigger = NULL;
+ } else if (fd >= 0) {
+ struct eventfd_ctx *efdctx;
+
+ efdctx = eventfd_ctx_fdget(fd);
+ if (IS_ERR(efdctx))
+ return PTR_ERR(efdctx);
+
+ if (vdev->err_trigger)
+ eventfd_ctx_put(vdev->err_trigger);
+
+ vdev->err_trigger = efdctx;
+ }
return 0;
- } else
- return -EINVAL;
+ }
+
+ return -EINVAL;
}
int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags,
unsigned index, unsigned start, unsigned count,