diff options
author | Patrick McHardy <kaber@trash.net> | 2009-09-04 02:41:18 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-09-06 05:07:03 -0400 |
commit | af356afa010f3cd2c8b8fcc3bce90f7a7b7ec02a (patch) | |
tree | 302d938363bbaec3e69a58e36dbf8a304b24144c /net/sched/sch_generic.c | |
parent | 5b9a9ccfad8553dbf7a9b17ba78bad70215ed0e2 (diff) |
net_sched: reintroduce dev->qdisc for use by sch_api
Currently the multiqueue integration with the qdisc API suffers from
a few problems:
- with multiple queues, all root qdiscs use the same handle. This means
they can't be exposed to userspace in a backwards compatible fashion.
- all API operations always refer to queue number 0. Newly created
qdiscs are automatically shared between all queues, its not possible
to address individual queues or restore multiqueue behaviour once a
shared qdisc has been attached.
- Dumps only contain the root qdisc of queue 0, in case of non-shared
qdiscs this means the statistics are incomplete.
This patch reintroduces dev->qdisc, which points to the (single) root qdisc
from userspace's point of view. Currently it either points to the first
(non-shared) default qdisc, or a qdisc shared between all queues. The
following patches will introduce a classful dummy qdisc, which will be used
as root qdisc and contain the per-queue qdiscs as children.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/sch_generic.c')
-rw-r--r-- | net/sched/sch_generic.c | 25 |
1 files changed, 11 insertions, 14 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 6128e6f24589..a91f079fb47a 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -623,19 +623,6 @@ void qdisc_destroy(struct Qdisc *qdisc) | |||
623 | } | 623 | } |
624 | EXPORT_SYMBOL(qdisc_destroy); | 624 | EXPORT_SYMBOL(qdisc_destroy); |
625 | 625 | ||
626 | static bool dev_all_qdisc_sleeping_noop(struct net_device *dev) | ||
627 | { | ||
628 | unsigned int i; | ||
629 | |||
630 | for (i = 0; i < dev->num_tx_queues; i++) { | ||
631 | struct netdev_queue *txq = netdev_get_tx_queue(dev, i); | ||
632 | |||
633 | if (txq->qdisc_sleeping != &noop_qdisc) | ||
634 | return false; | ||
635 | } | ||
636 | return true; | ||
637 | } | ||
638 | |||
639 | static void attach_one_default_qdisc(struct net_device *dev, | 626 | static void attach_one_default_qdisc(struct net_device *dev, |
640 | struct netdev_queue *dev_queue, | 627 | struct netdev_queue *dev_queue, |
641 | void *_unused) | 628 | void *_unused) |
@@ -677,6 +664,7 @@ static void transition_one_qdisc(struct net_device *dev, | |||
677 | 664 | ||
678 | void dev_activate(struct net_device *dev) | 665 | void dev_activate(struct net_device *dev) |
679 | { | 666 | { |
667 | struct netdev_queue *txq; | ||
680 | int need_watchdog; | 668 | int need_watchdog; |
681 | 669 | ||
682 | /* No queueing discipline is attached to device; | 670 | /* No queueing discipline is attached to device; |
@@ -685,9 +673,14 @@ void dev_activate(struct net_device *dev) | |||
685 | virtual interfaces | 673 | virtual interfaces |
686 | */ | 674 | */ |
687 | 675 | ||
688 | if (dev_all_qdisc_sleeping_noop(dev)) | 676 | if (dev->qdisc == &noop_qdisc) { |
689 | netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL); | 677 | netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL); |
690 | 678 | ||
679 | txq = netdev_get_tx_queue(dev, 0); | ||
680 | dev->qdisc = txq->qdisc_sleeping; | ||
681 | atomic_inc(&dev->qdisc->refcnt); | ||
682 | } | ||
683 | |||
691 | if (!netif_carrier_ok(dev)) | 684 | if (!netif_carrier_ok(dev)) |
692 | /* Delay activation until next carrier-on event */ | 685 | /* Delay activation until next carrier-on event */ |
693 | return; | 686 | return; |
@@ -777,6 +770,7 @@ static void dev_init_scheduler_queue(struct net_device *dev, | |||
777 | 770 | ||
778 | void dev_init_scheduler(struct net_device *dev) | 771 | void dev_init_scheduler(struct net_device *dev) |
779 | { | 772 | { |
773 | dev->qdisc = &noop_qdisc; | ||
780 | netdev_for_each_tx_queue(dev, dev_init_scheduler_queue, &noop_qdisc); | 774 | netdev_for_each_tx_queue(dev, dev_init_scheduler_queue, &noop_qdisc); |
781 | dev_init_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc); | 775 | dev_init_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc); |
782 | 776 | ||
@@ -802,5 +796,8 @@ void dev_shutdown(struct net_device *dev) | |||
802 | { | 796 | { |
803 | netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc); | 797 | netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc); |
804 | shutdown_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc); | 798 | shutdown_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc); |
799 | qdisc_destroy(dev->qdisc); | ||
800 | dev->qdisc = &noop_qdisc; | ||
801 | |||
805 | WARN_ON(timer_pending(&dev->watchdog_timer)); | 802 | WARN_ON(timer_pending(&dev->watchdog_timer)); |
806 | } | 803 | } |