]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
net: ftgmac100: Ensure tx descriptor updates are visible
authorJacky Chou <jacky_chou@aspeedtech.com>
Thu, 22 Aug 2024 07:30:06 +0000 (15:30 +0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 26 Aug 2024 13:05:29 +0000 (14:05 +0100)
The driver must ensure TX descriptor updates are visible
before updating TX pointer and TX clear pointer.

This resolves TX hangs observed on AST2600 when running
iperf3.

Signed-off-by: Jacky Chou <jacky_chou@aspeedtech.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/faraday/ftgmac100.c

index fddfd1dd50709fdf977f7a78eee4839c1d343ba6..4c546c3aef0fecfada101fe6a95b9aadc143b39c 100644 (file)
@@ -572,7 +572,7 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
        (*processed)++;
        return true;
 
- drop:
+drop:
        /* Clean rxdes0 (which resets own bit) */
        rxdes->rxdes0 = cpu_to_le32(status & priv->rxdes0_edorr_mask);
        priv->rx_pointer = ftgmac100_next_rx_pointer(priv, pointer);
@@ -656,6 +656,11 @@ static bool ftgmac100_tx_complete_packet(struct ftgmac100 *priv)
        ftgmac100_free_tx_packet(priv, pointer, skb, txdes, ctl_stat);
        txdes->txdes0 = cpu_to_le32(ctl_stat & priv->txdes0_edotr_mask);
 
+       /* Ensure the descriptor config is visible before setting the tx
+        * pointer.
+        */
+       smp_wmb();
+
        priv->tx_clean_pointer = ftgmac100_next_tx_pointer(priv, pointer);
 
        return true;
@@ -809,6 +814,11 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb,
        dma_wmb();
        first->txdes0 = cpu_to_le32(f_ctl_stat);
 
+       /* Ensure the descriptor config is visible before setting the tx
+        * pointer.
+        */
+       smp_wmb();
+
        /* Update next TX pointer */
        priv->tx_pointer = pointer;
 
@@ -829,7 +839,7 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb,
 
        return NETDEV_TX_OK;
 
- dma_err:
+dma_err:
        if (net_ratelimit())
                netdev_err(netdev, "map tx fragment failed\n");
 
@@ -851,7 +861,7 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb,
         * last fragment, so we know ftgmac100_free_tx_packet()
         * hasn't freed the skb yet.
         */
- drop:
+drop:
        /* Drop the packet */
        dev_kfree_skb_any(skb);
        netdev->stats.tx_dropped++;
@@ -1344,7 +1354,7 @@ static void ftgmac100_reset(struct ftgmac100 *priv)
        ftgmac100_init_all(priv, true);
 
        netdev_dbg(netdev, "Reset done !\n");
- bail:
+bail:
        if (priv->mii_bus)
                mutex_unlock(&priv->mii_bus->mdio_lock);
        if (netdev->phydev)
@@ -1543,15 +1553,15 @@ static int ftgmac100_open(struct net_device *netdev)
 
        return 0;
 
- err_ncsi:
+err_ncsi:
        napi_disable(&priv->napi);
        netif_stop_queue(netdev);
- err_alloc:
+err_alloc:
        ftgmac100_free_buffers(priv);
        free_irq(netdev->irq, netdev);
- err_irq:
+err_irq:
        netif_napi_del(&priv->napi);
- err_hw:
+err_hw:
        iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
        ftgmac100_free_rings(priv);
        return err;