Add patches for linux-5.4. The patches are from NXP LSDK-20.04 release which was tagged LSDK-20.04-V5.4. https://source.codeaurora.org/external/qoriq/qoriq-components/linux/ For boards LS1021A-IOT, and Traverse-LS1043 which are not involved in LSDK, port the dts patches from 4.14. The patches are sorted into the following categories: 301-arch-xxxx 302-dts-xxxx 303-core-xxxx 701-net-xxxx 801-audio-xxxx 802-can-xxxx 803-clock-xxxx 804-crypto-xxxx 805-display-xxxx 806-dma-xxxx 807-gpio-xxxx 808-i2c-xxxx 809-jailhouse-xxxx 810-keys-xxxx 811-kvm-xxxx 812-pcie-xxxx 813-pm-xxxx 814-qe-xxxx 815-sata-xxxx 816-sdhc-xxxx 817-spi-xxxx 818-thermal-xxxx 819-uart-xxxx 820-usb-xxxx 821-vfio-xxxx Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
		
			
				
	
	
		
			269 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			269 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
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 */
 |