net: bcmgenet: Implement TX coalescing control knobs
authorFlorian Fainelli <f.fainelli@gmail.com>
Wed, 16 Sep 2015 23:47:39 +0000 (16:47 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 18 Sep 2015 05:17:14 +0000 (22:17 -0700)
Configuring the ethtool tx-frames property, which translates into N
packets before a TX interrupt is the simplest configuration scheme
because it requires no locking neither at the softare nor hardware
level, and is completely indepedent from the link speed. Since ethtool
does not allow per-tx queue coalescing parameters, we apply the same
setting to any transmit queue.

We can no longer enable the BDONE/PDONE interrupts as those would fire
for each packet/buffer received, which would defeat the MBDONE interrupt
purpose. The MBDONE interrupt is guaranteed to correspond to a
PDONE/BDONE interrupt when the threshold is set to 1, but offers
interrupt coalescing when the value is > 1.

Since the HW is configured to generate an interrupt when the ring
becomes emtpy, we have to deny any timeout/timer settings coming from
user-space to indicate we can only generate an interrupt very <N>
packets.

While we are at it, fix the DMA_INTR_THRESHOLD_MASK value which was off
by one bit (0xff vs. 0x1ff).

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/broadcom/genet/bcmgenet.h

index fadbd0088d3e6b3fa6b748c419e2586393d7da6f..5e247c7b379e455785d966c4df87acb4029f78ed 100644 (file)
@@ -498,6 +498,51 @@ static void bcmgenet_set_msglevel(struct net_device *dev, u32 level)
        priv->msg_enable = level;
 }
 
+static int bcmgenet_get_coalesce(struct net_device *dev,
+                                struct ethtool_coalesce *ec)
+{
+       struct bcmgenet_priv *priv = netdev_priv(dev);
+
+       ec->tx_max_coalesced_frames =
+               bcmgenet_tdma_ring_readl(priv, DESC_INDEX,
+                                        DMA_MBUF_DONE_THRESH);
+
+       return 0;
+}
+
+static int bcmgenet_set_coalesce(struct net_device *dev,
+                                struct ethtool_coalesce *ec)
+{
+       struct bcmgenet_priv *priv = netdev_priv(dev);
+       unsigned int i;
+
+       if (ec->tx_max_coalesced_frames > DMA_INTR_THRESHOLD_MASK ||
+           ec->tx_max_coalesced_frames == 0)
+               return -EINVAL;
+
+       /* GENET TDMA hardware does not support a configurable timeout, but will
+        * always generate an interrupt either after MBDONE packets have been
+        * transmitted, or when the ring is emtpy.
+        */
+       if (ec->tx_coalesce_usecs || ec->tx_coalesce_usecs_high ||
+           ec->tx_coalesce_usecs_irq || ec->tx_coalesce_usecs_high ||
+           ec->tx_coalesce_usecs_low)
+               return -EOPNOTSUPP;
+
+       /* Program all TX queues with the same values, as there is no
+        * ethtool knob to do coalescing on a per-queue basis
+        */
+       for (i = 0; i < priv->hw_params->tx_queues; i++)
+               bcmgenet_tdma_ring_writel(priv, i,
+                                         ec->tx_max_coalesced_frames,
+                                         DMA_MBUF_DONE_THRESH);
+       bcmgenet_tdma_ring_writel(priv, DESC_INDEX,
+                                 ec->tx_max_coalesced_frames,
+                                 DMA_MBUF_DONE_THRESH);
+
+       return 0;
+}
+
 /* standard ethtool support functions. */
 enum bcmgenet_stat_type {
        BCMGENET_STAT_NETDEV = -1,
@@ -844,6 +889,8 @@ static struct ethtool_ops bcmgenet_ethtool_ops = {
        .get_eee                = bcmgenet_get_eee,
        .set_eee                = bcmgenet_set_eee,
        .nway_reset             = bcmgenet_nway_reset,
+       .get_coalesce           = bcmgenet_get_coalesce,
+       .set_coalesce           = bcmgenet_set_coalesce,
 };
 
 /* Power down the unimac, based on mode. */
index 7299d10754226680e71ace26cbe4f996c8867127..ef7829524d4699312b722ab2152f9706bf4edd8b 100644 (file)
@@ -309,8 +309,8 @@ struct bcmgenet_mib_counters {
 #define UMAC_IRQ_TXDMA_MBDONE          (1 << 16)
 #define UMAC_IRQ_TXDMA_PDONE           (1 << 17)
 #define UMAC_IRQ_TXDMA_BDONE           (1 << 18)
-#define UMAC_IRQ_TXDMA_DONE            (UMAC_IRQ_TXDMA_PDONE | \
-                                        UMAC_IRQ_TXDMA_BDONE)
+#define UMAC_IRQ_TXDMA_DONE            UMAC_IRQ_TXDMA_MBDONE
+
 /* Only valid for GENETv3+ */
 #define UMAC_IRQ_MDIO_DONE             (1 << 23)
 #define UMAC_IRQ_MDIO_ERROR            (1 << 24)
@@ -386,7 +386,7 @@ struct bcmgenet_mib_counters {
 #define DMA_RING_BUFFER_SIZE_MASK      0xFFFF
 
 /* DMA interrupt threshold register */
-#define DMA_INTR_THRESHOLD_MASK                0x00FF
+#define DMA_INTR_THRESHOLD_MASK                0x01FF
 
 /* DMA XON/XOFF register */
 #define DMA_XON_THREHOLD_MASK          0xFFFF