]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
net: macb: Allocate valid memory for TX and RX BD prefetch
authorHarini Katakam <harini.katakam@xilinx.com>
Fri, 6 Jul 2018 06:48:58 +0000 (12:18 +0530)
committerDavid S. Miller <davem@davemloft.net>
Sat, 7 Jul 2018 11:54:25 +0000 (20:54 +0900)
GEM version in ZynqMP and most versions greater than r1p07 supports
TX and RX BD prefetch. The number of BDs that can be prefetched is a
HW configurable parameter. For ZynqMP, this parameter is 4.

When GEM DMA is accessing the last BD in the ring, even before the
BD is processed and the WRAP bit is noticed, it will have prefetched
BDs outside the BD ring. These will not be processed but it is
necessary to have accessible memory after the last BD. Especially
in cases where SMMU is used, memory locations immediately after the
last BD may not have translation tables triggering HRESP errors. Hence
always allocate extra BDs to accommodate for prefetch.
The value of tx/rx bd prefetch for any given SoC version is:
2 ^ (corresponding field in design config 10 register).
(value of this field >= 1)

Added a capability flag so that older IP versions that do not have
DCFG10 or this prefetch capability are not affected.

Signed-off-by: Harini Katakam <harini.katakam@xilinx.com>
Reviewed-by: Claudiu Beznea <claudiu.beznea@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/cadence/macb_main.c

index 86659823b2592e20d16e1fbc0640d45c99508f47..3d45f4c92cf6e5d3f091ae654e5312165956d19f 100644 (file)
 #define GEM_DCFG6              0x0294 /* Design Config 6 */
 #define GEM_DCFG7              0x0298 /* Design Config 7 */
 #define GEM_DCFG8              0x029C /* Design Config 8 */
+#define GEM_DCFG10             0x02A4 /* Design Config 10 */
 
 #define GEM_TXBDCTRL   0x04cc /* TX Buffer Descriptor control register */
 #define GEM_RXBDCTRL   0x04d0 /* RX Buffer Descriptor control register */
 #define GEM_SCR2CMP_OFFSET                     0
 #define GEM_SCR2CMP_SIZE                       8
 
+/* Bitfields in DCFG10 */
+#define GEM_TXBD_RDBUFF_OFFSET                 12
+#define GEM_TXBD_RDBUFF_SIZE                   4
+#define GEM_RXBD_RDBUFF_OFFSET                 8
+#define GEM_RXBD_RDBUFF_SIZE                   4
+
 /* Bitfields in TISUBN */
 #define GEM_SUBNSINCR_OFFSET                   0
 #define GEM_SUBNSINCR_SIZE                     16
 #define MACB_CAPS_USRIO_DISABLED               0x00000010
 #define MACB_CAPS_JUMBO                                0x00000020
 #define MACB_CAPS_GEM_HAS_PTP                  0x00000040
+#define MACB_CAPS_BD_RD_PREFETCH               0x00000080
 #define MACB_CAPS_FIFO_MODE                    0x10000000
 #define MACB_CAPS_GIGABIT_MODE_AVAILABLE       0x20000000
 #define MACB_CAPS_SG_DISABLED                  0x40000000
@@ -1203,6 +1211,9 @@ struct macb {
        unsigned int max_tuples;
 
        struct tasklet_struct   hresp_err_tasklet;
+
+       int     rx_bd_rd_prefetch;
+       int     tx_bd_rd_prefetch;
 };
 
 #ifdef CONFIG_MACB_USE_HWSTAMP
index 2d5d0d1101512d4d8537cb8df929f226922abaf6..a6c911bb5ce22588276a9f92561947ff5bff2726 100644 (file)
@@ -1811,6 +1811,7 @@ static void macb_free_consistent(struct macb *bp)
 {
        struct macb_queue *queue;
        unsigned int q;
+       int size;
 
        bp->macbgem_ops.mog_free_rx_buffers(bp);
 
@@ -1818,12 +1819,14 @@ static void macb_free_consistent(struct macb *bp)
                kfree(queue->tx_skb);
                queue->tx_skb = NULL;
                if (queue->tx_ring) {
-                       dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES(bp),
+                       size = TX_RING_BYTES(bp) + bp->tx_bd_rd_prefetch;
+                       dma_free_coherent(&bp->pdev->dev, size,
                                          queue->tx_ring, queue->tx_ring_dma);
                        queue->tx_ring = NULL;
                }
                if (queue->rx_ring) {
-                       dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES(bp),
+                       size = RX_RING_BYTES(bp) + bp->rx_bd_rd_prefetch;
+                       dma_free_coherent(&bp->pdev->dev, size,
                                          queue->rx_ring, queue->rx_ring_dma);
                        queue->rx_ring = NULL;
                }
@@ -1873,7 +1876,7 @@ static int macb_alloc_consistent(struct macb *bp)
        int size;
 
        for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-               size = TX_RING_BYTES(bp);
+               size = TX_RING_BYTES(bp) + bp->tx_bd_rd_prefetch;
                queue->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
                                                    &queue->tx_ring_dma,
                                                    GFP_KERNEL);
@@ -1889,7 +1892,7 @@ static int macb_alloc_consistent(struct macb *bp)
                if (!queue->tx_skb)
                        goto out_err;
 
-               size = RX_RING_BYTES(bp);
+               size = RX_RING_BYTES(bp) + bp->rx_bd_rd_prefetch;
                queue->rx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
                                                 &queue->rx_ring_dma, GFP_KERNEL);
                if (!queue->rx_ring)
@@ -3796,7 +3799,7 @@ static const struct macb_config np4_config = {
 static const struct macb_config zynqmp_config = {
        .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
                        MACB_CAPS_JUMBO |
-                       MACB_CAPS_GEM_HAS_PTP,
+                       MACB_CAPS_GEM_HAS_PTP | MACB_CAPS_BD_RD_PREFETCH,
        .dma_burst_length = 16,
        .clk_init = macb_clk_init,
        .init = macb_init,
@@ -3857,7 +3860,7 @@ static int macb_probe(struct platform_device *pdev)
        void __iomem *mem;
        const char *mac;
        struct macb *bp;
-       int err;
+       int err, val;
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        mem = devm_ioremap_resource(&pdev->dev, regs);
@@ -3946,6 +3949,18 @@ static int macb_probe(struct platform_device *pdev)
        else
                dev->max_mtu = ETH_DATA_LEN;
 
+       if (bp->caps & MACB_CAPS_BD_RD_PREFETCH) {
+               val = GEM_BFEXT(RXBD_RDBUFF, gem_readl(bp, DCFG10));
+               if (val)
+                       bp->rx_bd_rd_prefetch = (2 << (val - 1)) *
+                                               macb_dma_desc_get_size(bp);
+
+               val = GEM_BFEXT(TXBD_RDBUFF, gem_readl(bp, DCFG10));
+               if (val)
+                       bp->tx_bd_rd_prefetch = (2 << (val - 1)) *
+                                               macb_dma_desc_get_size(bp);
+       }
+
        mac = of_get_mac_address(np);
        if (mac) {
                ether_addr_copy(bp->dev->dev_addr, mac);