[PATCH 3.16 011/294] net: bcmgenet: simplify __bcmgenet_tx_reclaim()

From: Ben Hutchings
Date: Mon Nov 06 2017 - 20:11:59 EST


3.16.50-rc1 review patch. If anyone has any objections, please let me know.

------------------

From: Petri Gynther <pgynther@xxxxxxxxxx>

commit 66d06757d9eb74a29775737b8c770e3b57e536d9 upstream.

1. Use c_index and ring->c_index to determine how many TxCBs/TxBDs are
ready for cleanup
- c_index = the current value of TDMA_CONS_INDEX
- TDMA_CONS_INDEX is HW-incremented and auto-wraparound (0x0-0xFFFF)
- ring->c_index = __bcmgenet_tx_reclaim() cleaned up to this point on
the previous invocation

2. Add bcmgenet_tx_ring->clean_ptr
- index of the next TxCB to be cleaned
- incremented as TxCBs/TxBDs are processed
- value always in range [ring->cb_ptr, ring->end_ptr]

3. Fix incrementing of dev->stats.tx_packets
- should be incremented only when tx_cb_ptr->skb != NULL

These changes simplify __bcmgenet_tx_reclaim(). Furthermore, Tx ring size
can now be any value.

With the old code, Tx ring size had to be a power-of-2:
num_tx_bds = ring->size;
c_index &= (num_tx_bds - 1);
last_c_index &= (num_tx_bds - 1);

Signed-off-by: Petri Gynther <pgynther@xxxxxxxxxx>
Reviewed-by: Florian Fainelli <f.fainelli@xxxxxxxxx>
Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>
[bwh: Backported to 3.16:
- __bcmgenet_tx_reclaim() did not count completions
- In bcmgenet_init_tx_ring(), use write_ptr not start_ptr
- Adjust context]
Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx>
---
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -946,34 +946,30 @@ static void __bcmgenet_tx_reclaim(struct
{
struct bcmgenet_priv *priv = netdev_priv(dev);
struct device *kdev = &priv->pdev->dev;
- int last_tx_cn, last_c_index, num_tx_bds;
struct enet_cb *tx_cb_ptr;
struct netdev_queue *txq;
unsigned int c_index;
+ unsigned int txbds_ready;
+ unsigned int txbds_processed = 0;

/* Compute how many buffers are transmited since last xmit call */
c_index = bcmgenet_tdma_ring_readl(priv, ring->index, TDMA_CONS_INDEX);
- txq = netdev_get_tx_queue(dev, ring->queue);
-
- last_c_index = ring->c_index;
- num_tx_bds = ring->size;
+ c_index &= DMA_C_INDEX_MASK;

- c_index &= (num_tx_bds - 1);
-
- if (c_index >= last_c_index)
- last_tx_cn = c_index - last_c_index;
+ if (likely(c_index >= ring->c_index))
+ txbds_ready = c_index - ring->c_index;
else
- last_tx_cn = num_tx_bds - last_c_index + c_index;
+ txbds_ready = (DMA_C_INDEX_MASK + 1) - ring->c_index + c_index;

netif_dbg(priv, tx_done, dev,
- "%s ring=%d index=%d last_tx_cn=%d last_index=%d\n",
- __func__, ring->index,
- c_index, last_tx_cn, last_c_index);
+ "%s ring=%d old_c_index=%u c_index=%u txbds_ready=%u\n",
+ __func__, ring->index, ring->c_index, c_index, txbds_ready);

/* Reclaim transmitted buffers */
- while (last_tx_cn-- > 0) {
- tx_cb_ptr = ring->cbs + last_c_index;
+ while (txbds_processed < txbds_ready) {
+ tx_cb_ptr = &priv->tx_cbs[ring->clean_ptr];
if (tx_cb_ptr->skb) {
+ dev->stats.tx_packets++;
dev->stats.tx_bytes += tx_cb_ptr->skb->len;
dma_unmap_single(kdev,
dma_unmap_addr(tx_cb_ptr, dma_addr),
@@ -989,20 +985,23 @@ static void __bcmgenet_tx_reclaim(struct
DMA_TO_DEVICE);
dma_unmap_addr_set(tx_cb_ptr, dma_addr, 0);
}
- dev->stats.tx_packets++;
- ring->free_bds += 1;

- last_c_index++;
- last_c_index &= (num_tx_bds - 1);
+ txbds_processed++;
+ if (likely(ring->clean_ptr < ring->end_ptr))
+ ring->clean_ptr++;
+ else
+ ring->clean_ptr = ring->cb_ptr;
}

+ ring->free_bds += txbds_processed;
+ ring->c_index = (ring->c_index + txbds_processed) & DMA_C_INDEX_MASK;
+
if (ring->free_bds > (MAX_SKB_FRAGS + 1))
ring->int_disable(priv, ring);

+ txq = netdev_get_tx_queue(dev, ring->queue);
if (netif_tx_queue_stopped(txq))
netif_tx_wake_queue(txq);
-
- ring->c_index = c_index;
}

static void bcmgenet_tx_reclaim(struct net_device *dev,
@@ -1644,6 +1643,7 @@ static void bcmgenet_init_tx_ring(struct
}
ring->cbs = priv->tx_cbs + write_ptr;
ring->size = size;
+ ring->clean_ptr = write_ptr;
ring->c_index = 0;
ring->free_bds = size;
ring->write_ptr = write_ptr;
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -510,6 +510,7 @@ struct bcmgenet_tx_ring {
unsigned int queue; /* queue index */
struct enet_cb *cbs; /* tx ring buffer control block*/
unsigned int size; /* size of each tx ring */
+ unsigned int clean_ptr; /* Tx ring clean pointer */
unsigned int c_index; /* last consumer index of each ring*/
unsigned int free_bds; /* # of free bds for each ring */
unsigned int write_ptr; /* Tx ring write pointer SW copy */