Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758798Ab2FQSYd (ORCPT ); Sun, 17 Jun 2012 14:24:33 -0400 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:50410 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758623Ab2FQSXE (ORCPT ); Sun, 17 Jun 2012 14:23:04 -0400 Message-Id: <20120617175944.476249157@decadent.org.uk> User-Agent: quilt/0.60-1 Date: Sun, 17 Jun 2012 19:00:03 +0100 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: torvalds@linux-foundation.org, akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk, AnilKumar Ch , Wolfgang Grandegger , Marc Kleine-Budde Subject: [ 22/69] can: c_can: fix an interrupt thrash issue with c_can driver In-Reply-To: <20120617175941.281333656@decadent.org.uk> X-SA-Exim-Connect-IP: 2001:470:1f08:1539:21c:bfff:fe03:f805 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2692 Lines: 77 3.2-stable review patch. If anyone has any objections, please let me know. ------------------ From: AnilKumar Ch commit 148c87c89e1a8863d3d965179f3ab1a06490569e upstream. This patch fixes an interrupt thrash issue with c_can driver. In c_can_isr() function interrupts are disabled and enabled only in c_can_poll() function. c_can_isr() & c_can_poll() both read the irqstatus flag. However, irqstatus is always read as 0 in c_can_poll() because all C_CAN interrupts are disabled in c_can_isr(). This causes all interrupts to be re-enabled in c_can_poll() which in turn causes another interrupt since the event is not really handled. This keeps happening causing a flood of interrupts. To fix this, read the irqstatus register in isr and use the same cached value in the poll function. Signed-off-by: AnilKumar Ch Acked-by: Wolfgang Grandegger Signed-off-by: Marc Kleine-Budde Signed-off-by: Ben Hutchings --- drivers/net/can/c_can/c_can.c | 7 +++---- drivers/net/can/c_can/c_can.h | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 9ac28df..fa01621 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -952,7 +952,7 @@ static int c_can_poll(struct napi_struct *napi, int quota) struct net_device *dev = napi->dev; struct c_can_priv *priv = netdev_priv(dev); - irqstatus = priv->read_reg(priv, &priv->regs->interrupt); + irqstatus = priv->irqstatus; if (!irqstatus) goto end; @@ -1030,12 +1030,11 @@ end: static irqreturn_t c_can_isr(int irq, void *dev_id) { - u16 irqstatus; struct net_device *dev = (struct net_device *)dev_id; struct c_can_priv *priv = netdev_priv(dev); - irqstatus = priv->read_reg(priv, &priv->regs->interrupt); - if (!irqstatus) + priv->irqstatus = priv->read_reg(priv, &priv->regs->interrupt); + if (!priv->irqstatus) return IRQ_NONE; /* disable all interrupts and schedule the NAPI */ diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index 9b7fbef..5f32d34 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -76,6 +76,7 @@ struct c_can_priv { unsigned int tx_next; unsigned int tx_echo; void *priv; /* for board-specific data */ + u16 irqstatus; }; struct net_device *alloc_c_can_dev(void); -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/