diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-08-18 21:34:07 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-08-18 21:34:07 -0400 |
commit | 2879a927bb7a3cf91ae3906a5e59215f9c17dd75 (patch) | |
tree | 870bdd1bd530a3d5d2abd10539700446b2878188 /net/sched/sch_api.c | |
parent | 7e7b43892b87b6be259479ef4de14029dcb4012f (diff) | |
parent | 20211e4d344729f4d4c93da37a590fc1c3a1fd9b (diff) |
Merge branch 'x86/oprofile' into oprofile
Diffstat (limited to 'net/sched/sch_api.c')
-rw-r--r-- | net/sched/sch_api.c | 115 |
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 | ||
186 | struct 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 | |||
186 | struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) | 201 | struct 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 | ||
206 | static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) | 216 | static 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 | } |
368 | EXPORT_SYMBOL(qdisc_put_stab); | 378 | EXPORT_SYMBOL(qdisc_put_stab); |
369 | 379 | ||
@@ -572,44 +582,21 @@ static u32 qdisc_alloc_handle(struct net_device *dev) | |||
572 | static struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue, | 582 | static 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 | ||
1271 | cont: | 1256 | cont: |
@@ -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 | ||
1564 | done: | 1549 | done: |