Tommy Christensen wrote:
jamal wrote:
Didnt see anymore discussion on this - have we given up on it?
It is not forgotten - just stalled ...
I'll try to look at it some more.
Sorry for the long delay.
Jamal, do you think something like this could work?
Flushing of the DMA ring could be added if the need arises.
e1000 does this already in the driver on link-down.
-Tommy
diff -ur linux-2.6.11-rc2-bk8/net/core/link_watch.c
linux-2.6.11-work/net/core/link_watch.c
--- linux-2.6.11-rc2-bk8/net/core/link_watch.c 2005-01-30 22:08:44.000000000
+0100
+++ linux-2.6.11-work/net/core/link_watch.c 2005-01-31 00:17:45.716039247
+0100
@@ -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,9 @@
clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
if (dev->flags & IFF_UP) {
+ if (netif_carrier_ok(dev) &&
+ dev->qdisc_sleeping != &noop_qdisc)
+ dev_activate(dev);
netdev_state_change(dev);
}
diff -ur linux-2.6.11-rc2-bk8/net/sched/sch_generic.c
linux-2.6.11-work/net/sched/sch_generic.c
--- linux-2.6.11-rc2-bk8/net/sched/sch_generic.c 2005-01-30
22:11:50.458216314 +0100
+++ linux-2.6.11-work/net/sched/sch_generic.c 2005-01-31 00:06:47.609769835
+0100
@@ -185,6 +185,7 @@
static void dev_watchdog(unsigned long arg)
{
struct net_device *dev = (struct net_device *)arg;
+ int check_carrier = 0;
spin_lock(&dev->xmit_lock);
if (dev->qdisc != &noop_qdisc) {
@@ -198,10 +199,23 @@
}
if (!mod_timer(&dev->watchdog_timer, jiffies +
dev->watchdog_timeo))
dev_hold(dev);
- }
+ } else
+ check_carrier = 1;
}
spin_unlock(&dev->xmit_lock);
+ if (check_carrier) {
+ spin_lock(&dev->queue_lock);
+ if (!netif_carrier_ok(dev) && netif_queue_stopped(dev)) {
+ struct Qdisc *qdisc;
+
+ qdisc = dev->qdisc;
+ dev->qdisc = &noop_qdisc;
+ qdisc_reset(qdisc);
+ }
+ spin_unlock(&dev->queue_lock);
+ }
+
dev_put(dev);
}
|