diff --git a/include/vfn/vfio/device.h b/include/vfn/vfio/device.h index 24eb208..503f643 100644 --- a/include/vfn/vfio/device.h +++ b/include/vfn/vfio/device.h @@ -61,6 +61,18 @@ int vfio_set_irq_from_start(struct vfio_device *dev, int *eventfds, int start, i */ int vfio_disable_irq(struct vfio_device *dev); +/** + * vfio_disable_irq_from_start - Disable number of count IRQs from given start + * @dev: &struct vfio_device + * @start: start irq number + * @count: number of eventfds + * + * Disable given number of IRQs from start. + * + * Return: ``0`` on success, ``-1`` on error and sets ``errno``. + */ +int vfio_disable_irq_from_start(struct vfio_device *dev, int start, int count); + /** * vfio_reset - reset vfio device * @dev: &struct vfio_device to reset diff --git a/src/vfio/device.c b/src/vfio/device.c index 35acbea..bc50139 100644 --- a/src/vfio/device.c +++ b/src/vfio/device.c @@ -87,18 +87,33 @@ int vfio_set_irq_from_start(struct vfio_device *dev, int *eventfds, int start, return __vfio_set_irq(dev, eventfds, start, count); } -int vfio_disable_irq(struct vfio_device *dev) +static int __vfio_disable_irq(struct vfio_device *dev, int start, int count) { - struct vfio_irq_set irq_set; + struct vfio_irq_set *irq_set; + size_t irq_set_size; + int *data; int ret; - irq_set = (struct vfio_irq_set) { - .argsz = sizeof(irq_set), - .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER, + irq_set_size = sizeof(*irq_set) + sizeof(int) * count; + irq_set = xmalloc(irq_set_size); + + data = xmalloc(sizeof(int) * count); + for (int i = 0; i < count; i++) + data[i] = -1; + + *irq_set = (struct vfio_irq_set) { + .argsz = (uint32_t)irq_set_size, + .flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER, .index = dev->irq_info.index, + .start = start, + .count = count, }; - ret = ioctl(dev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); + memcpy(irq_set->data, data, sizeof(int) * count); + + ret = ioctl(dev->fd, VFIO_DEVICE_SET_IRQS, irq_set); + free(data); + free(irq_set); if (ret) { log_debug("failed to disable device irq\n"); @@ -108,6 +123,16 @@ int vfio_disable_irq(struct vfio_device *dev) return 0; } +int vfio_disable_irq(struct vfio_device *dev) +{ + return __vfio_disable_irq(dev, 0, dev->irq_info.count); +} + +int vfio_disable_irq_from_start(struct vfio_device *dev, int start, int count) +{ + return __vfio_disable_irq(dev, start, count); +} + int vfio_reset(struct vfio_device *dev) { if (!(dev->device_info.flags & VFIO_DEVICE_FLAGS_RESET)) {