From 9cd264272eeacf83fc22ed6b59e0e563ce8c8298 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Francisco=20Trivi=C3=B1o?= Date: Fri, 30 Sep 2016 10:35:14 +0200 Subject: [PATCH] sif: eq: Add timeout to the threaded interrupt handler MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This commit implements a timeout that prevents soft lockup issues when the threaded interrupt function (sif_intr_worker) keeps processing events for a long period. If the timeout is reached, the threaded handler returns IRQ_HANDLED even if there are more events to be processed. In such a case, the coalescing mechanism will generate an IRQ for the last event. Orabug: 24839976 Signed-off-by: Francisco Triviño Reviewed-by: Håkon Bugge --- drivers/infiniband/hw/sif/sif_eq.c | 12 ++++++------ drivers/infiniband/hw/sif/sif_eq.h | 6 ++++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/hw/sif/sif_eq.c b/drivers/infiniband/hw/sif/sif_eq.c index 745fcb3508f7..fec8534a34b7 100644 --- a/drivers/infiniband/hw/sif/sif_eq.c +++ b/drivers/infiniband/hw/sif/sif_eq.c @@ -37,7 +37,7 @@ static void sif_eq_table_deinit(struct sif_dev *sdev, struct sif_eps *es, u16 eq static void sif_eq_deinit_tables(struct sif_dev *sdev, struct sif_eps *es); -static bool dispatch_eq(struct sif_eq *eq, int irq, bool interruptible); +static bool dispatch_eq(struct sif_eq *eq, int irq, unsigned int msecs); static enum ib_event_type epsc2ib_event(struct psif_eq_entry *eqe); @@ -338,7 +338,7 @@ static irqreturn_t sif_intr_worker(int irq, void *d) { struct sif_eq *eq = (struct sif_eq *)d; - dispatch_eq(eq, irq, false); + dispatch_eq(eq, irq, SIF_IRQ_THR_HANDLER_TIMEOUT); return IRQ_HANDLED; } @@ -351,7 +351,7 @@ static irqreturn_t sif_intr(int irq, void *d) struct sif_eq *eq = (struct sif_eq *)d; bool wakeup_thread; - wakeup_thread = dispatch_eq(eq, irq, true); + wakeup_thread = dispatch_eq(eq, irq, SIF_IRQ_HANDLER_TIMEOUT); elapsed = jiffies_to_msecs(jiffies - start_time); @@ -885,7 +885,7 @@ static u32 handle_srq_event(struct sif_eq *eq, struct ib_event *ibe) /* Called from interrupt threads */ -static bool dispatch_eq(struct sif_eq *eq, int irq, bool interruptible) +static bool dispatch_eq(struct sif_eq *eq, int irq, unsigned int msecs) { volatile struct psif_eq_entry *eqe; struct psif_eq_entry leqe; @@ -893,7 +893,7 @@ static bool dispatch_eq(struct sif_eq *eq, int irq, bool interruptible) struct sif_dev *sdev = eq->ba.sdev; struct ib_event ibe; struct ib_qp *ibqp = NULL; - ulong timeout = jiffies + msecs_to_jiffies(SIF_IRQ_HANDLER_TIMEOUT); + ulong timeout = jiffies + msecs_to_jiffies(msecs); bool wakeup_thread = false; u32 seqno; u32 nreqs = 0; @@ -1122,7 +1122,7 @@ only_cne: eqe = (struct psif_eq_entry *)get_eq_entry(eq, seqno); nreqs++; /* check whether we should stop processing events */ - wakeup_thread = interruptible ? time_after(jiffies, timeout) : false; + wakeup_thread = msecs ? time_after(jiffies, timeout) : false; } spin_unlock_irqrestore(&eq->ba.lock, flags); atomic_add(nreqs, &eq->intr_cnt); diff --git a/drivers/infiniband/hw/sif/sif_eq.h b/drivers/infiniband/hw/sif/sif_eq.h index 87c6cfd25094..8d6b3c3541db 100644 --- a/drivers/infiniband/hw/sif/sif_eq.h +++ b/drivers/infiniband/hw/sif/sif_eq.h @@ -20,6 +20,12 @@ */ #define SIF_IRQ_HANDLER_TIMEOUT 20 +/* This defines a timeout period in msecs to stop processing events + * from the threaded irq handler (sif_intr_worker) + */ +#define SIF_IRQ_THR_HANDLER_TIMEOUT 5000 + + extern uint sif_cq_eq_max; struct sif_dev; -- 2.50.1