diff options
author | Tommy S. Christensen <tommy.christensen@tpack.net> | 2005-05-03 16:18:52 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-05-03 16:18:52 -0700 |
commit | cacaddf57ed4d5ca994e9a7e2bd5558061f5d89d (patch) | |
tree | 6e4c59a9a27441a3196cbc67a3a79356baa679fb | |
parent | 0f4821e7b93fe72e89b8ff393bd8e705bd178aa5 (diff) | |
download | op-kernel-dev-cacaddf57ed4d5ca994e9a7e2bd5558061f5d89d.zip op-kernel-dev-cacaddf57ed4d5ca994e9a7e2bd5558061f5d89d.tar.gz |
[NET]: Disable queueing when carrier is lost.
Some network drivers call netif_stop_queue() when detecting loss of
carrier. This leads to packets being queued up at the qdisc level for
an unbound period of time. In order to prevent this effect, the core
networking stack will now cease to queue packets for any device, that
is operationally down (i.e. the queue is flushed and disabled).
Signed-off-by: Tommy S. Christensen <tommy.christensen@tpack.net>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/core/link_watch.c | 7 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 4 |
2 files changed, 11 insertions, 0 deletions
diff --git a/net/core/link_watch.c b/net/core/link_watch.c index 4859b74..d43d120 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -16,6 +16,7 @@ #include <linux/netdevice.h> #include <linux/if.h> #include <net/sock.h> +#include <net/pkt_sched.h> #include <linux/rtnetlink.h> #include <linux/jiffies.h> #include <linux/spinlock.h> @@ -74,6 +75,12 @@ void linkwatch_run_queue(void) clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state); if (dev->flags & IFF_UP) { + if (netif_carrier_ok(dev)) { + WARN_ON(dev->qdisc_sleeping == &noop_qdisc); + dev_activate(dev); + } else + dev_deactivate(dev); + netdev_state_change(dev); } diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 8c01e02..9a2f8e4 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -539,6 +539,10 @@ void dev_activate(struct net_device *dev) write_unlock_bh(&qdisc_tree_lock); } + if (!netif_carrier_ok(dev)) + /* Delay activation until next carrier-on event */ + return; + spin_lock_bh(&dev->queue_lock); rcu_assign_pointer(dev->qdisc, dev->qdisc_sleeping); if (dev->qdisc != &noqueue_qdisc) { |