aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-07-17 03:53:03 -0400
committerDavid S. Miller <davem@davemloft.net>2008-07-17 22:21:30 -0400
commit83874000929ed63aef30b44083a9f713135ff040 (patch)
tree7646fd185751cad8665eca19aa3f87d13c37eade
parentc7e4f3bbb4ba4e48ab3b529d5016e454cee1ccd6 (diff)
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>
-rw-r--r--drivers/net/ifb.c20
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--include/net/sch_generic.h7
-rw-r--r--net/core/dev.c9
-rw-r--r--net/mac80211/wme.c19
-rw-r--r--net/sched/sch_generic.c32
-rw-r--r--net/sched/sch_teql.c7
7 files changed, 43 insertions, 52 deletions
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 897b05e79ed0..0960e69b2da4 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -35,7 +35,6 @@
35#include <linux/moduleparam.h> 35#include <linux/moduleparam.h>
36#include <net/pkt_sched.h> 36#include <net/pkt_sched.h>
37#include <net/net_namespace.h> 37#include <net/net_namespace.h>
38#include <linux/lockdep.h>
39 38
40#define TX_TIMEOUT (2*HZ) 39#define TX_TIMEOUT (2*HZ)
41 40
@@ -228,22 +227,6 @@ static struct rtnl_link_ops ifb_link_ops __read_mostly = {
228module_param(numifbs, int, 0); 227module_param(numifbs, int, 0);
229MODULE_PARM_DESC(numifbs, "Number of ifb devices"); 228MODULE_PARM_DESC(numifbs, "Number of ifb devices");
230 229
231/*
232 * dev_ifb's TX queue lock is usually taken after dev->rx_queue.lock,
233 * reversely to e.g. qdisc_lock_tree(). It should be safe until
234 * ifb doesn't take dev's TX queue lock with dev_ifb->rx_queue.lock.
235 * But lockdep should know that ifb has different locks from dev.
236 */
237static struct lock_class_key ifb_tx_queue_lock_key;
238static struct lock_class_key ifb_rx_queue_lock_key;
239
240static void set_tx_lockdep_key(struct net_device *dev,
241 struct netdev_queue *txq,
242 void *_unused)
243{
244 lockdep_set_class(&txq->lock, &ifb_tx_queue_lock_key);
245}
246
247static int __init ifb_init_one(int index) 230static int __init ifb_init_one(int index)
248{ 231{
249 struct net_device *dev_ifb; 232 struct net_device *dev_ifb;
@@ -264,9 +247,6 @@ static int __init ifb_init_one(int index)
264 if (err < 0) 247 if (err < 0)
265 goto err; 248 goto err;
266 249
267 netdev_for_each_tx_queue(dev_ifb, set_tx_lockdep_key, NULL);
268 lockdep_set_class(&dev_ifb->rx_queue.lock, &ifb_rx_queue_lock_key);
269
270 return 0; 250 return 0;
271 251
272err: 252err:
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3170bcef734b..9c5a68850114 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -443,7 +443,6 @@ enum netdev_queue_state_t
443}; 443};
444 444
445struct netdev_queue { 445struct netdev_queue {
446 spinlock_t lock;
447 struct net_device *dev; 446 struct net_device *dev;
448 struct Qdisc *qdisc; 447 struct Qdisc *qdisc;
449 unsigned long state; 448 unsigned long state;
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 1eef8d0c9990..2902a42564f0 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -163,6 +163,11 @@ struct tcf_proto
163 struct tcf_proto_ops *ops; 163 struct tcf_proto_ops *ops;
164}; 164};
165 165
166static inline spinlock_t *qdisc_lock(struct Qdisc *qdisc)
167{
168 return &qdisc->q.lock;
169}
170
166static inline struct Qdisc *qdisc_root(struct Qdisc *qdisc) 171static inline struct Qdisc *qdisc_root(struct Qdisc *qdisc)
167{ 172{
168 return qdisc->dev_queue->qdisc; 173 return qdisc->dev_queue->qdisc;
@@ -172,7 +177,7 @@ static inline spinlock_t *qdisc_root_lock(struct Qdisc *qdisc)
172{ 177{
173 struct Qdisc *root = qdisc_root(qdisc); 178 struct Qdisc *root = qdisc_root(qdisc);
174 179
175 return &root->dev_queue->lock; 180 return qdisc_lock(root);
176} 181}
177 182
178static inline struct net_device *qdisc_dev(struct Qdisc *qdisc) 183static inline struct net_device *qdisc_dev(struct Qdisc *qdisc)
diff --git a/net/core/dev.c b/net/core/dev.c
index 6741e344ac59..32a13772c1cb 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2080,10 +2080,12 @@ static int ing_filter(struct sk_buff *skb)
2080 2080
2081 rxq = &dev->rx_queue; 2081 rxq = &dev->rx_queue;
2082 2082
2083 spin_lock(&rxq->lock); 2083 q = rxq->qdisc;
2084 if ((q = rxq->qdisc) != NULL) 2084 if (q) {
2085 spin_lock(qdisc_lock(q));
2085 result = q->enqueue(skb, q); 2086 result = q->enqueue(skb, q);
2086 spin_unlock(&rxq->lock); 2087 spin_unlock(qdisc_lock(q));
2088 }
2087 2089
2088 return result; 2090 return result;
2089} 2091}
@@ -4173,7 +4175,6 @@ static void netdev_init_one_queue(struct net_device *dev,
4173 struct netdev_queue *queue, 4175 struct netdev_queue *queue,
4174 void *_unused) 4176 void *_unused)
4175{ 4177{
4176 spin_lock_init(&queue->lock);
4177 queue->dev = dev; 4178 queue->dev = dev;
4178} 4179}
4179 4180
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index b21cfec4b6ce..6e8099e77043 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -237,12 +237,14 @@ void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
237 ieee80211_requeue(local, agg_queue); 237 ieee80211_requeue(local, agg_queue);
238 } else { 238 } else {
239 struct netdev_queue *txq; 239 struct netdev_queue *txq;
240 spinlock_t *root_lock;
240 241
241 txq = netdev_get_tx_queue(local->mdev, agg_queue); 242 txq = netdev_get_tx_queue(local->mdev, agg_queue);
243 root_lock = qdisc_root_lock(txq->qdisc);
242 244
243 spin_lock_bh(&txq->lock); 245 spin_lock_bh(root_lock);
244 qdisc_reset(txq->qdisc); 246 qdisc_reset(txq->qdisc);
245 spin_unlock_bh(&txq->lock); 247 spin_unlock_bh(root_lock);
246 } 248 }
247} 249}
248 250
@@ -250,6 +252,7 @@ void ieee80211_requeue(struct ieee80211_local *local, int queue)
250{ 252{
251 struct netdev_queue *txq = netdev_get_tx_queue(local->mdev, queue); 253 struct netdev_queue *txq = netdev_get_tx_queue(local->mdev, queue);
252 struct sk_buff_head list; 254 struct sk_buff_head list;
255 spinlock_t *root_lock;
253 struct Qdisc *qdisc; 256 struct Qdisc *qdisc;
254 u32 len; 257 u32 len;
255 258
@@ -261,14 +264,15 @@ void ieee80211_requeue(struct ieee80211_local *local, int queue)
261 264
262 skb_queue_head_init(&list); 265 skb_queue_head_init(&list);
263 266
264 spin_lock(&txq->lock); 267 root_lock = qdisc_root_lock(qdisc);
268 spin_lock(root_lock);
265 for (len = qdisc->q.qlen; len > 0; len--) { 269 for (len = qdisc->q.qlen; len > 0; len--) {
266 struct sk_buff *skb = qdisc->dequeue(qdisc); 270 struct sk_buff *skb = qdisc->dequeue(qdisc);
267 271
268 if (skb) 272 if (skb)
269 __skb_queue_tail(&list, skb); 273 __skb_queue_tail(&list, skb);
270 } 274 }
271 spin_unlock(&txq->lock); 275 spin_unlock(root_lock);
272 276
273 for (len = list.qlen; len > 0; len--) { 277 for (len = list.qlen; len > 0; len--) {
274 struct sk_buff *skb = __skb_dequeue(&list); 278 struct sk_buff *skb = __skb_dequeue(&list);
@@ -280,12 +284,13 @@ void ieee80211_requeue(struct ieee80211_local *local, int queue)
280 284
281 txq = netdev_get_tx_queue(local->mdev, new_queue); 285 txq = netdev_get_tx_queue(local->mdev, new_queue);
282 286
283 spin_lock(&txq->lock);
284 287
285 qdisc = rcu_dereference(txq->qdisc); 288 qdisc = rcu_dereference(txq->qdisc);
286 qdisc->enqueue(skb, qdisc); 289 root_lock = qdisc_root_lock(qdisc);
287 290
288 spin_unlock(&txq->lock); 291 spin_lock(root_lock);
292 qdisc->enqueue(skb, qdisc);
293 spin_unlock(root_lock);
289 } 294 }
290 295
291out_unlock: 296out_unlock:
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 3d53e92ad9c8..8fc580b3e173 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -96,15 +96,15 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb,
96} 96}
97 97
98/* 98/*
99 * NOTE: Called under queue->lock with locally disabled BH. 99 * NOTE: Called under qdisc_lock(q) with locally disabled BH.
100 * 100 *
101 * __QDISC_STATE_RUNNING guarantees only one CPU can process 101 * __QDISC_STATE_RUNNING guarantees only one CPU can process
102 * this qdisc at a time. queue->lock serializes queue accesses for 102 * this qdisc at a time. qdisc_lock(q) serializes queue accesses for
103 * this queue AND txq->qdisc pointer itself. 103 * this queue.
104 * 104 *
105 * netif_tx_lock serializes accesses to device driver. 105 * netif_tx_lock serializes accesses to device driver.
106 * 106 *
107 * queue->lock and netif_tx_lock are mutually exclusive, 107 * qdisc_lock(q) and netif_tx_lock are mutually exclusive,
108 * if one is grabbed, another must be free. 108 * if one is grabbed, another must be free.
109 * 109 *
110 * Note, that this procedure can be called by a watchdog timer 110 * Note, that this procedure can be called by a watchdog timer
@@ -317,7 +317,6 @@ struct Qdisc_ops noop_qdisc_ops __read_mostly = {
317}; 317};
318 318
319static struct netdev_queue noop_netdev_queue = { 319static struct netdev_queue noop_netdev_queue = {
320 .lock = __SPIN_LOCK_UNLOCKED(noop_netdev_queue.lock),
321 .qdisc = &noop_qdisc, 320 .qdisc = &noop_qdisc,
322}; 321};
323 322
@@ -327,6 +326,7 @@ struct Qdisc noop_qdisc = {
327 .flags = TCQ_F_BUILTIN, 326 .flags = TCQ_F_BUILTIN,
328 .ops = &noop_qdisc_ops, 327 .ops = &noop_qdisc_ops,
329 .list = LIST_HEAD_INIT(noop_qdisc.list), 328 .list = LIST_HEAD_INIT(noop_qdisc.list),
329 .q.lock = __SPIN_LOCK_UNLOCKED(noop_qdisc.q.lock),
330 .dev_queue = &noop_netdev_queue, 330 .dev_queue = &noop_netdev_queue,
331}; 331};
332EXPORT_SYMBOL(noop_qdisc); 332EXPORT_SYMBOL(noop_qdisc);
@@ -498,7 +498,7 @@ errout:
498} 498}
499EXPORT_SYMBOL(qdisc_create_dflt); 499EXPORT_SYMBOL(qdisc_create_dflt);
500 500
501/* Under queue->lock and BH! */ 501/* Under qdisc_root_lock(qdisc) and BH! */
502 502
503void qdisc_reset(struct Qdisc *qdisc) 503void qdisc_reset(struct Qdisc *qdisc)
504{ 504{
@@ -526,10 +526,12 @@ static void __qdisc_destroy(struct rcu_head *head)
526 module_put(ops->owner); 526 module_put(ops->owner);
527 dev_put(qdisc_dev(qdisc)); 527 dev_put(qdisc_dev(qdisc));
528 528
529 kfree_skb(qdisc->gso_skb);
530
529 kfree((char *) qdisc - qdisc->padded); 531 kfree((char *) qdisc - qdisc->padded);
530} 532}
531 533
532/* Under queue->lock and BH! */ 534/* Under qdisc_root_lock(qdisc) and BH! */
533 535
534void qdisc_destroy(struct Qdisc *qdisc) 536void qdisc_destroy(struct Qdisc *qdisc)
535{ 537{
@@ -586,13 +588,12 @@ static void transition_one_qdisc(struct net_device *dev,
586 struct netdev_queue *dev_queue, 588 struct netdev_queue *dev_queue,
587 void *_need_watchdog) 589 void *_need_watchdog)
588{ 590{
591 struct Qdisc *new_qdisc = dev_queue->qdisc_sleeping;
589 int *need_watchdog_p = _need_watchdog; 592 int *need_watchdog_p = _need_watchdog;
590 593
591 spin_lock_bh(&dev_queue->lock); 594 rcu_assign_pointer(dev_queue->qdisc, new_qdisc);
592 rcu_assign_pointer(dev_queue->qdisc, dev_queue->qdisc_sleeping); 595 if (new_qdisc != &noqueue_qdisc)
593 if (dev_queue->qdisc != &noqueue_qdisc)
594 *need_watchdog_p = 1; 596 *need_watchdog_p = 1;
595 spin_unlock_bh(&dev_queue->lock);
596} 597}
597 598
598void dev_activate(struct net_device *dev) 599void dev_activate(struct net_device *dev)
@@ -629,19 +630,16 @@ static void dev_deactivate_queue(struct net_device *dev,
629 struct sk_buff *skb = NULL; 630 struct sk_buff *skb = NULL;
630 struct Qdisc *qdisc; 631 struct Qdisc *qdisc;
631 632
632 spin_lock_bh(&dev_queue->lock);
633
634 qdisc = dev_queue->qdisc; 633 qdisc = dev_queue->qdisc;
635 if (qdisc) { 634 if (qdisc) {
635 spin_lock_bh(qdisc_lock(qdisc));
636
636 dev_queue->qdisc = qdisc_default; 637 dev_queue->qdisc = qdisc_default;
637 qdisc_reset(qdisc); 638 qdisc_reset(qdisc);
638 639
639 skb = qdisc->gso_skb; 640 spin_unlock_bh(qdisc_lock(qdisc));
640 qdisc->gso_skb = NULL;
641 } 641 }
642 642
643 spin_unlock_bh(&dev_queue->lock);
644
645 kfree_skb(skb); 643 kfree_skb(skb);
646} 644}
647 645
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index ade3372221c7..8b0ff345f9da 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -156,12 +156,15 @@ teql_destroy(struct Qdisc* sch)
156 master->slaves = NEXT_SLAVE(q); 156 master->slaves = NEXT_SLAVE(q);
157 if (q == master->slaves) { 157 if (q == master->slaves) {
158 struct netdev_queue *txq; 158 struct netdev_queue *txq;
159 spinlock_t *root_lock;
159 160
160 txq = netdev_get_tx_queue(master->dev, 0); 161 txq = netdev_get_tx_queue(master->dev, 0);
161 master->slaves = NULL; 162 master->slaves = NULL;
162 spin_lock_bh(&txq->lock); 163
164 root_lock = qdisc_root_lock(txq->qdisc);
165 spin_lock_bh(root_lock);
163 qdisc_reset(txq->qdisc); 166 qdisc_reset(txq->qdisc);
164 spin_unlock_bh(&txq->lock); 167 spin_unlock_bh(root_lock);
165 } 168 }
166 } 169 }
167 skb_queue_purge(&dat->q); 170 skb_queue_purge(&dat->q);