From 910f793b0e368a93f7db6ed8eda920ecf147471e Mon Sep 17 00:00:00 2001 From: John Klug Date: Fri, 4 Nov 2016 16:33:30 -0500 Subject: add Cadence ethernet patch. --- .../linux-3.12.27/linux-3.12-cadence-macb.patch | 106 +++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 recipes-kernel/linux/linux-3.12.27/linux-3.12-cadence-macb.patch (limited to 'recipes-kernel/linux/linux-3.12.27') diff --git a/recipes-kernel/linux/linux-3.12.27/linux-3.12-cadence-macb.patch b/recipes-kernel/linux/linux-3.12.27/linux-3.12-cadence-macb.patch new file mode 100644 index 0000000..c814ed1 --- /dev/null +++ b/recipes-kernel/linux/linux-3.12.27/linux-3.12-cadence-macb.patch @@ -0,0 +1,106 @@ +--- linux-3.12.27/drivers/net/ethernet/cadence/macb.c 2014-08-26 07:12:26.000000000 -0500 ++++ linux-3.12.27/drivers/net/ethernet/cadence/macb.c 2016-09-26 13:36:54.760657601 -0500 +@@ -755,7 +755,10 @@ + 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, +@@ -783,11 +786,27 @@ + return 0; + } + ++static inline void macb_init_rx_ring(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); ++ bp->rx_tail = 0; ++} ++ + static int macb_rx(struct macb *bp, int budget) + { + int received = 0; + unsigned int tail; + int first_frag = -1; ++ int reset_rx_queue = 0; + + for (tail = bp->rx_tail; budget > 0; tail++) { + struct macb_dma_desc *desc = macb_rx_desc(bp, tail); +@@ -810,10 +829,18 @@ + + if (ctrl & MACB_BIT(RX_EOF)) { + int dropped; +- BUG_ON(first_frag == -1); ++ ++ if (unlikely(first_frag == -1)) { ++ reset_rx_queue = 1; ++ continue; ++ } + + dropped = macb_rx_frame(bp, first_frag, tail); + first_frag = -1; ++ if (unlikely(dropped < 0)) { ++ reset_rx_queue = 1; ++ continue; ++ } + if (!dropped) { + received++; + budget--; +@@ -821,6 +848,26 @@ + } + } + ++ 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 +@@ -1189,15 +1236,8 @@ + 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->tx_ring[i].addr = 0; -- cgit v1.2.3