diff options
author | Jarek Poplawski <jarkao2@gmail.com> | 2008-09-07 21:41:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-09-07 21:41:21 -0400 |
commit | e8a83e10d7dfe5d0841062780769b30f65417e15 (patch) | |
tree | bc7069b34bb3173970ec06690323a1ab0f89ff56 /net | |
parent | e3b802ba885b54f4050164c3cfd9e0ba9c73173a (diff) |
pkt_sched: Fix qdisc state in net_tx_action()
net_tx_action() can skip __QDISC_STATE_SCHED bit clearing while qdisc
is neither ran nor rescheduled, which may cause endless loop in
dev_deactivate().
Reported-by: Denys Fedoryshchenko <denys@visp.net.lb>
Tested-by: Denys Fedoryshchenko <denys@visp.net.lb>
Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/dev.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 60c51f765887..e719ed29310f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1991,8 +1991,13 @@ static void net_tx_action(struct softirq_action *h) | |||
1991 | spin_unlock(root_lock); | 1991 | spin_unlock(root_lock); |
1992 | } else { | 1992 | } else { |
1993 | if (!test_bit(__QDISC_STATE_DEACTIVATED, | 1993 | if (!test_bit(__QDISC_STATE_DEACTIVATED, |
1994 | &q->state)) | 1994 | &q->state)) { |
1995 | __netif_reschedule(q); | 1995 | __netif_reschedule(q); |
1996 | } else { | ||
1997 | smp_mb__before_clear_bit(); | ||
1998 | clear_bit(__QDISC_STATE_SCHED, | ||
1999 | &q->state); | ||
2000 | } | ||
1996 | } | 2001 | } |
1997 | } | 2002 | } |
1998 | } | 2003 | } |