You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openwrt/target/linux/layerscape/patches-5.4/701-net-0309-staging-fsl_pp...

119 lines
3.3 KiB
Diff

From 0c072b46ecc8689be160bfdc750e95ad9879d706 Mon Sep 17 00:00:00 2001
From: Akhil Goyal <akhil.goyal@nxp.com>
Date: Thu, 5 Jul 2018 20:14:21 +0530
Subject: [PATCH] staging: fsl_ppfe: enable hif event from userspace
HIF interrupts are enabled using ioctl from user space,
and epoll wait from user space wakes up when there is an HIF
interrupt.
Signed-off-by: Akhil Goyal <akhil.goyal@nxp.com>
---
drivers/staging/fsl_ppfe/pfe_cdev.c | 57 +++++++++++++++++++++++++++++++++++++
drivers/staging/fsl_ppfe/pfe_cdev.h | 5 ++--
2 files changed, 60 insertions(+), 2 deletions(-)
--- a/drivers/staging/fsl_ppfe/pfe_cdev.c
+++ b/drivers/staging/fsl_ppfe/pfe_cdev.c
@@ -20,11 +20,18 @@
* - used for interacting with the kernel layer for link status
*/
+#include <linux/eventfd.h>
+#include <linux/irqreturn.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+
#include "pfe_cdev.h"
+#include "pfe_mod.h"
static int pfe_majno;
static struct class *pfe_char_class;
static struct device *pfe_char_dev;
+struct eventfd_ctx *g_trigger;
struct pfe_shared_info link_states[PFE_CDEV_ETH_COUNT];
@@ -80,10 +87,44 @@ static ssize_t pfe_cdev_write(struct fil
static int pfe_cdev_release(struct inode *inp, struct file *fp)
{
+ if (g_trigger) {
+ free_irq(pfe->hif_irq, g_trigger);
+ eventfd_ctx_put(g_trigger);
+ g_trigger = NULL;
+ }
+
pr_info("PFE_CDEV: Device successfully closed\n");
return 0;
}
+/*
+ * hif_us_isr-
+ * This ISR routine processes Rx/Tx done interrupts from the HIF hardware block
+ */
+static irqreturn_t hif_us_isr(int irq, void *arg)
+{
+ struct eventfd_ctx *trigger = (struct eventfd_ctx *)arg;
+ int int_status;
+ int int_enable_mask;
+
+ /*Read hif interrupt source register */
+ int_status = readl_relaxed(HIF_INT_SRC);
+ int_enable_mask = readl_relaxed(HIF_INT_ENABLE);
+
+ if ((int_status & HIF_INT) == 0)
+ return IRQ_NONE;
+
+ if (int_status & HIF_RXPKT_INT) {
+ int_enable_mask &= ~(HIF_RXPKT_INT);
+ eventfd_signal(trigger, 1);
+ }
+
+ /*Disable interrupts, they will be enabled after they are serviced */
+ writel_relaxed(int_enable_mask, HIF_INT_ENABLE);
+
+ return IRQ_HANDLED;
+}
+
static long pfe_cdev_ioctl(struct file *fp, unsigned int cmd,
unsigned long arg)
{
@@ -105,6 +146,22 @@ static long pfe_cdev_ioctl(struct file *
pr_debug("Returning state=%d for ETH1\n", *argp);
ret = 0;
break;
+ case PFE_CDEV_HIF_INTR_EN:
+ /* Return success/failure */
+ g_trigger = eventfd_ctx_fdget(*argp);
+ if (IS_ERR(g_trigger))
+ return PTR_ERR(g_trigger);
+ ret = request_irq(pfe->hif_irq, hif_us_isr, 0, "pfe_hif",
+ g_trigger);
+ if (ret) {
+ pr_err("%s: failed to get the hif IRQ = %d\n",
+ __func__, pfe->hif_irq);
+ eventfd_ctx_put(g_trigger);
+ g_trigger = NULL;
+ }
+ pr_debug("request_irq for hif interrupt: %d\n", pfe->hif_irq);
+ ret = 0;
+ break;
default:
pr_info("Unsupport cmd (%d) for PFE CDEV.\n", cmd);
break;
--- a/drivers/staging/fsl_ppfe/pfe_cdev.h
+++ b/drivers/staging/fsl_ppfe/pfe_cdev.h
@@ -43,8 +43,9 @@ struct pfe_shared_info {
extern struct pfe_shared_info link_states[PFE_CDEV_ETH_COUNT];
/* IOCTL Commands */
-#define PFE_CDEV_ETH0_STATE_GET 0
-#define PFE_CDEV_ETH1_STATE_GET 1
+#define PFE_CDEV_ETH0_STATE_GET _IOR('R', 0, int)
+#define PFE_CDEV_ETH1_STATE_GET _IOR('R', 1, int)
+#define PFE_CDEV_HIF_INTR_EN _IOWR('R', 2, int)
int pfe_cdev_init(void);
void pfe_cdev_exit(void);