===== net/sched/sch_generic.c 1.32 vs edited ===== --- 1.32/net/sched/sch_generic.c 2004-12-28 05:51:20 +01:00 +++ edited/net/sched/sch_generic.c 2005-01-02 23:55:18 +01:00 @@ -104,9 +104,17 @@ * locking again. These checks are worth it because * even uncongested locks can be quite expensive. * The driver can do trylock like here too, in case - * of lock congestion it should return -1 and the packet - * will be requeued. + * of lock congestion it should return NETDEV_TX_LOCKED + * and the packet will be requeued. + * + * Note: when the driver has LLTX set queue_lock cannot + * be dropped in here if we want to avoid having packets + * passing eachover during transmit. queue_lock can only + * be dropped in hard_start_xmit() after private tx lock + * has been grabbed. If hard_start_xmit() does release + * queue_lock it must grab it again before it returns. */ + if (!nolock) { if (!spin_trylock(&dev->xmit_lock)) { collision: @@ -128,12 +136,12 @@ } /* Remember that the driver is grabbed by us. */ dev->xmit_lock_owner = smp_processor_id(); + + /* And release queue */ + spin_unlock(&dev->queue_lock); } { - /* And release queue */ - spin_unlock(&dev->queue_lock); - if (!netif_queue_stopped(dev)) { int ret; if (netdev_nit) @@ -144,14 +152,12 @@ if (!nolock) { dev->xmit_lock_owner = -1; spin_unlock(&dev->xmit_lock); + spin_lock(&dev->queue_lock); } - spin_lock(&dev->queue_lock); return -1; } - if (ret == NETDEV_TX_LOCKED && nolock) { - spin_lock(&dev->queue_lock); + if (ret == NETDEV_TX_LOCKED && nolock) goto collision; - } } /* NETDEV_TX_BUSY - we need to requeue */ @@ -159,8 +165,8 @@ if (!nolock) { dev->xmit_lock_owner = -1; spin_unlock(&dev->xmit_lock); + spin_lock(&dev->queue_lock); } - spin_lock(&dev->queue_lock); q = dev->qdisc; }