diff options
Diffstat (limited to 'net/sched/sch_api.c')
| -rw-r--r-- | net/sched/sch_api.c | 57 |
1 files changed, 16 insertions, 41 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index b0601642e227..4840aff47256 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
| @@ -572,44 +572,21 @@ static u32 qdisc_alloc_handle(struct net_device *dev) | |||
| 572 | static struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue, | 572 | static struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue, |
| 573 | struct Qdisc *qdisc) | 573 | struct Qdisc *qdisc) |
| 574 | { | 574 | { |
| 575 | struct Qdisc *oqdisc = dev_queue->qdisc_sleeping; | ||
| 575 | spinlock_t *root_lock; | 576 | 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 | 577 | ||
| 589 | root_lock = qdisc_root_lock(oqdisc); | 578 | root_lock = qdisc_root_lock(oqdisc); |
| 590 | spin_lock_bh(root_lock); | 579 | spin_lock_bh(root_lock); |
| 591 | 580 | ||
| 592 | if (ingress) { | 581 | /* Prune old scheduler */ |
| 593 | /* Prune old scheduler */ | 582 | if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) |
| 594 | if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) { | 583 | qdisc_reset(oqdisc); |
| 595 | /* delete */ | ||
| 596 | qdisc_reset(oqdisc); | ||
| 597 | dev_queue->qdisc = NULL; | ||
| 598 | } else { /* new */ | ||
| 599 | dev_queue->qdisc = qdisc; | ||
| 600 | } | ||
| 601 | 584 | ||
| 602 | } else { | 585 | /* ... and graft new one */ |
| 603 | /* Prune old scheduler */ | 586 | if (qdisc == NULL) |
| 604 | if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) | 587 | qdisc = &noop_qdisc; |
| 605 | qdisc_reset(oqdisc); | 588 | dev_queue->qdisc_sleeping = qdisc; |
| 606 | 589 | 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 | 590 | ||
| 614 | spin_unlock_bh(root_lock); | 591 | spin_unlock_bh(root_lock); |
| 615 | 592 | ||
| @@ -678,7 +655,8 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
| 678 | 655 | ||
| 679 | ingress = 0; | 656 | ingress = 0; |
| 680 | num_q = dev->num_tx_queues; | 657 | num_q = dev->num_tx_queues; |
| 681 | if (q && q->flags & TCQ_F_INGRESS) { | 658 | if ((q && q->flags & TCQ_F_INGRESS) || |
| 659 | (new && new->flags & TCQ_F_INGRESS)) { | ||
| 682 | num_q = 1; | 660 | num_q = 1; |
| 683 | ingress = 1; | 661 | ingress = 1; |
| 684 | } | 662 | } |
| @@ -692,13 +670,10 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
| 692 | if (!ingress) | 670 | if (!ingress) |
| 693 | dev_queue = netdev_get_tx_queue(dev, i); | 671 | dev_queue = netdev_get_tx_queue(dev, i); |
| 694 | 672 | ||
| 695 | if (ingress) { | 673 | old = dev_graft_qdisc(dev_queue, new); |
| 696 | old = dev_graft_qdisc(dev_queue, q); | 674 | if (new && i > 0) |
| 697 | } else { | 675 | atomic_inc(&new->refcnt); |
| 698 | old = dev_graft_qdisc(dev_queue, new); | 676 | |
| 699 | if (new && i > 0) | ||
| 700 | atomic_inc(&new->refcnt); | ||
| 701 | } | ||
| 702 | notify_and_destroy(skb, n, classid, old, new); | 677 | notify_and_destroy(skb, n, classid, old, new); |
| 703 | } | 678 | } |
| 704 | 679 | ||
| @@ -817,7 +792,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, | |||
| 817 | goto err_out3; | 792 | goto err_out3; |
| 818 | } | 793 | } |
| 819 | } | 794 | } |
| 820 | if (parent) | 795 | if (parent && !(sch->flags & TCQ_F_INGRESS)) |
| 821 | list_add_tail(&sch->list, &dev_queue->qdisc->list); | 796 | list_add_tail(&sch->list, &dev_queue->qdisc->list); |
| 822 | 797 | ||
| 823 | return sch; | 798 | return sch; |
