pkt_sched: Kill netdev_queue lock.

We can simply use the qdisc->q.lock for all of the
qdisc tree synchronization.

Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 3d53e92..8fc580b 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -96,15 +96,15 @@
 }
 
 /*
- * NOTE: Called under queue->lock with locally disabled BH.
+ * NOTE: Called under qdisc_lock(q) with locally disabled BH.
  *
  * __QDISC_STATE_RUNNING guarantees only one CPU can process
- * this qdisc at a time. queue->lock serializes queue accesses for
- * this queue AND txq->qdisc pointer itself.
+ * this qdisc at a time. qdisc_lock(q) serializes queue accesses for
+ * this queue.
  *
  *  netif_tx_lock serializes accesses to device driver.
  *
- *  queue->lock and netif_tx_lock are mutually exclusive,
+ *  qdisc_lock(q) and netif_tx_lock are mutually exclusive,
  *  if one is grabbed, another must be free.
  *
  * Note, that this procedure can be called by a watchdog timer
@@ -317,7 +317,6 @@
 };
 
 static struct netdev_queue noop_netdev_queue = {
-	.lock		=	__SPIN_LOCK_UNLOCKED(noop_netdev_queue.lock),
 	.qdisc		=	&noop_qdisc,
 };
 
@@ -327,6 +326,7 @@
 	.flags		=	TCQ_F_BUILTIN,
 	.ops		=	&noop_qdisc_ops,
 	.list		=	LIST_HEAD_INIT(noop_qdisc.list),
+	.q.lock		=	__SPIN_LOCK_UNLOCKED(noop_qdisc.q.lock),
 	.dev_queue	=	&noop_netdev_queue,
 };
 EXPORT_SYMBOL(noop_qdisc);
@@ -498,7 +498,7 @@
 }
 EXPORT_SYMBOL(qdisc_create_dflt);
 
-/* Under queue->lock and BH! */
+/* Under qdisc_root_lock(qdisc) and BH! */
 
 void qdisc_reset(struct Qdisc *qdisc)
 {
@@ -526,10 +526,12 @@
 	module_put(ops->owner);
 	dev_put(qdisc_dev(qdisc));
 
+	kfree_skb(qdisc->gso_skb);
+
 	kfree((char *) qdisc - qdisc->padded);
 }
 
-/* Under queue->lock and BH! */
+/* Under qdisc_root_lock(qdisc) and BH! */
 
 void qdisc_destroy(struct Qdisc *qdisc)
 {
@@ -586,13 +588,12 @@
 				 struct netdev_queue *dev_queue,
 				 void *_need_watchdog)
 {
+	struct Qdisc *new_qdisc = dev_queue->qdisc_sleeping;
 	int *need_watchdog_p = _need_watchdog;
 
-	spin_lock_bh(&dev_queue->lock);
-	rcu_assign_pointer(dev_queue->qdisc, dev_queue->qdisc_sleeping);
-	if (dev_queue->qdisc != &noqueue_qdisc)
+	rcu_assign_pointer(dev_queue->qdisc, new_qdisc);
+	if (new_qdisc != &noqueue_qdisc)
 		*need_watchdog_p = 1;
-	spin_unlock_bh(&dev_queue->lock);
 }
 
 void dev_activate(struct net_device *dev)
@@ -629,19 +630,16 @@
 	struct sk_buff *skb = NULL;
 	struct Qdisc *qdisc;
 
-	spin_lock_bh(&dev_queue->lock);
-
 	qdisc = dev_queue->qdisc;
 	if (qdisc) {
+		spin_lock_bh(qdisc_lock(qdisc));
+
 		dev_queue->qdisc = qdisc_default;
 		qdisc_reset(qdisc);
 
-		skb = qdisc->gso_skb;
-		qdisc->gso_skb = NULL;
+		spin_unlock_bh(qdisc_lock(qdisc));
 	}
 
-	spin_unlock_bh(&dev_queue->lock);
-
 	kfree_skb(skb);
 }