From patchwork Fri Mar 25 09:37:34 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cyrille Pitchen X-Patchwork-Id: 8669321 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id C47849F6E1 for ; Fri, 25 Mar 2016 09:39:45 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C75D320382 for ; Fri, 25 Mar 2016 09:39:44 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CE6EE2037E for ; Fri, 25 Mar 2016 09:39:43 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ajOBv-000646-AB; Fri, 25 Mar 2016 09:38:03 +0000 Received: from eusmtp01.atmel.com ([212.144.249.242]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ajOBG-0005hS-V4 for linux-arm-kernel@lists.infradead.org; Fri, 25 Mar 2016 09:37:26 +0000 Received: from tenerife.corp.atmel.com (10.161.101.13) by eusmtp01.atmel.com (10.161.101.30) with Microsoft SMTP Server id 14.3.235.1; Fri, 25 Mar 2016 10:36:53 +0100 From: Cyrille Pitchen To: , , , , Subject: [PATCH v2 1/1] net: macb: remove BUG_ON() and reset the queue to handle RX errors Date: Fri, 25 Mar 2016 10:37:34 +0100 Message-ID: <1458898654-25864-1-git-send-email-cyrille.pitchen@atmel.com> X-Mailer: git-send-email 1.8.2.2 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160325_023723_516792_820C1012 X-CRM114-Status: GOOD ( 14.65 ) X-Spam-Score: -4.2 (----) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Cyrille Pitchen , linux-kernel@vger.kernel.org, narmstrong@baylibre.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-5.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch removes two BUG_ON() used to notify about RX queue corruptions on macb (not gem) hardware without actually handling the error. The new code skips corrupted frames but still processes faultless frames. Then it resets the RX queue before restarting the reception from a clean state. This patch is a rework of an older patch proposed by Neil Armstrong: http://patchwork.ozlabs.org/patch/371525/ Signed-off-by: Cyrille Pitchen Acked-by: Neil Armstrong Acked-by: Nicolas Ferre --- ChangeLog v1 -> v2 - add Acked-by Neil Armstrong and Nicolas Ferre - use bool type instead of int for the 'reset_rx_queue' variable - move longer declarations before shorter declarations drivers/net/ethernet/cadence/macb.c | 59 ++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index f715352a9b85..6c3dc27cb100 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -917,7 +917,10 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, unsigned int frag_len = bp->rx_buffer_size; if (offset + frag_len > len) { - BUG_ON(frag != last_frag); + if (unlikely(frag != last_frag)) { + dev_kfree_skb_any(skb); + return -1; + } frag_len = len - offset; } skb_copy_to_linear_data_offset(skb, offset, @@ -945,8 +948,23 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, return 0; } +static inline void macb_init_rx_ring(struct macb *bp) +{ + dma_addr_t addr; + int i; + + addr = bp->rx_buffers_dma; + for (i = 0; i < RX_RING_SIZE; i++) { + bp->rx_ring[i].addr = addr; + bp->rx_ring[i].ctrl = 0; + addr += bp->rx_buffer_size; + } + bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP); +} + static int macb_rx(struct macb *bp, int budget) { + bool reset_rx_queue = false; int received = 0; unsigned int tail; int first_frag = -1; @@ -972,10 +990,18 @@ static int macb_rx(struct macb *bp, int budget) if (ctrl & MACB_BIT(RX_EOF)) { int dropped; - BUG_ON(first_frag == -1); + + if (unlikely(first_frag == -1)) { + reset_rx_queue = true; + continue; + } dropped = macb_rx_frame(bp, first_frag, tail); first_frag = -1; + if (unlikely(dropped < 0)) { + reset_rx_queue = true; + continue; + } if (!dropped) { received++; budget--; @@ -983,6 +1009,26 @@ static int macb_rx(struct macb *bp, int budget) } } + if (unlikely(reset_rx_queue)) { + unsigned long flags; + u32 ctrl; + + netdev_err(bp->dev, "RX queue corruption: reset it\n"); + + spin_lock_irqsave(&bp->lock, flags); + + ctrl = macb_readl(bp, NCR); + macb_writel(bp, NCR, ctrl & ~MACB_BIT(RE)); + + macb_init_rx_ring(bp); + macb_writel(bp, RBQP, bp->rx_ring_dma); + + macb_writel(bp, NCR, ctrl | MACB_BIT(RE)); + + spin_unlock_irqrestore(&bp->lock, flags); + return received; + } + if (first_frag != -1) bp->rx_tail = first_frag; else @@ -1523,15 +1569,8 @@ static void gem_init_rings(struct macb *bp) static void macb_init_rings(struct macb *bp) { int i; - dma_addr_t addr; - addr = bp->rx_buffers_dma; - for (i = 0; i < RX_RING_SIZE; i++) { - bp->rx_ring[i].addr = addr; - bp->rx_ring[i].ctrl = 0; - addr += bp->rx_buffer_size; - } - bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP); + macb_init_rx_ring(bp); for (i = 0; i < TX_RING_SIZE; i++) { bp->queues[0].tx_ring[i].addr = 0;