Skip to content

Commit

Permalink
vfio/device: support enable/disable specific irq
Browse files Browse the repository at this point in the history
This patch added 'start' parameter to 'vfio_set_irq' API to specify
start IRQ number to configure to vfio-pci kernel driver.  This patch
also converted previous 'vfio_disable_irq' to 'vfio_disable_irq_all' to
disable all enabled irqs.  'vfio_disable_irq' has been updated to
disable specific irqs from the given 'start' parameter.

To disable (de-assign) one or more IRQs from vfio-pci kernel driver,
irq_set data -1 should be passed to irq_set->data.  uapi <linux/vfio.h>
says that value -1 with DATA_EVENTFD|ACTION_TRIGGER) will de-assign
interrupts if already assigned.

This patch also fixed de-assign behavior by replacing DATA_NONE to
DATA_EVENTFD with data -1 along with adding a new API to disable
specific interrupts with start and count.

Signed-off-by: Minwoo Im <[email protected]>
  • Loading branch information
minwooim committed Nov 19, 2024
1 parent a261331 commit 9d015c1
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 12 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

``nvme_pci_init`` has been deprecated and will generate a warning.

``vfio_set_irq`` has been updated to receive ``start`` parameter to specify
start irq number to enable. With this, ``vfio_disable_irq`` has been updated
to disable specific one or more irqs from ``start`` for ``count`` of irqs.
``vfio_disable_irq_all`` has been newly added to disable all the enabled irqs.

## v5.2.0: (unreleased)

### ``nvme_ctrl``
Expand Down
2 changes: 1 addition & 1 deletion examples/eventfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ int main(int argc, char **argv)
if (efd < 0)
err(1, "failed to create eventfd");

if (vfio_set_irq(&ctrl.pci.dev, efds, 2))
if (vfio_set_irq(&ctrl.pci.dev, efds, 0, 2))
err(1, "failed to set irqs");

if (nvme_create_ioqpair(&ctrl, 1, 64, 1, 0x0))
Expand Down
19 changes: 16 additions & 3 deletions include/vfn/vfio/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,37 @@ struct vfio_device {
* vfio_set_irq - Enable IRQs through eventfds
* @dev: &struct vfio_device
* @eventfds: array of eventfds
* @start: start irq number
* @count: number of eventfds
*
* Enable interrupts for a range of vectors. See linux/vfio.h for documentation
* on the format of @eventfds.
*
* Return: ``0`` on success, ``-1`` on error and sets ``errno``.
*/
int vfio_set_irq(struct vfio_device *dev, int *eventfds, int count);
int vfio_set_irq(struct vfio_device *dev, int *eventfds, int start, int count);

/**
* vfio_disable_irq - Disable all IRQs
* vfio_disable_irq - 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(struct vfio_device *dev, int start, int count);

/**
* vfio_disable_irq_all - Disable all IRQs
* @dev: &struct vfio_device
*
* Disable all IRQs.
*
* Return: ``0`` on success, ``-1`` on error and sets ``errno``.
*/
int vfio_disable_irq(struct vfio_device *dev);
int vfio_disable_irq_all(struct vfio_device *dev);

/**
* vfio_reset - reset vfio device
Expand Down
36 changes: 28 additions & 8 deletions src/vfio/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
#include "ccan/minmax/minmax.h"
#include "ccan/str/str.h"

int vfio_set_irq(struct vfio_device *dev, int *eventfds, int count)
int vfio_set_irq(struct vfio_device *dev, int *eventfds, int start, int count)
{
struct vfio_irq_set *irq_set;
size_t irq_set_size;
Expand All @@ -59,7 +59,7 @@ int vfio_set_irq(struct vfio_device *dev, int *eventfds, int count)
.argsz = (uint32_t)irq_set_size,
.flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER,
.index = dev->irq_info.index,
.start = 0,
.start = start,
.count = count,
};

Expand All @@ -76,18 +76,33 @@ int vfio_set_irq(struct vfio_device *dev, int *eventfds, int count)
return 0;
}

int vfio_disable_irq(struct vfio_device *dev)
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");
Expand All @@ -97,6 +112,11 @@ int vfio_disable_irq(struct vfio_device *dev)
return 0;
}

int vfio_disable_irq_all(struct vfio_device *dev)
{
return vfio_disable_irq(dev, 0, dev->irq_info.count);
}

int vfio_reset(struct vfio_device *dev)
{
if (!(dev->device_info.flags & VFIO_DEVICE_FLAGS_RESET)) {
Expand Down

0 comments on commit 9d015c1

Please sign in to comment.