[dpdk-dev] [PATCH v10 02/19] raw/ifpga/base: add irq support

Andy Pei andy.pei at intel.com
Mon Oct 21 08:23:04 CEST 2019


From: Tianfei zhang <tianfei.zhang at intel.com>

Add irq support for ifpga FME global error, port error and uint unit.
We implmented this feature by vfio interrupt mechanism.

To build this feature, CONFIG_RTE_EAL_VFIO should be enabled.

Signed-off-by: Tianfei zhang <tianfei.zhang at intel.com>
Signed-off-by: Andy Pei <andy.pei at intel.com>
---
 config/common_base                         |  2 +-
 config/common_linux                        |  6 +++
 drivers/raw/ifpga/base/ifpga_feature_dev.c | 59 ++++++++++++++++++++++++++++++
 drivers/raw/ifpga/base/ifpga_fme_error.c   | 19 ++++++++++
 drivers/raw/ifpga/base/ifpga_port.c        | 18 +++++++++
 drivers/raw/ifpga/base/ifpga_port_error.c  | 19 ++++++++++
 6 files changed, 122 insertions(+), 1 deletion(-)

diff --git a/config/common_base b/config/common_base
index e843a21..68a4f70 100644
--- a/config/common_base
+++ b/config/common_base
@@ -772,7 +772,7 @@ CONFIG_RTE_LIBRTE_PMD_DPAA2_QDMA_RAWDEV=n
 #
 # Compile PMD for Intel FPGA raw device
 #
-CONFIG_RTE_LIBRTE_PMD_IFPGA_RAWDEV=y
+CONFIG_RTE_LIBRTE_PMD_IFPGA_RAWDEV=n
 
 #
 # Compile PMD for Intel IOAT raw device
diff --git a/config/common_linux b/config/common_linux
index 96e2e1f..a78b8c6 100644
--- a/config/common_linux
+++ b/config/common_linux
@@ -68,3 +68,9 @@ CONFIG_RTE_LIBRTE_HINIC_PMD=y
 # Hisilicon HNS3 PMD driver
 #
 CONFIG_RTE_LIBRTE_HNS3_PMD=y
+
+#
+# Compile PMD for Intel FPGA raw device
+# To compile, CONFIG_RTE_EAL_VFIO should be enabled.
+#
+CONFIG_RTE_LIBRTE_PMD_IFPGA_RAWDEV=y
diff --git a/drivers/raw/ifpga/base/ifpga_feature_dev.c b/drivers/raw/ifpga/base/ifpga_feature_dev.c
index 63c8bcc..0f852a7 100644
--- a/drivers/raw/ifpga/base/ifpga_feature_dev.c
+++ b/drivers/raw/ifpga/base/ifpga_feature_dev.c
@@ -3,6 +3,7 @@
  */
 
 #include <sys/ioctl.h>
+#include <rte_vfio.h>
 
 #include "ifpga_feature_dev.h"
 
@@ -331,3 +332,61 @@ int port_hw_init(struct ifpga_port_hw *port)
 	port_hw_uinit(port);
 	return ret;
 }
+
+#define FPGA_MAX_MSIX_VEC_COUNT	128
+/* irq set buffer length for interrupt */
+#define MSIX_IRQ_SET_BUF_LEN (sizeof(struct vfio_irq_set) + \
+				sizeof(int) * FPGA_MAX_MSIX_VEC_COUNT)
+
+/* only support msix for now*/
+static int vfio_msix_enable_block(s32 vfio_dev_fd, unsigned int vec_start,
+				  unsigned int count, s32 *fds)
+{
+	char irq_set_buf[MSIX_IRQ_SET_BUF_LEN];
+	struct vfio_irq_set *irq_set;
+	int len, ret;
+	int *fd_ptr;
+
+	len = sizeof(irq_set_buf);
+
+	irq_set = (struct vfio_irq_set *)irq_set_buf;
+	irq_set->argsz = len;
+	/* 0 < irq_set->count < FPGA_MAX_MSIX_VEC_COUNT */
+	irq_set->count = count ?
+		(count > FPGA_MAX_MSIX_VEC_COUNT ?
+		 FPGA_MAX_MSIX_VEC_COUNT : count) : 1;
+	irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
+				VFIO_IRQ_SET_ACTION_TRIGGER;
+	irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
+	irq_set->start = vec_start;
+
+	fd_ptr = (int *)&irq_set->data;
+	opae_memcpy(fd_ptr, fds, sizeof(int) * count);
+
+	ret = ioctl(vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
+	if (ret)
+		printf("Error enabling MSI-X interrupts\n");
+
+	return ret;
+}
+
+int fpga_msix_set_block(struct ifpga_feature *feature, unsigned int start,
+			unsigned int count, s32 *fds)
+{
+	struct feature_irq_ctx *ctx = feature->ctx;
+	unsigned int i;
+	int ret;
+
+	if (start >= feature->ctx_num || start + count > feature->ctx_num)
+		return -EINVAL;
+
+	/* assume that each feature has continuous vector space in msix*/
+	ret = vfio_msix_enable_block(feature->vfio_dev_fd,
+				     ctx[start].idx, count, fds);
+	if (!ret) {
+		for (i = 0; i < count; i++)
+			ctx[i].eventfd = fds[i];
+	}
+
+	return ret;
+}
diff --git a/drivers/raw/ifpga/base/ifpga_fme_error.c b/drivers/raw/ifpga/base/ifpga_fme_error.c
index 3794564..2978c79 100644
--- a/drivers/raw/ifpga/base/ifpga_fme_error.c
+++ b/drivers/raw/ifpga/base/ifpga_fme_error.c
@@ -373,9 +373,28 @@ static int fme_global_error_set_prop(struct ifpga_feature *feature,
 	return -ENOENT;
 }
 
+static int fme_global_err_set_irq(struct ifpga_feature *feature, void *irq_set)
+{
+	struct fpga_fme_err_irq_set *err_irq_set = irq_set;
+	struct ifpga_fme_hw *fme;
+	int ret;
+
+	fme = (struct ifpga_fme_hw *)feature->parent;
+
+	if (!(fme->capability & FPGA_FME_CAP_ERR_IRQ))
+		return -ENODEV;
+
+	spinlock_lock(&fme->lock);
+	ret = fpga_msix_set_block(feature, 0, 1, &err_irq_set->evtfd);
+	spinlock_unlock(&fme->lock);
+
+	return ret;
+}
+
 struct ifpga_feature_ops fme_global_err_ops = {
 	.init = fme_global_error_init,
 	.uinit = fme_global_error_uinit,
 	.get_prop = fme_global_error_get_prop,
 	.set_prop = fme_global_error_set_prop,
+	.set_irq = fme_global_err_set_irq,
 };
diff --git a/drivers/raw/ifpga/base/ifpga_port.c b/drivers/raw/ifpga/base/ifpga_port.c
index 6c41164..c0aaf01 100644
--- a/drivers/raw/ifpga/base/ifpga_port.c
+++ b/drivers/raw/ifpga/base/ifpga_port.c
@@ -384,9 +384,27 @@ static void port_uint_uinit(struct ifpga_feature *feature)
 	dev_info(NULL, "PORT UINT UInit.\n");
 }
 
+static int port_uint_set_irq(struct ifpga_feature *feature, void *irq_set)
+{
+	struct fpga_uafu_irq_set *uafu_irq_set = irq_set;
+	struct ifpga_port_hw *port = feature->parent;
+	int ret;
+
+	if (!(port->capability & FPGA_PORT_CAP_UAFU_IRQ))
+		return -ENODEV;
+
+	spinlock_lock(&port->lock);
+	ret = fpga_msix_set_block(feature, uafu_irq_set->start,
+				  uafu_irq_set->count, uafu_irq_set->evtfds);
+	spinlock_unlock(&port->lock);
+
+	return ret;
+}
+
 struct ifpga_feature_ops ifpga_rawdev_port_uint_ops = {
 	.init = port_uint_init,
 	.uinit = port_uint_uinit,
+	.set_irq = port_uint_set_irq,
 };
 
 static int port_afu_init(struct ifpga_feature *feature)
diff --git a/drivers/raw/ifpga/base/ifpga_port_error.c b/drivers/raw/ifpga/base/ifpga_port_error.c
index 138284e..189f762 100644
--- a/drivers/raw/ifpga/base/ifpga_port_error.c
+++ b/drivers/raw/ifpga/base/ifpga_port_error.c
@@ -136,9 +136,28 @@ static int port_error_set_prop(struct ifpga_feature *feature,
 	return -ENOENT;
 }
 
+static int port_error_set_irq(struct ifpga_feature *feature, void *irq_set)
+{
+	struct fpga_port_err_irq_set *err_irq_set = irq_set;
+	struct ifpga_port_hw *port;
+	int ret;
+
+	port = feature->parent;
+
+	if (!(port->capability & FPGA_PORT_CAP_ERR_IRQ))
+		return -ENODEV;
+
+	spinlock_lock(&port->lock);
+	ret = fpga_msix_set_block(feature, 0, 1, &err_irq_set->evtfd);
+	spinlock_unlock(&port->lock);
+
+	return ret;
+}
+
 struct ifpga_feature_ops ifpga_rawdev_port_error_ops = {
 	.init = port_error_init,
 	.uinit = port_error_uinit,
 	.get_prop = port_error_get_prop,
 	.set_prop = port_error_set_prop,
+	.set_irq = port_error_set_irq,
 };
-- 
1.8.3.1



More information about the dev mailing list