Revert to Fedora kernel-2.6.17-1.2187_FC5 patched with vs2.0.2.1; there are too many...
[linux-2.6.git] / net / sched / sch_tbf.c
index e1eaf63..d8e03c7 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/module.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/jiffies.h>
@@ -137,11 +137,11 @@ struct tbf_sched_data
 
 static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 {
-       struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+       struct tbf_sched_data *q = qdisc_priv(sch);
        int ret;
 
        if (skb->len > q->max_size) {
-               sch->stats.drops++;
+               sch->qstats.drops++;
 #ifdef CONFIG_NET_CLS_POLICE
                if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch))
 #endif
@@ -151,35 +151,37 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch)
        }
 
        if ((ret = q->qdisc->enqueue(skb, q->qdisc)) != 0) {
-               sch->stats.drops++;
+               sch->qstats.drops++;
                return ret;
        }
 
        sch->q.qlen++;
-       sch->stats.bytes += skb->len;
-       sch->stats.packets++;
+       sch->bstats.bytes += skb->len;
+       sch->bstats.packets++;
        return 0;
 }
 
 static int tbf_requeue(struct sk_buff *skb, struct Qdisc* sch)
 {
-       struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+       struct tbf_sched_data *q = qdisc_priv(sch);
        int ret;
 
-       if ((ret = q->qdisc->ops->requeue(skb, q->qdisc)) == 0)
+       if ((ret = q->qdisc->ops->requeue(skb, q->qdisc)) == 0) {
                sch->q.qlen++;
+               sch->qstats.requeues++;
+       }
 
        return ret;
 }
 
 static unsigned int tbf_drop(struct Qdisc* sch)
 {
-       struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
-       unsigned int len;
+       struct tbf_sched_data *q = qdisc_priv(sch);
+       unsigned int len = 0;
 
-       if ((len = q->qdisc->ops->drop(q->qdisc)) != 0) {
+       if (q->qdisc->ops->drop && (len = q->qdisc->ops->drop(q->qdisc)) != 0) {
                sch->q.qlen--;
-               sch->stats.drops++;
+               sch->qstats.drops++;
        }
        return len;
 }
@@ -194,7 +196,7 @@ static void tbf_watchdog(unsigned long arg)
 
 static struct sk_buff *tbf_dequeue(struct Qdisc* sch)
 {
-       struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+       struct tbf_sched_data *q = qdisc_priv(sch);
        struct sk_buff *skb;
 
        skb = q->qdisc->dequeue(q->qdisc);
@@ -250,18 +252,18 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch)
                if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
                        /* When requeue fails skb is dropped */
                        sch->q.qlen--;
-                       sch->stats.drops++;
+                       sch->qstats.drops++;
                }
 
                sch->flags |= TCQ_F_THROTTLED;
-               sch->stats.overlimits++;
+               sch->qstats.overlimits++;
        }
        return NULL;
 }
 
 static void tbf_reset(struct Qdisc* sch)
 {
-       struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+       struct tbf_sched_data *q = qdisc_priv(sch);
 
        qdisc_reset(q->qdisc);
        sch->q.qlen = 0;
@@ -300,7 +302,7 @@ static struct Qdisc *tbf_create_dflt_qdisc(struct net_device *dev, u32 limit)
 static int tbf_change(struct Qdisc* sch, struct rtattr *opt)
 {
        int err = -EINVAL;
-       struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+       struct tbf_sched_data *q = qdisc_priv(sch);
        struct rtattr *tb[TCA_TBF_PTAB];
        struct tc_tbf_qopt *qopt;
        struct qdisc_rate_table *rtab = NULL;
@@ -308,7 +310,7 @@ static int tbf_change(struct Qdisc* sch, struct rtattr *opt)
        struct Qdisc *child = NULL;
        int max_size,n;
 
-       if (rtattr_parse(tb, TCA_TBF_PTAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) ||
+       if (rtattr_parse_nested(tb, TCA_TBF_PTAB, opt) ||
            tb[TCA_TBF_PARMS-1] == NULL ||
            RTA_PAYLOAD(tb[TCA_TBF_PARMS-1]) < sizeof(*qopt))
                goto done;
@@ -339,13 +341,14 @@ static int tbf_change(struct Qdisc* sch, struct rtattr *opt)
        if (max_size < 0)
                goto done;
 
-       if (q->qdisc == &noop_qdisc) {
+       if (qopt->limit > 0) {
                if ((child = tbf_create_dflt_qdisc(sch->dev, qopt->limit)) == NULL)
                        goto done;
        }
 
        sch_tree_lock(sch);
-       if (child) q->qdisc = child;
+       if (child)
+               qdisc_destroy(xchg(&q->qdisc, child));
        q->limit = qopt->limit;
        q->mtu = qopt->mtu;
        q->max_size = max_size;
@@ -366,7 +369,7 @@ done:
 
 static int tbf_init(struct Qdisc* sch, struct rtattr *opt)
 {
-       struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+       struct tbf_sched_data *q = qdisc_priv(sch);
 
        if (opt == NULL)
                return -EINVAL;
@@ -383,7 +386,7 @@ static int tbf_init(struct Qdisc* sch, struct rtattr *opt)
 
 static void tbf_destroy(struct Qdisc *sch)
 {
-       struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+       struct tbf_sched_data *q = qdisc_priv(sch);
 
        del_timer(&q->wd_timer);
 
@@ -393,12 +396,11 @@ static void tbf_destroy(struct Qdisc *sch)
                qdisc_put_rtab(q->R_tab);
 
        qdisc_destroy(q->qdisc);
-       q->qdisc = &noop_qdisc;
 }
 
 static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
-       struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+       struct tbf_sched_data *q = qdisc_priv(sch);
        unsigned char    *b = skb->tail;
        struct rtattr *rta;
        struct tc_tbf_qopt opt;
@@ -427,7 +429,7 @@ rtattr_failure:
 static int tbf_dump_class(struct Qdisc *sch, unsigned long cl,
                          struct sk_buff *skb, struct tcmsg *tcm)
 {
-       struct tbf_sched_data *q = (struct tbf_sched_data*)sch->data;
+       struct tbf_sched_data *q = qdisc_priv(sch);
 
        if (cl != 1)    /* only one class */
                return -ENOENT;
@@ -441,7 +443,7 @@ static int tbf_dump_class(struct Qdisc *sch, unsigned long cl,
 static int tbf_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
                     struct Qdisc **old)
 {
-       struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+       struct tbf_sched_data *q = qdisc_priv(sch);
 
        if (new == NULL)
                new = &noop_qdisc;
@@ -457,7 +459,7 @@ static int tbf_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
 
 static struct Qdisc *tbf_leaf(struct Qdisc *sch, unsigned long arg)
 {
-       struct tbf_sched_data *q = (struct tbf_sched_data *)sch->data;
+       struct tbf_sched_data *q = qdisc_priv(sch);
        return q->qdisc;
 }