aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/Makefile2
-rw-r--r--net/sched/cls_api.c12
-rw-r--r--net/sched/sch_api.c139
-rw-r--r--net/sched/sch_atm.c2
-rw-r--r--net/sched/sch_cbq.c40
-rw-r--r--net/sched/sch_drr.c2
-rw-r--r--net/sched/sch_generic.c130
-rw-r--r--net/sched/sch_hfsc.c6
-rw-r--r--net/sched/sch_htb.c37
-rw-r--r--net/sched/sch_ingress.c14
-rw-r--r--net/sched/sch_mq.c235
-rw-r--r--net/sched/sch_multiq.c33
-rw-r--r--net/sched/sch_prio.c32
-rw-r--r--net/sched/sch_red.c21
-rw-r--r--net/sched/sch_sfq.c7
-rw-r--r--net/sched/sch_tbf.c22
-rw-r--r--net/sched/sch_teql.c4
17 files changed, 448 insertions, 290 deletions
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 54d950cd4b8d..f14e71bfa58f 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -2,7 +2,7 @@
2# Makefile for the Linux Traffic Control Unit. 2# Makefile for the Linux Traffic Control Unit.
3# 3#
4 4
5obj-y := sch_generic.o 5obj-y := sch_generic.o sch_mq.o
6 6
7obj-$(CONFIG_NET_SCHED) += sch_api.o sch_blackhole.o 7obj-$(CONFIG_NET_SCHED) += sch_api.o sch_blackhole.o
8obj-$(CONFIG_NET_CLS) += cls_api.o 8obj-$(CONFIG_NET_CLS) += cls_api.o
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 09cdcdfe7e91..6a536949cdc0 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -168,8 +168,7 @@ replay:
168 168
169 /* Find qdisc */ 169 /* Find qdisc */
170 if (!parent) { 170 if (!parent) {
171 struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, 0); 171 q = dev->qdisc;
172 q = dev_queue->qdisc_sleeping;
173 parent = q->handle; 172 parent = q->handle;
174 } else { 173 } else {
175 q = qdisc_lookup(dev, TC_H_MAJ(t->tcm_parent)); 174 q = qdisc_lookup(dev, TC_H_MAJ(t->tcm_parent));
@@ -181,6 +180,9 @@ replay:
181 if ((cops = q->ops->cl_ops) == NULL) 180 if ((cops = q->ops->cl_ops) == NULL)
182 return -EINVAL; 181 return -EINVAL;
183 182
183 if (cops->tcf_chain == NULL)
184 return -EOPNOTSUPP;
185
184 /* Do we search for filter, attached to class? */ 186 /* Do we search for filter, attached to class? */
185 if (TC_H_MIN(parent)) { 187 if (TC_H_MIN(parent)) {
186 cl = cops->get(q, parent); 188 cl = cops->get(q, parent);
@@ -405,7 +407,6 @@ static int tcf_node_dump(struct tcf_proto *tp, unsigned long n,
405static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) 407static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
406{ 408{
407 struct net *net = sock_net(skb->sk); 409 struct net *net = sock_net(skb->sk);
408 struct netdev_queue *dev_queue;
409 int t; 410 int t;
410 int s_t; 411 int s_t;
411 struct net_device *dev; 412 struct net_device *dev;
@@ -424,15 +425,16 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
424 if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) 425 if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)
425 return skb->len; 426 return skb->len;
426 427
427 dev_queue = netdev_get_tx_queue(dev, 0);
428 if (!tcm->tcm_parent) 428 if (!tcm->tcm_parent)
429 q = dev_queue->qdisc_sleeping; 429 q = dev->qdisc;
430 else 430 else
431 q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent)); 431 q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent));
432 if (!q) 432 if (!q)
433 goto out; 433 goto out;
434 if ((cops = q->ops->cl_ops) == NULL) 434 if ((cops = q->ops->cl_ops) == NULL)
435 goto errout; 435 goto errout;
436 if (cops->tcf_chain == NULL)
437 goto errout;
436 if (TC_H_MIN(tcm->tcm_parent)) { 438 if (TC_H_MIN(tcm->tcm_parent)) {
437 cl = cops->get(q, tcm->tcm_parent); 439 cl = cops->get(q, tcm->tcm_parent);
438 if (cl == 0) 440 if (cl == 0)
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 24d17ce9c294..3af106140f35 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -207,7 +207,7 @@ static struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle)
207static void qdisc_list_add(struct Qdisc *q) 207static void qdisc_list_add(struct Qdisc *q)
208{ 208{
209 if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) 209 if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS))
210 list_add_tail(&q->list, &qdisc_root_sleeping(q)->list); 210 list_add_tail(&q->list, &qdisc_dev(q)->qdisc->list);
211} 211}
212 212
213void qdisc_list_del(struct Qdisc *q) 213void qdisc_list_del(struct Qdisc *q)
@@ -219,17 +219,11 @@ EXPORT_SYMBOL(qdisc_list_del);
219 219
220struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) 220struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
221{ 221{
222 unsigned int i;
223 struct Qdisc *q; 222 struct Qdisc *q;
224 223
225 for (i = 0; i < dev->num_tx_queues; i++) { 224 q = qdisc_match_from_root(dev->qdisc, handle);
226 struct netdev_queue *txq = netdev_get_tx_queue(dev, i); 225 if (q)
227 struct Qdisc *txq_root = txq->qdisc_sleeping; 226 goto out;
228
229 q = qdisc_match_from_root(txq_root, handle);
230 if (q)
231 goto out;
232 }
233 227
234 q = qdisc_match_from_root(dev->rx_queue.qdisc_sleeping, handle); 228 q = qdisc_match_from_root(dev->rx_queue.qdisc_sleeping, handle);
235out: 229out:
@@ -616,32 +610,6 @@ static u32 qdisc_alloc_handle(struct net_device *dev)
616 return i>0 ? autohandle : 0; 610 return i>0 ? autohandle : 0;
617} 611}
618 612
619/* Attach toplevel qdisc to device queue. */
620
621static struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
622 struct Qdisc *qdisc)
623{
624 struct Qdisc *oqdisc = dev_queue->qdisc_sleeping;
625 spinlock_t *root_lock;
626
627 root_lock = qdisc_lock(oqdisc);
628 spin_lock_bh(root_lock);
629
630 /* Prune old scheduler */
631 if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1)
632 qdisc_reset(oqdisc);
633
634 /* ... and graft new one */
635 if (qdisc == NULL)
636 qdisc = &noop_qdisc;
637 dev_queue->qdisc_sleeping = qdisc;
638 rcu_assign_pointer(dev_queue->qdisc, &noop_qdisc);
639
640 spin_unlock_bh(root_lock);
641
642 return oqdisc;
643}
644
645void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) 613void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
646{ 614{
647 const struct Qdisc_class_ops *cops; 615 const struct Qdisc_class_ops *cops;
@@ -710,6 +678,11 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
710 if (dev->flags & IFF_UP) 678 if (dev->flags & IFF_UP)
711 dev_deactivate(dev); 679 dev_deactivate(dev);
712 680
681 if (new && new->ops->attach) {
682 new->ops->attach(new);
683 num_q = 0;
684 }
685
713 for (i = 0; i < num_q; i++) { 686 for (i = 0; i < num_q; i++) {
714 struct netdev_queue *dev_queue = &dev->rx_queue; 687 struct netdev_queue *dev_queue = &dev->rx_queue;
715 688
@@ -720,22 +693,27 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
720 if (new && i > 0) 693 if (new && i > 0)
721 atomic_inc(&new->refcnt); 694 atomic_inc(&new->refcnt);
722 695
723 notify_and_destroy(skb, n, classid, old, new); 696 qdisc_destroy(old);
724 } 697 }
725 698
699 notify_and_destroy(skb, n, classid, dev->qdisc, new);
700 if (new && !new->ops->attach)
701 atomic_inc(&new->refcnt);
702 dev->qdisc = new ? : &noop_qdisc;
703
726 if (dev->flags & IFF_UP) 704 if (dev->flags & IFF_UP)
727 dev_activate(dev); 705 dev_activate(dev);
728 } else { 706 } else {
729 const struct Qdisc_class_ops *cops = parent->ops->cl_ops; 707 const struct Qdisc_class_ops *cops = parent->ops->cl_ops;
730 708
731 err = -EINVAL; 709 err = -EOPNOTSUPP;
732 710 if (cops && cops->graft) {
733 if (cops) {
734 unsigned long cl = cops->get(parent, classid); 711 unsigned long cl = cops->get(parent, classid);
735 if (cl) { 712 if (cl) {
736 err = cops->graft(parent, cl, new, &old); 713 err = cops->graft(parent, cl, new, &old);
737 cops->put(parent, cl); 714 cops->put(parent, cl);
738 } 715 } else
716 err = -ENOENT;
739 } 717 }
740 if (!err) 718 if (!err)
741 notify_and_destroy(skb, n, classid, old, new); 719 notify_and_destroy(skb, n, classid, old, new);
@@ -755,7 +733,8 @@ static struct lock_class_key qdisc_rx_lock;
755 733
756static struct Qdisc * 734static struct Qdisc *
757qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, 735qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
758 u32 parent, u32 handle, struct nlattr **tca, int *errp) 736 struct Qdisc *p, u32 parent, u32 handle,
737 struct nlattr **tca, int *errp)
759{ 738{
760 int err; 739 int err;
761 struct nlattr *kind = tca[TCA_KIND]; 740 struct nlattr *kind = tca[TCA_KIND];
@@ -832,24 +811,21 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
832 if (tca[TCA_RATE]) { 811 if (tca[TCA_RATE]) {
833 spinlock_t *root_lock; 812 spinlock_t *root_lock;
834 813
814 err = -EOPNOTSUPP;
815 if (sch->flags & TCQ_F_MQROOT)
816 goto err_out4;
817
835 if ((sch->parent != TC_H_ROOT) && 818 if ((sch->parent != TC_H_ROOT) &&
836 !(sch->flags & TCQ_F_INGRESS)) 819 !(sch->flags & TCQ_F_INGRESS) &&
820 (!p || !(p->flags & TCQ_F_MQROOT)))
837 root_lock = qdisc_root_sleeping_lock(sch); 821 root_lock = qdisc_root_sleeping_lock(sch);
838 else 822 else
839 root_lock = qdisc_lock(sch); 823 root_lock = qdisc_lock(sch);
840 824
841 err = gen_new_estimator(&sch->bstats, &sch->rate_est, 825 err = gen_new_estimator(&sch->bstats, &sch->rate_est,
842 root_lock, tca[TCA_RATE]); 826 root_lock, tca[TCA_RATE]);
843 if (err) { 827 if (err)
844 /* 828 goto err_out4;
845 * Any broken qdiscs that would require
846 * a ops->reset() here? The qdisc was never
847 * in action so it shouldn't be necessary.
848 */
849 if (ops->destroy)
850 ops->destroy(sch);
851 goto err_out3;
852 }
853 } 829 }
854 830
855 qdisc_list_add(sch); 831 qdisc_list_add(sch);
@@ -865,6 +841,15 @@ err_out2:
865err_out: 841err_out:
866 *errp = err; 842 *errp = err;
867 return NULL; 843 return NULL;
844
845err_out4:
846 /*
847 * Any broken qdiscs that would require a ops->reset() here?
848 * The qdisc was never in action so it shouldn't be necessary.
849 */
850 if (ops->destroy)
851 ops->destroy(sch);
852 goto err_out3;
868} 853}
869 854
870static int qdisc_change(struct Qdisc *sch, struct nlattr **tca) 855static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
@@ -889,13 +874,16 @@ static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
889 qdisc_put_stab(sch->stab); 874 qdisc_put_stab(sch->stab);
890 sch->stab = stab; 875 sch->stab = stab;
891 876
892 if (tca[TCA_RATE]) 877 if (tca[TCA_RATE]) {
893 /* NB: ignores errors from replace_estimator 878 /* NB: ignores errors from replace_estimator
894 because change can't be undone. */ 879 because change can't be undone. */
880 if (sch->flags & TCQ_F_MQROOT)
881 goto out;
895 gen_replace_estimator(&sch->bstats, &sch->rate_est, 882 gen_replace_estimator(&sch->bstats, &sch->rate_est,
896 qdisc_root_sleeping_lock(sch), 883 qdisc_root_sleeping_lock(sch),
897 tca[TCA_RATE]); 884 tca[TCA_RATE]);
898 885 }
886out:
899 return 0; 887 return 0;
900} 888}
901 889
@@ -974,9 +962,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
974 q = dev->rx_queue.qdisc_sleeping; 962 q = dev->rx_queue.qdisc_sleeping;
975 } 963 }
976 } else { 964 } else {
977 struct netdev_queue *dev_queue; 965 q = dev->qdisc;
978 dev_queue = netdev_get_tx_queue(dev, 0);
979 q = dev_queue->qdisc_sleeping;
980 } 966 }
981 if (!q) 967 if (!q)
982 return -ENOENT; 968 return -ENOENT;
@@ -1044,9 +1030,7 @@ replay:
1044 q = dev->rx_queue.qdisc_sleeping; 1030 q = dev->rx_queue.qdisc_sleeping;
1045 } 1031 }
1046 } else { 1032 } else {
1047 struct netdev_queue *dev_queue; 1033 q = dev->qdisc;
1048 dev_queue = netdev_get_tx_queue(dev, 0);
1049 q = dev_queue->qdisc_sleeping;
1050 } 1034 }
1051 1035
1052 /* It may be default qdisc, ignore it */ 1036 /* It may be default qdisc, ignore it */
@@ -1123,13 +1107,19 @@ create_n_graft:
1123 if (!(n->nlmsg_flags&NLM_F_CREATE)) 1107 if (!(n->nlmsg_flags&NLM_F_CREATE))
1124 return -ENOENT; 1108 return -ENOENT;
1125 if (clid == TC_H_INGRESS) 1109 if (clid == TC_H_INGRESS)
1126 q = qdisc_create(dev, &dev->rx_queue, 1110 q = qdisc_create(dev, &dev->rx_queue, p,
1127 tcm->tcm_parent, tcm->tcm_parent, 1111 tcm->tcm_parent, tcm->tcm_parent,
1128 tca, &err); 1112 tca, &err);
1129 else 1113 else {
1130 q = qdisc_create(dev, netdev_get_tx_queue(dev, 0), 1114 unsigned int ntx = 0;
1115
1116 if (p && p->ops->cl_ops && p->ops->cl_ops->select_queue)
1117 ntx = p->ops->cl_ops->select_queue(p, tcm);
1118
1119 q = qdisc_create(dev, netdev_get_tx_queue(dev, ntx), p,
1131 tcm->tcm_parent, tcm->tcm_handle, 1120 tcm->tcm_parent, tcm->tcm_handle,
1132 tca, &err); 1121 tca, &err);
1122 }
1133 if (q == NULL) { 1123 if (q == NULL) {
1134 if (err == -EAGAIN) 1124 if (err == -EAGAIN)
1135 goto replay; 1125 goto replay;
@@ -1291,8 +1281,7 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
1291 s_q_idx = 0; 1281 s_q_idx = 0;
1292 q_idx = 0; 1282 q_idx = 0;
1293 1283
1294 dev_queue = netdev_get_tx_queue(dev, 0); 1284 if (tc_dump_qdisc_root(dev->qdisc, skb, cb, &q_idx, s_q_idx) < 0)
1295 if (tc_dump_qdisc_root(dev_queue->qdisc_sleeping, skb, cb, &q_idx, s_q_idx) < 0)
1296 goto done; 1285 goto done;
1297 1286
1298 dev_queue = &dev->rx_queue; 1287 dev_queue = &dev->rx_queue;
@@ -1323,7 +1312,6 @@ done:
1323static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) 1312static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1324{ 1313{
1325 struct net *net = sock_net(skb->sk); 1314 struct net *net = sock_net(skb->sk);
1326 struct netdev_queue *dev_queue;
1327 struct tcmsg *tcm = NLMSG_DATA(n); 1315 struct tcmsg *tcm = NLMSG_DATA(n);
1328 struct nlattr *tca[TCA_MAX + 1]; 1316 struct nlattr *tca[TCA_MAX + 1];
1329 struct net_device *dev; 1317 struct net_device *dev;
@@ -1361,7 +1349,6 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1361 1349
1362 /* Step 1. Determine qdisc handle X:0 */ 1350 /* Step 1. Determine qdisc handle X:0 */
1363 1351
1364 dev_queue = netdev_get_tx_queue(dev, 0);
1365 if (pid != TC_H_ROOT) { 1352 if (pid != TC_H_ROOT) {
1366 u32 qid1 = TC_H_MAJ(pid); 1353 u32 qid1 = TC_H_MAJ(pid);
1367 1354
@@ -1372,7 +1359,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1372 } else if (qid1) { 1359 } else if (qid1) {
1373 qid = qid1; 1360 qid = qid1;
1374 } else if (qid == 0) 1361 } else if (qid == 0)
1375 qid = dev_queue->qdisc_sleeping->handle; 1362 qid = dev->qdisc->handle;
1376 1363
1377 /* Now qid is genuine qdisc handle consistent 1364 /* Now qid is genuine qdisc handle consistent
1378 both with parent and child. 1365 both with parent and child.
@@ -1383,7 +1370,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1383 pid = TC_H_MAKE(qid, pid); 1370 pid = TC_H_MAKE(qid, pid);
1384 } else { 1371 } else {
1385 if (qid == 0) 1372 if (qid == 0)
1386 qid = dev_queue->qdisc_sleeping->handle; 1373 qid = dev->qdisc->handle;
1387 } 1374 }
1388 1375
1389 /* OK. Locate qdisc */ 1376 /* OK. Locate qdisc */
@@ -1417,7 +1404,9 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1417 goto out; 1404 goto out;
1418 break; 1405 break;
1419 case RTM_DELTCLASS: 1406 case RTM_DELTCLASS:
1420 err = cops->delete(q, cl); 1407 err = -EOPNOTSUPP;
1408 if (cops->delete)
1409 err = cops->delete(q, cl);
1421 if (err == 0) 1410 if (err == 0)
1422 tclass_notify(skb, n, q, cl, RTM_DELTCLASS); 1411 tclass_notify(skb, n, q, cl, RTM_DELTCLASS);
1423 goto out; 1412 goto out;
@@ -1431,7 +1420,9 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1431 } 1420 }
1432 1421
1433 new_cl = cl; 1422 new_cl = cl;
1434 err = cops->change(q, clid, pid, tca, &new_cl); 1423 err = -EOPNOTSUPP;
1424 if (cops->change)
1425 err = cops->change(q, clid, pid, tca, &new_cl);
1435 if (err == 0) 1426 if (err == 0)
1436 tclass_notify(skb, n, q, new_cl, RTM_NEWTCLASS); 1427 tclass_notify(skb, n, q, new_cl, RTM_NEWTCLASS);
1437 1428
@@ -1584,8 +1575,7 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
1584 s_t = cb->args[0]; 1575 s_t = cb->args[0];
1585 t = 0; 1576 t = 0;
1586 1577
1587 dev_queue = netdev_get_tx_queue(dev, 0); 1578 if (tc_dump_tclass_root(dev->qdisc, skb, tcm, cb, &t, s_t) < 0)
1588 if (tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, &t, s_t) < 0)
1589 goto done; 1579 goto done;
1590 1580
1591 dev_queue = &dev->rx_queue; 1581 dev_queue = &dev->rx_queue;
@@ -1705,6 +1695,7 @@ static int __init pktsched_init(void)
1705{ 1695{
1706 register_qdisc(&pfifo_qdisc_ops); 1696 register_qdisc(&pfifo_qdisc_ops);
1707 register_qdisc(&bfifo_qdisc_ops); 1697 register_qdisc(&bfifo_qdisc_ops);
1698 register_qdisc(&mq_qdisc_ops);
1708 proc_net_fops_create(&init_net, "psched", 0, &psched_fops); 1699 proc_net_fops_create(&init_net, "psched", 0, &psched_fops);
1709 1700
1710 rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL); 1701 rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL);
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 2a8b83af7c47..ab82f145f689 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -49,7 +49,7 @@ struct atm_flow_data {
49 struct socket *sock; /* for closing */ 49 struct socket *sock; /* for closing */
50 u32 classid; /* x:y type ID */ 50 u32 classid; /* x:y type ID */
51 int ref; /* reference count */ 51 int ref; /* reference count */
52 struct gnet_stats_basic bstats; 52 struct gnet_stats_basic_packed bstats;
53 struct gnet_stats_queue qstats; 53 struct gnet_stats_queue qstats;
54 struct atm_flow_data *next; 54 struct atm_flow_data *next;
55 struct atm_flow_data *excess; /* flow for excess traffic; 55 struct atm_flow_data *excess; /* flow for excess traffic;
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 23a167670fd5..5b132c473264 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -128,7 +128,7 @@ struct cbq_class
128 long avgidle; 128 long avgidle;
129 long deficit; /* Saved deficit for WRR */ 129 long deficit; /* Saved deficit for WRR */
130 psched_time_t penalized; 130 psched_time_t penalized;
131 struct gnet_stats_basic bstats; 131 struct gnet_stats_basic_packed bstats;
132 struct gnet_stats_queue qstats; 132 struct gnet_stats_queue qstats;
133 struct gnet_stats_rate_est rate_est; 133 struct gnet_stats_rate_est rate_est;
134 struct tc_cbq_xstats xstats; 134 struct tc_cbq_xstats xstats;
@@ -1621,29 +1621,25 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
1621{ 1621{
1622 struct cbq_class *cl = (struct cbq_class*)arg; 1622 struct cbq_class *cl = (struct cbq_class*)arg;
1623 1623
1624 if (cl) { 1624 if (new == NULL) {
1625 if (new == NULL) { 1625 new = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
1626 new = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue, 1626 &pfifo_qdisc_ops, cl->common.classid);
1627 &pfifo_qdisc_ops, 1627 if (new == NULL)
1628 cl->common.classid); 1628 return -ENOBUFS;
1629 if (new == NULL) 1629 } else {
1630 return -ENOBUFS;
1631 } else {
1632#ifdef CONFIG_NET_CLS_ACT 1630#ifdef CONFIG_NET_CLS_ACT
1633 if (cl->police == TC_POLICE_RECLASSIFY) 1631 if (cl->police == TC_POLICE_RECLASSIFY)
1634 new->reshape_fail = cbq_reshape_fail; 1632 new->reshape_fail = cbq_reshape_fail;
1635#endif 1633#endif
1636 }
1637 sch_tree_lock(sch);
1638 *old = cl->q;
1639 cl->q = new;
1640 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
1641 qdisc_reset(*old);
1642 sch_tree_unlock(sch);
1643
1644 return 0;
1645 } 1634 }
1646 return -ENOENT; 1635 sch_tree_lock(sch);
1636 *old = cl->q;
1637 cl->q = new;
1638 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
1639 qdisc_reset(*old);
1640 sch_tree_unlock(sch);
1641
1642 return 0;
1647} 1643}
1648 1644
1649static struct Qdisc * 1645static struct Qdisc *
@@ -1651,7 +1647,7 @@ cbq_leaf(struct Qdisc *sch, unsigned long arg)
1651{ 1647{
1652 struct cbq_class *cl = (struct cbq_class*)arg; 1648 struct cbq_class *cl = (struct cbq_class*)arg;
1653 1649
1654 return cl ? cl->q : NULL; 1650 return cl->q;
1655} 1651}
1656 1652
1657static void cbq_qlen_notify(struct Qdisc *sch, unsigned long arg) 1653static void cbq_qlen_notify(struct Qdisc *sch, unsigned long arg)
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c
index 7597fe146866..12b2fb04b29b 100644
--- a/net/sched/sch_drr.c
+++ b/net/sched/sch_drr.c
@@ -22,7 +22,7 @@ struct drr_class {
22 unsigned int refcnt; 22 unsigned int refcnt;
23 unsigned int filter_cnt; 23 unsigned int filter_cnt;
24 24
25 struct gnet_stats_basic bstats; 25 struct gnet_stats_basic_packed bstats;
26 struct gnet_stats_queue qstats; 26 struct gnet_stats_queue qstats;
27 struct gnet_stats_rate_est rate_est; 27 struct gnet_stats_rate_est rate_est;
28 struct list_head alist; 28 struct list_head alist;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 693df7ae33d8..4ae6aa562f2b 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -406,18 +406,38 @@ static const u8 prio2band[TC_PRIO_MAX+1] =
406 406
407#define PFIFO_FAST_BANDS 3 407#define PFIFO_FAST_BANDS 3
408 408
409static inline struct sk_buff_head *prio2list(struct sk_buff *skb, 409/*
410 struct Qdisc *qdisc) 410 * Private data for a pfifo_fast scheduler containing:
411 * - queues for the three band
412 * - bitmap indicating which of the bands contain skbs
413 */
414struct pfifo_fast_priv {
415 u32 bitmap;
416 struct sk_buff_head q[PFIFO_FAST_BANDS];
417};
418
419/*
420 * Convert a bitmap to the first band number where an skb is queued, where:
421 * bitmap=0 means there are no skbs on any band.
422 * bitmap=1 means there is an skb on band 0.
423 * bitmap=7 means there are skbs on all 3 bands, etc.
424 */
425static const int bitmap2band[] = {-1, 0, 1, 0, 2, 0, 1, 0};
426
427static inline struct sk_buff_head *band2list(struct pfifo_fast_priv *priv,
428 int band)
411{ 429{
412 struct sk_buff_head *list = qdisc_priv(qdisc); 430 return priv->q + band;
413 return list + prio2band[skb->priority & TC_PRIO_MAX];
414} 431}
415 432
416static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc) 433static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
417{ 434{
418 struct sk_buff_head *list = prio2list(skb, qdisc); 435 if (skb_queue_len(&qdisc->q) < qdisc_dev(qdisc)->tx_queue_len) {
436 int band = prio2band[skb->priority & TC_PRIO_MAX];
437 struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
438 struct sk_buff_head *list = band2list(priv, band);
419 439
420 if (skb_queue_len(list) < qdisc_dev(qdisc)->tx_queue_len) { 440 priv->bitmap |= (1 << band);
421 qdisc->q.qlen++; 441 qdisc->q.qlen++;
422 return __qdisc_enqueue_tail(skb, qdisc, list); 442 return __qdisc_enqueue_tail(skb, qdisc, list);
423 } 443 }
@@ -427,14 +447,18 @@ static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
427 447
428static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc) 448static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc)
429{ 449{
430 int prio; 450 struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
431 struct sk_buff_head *list = qdisc_priv(qdisc); 451 int band = bitmap2band[priv->bitmap];
432 452
433 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) { 453 if (likely(band >= 0)) {
434 if (!skb_queue_empty(list + prio)) { 454 struct sk_buff_head *list = band2list(priv, band);
435 qdisc->q.qlen--; 455 struct sk_buff *skb = __qdisc_dequeue_head(qdisc, list);
436 return __qdisc_dequeue_head(qdisc, list + prio); 456
437 } 457 qdisc->q.qlen--;
458 if (skb_queue_empty(list))
459 priv->bitmap &= ~(1 << band);
460
461 return skb;
438 } 462 }
439 463
440 return NULL; 464 return NULL;
@@ -442,12 +466,13 @@ static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc)
442 466
443static struct sk_buff *pfifo_fast_peek(struct Qdisc* qdisc) 467static struct sk_buff *pfifo_fast_peek(struct Qdisc* qdisc)
444{ 468{
445 int prio; 469 struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
446 struct sk_buff_head *list = qdisc_priv(qdisc); 470 int band = bitmap2band[priv->bitmap];
471
472 if (band >= 0) {
473 struct sk_buff_head *list = band2list(priv, band);
447 474
448 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) { 475 return skb_peek(list);
449 if (!skb_queue_empty(list + prio))
450 return skb_peek(list + prio);
451 } 476 }
452 477
453 return NULL; 478 return NULL;
@@ -456,11 +481,12 @@ static struct sk_buff *pfifo_fast_peek(struct Qdisc* qdisc)
456static void pfifo_fast_reset(struct Qdisc* qdisc) 481static void pfifo_fast_reset(struct Qdisc* qdisc)
457{ 482{
458 int prio; 483 int prio;
459 struct sk_buff_head *list = qdisc_priv(qdisc); 484 struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
460 485
461 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) 486 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
462 __qdisc_reset_queue(qdisc, list + prio); 487 __qdisc_reset_queue(qdisc, band2list(priv, prio));
463 488
489 priv->bitmap = 0;
464 qdisc->qstats.backlog = 0; 490 qdisc->qstats.backlog = 0;
465 qdisc->q.qlen = 0; 491 qdisc->q.qlen = 0;
466} 492}
@@ -480,17 +506,17 @@ nla_put_failure:
480static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt) 506static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt)
481{ 507{
482 int prio; 508 int prio;
483 struct sk_buff_head *list = qdisc_priv(qdisc); 509 struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
484 510
485 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) 511 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
486 skb_queue_head_init(list + prio); 512 skb_queue_head_init(band2list(priv, prio));
487 513
488 return 0; 514 return 0;
489} 515}
490 516
491static struct Qdisc_ops pfifo_fast_ops __read_mostly = { 517struct Qdisc_ops pfifo_fast_ops __read_mostly = {
492 .id = "pfifo_fast", 518 .id = "pfifo_fast",
493 .priv_size = PFIFO_FAST_BANDS * sizeof(struct sk_buff_head), 519 .priv_size = sizeof(struct pfifo_fast_priv),
494 .enqueue = pfifo_fast_enqueue, 520 .enqueue = pfifo_fast_enqueue,
495 .dequeue = pfifo_fast_dequeue, 521 .dequeue = pfifo_fast_dequeue,
496 .peek = pfifo_fast_peek, 522 .peek = pfifo_fast_peek,
@@ -597,17 +623,29 @@ void qdisc_destroy(struct Qdisc *qdisc)
597} 623}
598EXPORT_SYMBOL(qdisc_destroy); 624EXPORT_SYMBOL(qdisc_destroy);
599 625
600static bool dev_all_qdisc_sleeping_noop(struct net_device *dev) 626/* Attach toplevel qdisc to device queue. */
627struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
628 struct Qdisc *qdisc)
601{ 629{
602 unsigned int i; 630 struct Qdisc *oqdisc = dev_queue->qdisc_sleeping;
631 spinlock_t *root_lock;
603 632
604 for (i = 0; i < dev->num_tx_queues; i++) { 633 root_lock = qdisc_lock(oqdisc);
605 struct netdev_queue *txq = netdev_get_tx_queue(dev, i); 634 spin_lock_bh(root_lock);
606 635
607 if (txq->qdisc_sleeping != &noop_qdisc) 636 /* Prune old scheduler */
608 return false; 637 if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1)
609 } 638 qdisc_reset(oqdisc);
610 return true; 639
640 /* ... and graft new one */
641 if (qdisc == NULL)
642 qdisc = &noop_qdisc;
643 dev_queue->qdisc_sleeping = qdisc;
644 rcu_assign_pointer(dev_queue->qdisc, &noop_qdisc);
645
646 spin_unlock_bh(root_lock);
647
648 return oqdisc;
611} 649}
612 650
613static void attach_one_default_qdisc(struct net_device *dev, 651static void attach_one_default_qdisc(struct net_device *dev,
@@ -632,6 +670,26 @@ static void attach_one_default_qdisc(struct net_device *dev,
632 dev_queue->qdisc_sleeping = qdisc; 670 dev_queue->qdisc_sleeping = qdisc;
633} 671}
634 672
673static void attach_default_qdiscs(struct net_device *dev)
674{
675 struct netdev_queue *txq;
676 struct Qdisc *qdisc;
677
678 txq = netdev_get_tx_queue(dev, 0);
679
680 if (!netif_is_multiqueue(dev) || dev->tx_queue_len == 0) {
681 netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL);
682 dev->qdisc = txq->qdisc_sleeping;
683 atomic_inc(&dev->qdisc->refcnt);
684 } else {
685 qdisc = qdisc_create_dflt(dev, txq, &mq_qdisc_ops, TC_H_ROOT);
686 if (qdisc) {
687 qdisc->ops->attach(qdisc);
688 dev->qdisc = qdisc;
689 }
690 }
691}
692
635static void transition_one_qdisc(struct net_device *dev, 693static void transition_one_qdisc(struct net_device *dev,
636 struct netdev_queue *dev_queue, 694 struct netdev_queue *dev_queue,
637 void *_need_watchdog) 695 void *_need_watchdog)
@@ -659,8 +717,8 @@ void dev_activate(struct net_device *dev)
659 virtual interfaces 717 virtual interfaces
660 */ 718 */
661 719
662 if (dev_all_qdisc_sleeping_noop(dev)) 720 if (dev->qdisc == &noop_qdisc)
663 netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL); 721 attach_default_qdiscs(dev);
664 722
665 if (!netif_carrier_ok(dev)) 723 if (!netif_carrier_ok(dev))
666 /* Delay activation until next carrier-on event */ 724 /* Delay activation until next carrier-on event */
@@ -751,6 +809,7 @@ static void dev_init_scheduler_queue(struct net_device *dev,
751 809
752void dev_init_scheduler(struct net_device *dev) 810void dev_init_scheduler(struct net_device *dev)
753{ 811{
812 dev->qdisc = &noop_qdisc;
754 netdev_for_each_tx_queue(dev, dev_init_scheduler_queue, &noop_qdisc); 813 netdev_for_each_tx_queue(dev, dev_init_scheduler_queue, &noop_qdisc);
755 dev_init_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc); 814 dev_init_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc);
756 815
@@ -776,5 +835,8 @@ void dev_shutdown(struct net_device *dev)
776{ 835{
777 netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc); 836 netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc);
778 shutdown_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc); 837 shutdown_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc);
838 qdisc_destroy(dev->qdisc);
839 dev->qdisc = &noop_qdisc;
840
779 WARN_ON(timer_pending(&dev->watchdog_timer)); 841 WARN_ON(timer_pending(&dev->watchdog_timer));
780} 842}
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 362c2811b2df..375d64cb1a3d 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -116,7 +116,7 @@ struct hfsc_class
116 struct Qdisc_class_common cl_common; 116 struct Qdisc_class_common cl_common;
117 unsigned int refcnt; /* usage count */ 117 unsigned int refcnt; /* usage count */
118 118
119 struct gnet_stats_basic bstats; 119 struct gnet_stats_basic_packed bstats;
120 struct gnet_stats_queue qstats; 120 struct gnet_stats_queue qstats;
121 struct gnet_stats_rate_est rate_est; 121 struct gnet_stats_rate_est rate_est;
122 unsigned int level; /* class level in hierarchy */ 122 unsigned int level; /* class level in hierarchy */
@@ -1203,8 +1203,6 @@ hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
1203{ 1203{
1204 struct hfsc_class *cl = (struct hfsc_class *)arg; 1204 struct hfsc_class *cl = (struct hfsc_class *)arg;
1205 1205
1206 if (cl == NULL)
1207 return -ENOENT;
1208 if (cl->level > 0) 1206 if (cl->level > 0)
1209 return -EINVAL; 1207 return -EINVAL;
1210 if (new == NULL) { 1208 if (new == NULL) {
@@ -1228,7 +1226,7 @@ hfsc_class_leaf(struct Qdisc *sch, unsigned long arg)
1228{ 1226{
1229 struct hfsc_class *cl = (struct hfsc_class *)arg; 1227 struct hfsc_class *cl = (struct hfsc_class *)arg;
1230 1228
1231 if (cl != NULL && cl->level == 0) 1229 if (cl->level == 0)
1232 return cl->qdisc; 1230 return cl->qdisc;
1233 1231
1234 return NULL; 1232 return NULL;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 88cd02626621..85acab9dc6fd 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -74,7 +74,7 @@ enum htb_cmode {
74struct htb_class { 74struct htb_class {
75 struct Qdisc_class_common common; 75 struct Qdisc_class_common common;
76 /* general class parameters */ 76 /* general class parameters */
77 struct gnet_stats_basic bstats; 77 struct gnet_stats_basic_packed bstats;
78 struct gnet_stats_queue qstats; 78 struct gnet_stats_queue qstats;
79 struct gnet_stats_rate_est rate_est; 79 struct gnet_stats_rate_est rate_est;
80 struct tc_htb_xstats xstats; /* our special stats */ 80 struct tc_htb_xstats xstats; /* our special stats */
@@ -1117,30 +1117,29 @@ static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
1117{ 1117{
1118 struct htb_class *cl = (struct htb_class *)arg; 1118 struct htb_class *cl = (struct htb_class *)arg;
1119 1119
1120 if (cl && !cl->level) { 1120 if (cl->level)
1121 if (new == NULL && 1121 return -EINVAL;
1122 (new = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue, 1122 if (new == NULL &&
1123 &pfifo_qdisc_ops, 1123 (new = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
1124 cl->common.classid)) 1124 &pfifo_qdisc_ops,
1125 == NULL) 1125 cl->common.classid)) == NULL)
1126 return -ENOBUFS; 1126 return -ENOBUFS;
1127 sch_tree_lock(sch); 1127
1128 *old = cl->un.leaf.q; 1128 sch_tree_lock(sch);
1129 cl->un.leaf.q = new; 1129 *old = cl->un.leaf.q;
1130 if (*old != NULL) { 1130 cl->un.leaf.q = new;
1131 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); 1131 if (*old != NULL) {
1132 qdisc_reset(*old); 1132 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
1133 } 1133 qdisc_reset(*old);
1134 sch_tree_unlock(sch);
1135 return 0;
1136 } 1134 }
1137 return -ENOENT; 1135 sch_tree_unlock(sch);
1136 return 0;
1138} 1137}
1139 1138
1140static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg) 1139static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg)
1141{ 1140{
1142 struct htb_class *cl = (struct htb_class *)arg; 1141 struct htb_class *cl = (struct htb_class *)arg;
1143 return (cl && !cl->level) ? cl->un.leaf.q : NULL; 1142 return !cl->level ? cl->un.leaf.q : NULL;
1144} 1143}
1145 1144
1146static void htb_qlen_notify(struct Qdisc *sch, unsigned long arg) 1145static void htb_qlen_notify(struct Qdisc *sch, unsigned long arg)
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index 4a2b77374358..a9e646bdb605 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -22,12 +22,6 @@ struct ingress_qdisc_data {
22 22
23/* ------------------------- Class/flow operations ------------------------- */ 23/* ------------------------- Class/flow operations ------------------------- */
24 24
25static int ingress_graft(struct Qdisc *sch, unsigned long arg,
26 struct Qdisc *new, struct Qdisc **old)
27{
28 return -EOPNOTSUPP;
29}
30
31static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg) 25static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
32{ 26{
33 return NULL; 27 return NULL;
@@ -48,12 +42,6 @@ static void ingress_put(struct Qdisc *sch, unsigned long cl)
48{ 42{
49} 43}
50 44
51static int ingress_change(struct Qdisc *sch, u32 classid, u32 parent,
52 struct nlattr **tca, unsigned long *arg)
53{
54 return 0;
55}
56
57static void ingress_walk(struct Qdisc *sch, struct qdisc_walker *walker) 45static void ingress_walk(struct Qdisc *sch, struct qdisc_walker *walker)
58{ 46{
59 return; 47 return;
@@ -123,11 +111,9 @@ nla_put_failure:
123} 111}
124 112
125static const struct Qdisc_class_ops ingress_class_ops = { 113static const struct Qdisc_class_ops ingress_class_ops = {
126 .graft = ingress_graft,
127 .leaf = ingress_leaf, 114 .leaf = ingress_leaf,
128 .get = ingress_get, 115 .get = ingress_get,
129 .put = ingress_put, 116 .put = ingress_put,
130 .change = ingress_change,
131 .walk = ingress_walk, 117 .walk = ingress_walk,
132 .tcf_chain = ingress_find_tcf, 118 .tcf_chain = ingress_find_tcf,
133 .bind_tcf = ingress_bind_filter, 119 .bind_tcf = ingress_bind_filter,
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c
new file mode 100644
index 000000000000..dd5ee022f1f7
--- /dev/null
+++ b/net/sched/sch_mq.c
@@ -0,0 +1,235 @@
1/*
2 * net/sched/sch_mq.c Classful multiqueue dummy scheduler
3 *
4 * Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 */
10
11#include <linux/types.h>
12#include <linux/kernel.h>
13#include <linux/string.h>
14#include <linux/errno.h>
15#include <linux/skbuff.h>
16#include <net/netlink.h>
17#include <net/pkt_sched.h>
18
19struct mq_sched {
20 struct Qdisc **qdiscs;
21};
22
23static void mq_destroy(struct Qdisc *sch)
24{
25 struct net_device *dev = qdisc_dev(sch);
26 struct mq_sched *priv = qdisc_priv(sch);
27 unsigned int ntx;
28
29 if (!priv->qdiscs)
30 return;
31 for (ntx = 0; ntx < dev->num_tx_queues && priv->qdiscs[ntx]; ntx++)
32 qdisc_destroy(priv->qdiscs[ntx]);
33 kfree(priv->qdiscs);
34}
35
36static int mq_init(struct Qdisc *sch, struct nlattr *opt)
37{
38 struct net_device *dev = qdisc_dev(sch);
39 struct mq_sched *priv = qdisc_priv(sch);
40 struct netdev_queue *dev_queue;
41 struct Qdisc *qdisc;
42 unsigned int ntx;
43
44 if (sch->parent != TC_H_ROOT)
45 return -EOPNOTSUPP;
46
47 if (!netif_is_multiqueue(dev))
48 return -EOPNOTSUPP;
49
50 /* pre-allocate qdiscs, attachment can't fail */
51 priv->qdiscs = kcalloc(dev->num_tx_queues, sizeof(priv->qdiscs[0]),
52 GFP_KERNEL);
53 if (priv->qdiscs == NULL)
54 return -ENOMEM;
55
56 for (ntx = 0; ntx < dev->num_tx_queues; ntx++) {
57 dev_queue = netdev_get_tx_queue(dev, ntx);
58 qdisc = qdisc_create_dflt(dev, dev_queue, &pfifo_fast_ops,
59 TC_H_MAKE(TC_H_MAJ(sch->handle),
60 TC_H_MIN(ntx + 1)));
61 if (qdisc == NULL)
62 goto err;
63 qdisc->flags |= TCQ_F_CAN_BYPASS;
64 priv->qdiscs[ntx] = qdisc;
65 }
66
67 sch->flags |= TCQ_F_MQROOT;
68 return 0;
69
70err:
71 mq_destroy(sch);
72 return -ENOMEM;
73}
74
75static void mq_attach(struct Qdisc *sch)
76{
77 struct net_device *dev = qdisc_dev(sch);
78 struct mq_sched *priv = qdisc_priv(sch);
79 struct Qdisc *qdisc;
80 unsigned int ntx;
81
82 for (ntx = 0; ntx < dev->num_tx_queues; ntx++) {
83 qdisc = priv->qdiscs[ntx];
84 qdisc = dev_graft_qdisc(qdisc->dev_queue, qdisc);
85 if (qdisc)
86 qdisc_destroy(qdisc);
87 }
88 kfree(priv->qdiscs);
89 priv->qdiscs = NULL;
90}
91
92static int mq_dump(struct Qdisc *sch, struct sk_buff *skb)
93{
94 struct net_device *dev = qdisc_dev(sch);
95 struct Qdisc *qdisc;
96 unsigned int ntx;
97
98 sch->q.qlen = 0;
99 memset(&sch->bstats, 0, sizeof(sch->bstats));
100 memset(&sch->qstats, 0, sizeof(sch->qstats));
101
102 for (ntx = 0; ntx < dev->num_tx_queues; ntx++) {
103 qdisc = netdev_get_tx_queue(dev, ntx)->qdisc_sleeping;
104 spin_lock_bh(qdisc_lock(qdisc));
105 sch->q.qlen += qdisc->q.qlen;
106 sch->bstats.bytes += qdisc->bstats.bytes;
107 sch->bstats.packets += qdisc->bstats.packets;
108 sch->qstats.qlen += qdisc->qstats.qlen;
109 sch->qstats.backlog += qdisc->qstats.backlog;
110 sch->qstats.drops += qdisc->qstats.drops;
111 sch->qstats.requeues += qdisc->qstats.requeues;
112 sch->qstats.overlimits += qdisc->qstats.overlimits;
113 spin_unlock_bh(qdisc_lock(qdisc));
114 }
115 return 0;
116}
117
118static struct netdev_queue *mq_queue_get(struct Qdisc *sch, unsigned long cl)
119{
120 struct net_device *dev = qdisc_dev(sch);
121 unsigned long ntx = cl - 1;
122
123 if (ntx >= dev->num_tx_queues)
124 return NULL;
125 return netdev_get_tx_queue(dev, ntx);
126}
127
128static unsigned int mq_select_queue(struct Qdisc *sch, struct tcmsg *tcm)
129{
130 unsigned int ntx = TC_H_MIN(tcm->tcm_parent);
131
132 if (!mq_queue_get(sch, ntx))
133 return 0;
134 return ntx - 1;
135}
136
137static int mq_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new,
138 struct Qdisc **old)
139{
140 struct netdev_queue *dev_queue = mq_queue_get(sch, cl);
141 struct net_device *dev = qdisc_dev(sch);
142
143 if (dev->flags & IFF_UP)
144 dev_deactivate(dev);
145
146 *old = dev_graft_qdisc(dev_queue, new);
147
148 if (dev->flags & IFF_UP)
149 dev_activate(dev);
150 return 0;
151}
152
153static struct Qdisc *mq_leaf(struct Qdisc *sch, unsigned long cl)
154{
155 struct netdev_queue *dev_queue = mq_queue_get(sch, cl);
156
157 return dev_queue->qdisc_sleeping;
158}
159
160static unsigned long mq_get(struct Qdisc *sch, u32 classid)
161{
162 unsigned int ntx = TC_H_MIN(classid);
163
164 if (!mq_queue_get(sch, ntx))
165 return 0;
166 return ntx;
167}
168
169static void mq_put(struct Qdisc *sch, unsigned long cl)
170{
171 return;
172}
173
174static int mq_dump_class(struct Qdisc *sch, unsigned long cl,
175 struct sk_buff *skb, struct tcmsg *tcm)
176{
177 struct netdev_queue *dev_queue = mq_queue_get(sch, cl);
178
179 tcm->tcm_parent = TC_H_ROOT;
180 tcm->tcm_handle |= TC_H_MIN(cl);
181 tcm->tcm_info = dev_queue->qdisc_sleeping->handle;
182 return 0;
183}
184
185static int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
186 struct gnet_dump *d)
187{
188 struct netdev_queue *dev_queue = mq_queue_get(sch, cl);
189
190 sch = dev_queue->qdisc_sleeping;
191 if (gnet_stats_copy_basic(d, &sch->bstats) < 0 ||
192 gnet_stats_copy_queue(d, &sch->qstats) < 0)
193 return -1;
194 return 0;
195}
196
197static void mq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
198{
199 struct net_device *dev = qdisc_dev(sch);
200 unsigned int ntx;
201
202 if (arg->stop)
203 return;
204
205 arg->count = arg->skip;
206 for (ntx = arg->skip; ntx < dev->num_tx_queues; ntx++) {
207 if (arg->fn(sch, ntx + 1, arg) < 0) {
208 arg->stop = 1;
209 break;
210 }
211 arg->count++;
212 }
213}
214
215static const struct Qdisc_class_ops mq_class_ops = {
216 .select_queue = mq_select_queue,
217 .graft = mq_graft,
218 .leaf = mq_leaf,
219 .get = mq_get,
220 .put = mq_put,
221 .walk = mq_walk,
222 .dump = mq_dump_class,
223 .dump_stats = mq_dump_class_stats,
224};
225
226struct Qdisc_ops mq_qdisc_ops __read_mostly = {
227 .cl_ops = &mq_class_ops,
228 .id = "mq",
229 .priv_size = sizeof(struct mq_sched),
230 .init = mq_init,
231 .destroy = mq_destroy,
232 .attach = mq_attach,
233 .dump = mq_dump,
234 .owner = THIS_MODULE,
235};
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
index 912731203047..069f81c97277 100644
--- a/net/sched/sch_multiq.c
+++ b/net/sched/sch_multiq.c
@@ -298,9 +298,6 @@ static int multiq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
298 struct multiq_sched_data *q = qdisc_priv(sch); 298 struct multiq_sched_data *q = qdisc_priv(sch);
299 unsigned long band = arg - 1; 299 unsigned long band = arg - 1;
300 300
301 if (band >= q->bands)
302 return -EINVAL;
303
304 if (new == NULL) 301 if (new == NULL)
305 new = &noop_qdisc; 302 new = &noop_qdisc;
306 303
@@ -320,9 +317,6 @@ multiq_leaf(struct Qdisc *sch, unsigned long arg)
320 struct multiq_sched_data *q = qdisc_priv(sch); 317 struct multiq_sched_data *q = qdisc_priv(sch);
321 unsigned long band = arg - 1; 318 unsigned long band = arg - 1;
322 319
323 if (band >= q->bands)
324 return NULL;
325
326 return q->queues[band]; 320 return q->queues[band];
327} 321}
328 322
@@ -348,36 +342,13 @@ static void multiq_put(struct Qdisc *q, unsigned long cl)
348 return; 342 return;
349} 343}
350 344
351static int multiq_change(struct Qdisc *sch, u32 handle, u32 parent,
352 struct nlattr **tca, unsigned long *arg)
353{
354 unsigned long cl = *arg;
355 struct multiq_sched_data *q = qdisc_priv(sch);
356
357 if (cl - 1 > q->bands)
358 return -ENOENT;
359 return 0;
360}
361
362static int multiq_delete(struct Qdisc *sch, unsigned long cl)
363{
364 struct multiq_sched_data *q = qdisc_priv(sch);
365 if (cl - 1 > q->bands)
366 return -ENOENT;
367 return 0;
368}
369
370
371static int multiq_dump_class(struct Qdisc *sch, unsigned long cl, 345static int multiq_dump_class(struct Qdisc *sch, unsigned long cl,
372 struct sk_buff *skb, struct tcmsg *tcm) 346 struct sk_buff *skb, struct tcmsg *tcm)
373{ 347{
374 struct multiq_sched_data *q = qdisc_priv(sch); 348 struct multiq_sched_data *q = qdisc_priv(sch);
375 349
376 if (cl - 1 > q->bands)
377 return -ENOENT;
378 tcm->tcm_handle |= TC_H_MIN(cl); 350 tcm->tcm_handle |= TC_H_MIN(cl);
379 if (q->queues[cl-1]) 351 tcm->tcm_info = q->queues[cl-1]->handle;
380 tcm->tcm_info = q->queues[cl-1]->handle;
381 return 0; 352 return 0;
382} 353}
383 354
@@ -430,8 +401,6 @@ static const struct Qdisc_class_ops multiq_class_ops = {
430 .leaf = multiq_leaf, 401 .leaf = multiq_leaf,
431 .get = multiq_get, 402 .get = multiq_get,
432 .put = multiq_put, 403 .put = multiq_put,
433 .change = multiq_change,
434 .delete = multiq_delete,
435 .walk = multiq_walk, 404 .walk = multiq_walk,
436 .tcf_chain = multiq_find_tcf, 405 .tcf_chain = multiq_find_tcf,
437 .bind_tcf = multiq_bind, 406 .bind_tcf = multiq_bind,
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 94cecef70145..0f73c412d04b 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -262,9 +262,6 @@ static int prio_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
262 struct prio_sched_data *q = qdisc_priv(sch); 262 struct prio_sched_data *q = qdisc_priv(sch);
263 unsigned long band = arg - 1; 263 unsigned long band = arg - 1;
264 264
265 if (band >= q->bands)
266 return -EINVAL;
267
268 if (new == NULL) 265 if (new == NULL)
269 new = &noop_qdisc; 266 new = &noop_qdisc;
270 267
@@ -284,9 +281,6 @@ prio_leaf(struct Qdisc *sch, unsigned long arg)
284 struct prio_sched_data *q = qdisc_priv(sch); 281 struct prio_sched_data *q = qdisc_priv(sch);
285 unsigned long band = arg - 1; 282 unsigned long band = arg - 1;
286 283
287 if (band >= q->bands)
288 return NULL;
289
290 return q->queues[band]; 284 return q->queues[band];
291} 285}
292 286
@@ -311,35 +305,13 @@ static void prio_put(struct Qdisc *q, unsigned long cl)
311 return; 305 return;
312} 306}
313 307
314static int prio_change(struct Qdisc *sch, u32 handle, u32 parent, struct nlattr **tca, unsigned long *arg)
315{
316 unsigned long cl = *arg;
317 struct prio_sched_data *q = qdisc_priv(sch);
318
319 if (cl - 1 > q->bands)
320 return -ENOENT;
321 return 0;
322}
323
324static int prio_delete(struct Qdisc *sch, unsigned long cl)
325{
326 struct prio_sched_data *q = qdisc_priv(sch);
327 if (cl - 1 > q->bands)
328 return -ENOENT;
329 return 0;
330}
331
332
333static int prio_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb, 308static int prio_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb,
334 struct tcmsg *tcm) 309 struct tcmsg *tcm)
335{ 310{
336 struct prio_sched_data *q = qdisc_priv(sch); 311 struct prio_sched_data *q = qdisc_priv(sch);
337 312
338 if (cl - 1 > q->bands)
339 return -ENOENT;
340 tcm->tcm_handle |= TC_H_MIN(cl); 313 tcm->tcm_handle |= TC_H_MIN(cl);
341 if (q->queues[cl-1]) 314 tcm->tcm_info = q->queues[cl-1]->handle;
342 tcm->tcm_info = q->queues[cl-1]->handle;
343 return 0; 315 return 0;
344} 316}
345 317
@@ -392,8 +364,6 @@ static const struct Qdisc_class_ops prio_class_ops = {
392 .leaf = prio_leaf, 364 .leaf = prio_leaf,
393 .get = prio_get, 365 .get = prio_get,
394 .put = prio_put, 366 .put = prio_put,
395 .change = prio_change,
396 .delete = prio_delete,
397 .walk = prio_walk, 367 .walk = prio_walk,
398 .tcf_chain = prio_find_tcf, 368 .tcf_chain = prio_find_tcf,
399 .bind_tcf = prio_bind, 369 .bind_tcf = prio_bind,
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 2bdf241f6315..072cdf442f8e 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -268,8 +268,6 @@ static int red_dump_class(struct Qdisc *sch, unsigned long cl,
268{ 268{
269 struct red_sched_data *q = qdisc_priv(sch); 269 struct red_sched_data *q = qdisc_priv(sch);
270 270
271 if (cl != 1)
272 return -ENOENT;
273 tcm->tcm_handle |= TC_H_MIN(1); 271 tcm->tcm_handle |= TC_H_MIN(1);
274 tcm->tcm_info = q->qdisc->handle; 272 tcm->tcm_info = q->qdisc->handle;
275 return 0; 273 return 0;
@@ -308,17 +306,6 @@ static void red_put(struct Qdisc *sch, unsigned long arg)
308 return; 306 return;
309} 307}
310 308
311static int red_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
312 struct nlattr **tca, unsigned long *arg)
313{
314 return -ENOSYS;
315}
316
317static int red_delete(struct Qdisc *sch, unsigned long cl)
318{
319 return -ENOSYS;
320}
321
322static void red_walk(struct Qdisc *sch, struct qdisc_walker *walker) 309static void red_walk(struct Qdisc *sch, struct qdisc_walker *walker)
323{ 310{
324 if (!walker->stop) { 311 if (!walker->stop) {
@@ -331,20 +318,12 @@ static void red_walk(struct Qdisc *sch, struct qdisc_walker *walker)
331 } 318 }
332} 319}
333 320
334static struct tcf_proto **red_find_tcf(struct Qdisc *sch, unsigned long cl)
335{
336 return NULL;
337}
338
339static const struct Qdisc_class_ops red_class_ops = { 321static const struct Qdisc_class_ops red_class_ops = {
340 .graft = red_graft, 322 .graft = red_graft,
341 .leaf = red_leaf, 323 .leaf = red_leaf,
342 .get = red_get, 324 .get = red_get,
343 .put = red_put, 325 .put = red_put,
344 .change = red_change_class,
345 .delete = red_delete,
346 .walk = red_walk, 326 .walk = red_walk,
347 .tcf_chain = red_find_tcf,
348 .dump = red_dump_class, 327 .dump = red_dump_class,
349}; 328};
350 329
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 8706920a6d45..cb21380c0605 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -496,12 +496,6 @@ nla_put_failure:
496 return -1; 496 return -1;
497} 497}
498 498
499static int sfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
500 struct nlattr **tca, unsigned long *arg)
501{
502 return -EOPNOTSUPP;
503}
504
505static unsigned long sfq_get(struct Qdisc *sch, u32 classid) 499static unsigned long sfq_get(struct Qdisc *sch, u32 classid)
506{ 500{
507 return 0; 501 return 0;
@@ -560,7 +554,6 @@ static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
560 554
561static const struct Qdisc_class_ops sfq_class_ops = { 555static const struct Qdisc_class_ops sfq_class_ops = {
562 .get = sfq_get, 556 .get = sfq_get,
563 .change = sfq_change_class,
564 .tcf_chain = sfq_find_tcf, 557 .tcf_chain = sfq_find_tcf,
565 .dump = sfq_dump_class, 558 .dump = sfq_dump_class,
566 .dump_stats = sfq_dump_class_stats, 559 .dump_stats = sfq_dump_class_stats,
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index e22dfe85e43e..8fb8107ab188 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -368,9 +368,6 @@ static int tbf_dump_class(struct Qdisc *sch, unsigned long cl,
368{ 368{
369 struct tbf_sched_data *q = qdisc_priv(sch); 369 struct tbf_sched_data *q = qdisc_priv(sch);
370 370
371 if (cl != 1) /* only one class */
372 return -ENOENT;
373
374 tcm->tcm_handle |= TC_H_MIN(1); 371 tcm->tcm_handle |= TC_H_MIN(1);
375 tcm->tcm_info = q->qdisc->handle; 372 tcm->tcm_info = q->qdisc->handle;
376 373
@@ -410,17 +407,6 @@ static void tbf_put(struct Qdisc *sch, unsigned long arg)
410{ 407{
411} 408}
412 409
413static int tbf_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
414 struct nlattr **tca, unsigned long *arg)
415{
416 return -ENOSYS;
417}
418
419static int tbf_delete(struct Qdisc *sch, unsigned long arg)
420{
421 return -ENOSYS;
422}
423
424static void tbf_walk(struct Qdisc *sch, struct qdisc_walker *walker) 410static void tbf_walk(struct Qdisc *sch, struct qdisc_walker *walker)
425{ 411{
426 if (!walker->stop) { 412 if (!walker->stop) {
@@ -433,21 +419,13 @@ static void tbf_walk(struct Qdisc *sch, struct qdisc_walker *walker)
433 } 419 }
434} 420}
435 421
436static struct tcf_proto **tbf_find_tcf(struct Qdisc *sch, unsigned long cl)
437{
438 return NULL;
439}
440
441static const struct Qdisc_class_ops tbf_class_ops = 422static const struct Qdisc_class_ops tbf_class_ops =
442{ 423{
443 .graft = tbf_graft, 424 .graft = tbf_graft,
444 .leaf = tbf_leaf, 425 .leaf = tbf_leaf,
445 .get = tbf_get, 426 .get = tbf_get,
446 .put = tbf_put, 427 .put = tbf_put,
447 .change = tbf_change_class,
448 .delete = tbf_delete,
449 .walk = tbf_walk, 428 .walk = tbf_walk,
450 .tcf_chain = tbf_find_tcf,
451 .dump = tbf_dump_class, 429 .dump = tbf_dump_class,
452}; 430};
453 431
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 12434b6c2042..5a002c247231 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -268,7 +268,7 @@ static inline int teql_resolve(struct sk_buff *skb,
268 return __teql_resolve(skb, skb_res, dev); 268 return __teql_resolve(skb, skb_res, dev);
269} 269}
270 270
271static int teql_master_xmit(struct sk_buff *skb, struct net_device *dev) 271static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev)
272{ 272{
273 struct teql_master *master = netdev_priv(dev); 273 struct teql_master *master = netdev_priv(dev);
274 struct netdev_queue *txq = netdev_get_tx_queue(dev, 0); 274 struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
@@ -307,7 +307,7 @@ restart:
307 307
308 if (!netif_tx_queue_stopped(slave_txq) && 308 if (!netif_tx_queue_stopped(slave_txq) &&
309 !netif_tx_queue_frozen(slave_txq) && 309 !netif_tx_queue_frozen(slave_txq) &&
310 slave_ops->ndo_start_xmit(skb, slave) == 0) { 310 slave_ops->ndo_start_xmit(skb, slave) == NETDEV_TX_OK) {
311 txq_trans_update(slave_txq); 311 txq_trans_update(slave_txq);
312 __netif_tx_unlock(slave_txq); 312 __netif_tx_unlock(slave_txq);
313 master->slaves = NEXT_SLAVE(q); 313 master->slaves = NEXT_SLAVE(q);