aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/sch_generic.h1
-rw-r--r--net/sched/sch_api.c42
-rw-r--r--net/sched/sch_mq.c1
3 files changed, 28 insertions, 16 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 9c69585a1be8..88eb9de095de 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -46,6 +46,7 @@ struct Qdisc
46#define TCQ_F_THROTTLED 2 46#define TCQ_F_THROTTLED 2
47#define TCQ_F_INGRESS 4 47#define TCQ_F_INGRESS 4
48#define TCQ_F_CAN_BYPASS 8 48#define TCQ_F_CAN_BYPASS 8
49#define TCQ_F_MQROOT 16
49#define TCQ_F_WARN_NONWC (1 << 16) 50#define TCQ_F_WARN_NONWC (1 << 16)
50 int padded; 51 int padded;
51 struct Qdisc_ops *ops; 52 struct Qdisc_ops *ops;
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 2a78d5410154..3af106140f35 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -733,7 +733,8 @@ static struct lock_class_key qdisc_rx_lock;
733 733
734static struct Qdisc * 734static struct Qdisc *
735qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, 735qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
736 u32 parent, u32 handle, struct nlattr **tca, int *errp) 736 struct Qdisc *p, u32 parent, u32 handle,
737 struct nlattr **tca, int *errp)
737{ 738{
738 int err; 739 int err;
739 struct nlattr *kind = tca[TCA_KIND]; 740 struct nlattr *kind = tca[TCA_KIND];
@@ -810,24 +811,21 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
810 if (tca[TCA_RATE]) { 811 if (tca[TCA_RATE]) {
811 spinlock_t *root_lock; 812 spinlock_t *root_lock;
812 813
814 err = -EOPNOTSUPP;
815 if (sch->flags & TCQ_F_MQROOT)
816 goto err_out4;
817
813 if ((sch->parent != TC_H_ROOT) && 818 if ((sch->parent != TC_H_ROOT) &&
814 !(sch->flags & TCQ_F_INGRESS)) 819 !(sch->flags & TCQ_F_INGRESS) &&
820 (!p || !(p->flags & TCQ_F_MQROOT)))
815 root_lock = qdisc_root_sleeping_lock(sch); 821 root_lock = qdisc_root_sleeping_lock(sch);
816 else 822 else
817 root_lock = qdisc_lock(sch); 823 root_lock = qdisc_lock(sch);
818 824
819 err = gen_new_estimator(&sch->bstats, &sch->rate_est, 825 err = gen_new_estimator(&sch->bstats, &sch->rate_est,
820 root_lock, tca[TCA_RATE]); 826 root_lock, tca[TCA_RATE]);
821 if (err) { 827 if (err)
822 /* 828 goto err_out4;
823 * Any broken qdiscs that would require
824 * a ops->reset() here? The qdisc was never
825 * in action so it shouldn't be necessary.
826 */
827 if (ops->destroy)
828 ops->destroy(sch);
829 goto err_out3;
830 }
831 } 829 }
832 830
833 qdisc_list_add(sch); 831 qdisc_list_add(sch);
@@ -843,6 +841,15 @@ err_out2:
843err_out: 841err_out:
844 *errp = err; 842 *errp = err;
845 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;
846} 853}
847 854
848static int qdisc_change(struct Qdisc *sch, struct nlattr **tca) 855static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
@@ -867,13 +874,16 @@ static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
867 qdisc_put_stab(sch->stab); 874 qdisc_put_stab(sch->stab);
868 sch->stab = stab; 875 sch->stab = stab;
869 876
870 if (tca[TCA_RATE]) 877 if (tca[TCA_RATE]) {
871 /* NB: ignores errors from replace_estimator 878 /* NB: ignores errors from replace_estimator
872 because change can't be undone. */ 879 because change can't be undone. */
880 if (sch->flags & TCQ_F_MQROOT)
881 goto out;
873 gen_replace_estimator(&sch->bstats, &sch->rate_est, 882 gen_replace_estimator(&sch->bstats, &sch->rate_est,
874 qdisc_root_sleeping_lock(sch), 883 qdisc_root_sleeping_lock(sch),
875 tca[TCA_RATE]); 884 tca[TCA_RATE]);
876 885 }
886out:
877 return 0; 887 return 0;
878} 888}
879 889
@@ -1097,7 +1107,7 @@ create_n_graft:
1097 if (!(n->nlmsg_flags&NLM_F_CREATE)) 1107 if (!(n->nlmsg_flags&NLM_F_CREATE))
1098 return -ENOENT; 1108 return -ENOENT;
1099 if (clid == TC_H_INGRESS) 1109 if (clid == TC_H_INGRESS)
1100 q = qdisc_create(dev, &dev->rx_queue, 1110 q = qdisc_create(dev, &dev->rx_queue, p,
1101 tcm->tcm_parent, tcm->tcm_parent, 1111 tcm->tcm_parent, tcm->tcm_parent,
1102 tca, &err); 1112 tca, &err);
1103 else { 1113 else {
@@ -1106,7 +1116,7 @@ create_n_graft:
1106 if (p && p->ops->cl_ops && p->ops->cl_ops->select_queue) 1116 if (p && p->ops->cl_ops && p->ops->cl_ops->select_queue)
1107 ntx = p->ops->cl_ops->select_queue(p, tcm); 1117 ntx = p->ops->cl_ops->select_queue(p, tcm);
1108 1118
1109 q = qdisc_create(dev, netdev_get_tx_queue(dev, ntx), 1119 q = qdisc_create(dev, netdev_get_tx_queue(dev, ntx), p,
1110 tcm->tcm_parent, tcm->tcm_handle, 1120 tcm->tcm_parent, tcm->tcm_handle,
1111 tca, &err); 1121 tca, &err);
1112 } 1122 }
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c
index c84dec9c8c7d..dd5ee022f1f7 100644
--- a/net/sched/sch_mq.c
+++ b/net/sched/sch_mq.c
@@ -64,6 +64,7 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt)
64 priv->qdiscs[ntx] = qdisc; 64 priv->qdiscs[ntx] = qdisc;
65 } 65 }
66 66
67 sch->flags |= TCQ_F_MQROOT;
67 return 0; 68 return 0;
68 69
69err: 70err: