diff options
| -rw-r--r-- | net/core/dev.c | 4 | ||||
| -rw-r--r-- | net/sched/sch_api.c | 57 | ||||
| -rw-r--r-- | net/sched/sch_generic.c | 8 |
3 files changed, 23 insertions, 46 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 8d13a9b9f1df..63d6bcddbf46 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -2100,7 +2100,7 @@ static int ing_filter(struct sk_buff *skb) | |||
| 2100 | rxq = &dev->rx_queue; | 2100 | rxq = &dev->rx_queue; |
| 2101 | 2101 | ||
| 2102 | q = rxq->qdisc; | 2102 | q = rxq->qdisc; |
| 2103 | if (q) { | 2103 | if (q != &noop_qdisc) { |
| 2104 | spin_lock(qdisc_lock(q)); | 2104 | spin_lock(qdisc_lock(q)); |
| 2105 | result = qdisc_enqueue_root(skb, q); | 2105 | result = qdisc_enqueue_root(skb, q); |
| 2106 | spin_unlock(qdisc_lock(q)); | 2106 | spin_unlock(qdisc_lock(q)); |
| @@ -2113,7 +2113,7 @@ static inline struct sk_buff *handle_ing(struct sk_buff *skb, | |||
| 2113 | struct packet_type **pt_prev, | 2113 | struct packet_type **pt_prev, |
| 2114 | int *ret, struct net_device *orig_dev) | 2114 | int *ret, struct net_device *orig_dev) |
| 2115 | { | 2115 | { |
| 2116 | if (!skb->dev->rx_queue.qdisc) | 2116 | if (skb->dev->rx_queue.qdisc == &noop_qdisc) |
| 2117 | goto out; | 2117 | goto out; |
| 2118 | 2118 | ||
| 2119 | if (*pt_prev) { | 2119 | if (*pt_prev) { |
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; |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index fd2a6cadb115..345838a2e369 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
| @@ -596,7 +596,7 @@ static void transition_one_qdisc(struct net_device *dev, | |||
| 596 | int *need_watchdog_p = _need_watchdog; | 596 | int *need_watchdog_p = _need_watchdog; |
| 597 | 597 | ||
| 598 | rcu_assign_pointer(dev_queue->qdisc, new_qdisc); | 598 | rcu_assign_pointer(dev_queue->qdisc, new_qdisc); |
| 599 | if (new_qdisc != &noqueue_qdisc) | 599 | if (need_watchdog_p && new_qdisc != &noqueue_qdisc) |
| 600 | *need_watchdog_p = 1; | 600 | *need_watchdog_p = 1; |
| 601 | } | 601 | } |
| 602 | 602 | ||
| @@ -619,6 +619,7 @@ void dev_activate(struct net_device *dev) | |||
| 619 | 619 | ||
| 620 | need_watchdog = 0; | 620 | need_watchdog = 0; |
| 621 | netdev_for_each_tx_queue(dev, transition_one_qdisc, &need_watchdog); | 621 | netdev_for_each_tx_queue(dev, transition_one_qdisc, &need_watchdog); |
| 622 | transition_one_qdisc(dev, &dev->rx_queue, NULL); | ||
| 622 | 623 | ||
| 623 | if (need_watchdog) { | 624 | if (need_watchdog) { |
| 624 | dev->trans_start = jiffies; | 625 | dev->trans_start = jiffies; |
| @@ -677,6 +678,7 @@ void dev_deactivate(struct net_device *dev) | |||
| 677 | bool running; | 678 | bool running; |
| 678 | 679 | ||
| 679 | netdev_for_each_tx_queue(dev, dev_deactivate_queue, &noop_qdisc); | 680 | netdev_for_each_tx_queue(dev, dev_deactivate_queue, &noop_qdisc); |
| 681 | dev_deactivate_queue(dev, &dev->rx_queue, &noop_qdisc); | ||
| 680 | 682 | ||
| 681 | dev_watchdog_down(dev); | 683 | dev_watchdog_down(dev); |
| 682 | 684 | ||
| @@ -718,7 +720,7 @@ static void dev_init_scheduler_queue(struct net_device *dev, | |||
| 718 | void dev_init_scheduler(struct net_device *dev) | 720 | void dev_init_scheduler(struct net_device *dev) |
| 719 | { | 721 | { |
| 720 | netdev_for_each_tx_queue(dev, dev_init_scheduler_queue, &noop_qdisc); | 722 | netdev_for_each_tx_queue(dev, dev_init_scheduler_queue, &noop_qdisc); |
| 721 | dev_init_scheduler_queue(dev, &dev->rx_queue, NULL); | 723 | dev_init_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc); |
| 722 | 724 | ||
| 723 | setup_timer(&dev->watchdog_timer, dev_watchdog, (unsigned long)dev); | 725 | setup_timer(&dev->watchdog_timer, dev_watchdog, (unsigned long)dev); |
| 724 | } | 726 | } |
| @@ -745,6 +747,6 @@ static void shutdown_scheduler_queue(struct net_device *dev, | |||
| 745 | void dev_shutdown(struct net_device *dev) | 747 | void dev_shutdown(struct net_device *dev) |
| 746 | { | 748 | { |
| 747 | netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc); | 749 | netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc); |
| 748 | shutdown_scheduler_queue(dev, &dev->rx_queue, NULL); | 750 | shutdown_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc); |
| 749 | WARN_ON(timer_pending(&dev->watchdog_timer)); | 751 | WARN_ON(timer_pending(&dev->watchdog_timer)); |
| 750 | } | 752 | } |
