bcmgenet_xmit() only writes the producer index at the end of a batch. The error exits return before that write. If the dropped frame was the last of an xmit_more batch, the frames queued before it stay in the ring until the next transmit. The queue is still running, so the watchdog does not fire. Found by a sashiko review, not by a bug report. The existing exits only trigger on an allocation or DMA mapping failure, and the padding in a later patch adds three more. Write the producer index on those exits too. Fixes: ddd0ca5d60b3 ("net: bcmgenet: add support for xmit_more") Reviewed-by: Florian Fainelli Signed-off-by: Nicolai Buchwitz --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 4c9db2f9fc25..06ec8c211dd7 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -2119,6 +2119,15 @@ static void bcmgenet_hide_tsb(struct sk_buff *skb) __skb_pull(skb, sizeof(struct status_64)); } +static void bcmgenet_tx_kick(struct bcmgenet_priv *priv, + struct bcmgenet_tx_ring *ring, + struct netdev_queue *txq) +{ + if (!netdev_xmit_more() || netif_xmit_stopped(txq)) + bcmgenet_tdma_ring_writel(priv, ring->index, + ring->prod_index, TDMA_PROD_INDEX); +} + static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) { struct bcmgenet_priv *priv = netdev_priv(dev); @@ -2155,10 +2164,8 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) /* add the Transmit Status Block */ skb = bcmgenet_add_tsb(dev, skb, ring); - if (!skb) { - ret = NETDEV_TX_OK; - goto out; - } + if (!skb) + goto drop; for (i = 0; i <= nr_frags; i++) { tx_cb_ptr = bcmgenet_get_txcb(priv, ring); @@ -2183,7 +2190,6 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) if (ret) { priv->mib.tx_dma_failed++; netif_err(priv, tx_err, dev, "Tx DMA map failed\n"); - ret = NETDEV_TX_OK; goto out_unmap_frags; } dma_unmap_addr_set(tx_cb_ptr, dma_addr, mapping); @@ -2225,10 +2231,7 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) if (ring->free_bds <= (MAX_SKB_FRAGS + 1)) netif_tx_stop_queue(txq); - if (!netdev_xmit_more() || netif_xmit_stopped(txq)) - /* Packets are ready, update producer index */ - bcmgenet_tdma_ring_writel(priv, ring->index, - ring->prod_index, TDMA_PROD_INDEX); + bcmgenet_tx_kick(priv, ring, txq); out: spin_unlock(&ring->lock); @@ -2245,6 +2248,10 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) } dev_kfree_skb(skb); +drop: + /* The dropped frame may have been the last one of the batch */ + bcmgenet_tx_kick(priv, ring, txq); + ret = NETDEV_TX_OK; goto out; } -- 2.53.0