fpga: dfl: afu: add interrupt support for port error reporting
authorXu Yilun <yilun.xu@intel.com>
Tue, 16 Jun 2020 04:08:45 +0000 (12:08 +0800)
committerMoritz Fischer <mdf@kernel.org>
Tue, 7 Jul 2020 04:34:46 +0000 (21:34 -0700)
Error reporting interrupt is very useful to notify users that some
errors are detected by the hardware. Once users are notified, they
could query hardware logged error states, no need to continuously
poll on these states.

This patch adds interrupt support for port error reporting sub feature.
It follows the common DFL interrupt notification and handling mechanism,
implements two ioctl commands below for user to query number of irqs
supported, and set/unset interrupt triggers.

 Ioctls:
 * DFL_FPGA_PORT_ERR_GET_IRQ_NUM
   get the number of irqs, which is used to determine whether/how many
   interrupts error reporting feature supports.

 * DFL_FPGA_PORT_ERR_SET_IRQ
   set/unset given eventfds as error interrupt triggers.

Signed-off-by: Luwei Kang <luwei.kang@intel.com>
Signed-off-by: Wu Hao <hao.wu@intel.com>
Signed-off-by: Xu Yilun <yilun.xu@intel.com>
Reviewed-by: Marcelo Tosatti <mtosatti@redhat.com>
Acked-by: Wu Hao <hao.wu@intel.com>
Signed-off-by: Moritz Fischer <mdf@kernel.org>
drivers/fpga/dfl-afu-error.c
drivers/fpga/dfl-afu-main.c
include/uapi/linux/fpga-dfl.h

index c1467ae1a6b636b60c287ceb5f397e7fc0d79f9b..c4691187cca9118f278ad3894dc95ff638567740 100644 (file)
@@ -14,6 +14,7 @@
  *   Mitchel Henry <henry.mitchel@intel.com>
  */
 
+#include <linux/fpga-dfl.h>
 #include <linux/uaccess.h>
 
 #include "dfl-afu.h"
@@ -219,6 +220,21 @@ static void port_err_uinit(struct platform_device *pdev,
        afu_port_err_mask(&pdev->dev, true);
 }
 
+static long
+port_err_ioctl(struct platform_device *pdev, struct dfl_feature *feature,
+              unsigned int cmd, unsigned long arg)
+{
+       switch (cmd) {
+       case DFL_FPGA_PORT_ERR_GET_IRQ_NUM:
+               return dfl_feature_ioctl_get_num_irqs(pdev, feature, arg);
+       case DFL_FPGA_PORT_ERR_SET_IRQ:
+               return dfl_feature_ioctl_set_irq(pdev, feature, arg);
+       default:
+               dev_dbg(&pdev->dev, "%x cmd not handled", cmd);
+               return -ENODEV;
+       }
+}
+
 const struct dfl_feature_id port_err_id_table[] = {
        {.id = PORT_FEATURE_ID_ERROR,},
        {0,}
@@ -227,4 +243,5 @@ const struct dfl_feature_id port_err_id_table[] = {
 const struct dfl_feature_ops port_err_ops = {
        .init = port_err_init,
        .uinit = port_err_uinit,
+       .ioctl = port_err_ioctl,
 };
index b0c31789a9096b81e7188397cb9ae6e3017afff9..357cd5d9b26728ae8b13ead713a2380a8eb08408 100644 (file)
@@ -577,6 +577,7 @@ static int afu_release(struct inode *inode, struct file *filp)
 {
        struct platform_device *pdev = filp->private_data;
        struct dfl_feature_platform_data *pdata;
+       struct dfl_feature *feature;
 
        dev_dbg(&pdev->dev, "Device File Release\n");
 
@@ -586,6 +587,9 @@ static int afu_release(struct inode *inode, struct file *filp)
        dfl_feature_dev_use_end(pdata);
 
        if (!dfl_feature_dev_use_count(pdata)) {
+               dfl_fpga_dev_for_each_feature(pdata, feature)
+                       dfl_fpga_set_irq_triggers(feature, 0,
+                                                 feature->nr_irqs, NULL);
                __port_reset(pdev);
                afu_dma_region_destroy(pdata);
        }
index 7331350f30673df8b9fe0212f25535e9e7dfc1c5..6c71c9d7e926be8c4b68c9b0e662df8daf7320b0 100644 (file)
@@ -164,6 +164,29 @@ struct dfl_fpga_irq_set {
        __s32 evtfds[];
 };
 
+/**
+ * DFL_FPGA_PORT_ERR_GET_IRQ_NUM - _IOR(DFL_FPGA_MAGIC, DFL_PORT_BASE + 5,
+ *                                                             __u32 num_irqs)
+ *
+ * Get the number of irqs supported by the fpga port error reporting private
+ * feature. Currently hardware supports up to 1 irq.
+ * Return: 0 on success, -errno on failure.
+ */
+#define DFL_FPGA_PORT_ERR_GET_IRQ_NUM  _IOR(DFL_FPGA_MAGIC,    \
+                                            DFL_PORT_BASE + 5, __u32)
+
+/**
+ * DFL_FPGA_PORT_ERR_SET_IRQ - _IOW(DFL_FPGA_MAGIC, DFL_PORT_BASE + 6,
+ *                                             struct dfl_fpga_irq_set)
+ *
+ * Set fpga port error reporting interrupt trigger if evtfds[n] is valid.
+ * Unset related interrupt trigger if evtfds[n] is a negative value.
+ * Return: 0 on success, -errno on failure.
+ */
+#define DFL_FPGA_PORT_ERR_SET_IRQ      _IOW(DFL_FPGA_MAGIC,    \
+                                            DFL_PORT_BASE + 6, \
+                                            struct dfl_fpga_irq_set)
+
 /* IOCTLs for FME file descriptor */
 
 /**