| From aa8dac23408e24432f7d6c404cddc8997a142bd6 Mon Sep 17 00:00:00 2001 |
| From: Diana Craciun <diana.craciun@nxp.com> |
| Date: Mon, 30 Sep 2019 11:56:35 +0300 |
| Subject: [PATCH] vfio/fsl-mc: Add irq infrastructure for fsl-mc devices |
| |
| This patch adds the skeleton for interrupt support |
| for fsl-mc devices. The interrupts are not yet functional, |
| the functionality will be added by subsequent patches. |
| |
| Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com> |
| Signed-off-by: Diana Craciun <diana.craciun@nxp.com> |
| --- |
| drivers/vfio/fsl-mc/Makefile | 2 +- |
| drivers/vfio/fsl-mc/vfio_fsl_mc.c | 71 ++++++++++++++++++++++++++++++- |
| drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c | 62 +++++++++++++++++++++++++++ |
| drivers/vfio/fsl-mc/vfio_fsl_mc_private.h | 5 +++ |
| 4 files changed, 137 insertions(+), 3 deletions(-) |
| create mode 100644 drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c |
| |
| --- a/drivers/vfio/fsl-mc/Makefile |
| +++ b/drivers/vfio/fsl-mc/Makefile |
| @@ -1,2 +1,2 @@ |
| vfio-fsl_mc-y := vfio_fsl_mc.o |
| -obj-$(CONFIG_VFIO_FSL_MC) += vfio_fsl_mc.o |
| +obj-$(CONFIG_VFIO_FSL_MC) += vfio_fsl_mc.o vfio_fsl_mc_intr.o |
| --- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c |
| +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c |
| @@ -208,11 +208,75 @@ static long vfio_fsl_mc_ioctl(void *devi |
| } |
| case VFIO_DEVICE_GET_IRQ_INFO: |
| { |
| - return -EINVAL; |
| + struct vfio_irq_info info; |
| + |
| + minsz = offsetofend(struct vfio_irq_info, count); |
| + if (copy_from_user(&info, (void __user *)arg, minsz)) |
| + return -EFAULT; |
| + |
| + if (info.argsz < minsz) |
| + return -EINVAL; |
| + |
| + if (info.index >= mc_dev->obj_desc.irq_count) |
| + return -EINVAL; |
| + |
| + info.flags = VFIO_IRQ_INFO_EVENTFD; |
| + info.count = 1; |
| + |
| + return copy_to_user((void __user *)arg, &info, minsz); |
| } |
| case VFIO_DEVICE_SET_IRQS: |
| { |
| - return -EINVAL; |
| + struct vfio_irq_set hdr; |
| + u8 *data = NULL; |
| + int ret = 0; |
| + |
| + minsz = offsetofend(struct vfio_irq_set, count); |
| + |
| + if (copy_from_user(&hdr, (void __user *)arg, minsz)) |
| + return -EFAULT; |
| + |
| + if (hdr.argsz < minsz) |
| + return -EINVAL; |
| + |
| + if (hdr.index >= mc_dev->obj_desc.irq_count) |
| + return -EINVAL; |
| + |
| + if (hdr.start != 0 || hdr.count > 1) |
| + return -EINVAL; |
| + |
| + if (hdr.count == 0 && |
| + (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE) || |
| + !(hdr.flags & VFIO_IRQ_SET_ACTION_TRIGGER))) |
| + return -EINVAL; |
| + |
| + if (hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK | |
| + VFIO_IRQ_SET_ACTION_TYPE_MASK)) |
| + return -EINVAL; |
| + |
| + if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) { |
| + size_t size; |
| + |
| + if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL) |
| + size = sizeof(uint8_t); |
| + else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD) |
| + size = sizeof(int32_t); |
| + else |
| + return -EINVAL; |
| + |
| + if (hdr.argsz - minsz < hdr.count * size) |
| + return -EINVAL; |
| + |
| + data = memdup_user((void __user *)(arg + minsz), |
| + hdr.count * size); |
| + if (IS_ERR(data)) |
| + return PTR_ERR(data); |
| + } |
| + |
| + ret = vfio_fsl_mc_set_irqs_ioctl(vdev, hdr.flags, |
| + hdr.index, hdr.start, |
| + hdr.count, data); |
| + return ret; |
| } |
| case VFIO_DEVICE_RESET: |
| { |
| @@ -304,6 +368,9 @@ static int vfio_fsl_mc_init_device(struc |
| int ret = 0; |
| unsigned int irq_count; |
| |
| + /* innherit the msi domain from parent */ |
| + dev_set_msi_domain(&mc_dev->dev, dev_get_msi_domain(mc_dev->dev.parent)); |
| + |
| /* Non-dprc devices share mc_io from parent */ |
| if (!is_fsl_mc_bus_dprc(mc_dev)) { |
| struct fsl_mc_device *mc_cont = to_fsl_mc_device(mc_dev->dev.parent); |
| --- /dev/null |
| +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c |
| @@ -0,0 +1,62 @@ |
| +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
| +/* |
| + * Copyright 2013-2016 Freescale Semiconductor Inc. |
| + * Copyright 2019 NXP |
| + */ |
| + |
| +#include <linux/vfio.h> |
| +#include <linux/slab.h> |
| +#include <linux/types.h> |
| +#include <linux/eventfd.h> |
| +#include <linux/msi.h> |
| + |
| +#include "linux/fsl/mc.h" |
| +#include "vfio_fsl_mc_private.h" |
| + |
| +static int vfio_fsl_mc_irq_mask(struct vfio_fsl_mc_device *vdev, |
| + unsigned int index, unsigned int start, |
| + unsigned int count, uint32_t flags, |
| + void *data) |
| +{ |
| + return -EINVAL; |
| +} |
| + |
| +static int vfio_fsl_mc_irq_unmask(struct vfio_fsl_mc_device *vdev, |
| + unsigned int index, unsigned int start, |
| + unsigned int count, uint32_t flags, |
| + void *data) |
| +{ |
| + return -EINVAL; |
| +} |
| + |
| +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; |
| +} |
| +int vfio_fsl_mc_set_irqs_ioctl(struct vfio_fsl_mc_device *vdev, |
| + uint32_t flags, unsigned int index, |
| + unsigned int start, unsigned int count, |
| + void *data) |
| +{ |
| + int ret = -ENOTTY; |
| + |
| + switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) { |
| + case VFIO_IRQ_SET_ACTION_MASK: |
| + ret = vfio_fsl_mc_irq_mask(vdev, index, start, count, |
| + flags, data); |
| + break; |
| + case VFIO_IRQ_SET_ACTION_UNMASK: |
| + ret = vfio_fsl_mc_irq_unmask(vdev, index, start, count, |
| + flags, data); |
| + break; |
| + case VFIO_IRQ_SET_ACTION_TRIGGER: |
| + ret = vfio_fsl_mc_set_irq_trigger(vdev, index, start, |
| + count, flags, data); |
| + break; |
| + } |
| + |
| + return ret; |
| +} |
| --- a/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h |
| +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h |
| @@ -35,4 +35,9 @@ struct vfio_fsl_mc_device { |
| struct vfio_fsl_mc_reflck *reflck; |
| }; |
| |
| +int vfio_fsl_mc_set_irqs_ioctl(struct vfio_fsl_mc_device *vdev, |
| + uint32_t flags, unsigned int index, |
| + unsigned int start, unsigned int count, |
| + void *data); |
| + |
| #endif /* VFIO_PCI_PRIVATE_H */ |