macb: prepare at91 to use a 2-frame TX queue
authorWilly Tarreau <w@1wt.eu>
Sun, 11 Oct 2020 09:09:43 +0000 (11:09 +0200)
committerJakub Kicinski <kuba@kernel.org>
Tue, 13 Oct 2020 23:57:12 +0000 (16:57 -0700)
The RM9200 supports one frame being sent while another one is waiting in
queue. This avoids the dead time that follows the emission of a frame
and which prevents one from reaching line speed.

Right now the driver supports only a single skb, so we'll first replace
the rm9200-specific skb info with an array of two macb_tx_skb (already
used by other drivers). This patch only moves the skb_length to
txq[0].size and skb_physaddr to skb[0].mapping but doesn't perform any
other change. It already uses [desc] in order to minimize future changes.

Cc: Nicolas Ferre <nicolas.ferre@microchip.com>
Cc: Claudiu Beznea <claudiu.beznea@microchip.com>
Cc: Daniel Palmer <daniel@0x0f.com>
Signed-off-by: Willy Tarreau <w@1wt.eu>
Link: https://lore.kernel.org/r/20201011090944.10607-3-w@1wt.eu
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/cadence/macb_main.c

index 1dbf7d86d2671d6fc4c55aef865dd53473233fca..4c4672ff66a30bd55d453306090f43d9b69377c0 100644 (file)
@@ -1207,10 +1207,8 @@ struct macb {
 
        phy_interface_t         phy_interface;
 
-       /* AT91RM9200 transmit */
-       struct sk_buff *skb;                    /* holds skb until xmit interrupt completes */
-       dma_addr_t skb_physaddr;                /* phys addr from pci_map_single */
-       int skb_length;                         /* saved skb length for pci_unmap_single */
+       /* AT91RM9200 transmit queue (1 on wire + 1 queued) */
+       struct macb_tx_skb      rm9200_txq[2];
        unsigned int            max_tx_length;
 
        u64                     ethtool_stats[GEM_STATS_LEN + QUEUE_STATS_LEN * MACB_MAX_QUEUES];
index 4b42b2d6398cc25f442cf6c5598ff2e65c24a25e..35d2f7f42e0b3b4d3de39ce096afee309221f98c 100644 (file)
@@ -3995,14 +3995,16 @@ static netdev_tx_t at91ether_start_xmit(struct sk_buff *skb,
        struct macb *lp = netdev_priv(dev);
 
        if (macb_readl(lp, TSR) & MACB_BIT(RM9200_BNQ)) {
+               int desc = 0;
+
                netif_stop_queue(dev);
 
                /* Store packet information (to free when Tx completed) */
-               lp->skb = skb;
-               lp->skb_length = skb->len;
-               lp->skb_physaddr = dma_map_single(&lp->pdev->dev, skb->data,
-                                                 skb->len, DMA_TO_DEVICE);
-               if (dma_mapping_error(&lp->pdev->dev, lp->skb_physaddr)) {
+               lp->rm9200_txq[desc].skb = skb;
+               lp->rm9200_txq[desc].size = skb->len;
+               lp->rm9200_txq[desc].mapping = dma_map_single(&lp->pdev->dev, skb->data,
+                                                             skb->len, DMA_TO_DEVICE);
+               if (dma_mapping_error(&lp->pdev->dev, lp->rm9200_txq[desc].mapping)) {
                        dev_kfree_skb_any(skb);
                        dev->stats.tx_dropped++;
                        netdev_err(dev, "%s: DMA mapping error\n", __func__);
@@ -4010,7 +4012,7 @@ static netdev_tx_t at91ether_start_xmit(struct sk_buff *skb,
                }
 
                /* Set address of the data in the Transmit Address register */
-               macb_writel(lp, TAR, lp->skb_physaddr);
+               macb_writel(lp, TAR, lp->rm9200_txq[desc].mapping);
                /* Set length of the packet in the Transmit Control register */
                macb_writel(lp, TCR, skb->len);
 
@@ -4073,6 +4075,7 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
        struct net_device *dev = dev_id;
        struct macb *lp = netdev_priv(dev);
        u32 intstatus, ctl;
+       unsigned int desc;
 
        /* MAC Interrupt Status register indicates what interrupts are pending.
         * It is automatically cleared once read.
@@ -4089,13 +4092,14 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
                if (intstatus & (MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE)))
                        dev->stats.tx_errors++;
 
-               if (lp->skb) {
-                       dev_consume_skb_irq(lp->skb);
-                       lp->skb = NULL;
-                       dma_unmap_single(&lp->pdev->dev, lp->skb_physaddr,
-                                        lp->skb_length, DMA_TO_DEVICE);
+               desc = 0;
+               if (lp->rm9200_txq[desc].skb) {
+                       dev_consume_skb_irq(lp->rm9200_txq[desc].skb);
+                       lp->rm9200_txq[desc].skb = NULL;
+                       dma_unmap_single(&lp->pdev->dev, lp->rm9200_txq[desc].mapping,
+                                        lp->rm9200_txq[desc].size, DMA_TO_DEVICE);
                        dev->stats.tx_packets++;
-                       dev->stats.tx_bytes += lp->skb_length;
+                       dev->stats.tx_bytes += lp->rm9200_txq[desc].size;
                }
                netif_wake_queue(dev);
        }