summaryrefslogtreecommitdiff
path: root/debian/patches/libdde_trans_start.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/libdde_trans_start.patch')
-rw-r--r--debian/patches/libdde_trans_start.patch138
1 files changed, 138 insertions, 0 deletions
diff --git a/debian/patches/libdde_trans_start.patch b/debian/patches/libdde_trans_start.patch
new file mode 100644
index 00000000..07acc6dd
--- /dev/null
+++ b/debian/patches/libdde_trans_start.patch
@@ -0,0 +1,138 @@
+commit 9d21493b4beb8f918ba248032fefa393074a5e2b
+Author: Eric Dumazet <dada1@cosmosbay.com>
+Date: Sun May 17 20:55:16 2009 -0700
+
+ net: tx scalability works : trans_start
+
+ struct net_device trans_start field is a hot spot on SMP and high performance
+ devices, particularly multi queues ones, because every transmitter dirties
+ it. Is main use is tx watchdog and bonding alive checks.
+
+ But as most devices dont use NETIF_F_LLTX, we have to lock
+ a netdev_queue before calling their ndo_start_xmit(). So it makes
+ sense to move trans_start from net_device to netdev_queue. Its update
+ will occur on a already present (and in exclusive state) cache line, for
+ free.
+
+ We can do this transition smoothly. An old driver continue to
+ update dev->trans_start, while an updated one updates txq->trans_start.
+
+ Further patches could also put tx_bytes/tx_packets counters in
+ netdev_queue to avoid dirtying dev->stats (vlan device comes to mind)
+
+ Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
+ Signed-off-by: David S. Miller <davem@davemloft.net>
+
+Index: hurd-debian/libdde_linux26/contrib/include/linux/netdevice.h
+===================================================================
+--- hurd-debian.orig/libdde_linux26/contrib/include/linux/netdevice.h 2012-04-16 00:34:54.000000000 +0000
++++ hurd-debian/libdde_linux26/contrib/include/linux/netdevice.h 2012-04-16 00:35:04.000000000 +0000
+@@ -462,6 +462,10 @@
+ spinlock_t _xmit_lock;
+ int xmit_lock_owner;
+ struct Qdisc *qdisc_sleeping;
++ /*
++ * please use this field instead of dev->trans_start
++ */
++ unsigned long trans_start;
+ } ____cacheline_aligned_in_smp;
+
+
+@@ -801,6 +805,11 @@
+ * One part is mostly used on xmit path (device)
+ */
+ /* These may be needed for future network-power-down code. */
++
++ /*
++ * trans_start here is expensive for high speed devices on SMP,
++ * please use netdev_queue->trans_start instead.
++ */
+ unsigned long trans_start; /* Time (in jiffies) of last Tx */
+
+ int watchdog_timeo; /* used by dev_watchdog() */
+@@ -1477,6 +1486,8 @@
+ return !test_bit(__LINK_STATE_NOCARRIER, &dev->state);
+ }
+
++extern unsigned long dev_trans_start(struct net_device *dev);
++
+ extern void __netdev_watchdog_up(struct net_device *dev);
+
+ extern void netif_carrier_on(struct net_device *dev);
+Index: hurd-debian/libdde_linux26/lib/src/net/sched/sch_generic.c
+===================================================================
+--- hurd-debian.orig/libdde_linux26/lib/src/net/sched/sch_generic.c 2012-04-16 00:26:38.000000000 +0000
++++ hurd-debian/libdde_linux26/lib/src/net/sched/sch_generic.c 2012-04-16 00:35:04.000000000 +0000
+@@ -200,6 +200,21 @@
+ clear_bit(__QDISC_STATE_RUNNING, &q->state);
+ }
+
++unsigned long dev_trans_start(struct net_device *dev)
++{
++ unsigned long val, res = dev->trans_start;
++ unsigned int i;
++
++ for (i = 0; i < dev->num_tx_queues; i++) {
++ val = netdev_get_tx_queue(dev, i)->trans_start;
++ if (val && time_after(val, res))
++ res = val;
++ }
++ dev->trans_start = res;
++ return res;
++}
++EXPORT_SYMBOL(dev_trans_start);
++
+ static void dev_watchdog(unsigned long arg)
+ {
+ struct net_device *dev = (struct net_device *)arg;
+@@ -209,25 +224,30 @@
+ if (netif_device_present(dev) &&
+ netif_running(dev) &&
+ netif_carrier_ok(dev)) {
+- int some_queue_stopped = 0;
++ int some_queue_timedout = 0;
+ unsigned int i;
++ unsigned long trans_start;
+
+ for (i = 0; i < dev->num_tx_queues; i++) {
+ struct netdev_queue *txq;
+
+ txq = netdev_get_tx_queue(dev, i);
+- if (netif_tx_queue_stopped(txq)) {
+- some_queue_stopped = 1;
++ /*
++ * old device drivers set dev->trans_start
++ */
++ trans_start = txq->trans_start ? : dev->trans_start;
++ if (netif_tx_queue_stopped(txq) &&
++ time_after(jiffies, (trans_start +
++ dev->watchdog_timeo))) {
++ some_queue_timedout = 1;
+ break;
+ }
+ }
+
+- if (some_queue_stopped &&
+- time_after(jiffies, (dev->trans_start +
+- dev->watchdog_timeo))) {
++ if (some_queue_timedout) {
+ char drivername[64];
+- WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit timed out\n",
+- dev->name, netdev_drivername(dev, drivername, 64));
++ WARN_ONCE(1, KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit queue %u timed out\n",
++ dev->name, netdev_drivername(dev, drivername, 64), i);
+ dev->netdev_ops->ndo_tx_timeout(dev);
+ }
+ if (!mod_timer(&dev->watchdog_timer,
+@@ -612,8 +632,10 @@
+ clear_bit(__QDISC_STATE_DEACTIVATED, &new_qdisc->state);
+
+ rcu_assign_pointer(dev_queue->qdisc, new_qdisc);
+- if (need_watchdog_p && new_qdisc != &noqueue_qdisc)
++ if (need_watchdog_p && new_qdisc != &noqueue_qdisc) {
++ dev_queue->trans_start = 0;
+ *need_watchdog_p = 1;
++ }
+ }
+
+ void dev_activate(struct net_device *dev)