net: ll_temac: Allow configuration of IRQ coalescing
authorEsben Haabendal <esben@geanix.com>
Tue, 30 Apr 2019 07:17:58 +0000 (09:17 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 1 May 2019 18:33:30 +0000 (14:33 -0400)
This allows custom setup of IRQ coalescing for platforms using legacy
platform_device. The irq timeout and count parameters can be used for
tuning cpu load vs. latency.

I have maintained the 0x00000400 bit in TX_CHNL_CTRL.  It is specified as
unused in the documentation I have available.  It does not make any
difference in the hardware I have available, so it is left in to not risk
breaking other platforms where it might be used.

Signed-off-by: Esben Haabendal <esben@geanix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/xilinx/ll_temac.h
drivers/net/ethernet/xilinx/ll_temac_main.c
include/linux/platform_data/xilinx-ll-temac.h

index 990f9ed151b2746651539ef409c9d602c8a4a99f..1aeda084b8f15e773e0abda0f7d27ba4a160ff74 100644 (file)
@@ -375,6 +375,10 @@ struct temac_local {
        int tx_bd_next;
        int tx_bd_tail;
        int rx_bd_ci;
+
+       /* DMA channel control setup */
+       u32 tx_chnl_ctrl;
+       u32 rx_chnl_ctrl;
 };
 
 /* Wrappers for temac_ior()/temac_iow() function pointers above */
index fec8e4c229448ba2d11150f46d45e74a66bd29a5..bccef30bf64eba1e7ba1f69cd95c2cfe1fe0b364 100644 (file)
@@ -304,18 +304,15 @@ static int temac_dma_bd_init(struct net_device *ndev)
                lp->rx_bd_v[i].app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND);
        }
 
-       lp->dma_out(lp, TX_CHNL_CTRL, 0x10220400 |
-                                         CHNL_CTRL_IRQ_EN |
-                                         CHNL_CTRL_IRQ_DLY_EN |
-                                         CHNL_CTRL_IRQ_COAL_EN);
-       /* 0x10220483 */
-       /* 0x00100483 */
-       lp->dma_out(lp, RX_CHNL_CTRL, 0xff070000 |
-                                         CHNL_CTRL_IRQ_EN |
-                                         CHNL_CTRL_IRQ_DLY_EN |
-                                         CHNL_CTRL_IRQ_COAL_EN |
-                                         CHNL_CTRL_IRQ_IOE);
-       /* 0xff010283 */
+       /* Configure DMA channel (irq setup) */
+       lp->dma_out(lp, TX_CHNL_CTRL, lp->tx_chnl_ctrl |
+                   0x00000400 | // Use 1 Bit Wide Counters. Currently Not Used!
+                   CHNL_CTRL_IRQ_EN | CHNL_CTRL_IRQ_ERR_EN |
+                   CHNL_CTRL_IRQ_DLY_EN | CHNL_CTRL_IRQ_COAL_EN);
+       lp->dma_out(lp, RX_CHNL_CTRL, lp->rx_chnl_ctrl |
+                   CHNL_CTRL_IRQ_IOE |
+                   CHNL_CTRL_IRQ_EN | CHNL_CTRL_IRQ_ERR_EN |
+                   CHNL_CTRL_IRQ_DLY_EN | CHNL_CTRL_IRQ_COAL_EN);
 
        lp->dma_out(lp, RX_CURDESC_PTR,  lp->rx_bd_p);
        lp->dma_out(lp, RX_TAILDESC_PTR,
@@ -1191,6 +1188,13 @@ static int temac_probe(struct platform_device *pdev)
                lp->rx_irq = irq_of_parse_and_map(dma_np, 0);
                lp->tx_irq = irq_of_parse_and_map(dma_np, 1);
 
+               /* Use defaults for IRQ delay/coalescing setup.  These
+                * are configuration values, so does not belong in
+                * device-tree.
+                */
+               lp->tx_chnl_ctrl = 0x10220000;
+               lp->rx_chnl_ctrl = 0xff070000;
+
                /* Finished with the DMA node; drop the reference */
                of_node_put(dma_np);
        } else if (pdata) {
@@ -1214,6 +1218,18 @@ static int temac_probe(struct platform_device *pdev)
                /* Get DMA RX and TX interrupts */
                lp->rx_irq = platform_get_irq(pdev, 0);
                lp->tx_irq = platform_get_irq(pdev, 1);
+
+               /* IRQ delay/coalescing setup */
+               if (pdata->tx_irq_timeout || pdata->tx_irq_count)
+                       lp->tx_chnl_ctrl = (pdata->tx_irq_timeout << 24) |
+                               (pdata->tx_irq_count << 16);
+               else
+                       lp->tx_chnl_ctrl = 0x10220000;
+               if (pdata->rx_irq_timeout || pdata->rx_irq_count)
+                       lp->rx_chnl_ctrl = (pdata->rx_irq_timeout << 24) |
+                               (pdata->rx_irq_count << 16);
+               else
+                       lp->rx_chnl_ctrl = 0xff070000;
        }
 
        /* Error handle returned DMA RX and TX interrupts */
index b0b8238a9b7d473468b809e0459f12cca34be1e2..368530f9817637125e53c5d6d0282dd9c399c014 100644 (file)
@@ -22,6 +22,11 @@ struct ll_temac_platform_data {
         * they share the same DCR bus bridge.
         */
        struct mutex *indirect_mutex;
+       /* DMA channel control setup */
+       u8 tx_irq_timeout;      /* TX Interrupt Delay Time-out */
+       u8 tx_irq_count;        /* TX Interrupt Coalescing Threshold Count */
+       u8 rx_irq_timeout;      /* RX Interrupt Delay Time-out */
+       u8 rx_irq_count;        /* RX Interrupt Coalescing Threshold Count */
 };
 
 #endif /* __LINUX_XILINX_LL_TEMAC_H */