From: Stephen Hemminger <[EMAIL PROTECTED]>
Date: Mon, 5 Dec 2005 16:37:53 -0800

> I assert that with lockless transmit (ie NETIF_F_LLTX) it is
> possible for two cpu's to race with the transmit flow control
> (netif_stop_queue/netif_wake_queue).  I see it with sky2, and
> probably could reproduce with tg3 as well.
>
> A. CPU is in middle of building up a transmit,
>                                       B. CPU gets packet and passes 
> netif_queue_stopped test
> A. CPU completes transmit and since tx queue is full sets stopped
>                                       B. tests for tx queue full and....
> 
> This will cause the driver to return DEVICE_BUSY
> Tg3, skge, sky2 and rionet all print message, that this is a BUG!
> but it is just losing a corner case race, and should be silent.

I totally agree, but would recommend something like the patch below,
using tg3 as an example.

We should still warn if the transmit ring is full _and_ netif_stop_queue()
is false.  That is an illegal state to observe while holding the tx_lock.
If netif_stop_queue() is true, then it's just the race you describe above,
and should just silently return NETDEV_TX_BUSY, as you recommend.

Agreed?

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 1828a6b..d9f65f4 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -3565,12 +3565,20 @@ static int tg3_start_xmit(struct sk_buff
        if (!spin_trylock(&tp->tx_lock))
                return NETDEV_TX_LOCKED; 
 
-       /* This is a hard error, log it. */
        if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
-               netif_stop_queue(dev);
+               int was_stopped = netif_queue_stopped(dev);
+
+               if (!was_stopped)
+                       netif_stop_queue(dev);
+
                spin_unlock(&tp->tx_lock);
-               printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
-                      dev->name);
+
+               if (!was_stopped) {
+                       /* This is a hard error, log it. */
+                       printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
+                              "queue awake!\n", dev->name);
+               }
+
                return NETDEV_TX_BUSY;
        }
 
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to