]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: annotate accesses to queue->trans_start
authorEric Dumazet <edumazet@google.com>
Wed, 17 Nov 2021 03:29:22 +0000 (19:29 -0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 17 Nov 2021 14:56:16 +0000 (14:56 +0000)
In following patches, dev_watchdog() will no longer stop all queues.
It will read queue->trans_start locklessly.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
14 files changed:
drivers/net/ethernet/apm/xgene/xgene_enet_main.c
drivers/net/ethernet/atheros/ag71xx.c
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/ti/am65-cpsw-nuss.c
drivers/net/virtio_net.c
drivers/net/wireless/marvell/mwifiex/init.c
drivers/staging/rtl8192e/rtllib_softmac.c
include/linux/netdevice.h
net/sched/sch_generic.c

index 220dc42af31ae1200ca05441000bb2a1abd0fd89..ff2d099aab218b30783266d5f905e3f0846f0951 100644 (file)
@@ -869,7 +869,7 @@ static void xgene_enet_timeout(struct net_device *ndev, unsigned int txqueue)
 
        for (i = 0; i < pdata->txq_cnt; i++) {
                txq = netdev_get_tx_queue(ndev, i);
-               txq->trans_start = jiffies;
+               txq_trans_cond_update(txq);
                netif_tx_start_queue(txq);
        }
 }
index 88d2ab7483994a850efcea1228d9718e0f6bc2ae..e4f30bb7498fec02742376a37a22495cba38a9ea 100644 (file)
@@ -766,7 +766,7 @@ static bool ag71xx_check_dma_stuck(struct ag71xx *ag)
        unsigned long timestamp;
        u32 rx_sm, tx_sm, rx_fd;
 
-       timestamp = netdev_get_tx_queue(ag->ndev, 0)->trans_start;
+       timestamp = READ_ONCE(netdev_get_tx_queue(ag->ndev, 0)->trans_start);
        if (likely(time_before(jiffies, timestamp + HZ / 10)))
                return false;
 
index 6b2927d863e2cc7569dadd4cd1e974dcc347274e..d6871437d9515df18c7819817799f9ade8bcb57e 100644 (file)
@@ -2325,7 +2325,7 @@ dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
        txq = netdev_get_tx_queue(net_dev, queue_mapping);
 
        /* LLTX requires to do our own update of trans_start */
-       txq->trans_start = jiffies;
+       txq_trans_cond_update(txq);
 
        if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
                fd.cmd |= cpu_to_be32(FM_FD_CMD_UPD);
@@ -2531,7 +2531,7 @@ static int dpaa_xdp_xmit_frame(struct net_device *net_dev,
 
        /* Bump the trans_start */
        txq = netdev_get_tx_queue(net_dev, smp_processor_id());
-       txq->trans_start = jiffies;
+       txq_trans_cond_update(txq);
 
        err = dpaa_xmit(priv, percpu_stats, smp_processor_id(), &fd);
        if (err) {
index 13835a37b3a2fd13d557750fb3943172fc2eb700..d5100179f8d589dc4ea517f5bafca0612a5fcc38 100644 (file)
@@ -2679,7 +2679,7 @@ static bool hns3_get_tx_timeo_queue_info(struct net_device *ndev)
                unsigned long trans_start;
 
                q = netdev_get_tx_queue(ndev, i);
-               trans_start = q->trans_start;
+               trans_start = READ_ONCE(q->trans_start);
                if (netif_xmit_stopped(q) &&
                    time_after(jiffies,
                               (trans_start + ndev->watchdog_timeo))) {
index 3cca51735421a7435f4c7f32fa3f5af9003f2d37..c327fc8860da20e16b6801adc071bfb90dd05c36 100644 (file)
@@ -2058,7 +2058,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
 
        tx_packets++;
        tx_bytes += skb->len;
-       txq->trans_start = jiffies;
+       txq_trans_cond_update(txq);
        ret = NETDEV_TX_OK;
        goto out;
 
index 836be0d3b29105d48530e2ce6b3f8db13c730e71..18a019a47182218ff85a83a00e75c99005e22a34 100644 (file)
@@ -2927,7 +2927,7 @@ static int igb_xdp_xmit_back(struct igb_adapter *adapter, struct xdp_buff *xdp)
        nq = txring_txq(tx_ring);
        __netif_tx_lock(nq, cpu);
        /* Avoid transmit queue timeout since we share it with the slow path */
-       nq->trans_start = jiffies;
+       txq_trans_cond_update(nq);
        ret = igb_xmit_xdp_ring(adapter, tx_ring, xdpf);
        __netif_tx_unlock(nq);
 
@@ -2961,7 +2961,7 @@ static int igb_xdp_xmit(struct net_device *dev, int n,
        __netif_tx_lock(nq, cpu);
 
        /* Avoid transmit queue timeout since we share it with the slow path */
-       nq->trans_start = jiffies;
+       txq_trans_cond_update(nq);
 
        for (i = 0; i < n; i++) {
                struct xdp_frame *xdpf = frames[i];
index 4f4bc8726ec4fa2b20a32edb25780ad177f6860a..86060513328739ecd6702525a6902bd82c7d2db6 100644 (file)
@@ -565,7 +565,7 @@ int mlx5e_reporter_tx_timeout(struct mlx5e_txqsq *sq)
        snprintf(err_str, sizeof(err_str),
                 "TX timeout on queue: %d, SQ: 0x%x, CQ: 0x%x, SQ Cons: 0x%x SQ Prod: 0x%x, usecs since last trans: %u",
                 sq->ch_ix, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc,
-                jiffies_to_usecs(jiffies - sq->txq->trans_start));
+                jiffies_to_usecs(jiffies - READ_ONCE(sq->txq->trans_start)));
 
        mlx5e_health_report(priv, priv->tx_reporter, err_str, &err_ctx);
        return to_ctx.status;
index 033c35c09a54876eeb87e30aad5ec8e8613f13b9..389d125310c151e54b428d19616fd07531051f54 100644 (file)
@@ -2356,7 +2356,7 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
        bool work_done = true;
 
        /* Avoids TX time-out as we are sharing with slow path */
-       nq->trans_start = jiffies;
+       txq_trans_cond_update(nq->trans_start);
 
        budget = min(budget, stmmac_tx_avail(priv, queue));
 
@@ -4657,7 +4657,7 @@ static int stmmac_xdp_xmit_back(struct stmmac_priv *priv,
 
        __netif_tx_lock(nq, cpu);
        /* Avoids TX time-out as we are sharing with slow path */
-       nq->trans_start = jiffies;
+       txq_trans_cond_update(nq->trans_start);
 
        res = stmmac_xdp_xmit_xdpf(priv, queue, xdpf, false);
        if (res == STMMAC_XDP_TX)
@@ -6293,7 +6293,7 @@ static int stmmac_xdp_xmit(struct net_device *dev, int num_frames,
 
        __netif_tx_lock(nq, cpu);
        /* Avoids TX time-out as we are sharing with slow path */
-       nq->trans_start = jiffies;
+       txq_trans_cond_update(nq);
 
        for (i = 0; i < num_frames; i++) {
                int res;
index c092cb61416a180a5ce1d0d28bd163e4a1dab302..750cea23e9cd02bba139a58553c4b1753956ad10 100644 (file)
@@ -345,7 +345,7 @@ static void am65_cpsw_nuss_ndo_host_tx_timeout(struct net_device *ndev,
 
        netif_txq = netdev_get_tx_queue(ndev, txqueue);
        tx_chn = &common->tx_chns[txqueue];
-       trans_start = netif_txq->trans_start;
+       trans_start = READ_ONCE(netif_txq->trans_start);
 
        netdev_err(ndev, "txq:%d DRV_XOFF:%d tmo:%u dql_avail:%d free_desc:%zu\n",
                   txqueue,
index 1771d6e5224fd834a4dfca4ba578134439d4d201..03e38e38ee4b5a97567eb692cd84a55722a1a8b2 100644 (file)
@@ -2694,7 +2694,7 @@ static void virtnet_tx_timeout(struct net_device *dev, unsigned int txqueue)
 
        netdev_err(dev, "TX timeout on queue: %u, sq: %s, vq: 0x%x, name: %s, %u usecs ago\n",
                   txqueue, sq->name, sq->vq->index, sq->vq->name,
-                  jiffies_to_usecs(jiffies - txq->trans_start));
+                  jiffies_to_usecs(jiffies - READ_ONCE(txq->trans_start)));
 }
 
 static const struct net_device_ops virtnet_netdev = {
index f006a3d72b4046f435739e9218e3be6bf7001adc..88c72d1827a00d608e90e03beb20202228cd8699 100644 (file)
@@ -332,7 +332,7 @@ void mwifiex_set_trans_start(struct net_device *dev)
        int i;
 
        for (i = 0; i < dev->num_tx_queues; i++)
-               netdev_get_tx_queue(dev, i)->trans_start = jiffies;
+               txq_trans_cond_update(netdev_get_tx_queue(dev, i));
 
        netif_trans_update(dev);
 }
index d2726d01c7573fe8230e0a7e0f7f811c1ff8cffc..aabbea48223d2f7915285c883e2ae94111bd91b6 100644 (file)
@@ -2515,7 +2515,7 @@ void rtllib_stop_all_queues(struct rtllib_device *ieee)
        unsigned int i;
 
        for (i = 0; i < ieee->dev->num_tx_queues; i++)
-               netdev_get_tx_queue(ieee->dev, i)->trans_start = jiffies;
+               txq_trans_cond_update(netdev_get_tx_queue(ieee->dev, i));
 
        netif_tx_stop_all_queues(ieee->dev);
 }
index 1d22483cf78ccc60d5cd2d79770f65e1e988c28b..279409ef2b18c31fc1709d1e70bf0fc0b81d0de7 100644 (file)
@@ -4095,10 +4095,21 @@ static inline void __netif_tx_unlock_bh(struct netdev_queue *txq)
        spin_unlock_bh(&txq->_xmit_lock);
 }
 
+/*
+ * txq->trans_start can be read locklessly from dev_watchdog()
+ */
 static inline void txq_trans_update(struct netdev_queue *txq)
 {
        if (txq->xmit_lock_owner != -1)
-               txq->trans_start = jiffies;
+               WRITE_ONCE(txq->trans_start, jiffies);
+}
+
+static inline void txq_trans_cond_update(struct netdev_queue *txq)
+{
+       unsigned long now = jiffies;
+
+       if (READ_ONCE(txq->trans_start) != now)
+               WRITE_ONCE(txq->trans_start, now);
 }
 
 /* legacy drivers only, netdev_start_xmit() sets txq->trans_start */
@@ -4106,8 +4117,7 @@ static inline void netif_trans_update(struct net_device *dev)
 {
        struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
 
-       if (txq->trans_start != jiffies)
-               txq->trans_start = jiffies;
+       txq_trans_cond_update(txq);
 }
 
 /**
index 1b4328bd495d54d44a9d51b53c8e8bc18b9cc294..02c46041f76e85571fd2862e02fb409bfd8e6611 100644 (file)
@@ -434,9 +434,9 @@ unsigned long dev_trans_start(struct net_device *dev)
                dev = vlan_dev_real_dev(dev);
        else if (netif_is_macvlan(dev))
                dev = macvlan_dev_real_dev(dev);
-       res = netdev_get_tx_queue(dev, 0)->trans_start;
+       res = READ_ONCE(netdev_get_tx_queue(dev, 0)->trans_start);
        for (i = 1; i < dev->num_tx_queues; i++) {
-               val = netdev_get_tx_queue(dev, i)->trans_start;
+               val = READ_ONCE(netdev_get_tx_queue(dev, i)->trans_start);
                if (val && time_after(val, res))
                        res = val;
        }
@@ -462,7 +462,7 @@ static void dev_watchdog(struct timer_list *t)
                                struct netdev_queue *txq;
 
                                txq = netdev_get_tx_queue(dev, i);
-                               trans_start = txq->trans_start;
+                               trans_start = READ_ONCE(txq->trans_start);
                                if (netif_xmit_stopped(txq) &&
                                    time_after(jiffies, (trans_start +
                                                         dev->watchdog_timeo))) {
@@ -1148,7 +1148,7 @@ static void transition_one_qdisc(struct net_device *dev,
 
        rcu_assign_pointer(dev_queue->qdisc, new_qdisc);
        if (need_watchdog_p) {
-               dev_queue->trans_start = 0;
+               WRITE_ONCE(dev_queue->trans_start, 0);
                *need_watchdog_p = 1;
        }
 }