+static clib_error_t *
+vfio_set_irqs (vlib_main_t * vm, linux_pci_device_t * p, u32 index, u32 start,
+ u32 count, u32 flags, int *efds)
+{
+ int data_len = efds ? count * sizeof (int) : 0;
+ u8 buf[sizeof (struct vfio_irq_set) + data_len];
+ struct vfio_irq_info ii = { 0 };
+ struct vfio_irq_set *irq_set = (struct vfio_irq_set *) buf;
+
+
+ ii.argsz = sizeof (struct vfio_irq_info);
+ ii.index = index;
+
+ if (ioctl (p->fd, VFIO_DEVICE_GET_IRQ_INFO, &ii) < 0)
+ return clib_error_return_unix (0, "ioctl(VFIO_DEVICE_GET_IRQ_INFO) "
+ "'%U'", format_vlib_pci_addr, &p->addr);
+
+ pci_log_debug (vm, p, "%s index:%u count:%u flags: %s%s%s%s(0x%x)",
+ __func__, ii.index, ii.count,
+ ii.flags & VFIO_IRQ_INFO_EVENTFD ? "eventfd " : "",
+ ii.flags & VFIO_IRQ_INFO_MASKABLE ? "maskable " : "",
+ ii.flags & VFIO_IRQ_INFO_AUTOMASKED ? "automasked " : "",
+ ii.flags & VFIO_IRQ_INFO_NORESIZE ? "noresize " : "",
+ ii.flags);
+
+ if (ii.count < start + count)
+ return clib_error_return_unix (0, "vfio_set_irq: unexistng interrupt on "
+ "'%U'", format_vlib_pci_addr, &p->addr);
+
+
+ if (efds)
+ {
+ flags |= VFIO_IRQ_SET_DATA_EVENTFD;
+ clib_memcpy_fast (&irq_set->data, efds, data_len);
+ }
+ else
+ flags |= VFIO_IRQ_SET_DATA_NONE;
+
+ ASSERT ((flags & (VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_DATA_EVENTFD)) !=
+ (VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_DATA_EVENTFD));
+
+ irq_set->argsz = sizeof (struct vfio_irq_set) + data_len;
+ irq_set->index = index;
+ irq_set->start = start;
+ irq_set->count = count;
+ irq_set->flags = flags;
+
+ if (ioctl (p->fd, VFIO_DEVICE_SET_IRQS, irq_set) < 0)
+ return clib_error_return_unix (0, "%U:ioctl(VFIO_DEVICE_SET_IRQS) "
+ "[index = %u, start = %u, count = %u, "
+ "flags = 0x%x]",
+ format_vlib_pci_addr, &p->addr,
+ index, start, count, flags);
+ return 0;
+}
+