aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_api.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-08-18 21:34:07 -0400
committerIngo Molnar <mingo@elte.hu>2008-08-18 21:34:07 -0400
commit2879a927bb7a3cf91ae3906a5e59215f9c17dd75 (patch)
tree870bdd1bd530a3d5d2abd10539700446b2878188 /net/sched/sch_api.c
parent7e7b43892b87b6be259479ef4de14029dcb4012f (diff)
parent20211e4d344729f4d4c93da37a590fc1c3a1fd9b (diff)
Merge branch 'x86/oprofile' into oprofile
Diffstat (limited to 'net/sched/sch_api.c')
-rw-r--r--net/sched/sch_api.c115
1 files changed, 50 insertions, 65 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index b0601642e227..c25465e5607a 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -183,24 +183,34 @@ EXPORT_SYMBOL(unregister_qdisc);
183 (root qdisc, all its children, children of children etc.) 183 (root qdisc, all its children, children of children etc.)
184 */ 184 */
185 185
186struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle)
187{
188 struct Qdisc *q;
189
190 if (!(root->flags & TCQ_F_BUILTIN) &&
191 root->handle == handle)
192 return root;
193
194 list_for_each_entry(q, &root->list, list) {
195 if (q->handle == handle)
196 return q;
197 }
198 return NULL;
199}
200
186struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) 201struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
187{ 202{
188 unsigned int i; 203 unsigned int i;
189 204
190 for (i = 0; i < dev->num_tx_queues; i++) { 205 for (i = 0; i < dev->num_tx_queues; i++) {
191 struct netdev_queue *txq = netdev_get_tx_queue(dev, i); 206 struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
192 struct Qdisc *q, *txq_root = txq->qdisc; 207 struct Qdisc *q, *txq_root = txq->qdisc_sleeping;
193 208
194 if (!(txq_root->flags & TCQ_F_BUILTIN) && 209 q = qdisc_match_from_root(txq_root, handle);
195 txq_root->handle == handle) 210 if (q)
196 return txq_root; 211 return q;
197
198 list_for_each_entry(q, &txq_root->list, list) {
199 if (q->handle == handle)
200 return q;
201 }
202 } 212 }
203 return NULL; 213 return qdisc_match_from_root(dev->rx_queue.qdisc_sleeping, handle);
204} 214}
205 215
206static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) 216static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid)
@@ -321,7 +331,7 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
321 if (!s || tsize != s->tsize || (!tab && tsize > 0)) 331 if (!s || tsize != s->tsize || (!tab && tsize > 0))
322 return ERR_PTR(-EINVAL); 332 return ERR_PTR(-EINVAL);
323 333
324 spin_lock(&qdisc_stab_lock); 334 spin_lock_bh(&qdisc_stab_lock);
325 335
326 list_for_each_entry(stab, &qdisc_stab_list, list) { 336 list_for_each_entry(stab, &qdisc_stab_list, list) {
327 if (memcmp(&stab->szopts, s, sizeof(*s))) 337 if (memcmp(&stab->szopts, s, sizeof(*s)))
@@ -329,11 +339,11 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
329 if (tsize > 0 && memcmp(stab->data, tab, tsize * sizeof(u16))) 339 if (tsize > 0 && memcmp(stab->data, tab, tsize * sizeof(u16)))
330 continue; 340 continue;
331 stab->refcnt++; 341 stab->refcnt++;
332 spin_unlock(&qdisc_stab_lock); 342 spin_unlock_bh(&qdisc_stab_lock);
333 return stab; 343 return stab;
334 } 344 }
335 345
336 spin_unlock(&qdisc_stab_lock); 346 spin_unlock_bh(&qdisc_stab_lock);
337 347
338 stab = kmalloc(sizeof(*stab) + tsize * sizeof(u16), GFP_KERNEL); 348 stab = kmalloc(sizeof(*stab) + tsize * sizeof(u16), GFP_KERNEL);
339 if (!stab) 349 if (!stab)
@@ -344,9 +354,9 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
344 if (tsize > 0) 354 if (tsize > 0)
345 memcpy(stab->data, tab, tsize * sizeof(u16)); 355 memcpy(stab->data, tab, tsize * sizeof(u16));
346 356
347 spin_lock(&qdisc_stab_lock); 357 spin_lock_bh(&qdisc_stab_lock);
348 list_add_tail(&stab->list, &qdisc_stab_list); 358 list_add_tail(&stab->list, &qdisc_stab_list);
349 spin_unlock(&qdisc_stab_lock); 359 spin_unlock_bh(&qdisc_stab_lock);
350 360
351 return stab; 361 return stab;
352} 362}
@@ -356,14 +366,14 @@ void qdisc_put_stab(struct qdisc_size_table *tab)
356 if (!tab) 366 if (!tab)
357 return; 367 return;
358 368
359 spin_lock(&qdisc_stab_lock); 369 spin_lock_bh(&qdisc_stab_lock);
360 370
361 if (--tab->refcnt == 0) { 371 if (--tab->refcnt == 0) {
362 list_del(&tab->list); 372 list_del(&tab->list);
363 kfree(tab); 373 kfree(tab);
364 } 374 }
365 375
366 spin_unlock(&qdisc_stab_lock); 376 spin_unlock_bh(&qdisc_stab_lock);
367} 377}
368EXPORT_SYMBOL(qdisc_put_stab); 378EXPORT_SYMBOL(qdisc_put_stab);
369 379
@@ -572,44 +582,21 @@ static u32 qdisc_alloc_handle(struct net_device *dev)
572static struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue, 582static struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
573 struct Qdisc *qdisc) 583 struct Qdisc *qdisc)
574{ 584{
585 struct Qdisc *oqdisc = dev_queue->qdisc_sleeping;
575 spinlock_t *root_lock; 586 spinlock_t *root_lock;
576 struct Qdisc *oqdisc;
577 int ingress;
578
579 ingress = 0;
580 if (qdisc && qdisc->flags&TCQ_F_INGRESS)
581 ingress = 1;
582
583 if (ingress) {
584 oqdisc = dev_queue->qdisc;
585 } else {
586 oqdisc = dev_queue->qdisc_sleeping;
587 }
588 587
589 root_lock = qdisc_root_lock(oqdisc); 588 root_lock = qdisc_root_lock(oqdisc);
590 spin_lock_bh(root_lock); 589 spin_lock_bh(root_lock);
591 590
592 if (ingress) { 591 /* Prune old scheduler */
593 /* Prune old scheduler */ 592 if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1)
594 if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) { 593 qdisc_reset(oqdisc);
595 /* delete */
596 qdisc_reset(oqdisc);
597 dev_queue->qdisc = NULL;
598 } else { /* new */
599 dev_queue->qdisc = qdisc;
600 }
601 594
602 } else { 595 /* ... and graft new one */
603 /* Prune old scheduler */ 596 if (qdisc == NULL)
604 if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) 597 qdisc = &noop_qdisc;
605 qdisc_reset(oqdisc); 598 dev_queue->qdisc_sleeping = qdisc;
606 599 dev_queue->qdisc = &noop_qdisc;
607 /* ... and graft new one */
608 if (qdisc == NULL)
609 qdisc = &noop_qdisc;
610 dev_queue->qdisc_sleeping = qdisc;
611 dev_queue->qdisc = &noop_qdisc;
612 }
613 600
614 spin_unlock_bh(root_lock); 601 spin_unlock_bh(root_lock);
615 602
@@ -678,7 +665,8 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
678 665
679 ingress = 0; 666 ingress = 0;
680 num_q = dev->num_tx_queues; 667 num_q = dev->num_tx_queues;
681 if (q && q->flags & TCQ_F_INGRESS) { 668 if ((q && q->flags & TCQ_F_INGRESS) ||
669 (new && new->flags & TCQ_F_INGRESS)) {
682 num_q = 1; 670 num_q = 1;
683 ingress = 1; 671 ingress = 1;
684 } 672 }
@@ -692,13 +680,10 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
692 if (!ingress) 680 if (!ingress)
693 dev_queue = netdev_get_tx_queue(dev, i); 681 dev_queue = netdev_get_tx_queue(dev, i);
694 682
695 if (ingress) { 683 old = dev_graft_qdisc(dev_queue, new);
696 old = dev_graft_qdisc(dev_queue, q); 684 if (new && i > 0)
697 } else { 685 atomic_inc(&new->refcnt);
698 old = dev_graft_qdisc(dev_queue, new); 686
699 if (new && i > 0)
700 atomic_inc(&new->refcnt);
701 }
702 notify_and_destroy(skb, n, classid, old, new); 687 notify_and_destroy(skb, n, classid, old, new);
703 } 688 }
704 689
@@ -817,8 +802,8 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
817 goto err_out3; 802 goto err_out3;
818 } 803 }
819 } 804 }
820 if (parent) 805 if ((parent != TC_H_ROOT) && !(sch->flags & TCQ_F_INGRESS))
821 list_add_tail(&sch->list, &dev_queue->qdisc->list); 806 list_add_tail(&sch->list, &dev_queue->qdisc_sleeping->list);
822 807
823 return sch; 808 return sch;
824 } 809 }
@@ -933,7 +918,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
933 return -ENOENT; 918 return -ENOENT;
934 q = qdisc_leaf(p, clid); 919 q = qdisc_leaf(p, clid);
935 } else { /* ingress */ 920 } else { /* ingress */
936 q = dev->rx_queue.qdisc; 921 q = dev->rx_queue.qdisc_sleeping;
937 } 922 }
938 } else { 923 } else {
939 struct netdev_queue *dev_queue; 924 struct netdev_queue *dev_queue;
@@ -1003,7 +988,7 @@ replay:
1003 return -ENOENT; 988 return -ENOENT;
1004 q = qdisc_leaf(p, clid); 989 q = qdisc_leaf(p, clid);
1005 } else { /*ingress */ 990 } else { /*ingress */
1006 q = dev->rx_queue.qdisc; 991 q = dev->rx_queue.qdisc_sleeping;
1007 } 992 }
1008 } else { 993 } else {
1009 struct netdev_queue *dev_queue; 994 struct netdev_queue *dev_queue;
@@ -1261,11 +1246,11 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
1261 q_idx = 0; 1246 q_idx = 0;
1262 1247
1263 dev_queue = netdev_get_tx_queue(dev, 0); 1248 dev_queue = netdev_get_tx_queue(dev, 0);
1264 if (tc_dump_qdisc_root(dev_queue->qdisc, skb, cb, &q_idx, s_q_idx) < 0) 1249 if (tc_dump_qdisc_root(dev_queue->qdisc_sleeping, skb, cb, &q_idx, s_q_idx) < 0)
1265 goto done; 1250 goto done;
1266 1251
1267 dev_queue = &dev->rx_queue; 1252 dev_queue = &dev->rx_queue;
1268 if (tc_dump_qdisc_root(dev_queue->qdisc, skb, cb, &q_idx, s_q_idx) < 0) 1253 if (tc_dump_qdisc_root(dev_queue->qdisc_sleeping, skb, cb, &q_idx, s_q_idx) < 0)
1269 goto done; 1254 goto done;
1270 1255
1271cont: 1256cont:
@@ -1554,11 +1539,11 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
1554 t = 0; 1539 t = 0;
1555 1540
1556 dev_queue = netdev_get_tx_queue(dev, 0); 1541 dev_queue = netdev_get_tx_queue(dev, 0);
1557 if (tc_dump_tclass_root(dev_queue->qdisc, skb, tcm, cb, &t, s_t) < 0) 1542 if (tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, &t, s_t) < 0)
1558 goto done; 1543 goto done;
1559 1544
1560 dev_queue = &dev->rx_queue; 1545 dev_queue = &dev->rx_queue;
1561 if (tc_dump_tclass_root(dev_queue->qdisc, skb, tcm, cb, &t, s_t) < 0) 1546 if (tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, &t, s_t) < 0)
1562 goto done; 1547 goto done;
1563 1548
1564done: 1549done: