diff options
Diffstat (limited to 'target/linux/layerscape/patches-5.4/821-vfio-0008-vfio-fsl-mc-trigger-an-interrupt-via-eventfd.patch')
-rw-r--r-- | target/linux/layerscape/patches-5.4/821-vfio-0008-vfio-fsl-mc-trigger-an-interrupt-via-eventfd.patch | 268 |
1 files changed, 0 insertions, 268 deletions
diff --git a/target/linux/layerscape/patches-5.4/821-vfio-0008-vfio-fsl-mc-trigger-an-interrupt-via-eventfd.patch b/target/linux/layerscape/patches-5.4/821-vfio-0008-vfio-fsl-mc-trigger-an-interrupt-via-eventfd.patch deleted file mode 100644 index 4f1e0997f7..0000000000 --- a/target/linux/layerscape/patches-5.4/821-vfio-0008-vfio-fsl-mc-trigger-an-interrupt-via-eventfd.patch +++ /dev/null @@ -1,268 +0,0 @@ -From 8f0239c9385028a0c15306966c66a56315b11dbc Mon Sep 17 00:00:00 2001 -From: Diana Craciun <diana.craciun@nxp.com> -Date: Tue, 1 Oct 2019 16:44:04 +0300 -Subject: [PATCH] vfio/fsl-mc: trigger an interrupt via eventfd - -This patch allows to set an eventfd for fsl-mc device interrupt -and also to trigger the interrupt eventfd from userspace for testing. - -All fsl-mc device interrupts are MSI type. This does not yet handle -correctly DPRC container interrupt where re-scanning on container is -required. - -Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com> -Signed-off-by: Diana Craciun <diana.craciun@nxp.com> ---- - drivers/vfio/fsl-mc/vfio_fsl_mc.c | 20 +++- - drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c | 165 +++++++++++++++++++++++++++++- - drivers/vfio/fsl-mc/vfio_fsl_mc_private.h | 10 ++ - 3 files changed, 193 insertions(+), 2 deletions(-) - ---- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c -+++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c -@@ -144,12 +144,30 @@ err_reg_init: - static void vfio_fsl_mc_release(void *device_data) - { - struct vfio_fsl_mc_device *vdev = device_data; -+ int ret; - - mutex_lock(&vdev->reflck->lock); - -- if (!(--vdev->refcnt)) -+ if (!(--vdev->refcnt)) { -+ struct fsl_mc_device *mc_dev = vdev->mc_dev; -+ struct device *cont_dev = fsl_mc_cont_dev(&mc_dev->dev); -+ struct fsl_mc_device *mc_cont = to_fsl_mc_device(cont_dev); -+ struct fsl_mc_bus *mc_bus; -+ -+ mc_bus = to_fsl_mc_bus(mc_cont); -+ - vfio_fsl_mc_regions_cleanup(vdev); - -+ /* reset the device before cleaning up the interrupts */ -+ ret = dprc_reset_container(mc_dev->mc_io, 0, -+ mc_dev->mc_handle, -+ mc_dev->obj_desc.id); -+ -+ vfio_fsl_mc_irqs_cleanup(vdev); -+ -+ fsl_mc_cleanup_irq_pool(mc_bus); -+ } -+ - mutex_unlock(&vdev->reflck->lock); - - module_put(THIS_MODULE); ---- a/drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c -+++ b/drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c -@@ -29,12 +29,154 @@ static int vfio_fsl_mc_irq_unmask(struct - return -EINVAL; - } - -+int vfio_fsl_mc_irqs_allocate(struct vfio_fsl_mc_device *vdev) -+{ -+ struct fsl_mc_device *mc_dev = vdev->mc_dev; -+ struct vfio_fsl_mc_irq *mc_irq; -+ int irq_count; -+ int ret, i; -+ -+ /* Device does not support any interrupt */ -+ if (mc_dev->obj_desc.irq_count == 0) -+ return 0; -+ -+ /* interrupts were already allocated for this device */ -+ if (vdev->mc_irqs) -+ return 0; -+ -+ irq_count = mc_dev->obj_desc.irq_count; -+ -+ mc_irq = kcalloc(irq_count, sizeof(*mc_irq), GFP_KERNEL); -+ if (mc_irq == NULL) -+ return -ENOMEM; -+ -+ /* Allocate IRQs */ -+ ret = fsl_mc_allocate_irqs(mc_dev); -+ if (ret) { -+ kfree(mc_irq); -+ return ret; -+ } -+ -+ for (i = 0; i < irq_count; i++) { -+ mc_irq[i].count = 1; -+ mc_irq[i].flags = VFIO_IRQ_INFO_EVENTFD; -+ } -+ -+ vdev->mc_irqs = mc_irq; -+ -+ return 0; -+} -+static irqreturn_t vfio_fsl_mc_irq_handler(int irq_num, void *arg) -+{ -+ struct vfio_fsl_mc_irq *mc_irq = (struct vfio_fsl_mc_irq *)arg; -+ -+ eventfd_signal(mc_irq->trigger, 1); -+ return IRQ_HANDLED; -+} -+ -+static int vfio_set_trigger(struct vfio_fsl_mc_device *vdev, -+ int index, int fd) -+{ -+ struct vfio_fsl_mc_irq *irq = &vdev->mc_irqs[index]; -+ struct eventfd_ctx *trigger; -+ int hwirq; -+ int ret; -+ -+ hwirq = vdev->mc_dev->irqs[index]->msi_desc->irq; -+ if (irq->trigger) { -+ free_irq(hwirq, irq); -+ kfree(irq->name); -+ eventfd_ctx_put(irq->trigger); -+ irq->trigger = NULL; -+ } -+ -+ if (fd < 0) /* Disable only */ -+ return 0; -+ -+ irq->name = kasprintf(GFP_KERNEL, "vfio-irq[%d](%s)", -+ hwirq, dev_name(&vdev->mc_dev->dev)); -+ if (!irq->name) -+ return -ENOMEM; -+ -+ trigger = eventfd_ctx_fdget(fd); -+ if (IS_ERR(trigger)) { -+ kfree(irq->name); -+ return PTR_ERR(trigger); -+ } -+ -+ irq->trigger = trigger; -+ -+ ret = request_irq(hwirq, vfio_fsl_mc_irq_handler, 0, -+ irq->name, irq); -+ if (ret) { -+ kfree(irq->name); -+ eventfd_ctx_put(trigger); -+ irq->trigger = NULL; -+ return ret; -+ } -+ -+ return 0; -+} -+ - static int vfio_fsl_mc_set_irq_trigger(struct vfio_fsl_mc_device *vdev, - unsigned int index, unsigned int start, - unsigned int count, uint32_t flags, - void *data) - { -- return -EINVAL; -+ struct fsl_mc_device *mc_dev = vdev->mc_dev; -+ struct fsl_mc_bus *mc_bus; -+ int ret, hwirq; -+ struct vfio_fsl_mc_irq *irq; -+ struct device *cont_dev = fsl_mc_cont_dev(&mc_dev->dev); -+ struct fsl_mc_device *mc_cont = to_fsl_mc_device(cont_dev); -+ -+ if (start != 0 || count != 1) -+ return -EINVAL; -+ -+ mc_bus = to_fsl_mc_bus(mc_cont); -+ -+ mutex_lock(&vdev->reflck->lock); -+ if (!mc_bus->irq_resources) { -+ -+ ret = fsl_mc_populate_irq_pool(mc_bus, -+ FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); -+ if (ret) -+ goto unlock; -+ } -+ -+ ret = vfio_fsl_mc_irqs_allocate(vdev); -+ if (ret) -+ goto unlock; -+ mutex_unlock(&vdev->reflck->lock); -+ -+ if (!count && (flags & VFIO_IRQ_SET_DATA_NONE)) -+ return vfio_set_trigger(vdev, index, -1); -+ -+ if (flags & VFIO_IRQ_SET_DATA_EVENTFD) { -+ int32_t fd = *(int32_t *)data; -+ -+ return vfio_set_trigger(vdev, index, fd); -+ } -+ -+ hwirq = vdev->mc_dev->irqs[index]->msi_desc->irq; -+ -+ irq = &vdev->mc_irqs[index]; -+ -+ if (flags & VFIO_IRQ_SET_DATA_NONE) { -+ vfio_fsl_mc_irq_handler(hwirq, irq); -+ -+ } else if (flags & VFIO_IRQ_SET_DATA_BOOL) { -+ uint8_t trigger = *(uint8_t *)data; -+ -+ if (trigger) -+ vfio_fsl_mc_irq_handler(hwirq, irq); -+ } -+ -+ return 0; -+ -+unlock: -+ mutex_unlock(&vdev->reflck->lock); -+ return ret; - } - int vfio_fsl_mc_set_irqs_ioctl(struct vfio_fsl_mc_device *vdev, - uint32_t flags, unsigned int index, -@@ -60,3 +202,24 @@ int vfio_fsl_mc_set_irqs_ioctl(struct vf - - return ret; - } -+ -+/* Free All IRQs for the given MC object */ -+void vfio_fsl_mc_irqs_cleanup(struct vfio_fsl_mc_device *vdev) -+{ -+ struct fsl_mc_device *mc_dev = vdev->mc_dev; -+ int irq_count = mc_dev->obj_desc.irq_count; -+ int i; -+ -+ /* Device does not support any interrupt or the interrupts -+ * were not configured -+ */ -+ if (mc_dev->obj_desc.irq_count == 0 || !vdev->mc_irqs) -+ return; -+ -+ for (i = 0; i < irq_count; i++) -+ vfio_set_trigger(vdev, i, -1); -+ -+ fsl_mc_free_irqs(mc_dev); -+ kfree(vdev->mc_irqs); -+ vdev->mc_irqs = NULL; -+} ---- a/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h -+++ b/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h -@@ -15,6 +15,13 @@ - #define VFIO_FSL_MC_INDEX_TO_OFFSET(index) \ - ((u64)(index) << VFIO_FSL_MC_OFFSET_SHIFT) - -+struct vfio_fsl_mc_irq { -+ u32 flags; -+ u32 count; -+ struct eventfd_ctx *trigger; -+ char *name; -+}; -+ - struct vfio_fsl_mc_reflck { - struct kref kref; - struct mutex lock; -@@ -33,6 +40,7 @@ struct vfio_fsl_mc_device { - u32 num_regions; - struct vfio_fsl_mc_region *regions; - struct vfio_fsl_mc_reflck *reflck; -+ struct vfio_fsl_mc_irq *mc_irqs; - }; - - int vfio_fsl_mc_set_irqs_ioctl(struct vfio_fsl_mc_device *vdev, -@@ -40,4 +48,6 @@ int vfio_fsl_mc_set_irqs_ioctl(struct vf - unsigned int start, unsigned int count, - void *data); - -+void vfio_fsl_mc_irqs_cleanup(struct vfio_fsl_mc_device *vdev); -+ - #endif /* VFIO_PCI_PRIVATE_H */ |