aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c4
-rw-r--r--net/sched/sch_api.c57
-rw-r--r--net/sched/sch_generic.c8
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)
572static struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue, 572static 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,
718void dev_init_scheduler(struct net_device *dev) 720void 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,
745void dev_shutdown(struct net_device *dev) 747void 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}