]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/sched/sch_cbq.c
V4L/DVB (7902): fix handling of tea5761_autodetection return value
[linux-2.6-omap-h63xx.git] / net / sched / sch_cbq.c
index a294542cb8e4724eba3f3995e775568123cb481b..09969c1fbc08f287cb8b6bbc749e8a360fb9ea26 100644 (file)
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/netlink.h>
 #include <net/pkt_sched.h>
 
 
@@ -98,7 +82,7 @@ struct cbq_class
        unsigned char           priority2;      /* priority to be used after overlimit */
        unsigned char           ewma_log;       /* time constant for idle time calculation */
        unsigned char           ovl_strategy;
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
        unsigned char           police;
 #endif
 
@@ -148,7 +132,6 @@ struct cbq_class
        struct gnet_stats_basic bstats;
        struct gnet_stats_queue qstats;
        struct gnet_stats_rate_est rate_est;
-       spinlock_t              *stats_lock;
        struct tc_cbq_xstats    xstats;
 
        struct tcf_proto        *filter_list;
@@ -171,7 +154,7 @@ struct cbq_sched_data
        struct cbq_class        *active[TC_CBQ_MAXPRIO+1];      /* List of all classes
                                                                   with backlog */
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
        struct cbq_class        *rx_class;
 #endif
        struct cbq_class        *tx_class;
@@ -192,7 +175,7 @@ struct cbq_sched_data
 };
 
 
-#define L2T(cl,len)    ((cl)->R_tab->data[(len)>>(cl)->R_tab->rate.cell_log])
+#define L2T(cl,len)    qdisc_l2t((cl)->R_tab,len)
 
 
 static __inline__ unsigned cbq_hash(u32 h)
@@ -213,7 +196,7 @@ cbq_class_lookup(struct cbq_sched_data *q, u32 classid)
        return NULL;
 }
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 
 static struct cbq_class *
 cbq_reclassify(struct sk_buff *skb, struct cbq_class *this)
@@ -264,7 +247,8 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
                /*
                 * Step 2+n. Apply classifier.
                 */
-               if (!head->filter_list || (result = tc_classify(skb, head->filter_list, &res)) < 0)
+               if (!head->filter_list ||
+                   (result = tc_classify_compat(skb, head->filter_list, &res)) < 0)
                        goto fallback;
 
                if ((cl = (void*)res.class) == NULL) {
@@ -284,15 +268,8 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
                        *qerr = NET_XMIT_SUCCESS;
                case TC_ACT_SHOT:
                        return NULL;
-               }
-#elif defined(CONFIG_NET_CLS_POLICE)
-               switch (result) {
-               case TC_POLICE_RECLASSIFY:
+               case TC_ACT_RECLASSIFY:
                        return cbq_reclassify(skb, cl);
-               case TC_POLICE_SHOT:
-                       return NULL;
-               default:
-                       break;
                }
 #endif
                if (cl->level == 0)
@@ -403,10 +380,10 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
        struct cbq_sched_data *q = qdisc_priv(sch);
        int len = skb->len;
-       int ret;
+       int uninitialized_var(ret);
        struct cbq_class *cl = cbq_classify(skb, sch, &ret);
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
        q->rx_class = cl;
 #endif
        if (cl == NULL) {
@@ -416,7 +393,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                return ret;
        }
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
        cl->q->__parent = sch;
 #endif
        if ((ret = cl->q->enqueue(skb, cl->q)) == NET_XMIT_SUCCESS) {
@@ -451,7 +428,7 @@ cbq_requeue(struct sk_buff *skb, struct Qdisc *sch)
 
        cbq_mark_toplevel(q, cl);
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
        q->rx_class = cl;
        cl->q->__parent = sch;
 #endif
@@ -686,9 +663,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer)
        return HRTIMER_NORESTART;
 }
 
-
-#ifdef CONFIG_NET_CLS_POLICE
-
+#ifdef CONFIG_NET_CLS_ACT
 static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child)
 {
        int len = skb->len;
@@ -1381,7 +1356,7 @@ static int cbq_set_overlimit(struct cbq_class *cl, struct tc_cbq_ovl *ovl)
        return 0;
 }
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 static int cbq_set_police(struct cbq_class *cl, struct tc_cbq_police *p)
 {
        cl->police = p->police;
@@ -1402,24 +1377,33 @@ static int cbq_set_fopt(struct cbq_class *cl, struct tc_cbq_fopt *fopt)
        return 0;
 }
 
-static int cbq_init(struct Qdisc *sch, struct rtattr *opt)
+static const struct nla_policy cbq_policy[TCA_CBQ_MAX + 1] = {
+       [TCA_CBQ_LSSOPT]        = { .len = sizeof(struct tc_cbq_lssopt) },
+       [TCA_CBQ_WRROPT]        = { .len = sizeof(struct tc_cbq_wrropt) },
+       [TCA_CBQ_FOPT]          = { .len = sizeof(struct tc_cbq_fopt) },
+       [TCA_CBQ_OVL_STRATEGY]  = { .len = sizeof(struct tc_cbq_ovl) },
+       [TCA_CBQ_RATE]          = { .len = sizeof(struct tc_ratespec) },
+       [TCA_CBQ_RTAB]          = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+       [TCA_CBQ_POLICE]        = { .len = sizeof(struct tc_cbq_police) },
+};
+
+static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
 {
        struct cbq_sched_data *q = qdisc_priv(sch);
-       struct rtattr *tb[TCA_CBQ_MAX];
+       struct nlattr *tb[TCA_CBQ_MAX + 1];
        struct tc_ratespec *r;
+       int err;
 
-       if (rtattr_parse_nested(tb, TCA_CBQ_MAX, opt) < 0 ||
-           tb[TCA_CBQ_RTAB-1] == NULL || tb[TCA_CBQ_RATE-1] == NULL ||
-           RTA_PAYLOAD(tb[TCA_CBQ_RATE-1]) < sizeof(struct tc_ratespec))
-               return -EINVAL;
+       err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy);
+       if (err < 0)
+               return err;
 
-       if (tb[TCA_CBQ_LSSOPT-1] &&
-           RTA_PAYLOAD(tb[TCA_CBQ_LSSOPT-1]) < sizeof(struct tc_cbq_lssopt))
+       if (tb[TCA_CBQ_RTAB] == NULL || tb[TCA_CBQ_RATE] == NULL)
                return -EINVAL;
 
-       r = RTA_DATA(tb[TCA_CBQ_RATE-1]);
+       r = nla_data(tb[TCA_CBQ_RATE]);
 
-       if ((q->link.R_tab = qdisc_get_rtab(r, tb[TCA_CBQ_RTAB-1])) == NULL)
+       if ((q->link.R_tab = qdisc_get_rtab(r, tb[TCA_CBQ_RTAB])) == NULL)
                return -EINVAL;
 
        q->link.refcnt = 1;
@@ -1442,7 +1426,6 @@ static int cbq_init(struct Qdisc *sch, struct rtattr *opt)
        q->link.ewma_log = TC_CBQ_DEF_EWMA;
        q->link.avpkt = q->link.allot/2;
        q->link.minidle = -0x7FFFFFFF;
-       q->link.stats_lock = &sch->dev->queue_lock;
 
        qdisc_watchdog_init(&q->watchdog, sch);
        hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
@@ -1453,8 +1436,8 @@ static int cbq_init(struct Qdisc *sch, struct rtattr *opt)
 
        cbq_link_class(&q->link);
 
-       if (tb[TCA_CBQ_LSSOPT-1])
-               cbq_set_lss(&q->link, RTA_DATA(tb[TCA_CBQ_LSSOPT-1]));
+       if (tb[TCA_CBQ_LSSOPT])
+               cbq_set_lss(&q->link, nla_data(tb[TCA_CBQ_LSSOPT]));
 
        cbq_addprio(q, &q->link);
        return 0;
@@ -1464,10 +1447,10 @@ static __inline__ int cbq_dump_rate(struct sk_buff *skb, struct cbq_class *cl)
 {
        unsigned char *b = skb_tail_pointer(skb);
 
-       RTA_PUT(skb, TCA_CBQ_RATE, sizeof(cl->R_tab->rate), &cl->R_tab->rate);
+       NLA_PUT(skb, TCA_CBQ_RATE, sizeof(cl->R_tab->rate), &cl->R_tab->rate);
        return skb->len;
 
-rtattr_failure:
+nla_put_failure:
        nlmsg_trim(skb, b);
        return -1;
 }
@@ -1489,10 +1472,10 @@ static __inline__ int cbq_dump_lss(struct sk_buff *skb, struct cbq_class *cl)
        opt.minidle = (u32)(-cl->minidle);
        opt.offtime = cl->offtime;
        opt.change = ~0;
-       RTA_PUT(skb, TCA_CBQ_LSSOPT, sizeof(opt), &opt);
+       NLA_PUT(skb, TCA_CBQ_LSSOPT, sizeof(opt), &opt);
        return skb->len;
 
-rtattr_failure:
+nla_put_failure:
        nlmsg_trim(skb, b);
        return -1;
 }
@@ -1507,10 +1490,10 @@ static __inline__ int cbq_dump_wrr(struct sk_buff *skb, struct cbq_class *cl)
        opt.priority = cl->priority+1;
        opt.cpriority = cl->cpriority+1;
        opt.weight = cl->weight;
-       RTA_PUT(skb, TCA_CBQ_WRROPT, sizeof(opt), &opt);
+       NLA_PUT(skb, TCA_CBQ_WRROPT, sizeof(opt), &opt);
        return skb->len;
 
-rtattr_failure:
+nla_put_failure:
        nlmsg_trim(skb, b);
        return -1;
 }
@@ -1524,10 +1507,10 @@ static __inline__ int cbq_dump_ovl(struct sk_buff *skb, struct cbq_class *cl)
        opt.priority2 = cl->priority2+1;
        opt.pad = 0;
        opt.penalty = cl->penalty;
-       RTA_PUT(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt);
+       NLA_PUT(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt);
        return skb->len;
 
-rtattr_failure:
+nla_put_failure:
        nlmsg_trim(skb, b);
        return -1;
 }
@@ -1541,16 +1524,16 @@ static __inline__ int cbq_dump_fopt(struct sk_buff *skb, struct cbq_class *cl)
                opt.split = cl->split ? cl->split->classid : 0;
                opt.defmap = cl->defmap;
                opt.defchange = ~0;
-               RTA_PUT(skb, TCA_CBQ_FOPT, sizeof(opt), &opt);
+               NLA_PUT(skb, TCA_CBQ_FOPT, sizeof(opt), &opt);
        }
        return skb->len;
 
-rtattr_failure:
+nla_put_failure:
        nlmsg_trim(skb, b);
        return -1;
 }
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
 static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl)
 {
        unsigned char *b = skb_tail_pointer(skb);
@@ -1560,11 +1543,11 @@ static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl)
                opt.police = cl->police;
                opt.__res1 = 0;
                opt.__res2 = 0;
-               RTA_PUT(skb, TCA_CBQ_POLICE, sizeof(opt), &opt);
+               NLA_PUT(skb, TCA_CBQ_POLICE, sizeof(opt), &opt);
        }
        return skb->len;
 
-rtattr_failure:
+nla_put_failure:
        nlmsg_trim(skb, b);
        return -1;
 }
@@ -1576,7 +1559,7 @@ static int cbq_dump_attr(struct sk_buff *skb, struct cbq_class *cl)
            cbq_dump_rate(skb, cl) < 0 ||
            cbq_dump_wrr(skb, cl) < 0 ||
            cbq_dump_ovl(skb, cl) < 0 ||
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
            cbq_dump_police(skb, cl) < 0 ||
 #endif
            cbq_dump_fopt(skb, cl) < 0)
@@ -1587,18 +1570,18 @@ static int cbq_dump_attr(struct sk_buff *skb, struct cbq_class *cl)
 static int cbq_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
        struct cbq_sched_data *q = qdisc_priv(sch);
-       unsigned char *b = skb_tail_pointer(skb);
-       struct rtattr *rta;
+       struct nlattr *nest;
 
-       rta = (struct rtattr*)b;
-       RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+       nest = nla_nest_start(skb, TCA_OPTIONS);
+       if (nest == NULL)
+               goto nla_put_failure;
        if (cbq_dump_attr(skb, &q->link) < 0)
-               goto rtattr_failure;
-       rta->rta_len = skb_tail_pointer(skb) - b;
+               goto nla_put_failure;
+       nla_nest_end(skb, nest);
        return skb->len;
 
-rtattr_failure:
-       nlmsg_trim(skb, b);
+nla_put_failure:
+       nla_nest_cancel(skb, nest);
        return -1;
 }
 
@@ -1616,8 +1599,7 @@ cbq_dump_class(struct Qdisc *sch, unsigned long arg,
               struct sk_buff *skb, struct tcmsg *tcm)
 {
        struct cbq_class *cl = (struct cbq_class*)arg;
-       unsigned char *b = skb_tail_pointer(skb);
-       struct rtattr *rta;
+       struct nlattr *nest;
 
        if (cl->tparent)
                tcm->tcm_parent = cl->tparent->classid;
@@ -1626,15 +1608,16 @@ cbq_dump_class(struct Qdisc *sch, unsigned long arg,
        tcm->tcm_handle = cl->classid;
        tcm->tcm_info = cl->q->handle;
 
-       rta = (struct rtattr*)b;
-       RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+       nest = nla_nest_start(skb, TCA_OPTIONS);
+       if (nest == NULL)
+               goto nla_put_failure;
        if (cbq_dump_attr(skb, cl) < 0)
-               goto rtattr_failure;
-       rta->rta_len = skb_tail_pointer(skb) - b;
+               goto nla_put_failure;
+       nla_nest_end(skb, nest);
        return skb->len;
 
-rtattr_failure:
-       nlmsg_trim(skb, b);
+nla_put_failure:
+       nla_nest_cancel(skb, nest);
        return -1;
 }
 
@@ -1653,9 +1636,7 @@ cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
                cl->xstats.undertime = cl->undertime - q->now;
 
        if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
            gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
-#endif
            gnet_stats_copy_queue(d, &cl->qstats) < 0)
                return -1;
 
@@ -1673,7 +1654,7 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
                                                     cl->classid)) == NULL)
                                return -ENOBUFS;
                } else {
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
                        if (cl->police == TC_POLICE_RECLASSIFY)
                                new->reshape_fail = cbq_reshape_fail;
 #endif
@@ -1726,9 +1707,7 @@ static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl)
        tcf_destroy_chain(cl->filter_list);
        qdisc_destroy(cl->q);
        qdisc_put_rtab(cl->R_tab);
-#ifdef CONFIG_NET_ESTIMATOR
        gen_kill_estimator(&cl->bstats, &cl->rate_est);
-#endif
        if (cl != &q->link)
                kfree(cl);
 }
@@ -1740,7 +1719,7 @@ cbq_destroy(struct Qdisc* sch)
        struct cbq_class *cl;
        unsigned h;
 
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
        q->rx_class = NULL;
 #endif
        /*
@@ -1748,10 +1727,12 @@ cbq_destroy(struct Qdisc* sch)
         * classes from root to leafs which means that filters can still
         * be bound to classes which have been destroyed already. --TGR '04
         */
-       for (h = 0; h < 16; h++)
-               for (cl = q->classes[h]; cl; cl = cl->next)
+       for (h = 0; h < 16; h++) {
+               for (cl = q->classes[h]; cl; cl = cl->next) {
                        tcf_destroy_chain(cl->filter_list);
-
+                       cl->filter_list = NULL;
+               }
+       }
        for (h = 0; h < 16; h++) {
                struct cbq_class *next;
 
@@ -1767,7 +1748,7 @@ static void cbq_put(struct Qdisc *sch, unsigned long arg)
        struct cbq_class *cl = (struct cbq_class*)arg;
 
        if (--cl->refcnt == 0) {
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
                struct cbq_sched_data *q = qdisc_priv(sch);
 
                spin_lock_bh(&sch->dev->queue_lock);
@@ -1781,45 +1762,23 @@ static void cbq_put(struct Qdisc *sch, unsigned long arg)
 }
 
 static int
-cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **tca,
+cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **tca,
                 unsigned long *arg)
 {
        int err;
        struct cbq_sched_data *q = qdisc_priv(sch);
        struct cbq_class *cl = (struct cbq_class*)*arg;
-       struct rtattr *opt = tca[TCA_OPTIONS-1];
-       struct rtattr *tb[TCA_CBQ_MAX];
+       struct nlattr *opt = tca[TCA_OPTIONS];
+       struct nlattr *tb[TCA_CBQ_MAX + 1];
        struct cbq_class *parent;
        struct qdisc_rate_table *rtab = NULL;
 
-       if (opt==NULL || rtattr_parse_nested(tb, TCA_CBQ_MAX, opt))
+       if (opt == NULL)
                return -EINVAL;
 
-       if (tb[TCA_CBQ_OVL_STRATEGY-1] &&
-           RTA_PAYLOAD(tb[TCA_CBQ_OVL_STRATEGY-1]) < sizeof(struct tc_cbq_ovl))
-               return -EINVAL;
-
-       if (tb[TCA_CBQ_FOPT-1] &&
-           RTA_PAYLOAD(tb[TCA_CBQ_FOPT-1]) < sizeof(struct tc_cbq_fopt))
-               return -EINVAL;
-
-       if (tb[TCA_CBQ_RATE-1] &&
-           RTA_PAYLOAD(tb[TCA_CBQ_RATE-1]) < sizeof(struct tc_ratespec))
-                       return -EINVAL;
-
-       if (tb[TCA_CBQ_LSSOPT-1] &&
-           RTA_PAYLOAD(tb[TCA_CBQ_LSSOPT-1]) < sizeof(struct tc_cbq_lssopt))
-                       return -EINVAL;
-
-       if (tb[TCA_CBQ_WRROPT-1] &&
-           RTA_PAYLOAD(tb[TCA_CBQ_WRROPT-1]) < sizeof(struct tc_cbq_wrropt))
-                       return -EINVAL;
-
-#ifdef CONFIG_NET_CLS_POLICE
-       if (tb[TCA_CBQ_POLICE-1] &&
-           RTA_PAYLOAD(tb[TCA_CBQ_POLICE-1]) < sizeof(struct tc_cbq_police))
-                       return -EINVAL;
-#endif
+       err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy);
+       if (err < 0)
+               return err;
 
        if (cl) {
                /* Check parent */
@@ -1830,8 +1789,8 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
                                return -EINVAL;
                }
 
-               if (tb[TCA_CBQ_RATE-1]) {
-                       rtab = qdisc_get_rtab(RTA_DATA(tb[TCA_CBQ_RATE-1]), tb[TCA_CBQ_RTAB-1]);
+               if (tb[TCA_CBQ_RATE]) {
+                       rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), tb[TCA_CBQ_RTAB]);
                        if (rtab == NULL)
                                return -EINVAL;
                }
@@ -1847,46 +1806,45 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
                        qdisc_put_rtab(rtab);
                }
 
-               if (tb[TCA_CBQ_LSSOPT-1])
-                       cbq_set_lss(cl, RTA_DATA(tb[TCA_CBQ_LSSOPT-1]));
+               if (tb[TCA_CBQ_LSSOPT])
+                       cbq_set_lss(cl, nla_data(tb[TCA_CBQ_LSSOPT]));
 
-               if (tb[TCA_CBQ_WRROPT-1]) {
+               if (tb[TCA_CBQ_WRROPT]) {
                        cbq_rmprio(q, cl);
-                       cbq_set_wrr(cl, RTA_DATA(tb[TCA_CBQ_WRROPT-1]));
+                       cbq_set_wrr(cl, nla_data(tb[TCA_CBQ_WRROPT]));
                }
 
-               if (tb[TCA_CBQ_OVL_STRATEGY-1])
-                       cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1]));
+               if (tb[TCA_CBQ_OVL_STRATEGY])
+                       cbq_set_overlimit(cl, nla_data(tb[TCA_CBQ_OVL_STRATEGY]));
 
-#ifdef CONFIG_NET_CLS_POLICE
-               if (tb[TCA_CBQ_POLICE-1])
-                       cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1]));
+#ifdef CONFIG_NET_CLS_ACT
+               if (tb[TCA_CBQ_POLICE])
+                       cbq_set_police(cl, nla_data(tb[TCA_CBQ_POLICE]));
 #endif
 
-               if (tb[TCA_CBQ_FOPT-1])
-                       cbq_set_fopt(cl, RTA_DATA(tb[TCA_CBQ_FOPT-1]));
+               if (tb[TCA_CBQ_FOPT])
+                       cbq_set_fopt(cl, nla_data(tb[TCA_CBQ_FOPT]));
 
                if (cl->q->q.qlen)
                        cbq_activate_class(cl);
 
                sch_tree_unlock(sch);
 
-#ifdef CONFIG_NET_ESTIMATOR
-               if (tca[TCA_RATE-1])
+               if (tca[TCA_RATE])
                        gen_replace_estimator(&cl->bstats, &cl->rate_est,
-                               cl->stats_lock, tca[TCA_RATE-1]);
-#endif
+                                             &sch->dev->queue_lock,
+                                             tca[TCA_RATE]);
                return 0;
        }
 
        if (parentid == TC_H_ROOT)
                return -EINVAL;
 
-       if (tb[TCA_CBQ_WRROPT-1] == NULL || tb[TCA_CBQ_RATE-1] == NULL ||
-           tb[TCA_CBQ_LSSOPT-1] == NULL)
+       if (tb[TCA_CBQ_WRROPT] == NULL || tb[TCA_CBQ_RATE] == NULL ||
+           tb[TCA_CBQ_LSSOPT] == NULL)
                return -EINVAL;
 
-       rtab = qdisc_get_rtab(RTA_DATA(tb[TCA_CBQ_RATE-1]), tb[TCA_CBQ_RTAB-1]);
+       rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), tb[TCA_CBQ_RTAB]);
        if (rtab == NULL)
                return -EINVAL;
 
@@ -1933,7 +1891,6 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
        cl->allot = parent->allot;
        cl->quantum = cl->allot;
        cl->weight = cl->R_tab->rate.rate;
-       cl->stats_lock = &sch->dev->queue_lock;
 
        sch_tree_lock(sch);
        cbq_link_class(cl);
@@ -1942,8 +1899,8 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
                cl->share = cl->tparent;
        cbq_adjust_levels(parent);
        cl->minidle = -0x7FFFFFFF;
-       cbq_set_lss(cl, RTA_DATA(tb[TCA_CBQ_LSSOPT-1]));
-       cbq_set_wrr(cl, RTA_DATA(tb[TCA_CBQ_WRROPT-1]));
+       cbq_set_lss(cl, nla_data(tb[TCA_CBQ_LSSOPT]));
+       cbq_set_wrr(cl, nla_data(tb[TCA_CBQ_WRROPT]));
        if (cl->ewma_log==0)
                cl->ewma_log = q->link.ewma_log;
        if (cl->maxidle==0)
@@ -1951,21 +1908,19 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
        if (cl->avpkt==0)
                cl->avpkt = q->link.avpkt;
        cl->overlimit = cbq_ovl_classic;
-       if (tb[TCA_CBQ_OVL_STRATEGY-1])
-               cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1]));
-#ifdef CONFIG_NET_CLS_POLICE
-       if (tb[TCA_CBQ_POLICE-1])
-               cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1]));
+       if (tb[TCA_CBQ_OVL_STRATEGY])
+               cbq_set_overlimit(cl, nla_data(tb[TCA_CBQ_OVL_STRATEGY]));
+#ifdef CONFIG_NET_CLS_ACT
+       if (tb[TCA_CBQ_POLICE])
+               cbq_set_police(cl, nla_data(tb[TCA_CBQ_POLICE]));
 #endif
-       if (tb[TCA_CBQ_FOPT-1])
-               cbq_set_fopt(cl, RTA_DATA(tb[TCA_CBQ_FOPT-1]));
+       if (tb[TCA_CBQ_FOPT])
+               cbq_set_fopt(cl, nla_data(tb[TCA_CBQ_FOPT]));
        sch_tree_unlock(sch);
 
-#ifdef CONFIG_NET_ESTIMATOR
-       if (tca[TCA_RATE-1])
+       if (tca[TCA_RATE])
                gen_new_estimator(&cl->bstats, &cl->rate_est,
-                       cl->stats_lock, tca[TCA_RATE-1]);
-#endif
+                                 &sch->dev->queue_lock, tca[TCA_RATE]);
 
        *arg = (unsigned long)cl;
        return 0;
@@ -1999,7 +1954,7 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg)
                q->tx_class = NULL;
                q->tx_borrowed = NULL;
        }
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
        if (q->rx_class == cl)
                q->rx_class = NULL;
 #endif
@@ -2077,7 +2032,7 @@ static void cbq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
        }
 }
 
-static struct Qdisc_class_ops cbq_class_ops = {
+static const struct Qdisc_class_ops cbq_class_ops = {
        .graft          =       cbq_graft,
        .leaf           =       cbq_leaf,
        .qlen_notify    =       cbq_qlen_notify,
@@ -2093,7 +2048,7 @@ static struct Qdisc_class_ops cbq_class_ops = {
        .dump_stats     =       cbq_dump_class_stats,
 };
 
-static struct Qdisc_ops cbq_qdisc_ops = {
+static struct Qdisc_ops cbq_qdisc_ops __read_mostly = {
        .next           =       NULL,
        .cl_ops         =       &cbq_class_ops,
        .id             =       "cbq",