]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: stmmac: Re-work the queue selection for TSO packets
authorJose Abreu <Jose.Abreu@synopsys.com>
Mon, 8 Jul 2019 12:26:28 +0000 (14:26 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 28 Jul 2019 06:28:30 +0000 (08:28 +0200)
[ Upstream commit 4993e5b37e8bcb55ac90f76eb6d2432647273747 ]

Ben Hutchings says:
"This is the wrong place to change the queue mapping.
stmmac_xmit() is called with a specific TX queue locked,
and accessing a different TX queue results in a data race
for all of that queue's state.

I think this commit should be reverted upstream and in all
stable branches.  Instead, the driver should implement the
ndo_select_queue operation and override the queue mapping there."

Fixes: c5acdbee22a1 ("net: stmmac: Send TSO packets always from Queue 0")
Suggested-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

index f3735d0458ebc8339def261b490ed3b7ede552cc..ee3a5a4b20428c74290ea14b28fab9283c1d6178 100644 (file)
@@ -3058,17 +3058,8 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* Manage oversized TCP frames for GMAC4 device */
        if (skb_is_gso(skb) && priv->tso) {
-               if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
-                       /*
-                        * There is no way to determine the number of TSO
-                        * capable Queues. Let's use always the Queue 0
-                        * because if TSO is supported then at least this
-                        * one will be capable.
-                        */
-                       skb_set_queue_mapping(skb, 0);
-
+               if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))
                        return stmmac_tso_xmit(skb, dev);
-               }
        }
 
        if (unlikely(stmmac_tx_avail(priv, queue) < nfrags + 1)) {
@@ -3885,6 +3876,23 @@ static int stmmac_setup_tc(struct net_device *ndev, enum tc_setup_type type,
        }
 }
 
+static u16 stmmac_select_queue(struct net_device *dev, struct sk_buff *skb,
+                              struct net_device *sb_dev,
+                              select_queue_fallback_t fallback)
+{
+       if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
+               /*
+                * There is no way to determine the number of TSO
+                * capable Queues. Let's use always the Queue 0
+                * because if TSO is supported then at least this
+                * one will be capable.
+                */
+               return 0;
+       }
+
+       return fallback(dev, skb, NULL) % dev->real_num_tx_queues;
+}
+
 static int stmmac_set_mac_address(struct net_device *ndev, void *addr)
 {
        struct stmmac_priv *priv = netdev_priv(ndev);
@@ -4101,6 +4109,7 @@ static const struct net_device_ops stmmac_netdev_ops = {
        .ndo_tx_timeout = stmmac_tx_timeout,
        .ndo_do_ioctl = stmmac_ioctl,
        .ndo_setup_tc = stmmac_setup_tc,
+       .ndo_select_queue = stmmac_select_queue,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = stmmac_poll_controller,
 #endif