diff options
author | Willy Tarreau <w@1wt.eu> | 2020-10-11 11:09:43 +0200 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2020-10-13 16:57:12 -0700 |
commit | 73d7422813839bbcae3dd28ff0d3c48d916e0b57 (patch) | |
tree | 01a2f1d7d9f082fbd0201893a58c6cce0029e1bf /drivers/net | |
parent | fa6031df12fcbc1cd21586576046d821f2cef2e2 (diff) | |
download | linux-73d7422813839bbcae3dd28ff0d3c48d916e0b57.tar.bz2 |
macb: prepare at91 to use a 2-frame TX queue
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>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/cadence/macb.h | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/cadence/macb_main.c | 28 |
2 files changed, 18 insertions, 16 deletions
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 1dbf7d86d267..4c4672ff66a3 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -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]; diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 4b42b2d6398c..35d2f7f42e0b 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -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); } |