aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-5.4/821-vfio-0008-vfio-fsl-mc-trigger-an-interrupt-via-eventfd.patch
diff options
context:
space:
mode:
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.patch268
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 */