netdev
[Top] [All Lists]

[PATCH] (3/4) delay scheduler race with device stopped

To: "David S. Miller" <davem@xxxxxxxxxx>
Subject: [PATCH] (3/4) delay scheduler race with device stopped
From: Stephen Hemminger <shemminger@xxxxxxxx>
Date: Thu, 17 Jun 2004 15:56:03 -0700
Cc: "Dabney, Nathanx T" <nathanx.t.dabney@xxxxxxxxx>, "Venkatesan, Ganesh" <ganesh.venkatesan@xxxxxxxxx>, "Glick, Kevin" <kevin.glick@xxxxxxxxx>, netdev@xxxxxxxxxxx, lartc@xxxxxxxxxxxxxxx
In-reply-to: <58D550446979A646A05649BF9EAF113AA2E995@orsmsx407>
Organization: Open Source Development Lab
References: <58D550446979A646A05649BF9EAF113AA2E995@orsmsx407>
Sender: netdev-bounce@xxxxxxxxxxx
The delay scheduler dequeue routine has some code cut&pasted from the TBF 
scheduler
that caused a race with E1000 when ring got full.

It looks like net schedulers should never be calling netif_queue_stopped because
the queue may get unstopped by interrrupt or receive soft irq (NAPI) which races
with the dequeue in the transmit scheduler. 

Also, if requeuing the packet fails, it is probably because the queue became 
full
by a racing enqueue.  So the right thing to do is to go back and try again.

Same patch should apply to both 2.6 and 2.4

Signed-off-by: Stephen Hemminger <shemminger@xxxxxxxx>

diff -Nru a/net/sched/sch_delay.c b/net/sched/sch_delay.c
--- a/net/sched/sch_delay.c     2004-06-17 15:21:49 -07:00
+++ b/net/sched/sch_delay.c     2004-06-17 15:21:49 -07:00
@@ -111,7 +111,7 @@
        if (skb) {
                struct dly_skb_cb *cb = (struct dly_skb_cb *)skb->cb;
                psched_time_t now;
-               long diff;
+               long diff, delay;
 
                PSCHED_GET_TIME(now);
                diff = q->latency - PSCHED_TDIFF(now, cb->queuetime);
@@ -128,13 +128,10 @@
                        goto retry;
                }
 
-               if (!netif_queue_stopped(sch->dev)) {
-                       long delay = PSCHED_US2JIFFIE(diff);
-                       if (delay <= 0)
-                               delay = 1;
-                       mod_timer(&q->timer, jiffies+delay);
-               }
-
+               delay = PSCHED_US2JIFFIE(diff);
+               if (delay <= 0) 
+                       delay = 1;
+               mod_timer(&q->timer, jiffies+delay);
                sch->flags |= TCQ_F_THROTTLED;
        }
        return NULL;

<Prev in Thread] Current Thread [Next in Thread>