Add IRQ support for ifpga FME global error, port error and unit.
We implemented this feature by vfio interrupt mechanism.
To build this feature, CONFIG_RTE_EAL_VFIO should be enabled.
Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com>
Signed-off-by: Andy Pei <andy.pei@intel.com>
#
# 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
# 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
*/
#include <sys/ioctl.h>
+#include <rte_vfio.h>
#include "ifpga_feature_dev.h"
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;
+}
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,
};
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)
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,
};