net/macb: increase RX buffer size for GEM
[firefly-linux-kernel-4.4.55.git] / drivers / net / ethernet / cadence / macb.c
index 6be513deb17f69b73be4b321821e99d3ec7a17cd..aab7bb22b1d0b1d101e762df9a66ec1ff9676f83 100644 (file)
@@ -32,7 +32,9 @@
 
 #include "macb.h"
 
-#define RX_BUFFER_SIZE         128
+#define MACB_RX_BUFFER_SIZE    128
+#define GEM_RX_BUFFER_SIZE     2048
+#define RX_BUFFER_MULTIPLE     64  /* bytes */
 #define RX_RING_SIZE           512 /* must be power of 2 */
 #define RX_RING_BYTES          (sizeof(struct macb_dma_desc) * RX_RING_SIZE)
 
@@ -92,7 +94,7 @@ static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
 
 static void *macb_rx_buffer(struct macb *bp, unsigned int index)
 {
-       return bp->rx_buffers + RX_BUFFER_SIZE * macb_rx_ring_wrap(index);
+       return bp->rx_buffers + bp->rx_buffer_size * macb_rx_ring_wrap(index);
 }
 
 void macb_set_hwaddr(struct macb *bp)
@@ -485,7 +487,8 @@ static void macb_tx_interrupt(struct macb *bp)
        status = macb_readl(bp, TSR);
        macb_writel(bp, TSR, status);
 
-       macb_writel(bp, ISR, MACB_BIT(TCOMP));
+       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+               macb_writel(bp, ISR, MACB_BIT(TCOMP));
 
        netdev_vdbg(bp->dev, "macb_tx_interrupt status = 0x%03lx\n",
                (unsigned long)status);
@@ -574,7 +577,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
        skb_put(skb, len);
 
        for (frag = first_frag; ; frag++) {
-               unsigned int frag_len = RX_BUFFER_SIZE;
+               unsigned int frag_len = bp->rx_buffer_size;
 
                if (offset + frag_len > len) {
                        BUG_ON(frag != last_frag);
@@ -582,7 +585,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
                }
                skb_copy_to_linear_data_offset(skb, offset,
                                macb_rx_buffer(bp, frag), frag_len);
-               offset += RX_BUFFER_SIZE;
+               offset += bp->rx_buffer_size;
                desc = macb_rx_desc(bp, frag);
                desc->addr &= ~MACB_BIT(RX_USED);
 
@@ -738,7 +741,8 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
                         * now.
                         */
                        macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
-                       macb_writel(bp, ISR, MACB_BIT(RCOMP));
+                       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+                               macb_writel(bp, ISR, MACB_BIT(RCOMP));
 
                        if (napi_schedule_prep(&bp->napi)) {
                                netdev_vdbg(bp->dev, "scheduling RX softirq\n");
@@ -868,6 +872,30 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
+static void macb_init_rx_buffer_size(struct macb *bp)
+{
+       if (!macb_is_gem(bp)) {
+               bp->rx_buffer_size = MACB_RX_BUFFER_SIZE;
+       } else {
+               bp->rx_buffer_size = GEM_RX_BUFFER_SIZE;
+
+               if (bp->rx_buffer_size > PAGE_SIZE) {
+                       netdev_warn(bp->dev,
+                                   "RX buffer cannot be bigger than PAGE_SIZE, shrinking\n");
+                       bp->rx_buffer_size = PAGE_SIZE;
+               }
+               if (bp->rx_buffer_size % RX_BUFFER_MULTIPLE) {
+                       netdev_warn(bp->dev,
+                                   "RX buffer must be multiple of %d bytes, shrinking\n",
+                                   RX_BUFFER_MULTIPLE);
+                       bp->rx_buffer_size =
+                               rounddown(bp->rx_buffer_size, RX_BUFFER_MULTIPLE);
+               }
+               bp->rx_buffer_size = max(RX_BUFFER_MULTIPLE, GEM_RX_BUFFER_SIZE);
+       }
+}
+
+
 static void macb_free_consistent(struct macb *bp)
 {
        if (bp->tx_skb) {
@@ -886,7 +914,7 @@ static void macb_free_consistent(struct macb *bp)
        }
        if (bp->rx_buffers) {
                dma_free_coherent(&bp->pdev->dev,
-                                 RX_RING_SIZE * RX_BUFFER_SIZE,
+                                 RX_RING_SIZE * bp->rx_buffer_size,
                                  bp->rx_buffers, bp->rx_buffers_dma);
                bp->rx_buffers = NULL;
        }
@@ -919,7 +947,7 @@ static int macb_alloc_consistent(struct macb *bp)
                   "Allocated TX ring of %d bytes at %08lx (mapped %p)\n",
                   size, (unsigned long)bp->tx_ring_dma, bp->tx_ring);
 
-       size = RX_RING_SIZE * RX_BUFFER_SIZE;
+       size = RX_RING_SIZE * bp->rx_buffer_size;
        bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size,
                                            &bp->rx_buffers_dma, GFP_KERNEL);
        if (!bp->rx_buffers)
@@ -944,7 +972,7 @@ static void macb_init_rings(struct macb *bp)
        for (i = 0; i < RX_RING_SIZE; i++) {
                bp->rx_ring[i].addr = addr;
                bp->rx_ring[i].ctrl = 0;
-               addr += RX_BUFFER_SIZE;
+               addr += bp->rx_buffer_size;
        }
        bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP);
 
@@ -1054,7 +1082,7 @@ static void macb_configure_dma(struct macb *bp)
 
        if (macb_is_gem(bp)) {
                dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
-               dmacfg |= GEM_BF(RXBS, RX_BUFFER_SIZE / 64);
+               dmacfg |= GEM_BF(RXBS, bp->rx_buffer_size / RX_BUFFER_MULTIPLE);
                dmacfg |= GEM_BF(FBLDO, 16);
                dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
                dmacfg &= ~GEM_BIT(ENDIA);
@@ -1062,6 +1090,17 @@ static void macb_configure_dma(struct macb *bp)
        }
 }
 
+/*
+ * Configure peripheral capacities according to integration options used
+ */
+static void macb_configure_caps(struct macb *bp)
+{
+       if (macb_is_gem(bp)) {
+               if (GEM_BF(IRQCOR, gem_readl(bp, DCFG1)) == 0)
+                       bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
+       }
+}
+
 static void macb_init_hw(struct macb *bp)
 {
        u32 config;
@@ -1084,6 +1123,7 @@ static void macb_init_hw(struct macb *bp)
        bp->duplex = DUPLEX_HALF;
 
        macb_configure_dma(bp);
+       macb_configure_caps(bp);
 
        /* Initialize TX and RX buffers */
        macb_writel(bp, RBQP, bp->rx_ring_dma);
@@ -1230,6 +1270,9 @@ static int macb_open(struct net_device *dev)
        if (!bp->phy_dev)
                return -EAGAIN;
 
+       /* RX buffers initialization */
+       macb_init_rx_buffer_size(bp);
+
        err = macb_alloc_consistent(bp);
        if (err) {
                netdev_err(dev, "Unable to allocate DMA memory (error %d)\n",
@@ -1635,7 +1678,6 @@ err_out_put_pclk:
 err_out_free_dev:
        free_netdev(dev);
 err_out:
-       platform_set_drvdata(pdev, NULL);
        return err;
 }
 
@@ -1661,7 +1703,6 @@ static int __exit macb_remove(struct platform_device *pdev)
                clk_disable_unprepare(bp->pclk);
                clk_put(bp->pclk);
                free_netdev(dev);
-               platform_set_drvdata(pdev, NULL);
        }
 
        return 0;