aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-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
4 files changed, 37 insertions, 30 deletions
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);