Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / net / sched / sch_tbf.c
index 7854980..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,20 +196,20 @@ 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);
 
        if (skb) {
                psched_time_t now;
-               long toks;
+               long toks, delay;
                long ptoks = 0;
                unsigned int len = skb->len;
 
                PSCHED_GET_TIME(now);
 
-               toks = PSCHED_TDIFF_SAFE(now, q->t_c, q->buffer, 0);
+               toks = PSCHED_TDIFF_SAFE(now, q->t_c, q->buffer);
 
                if (q->P_tab) {
                        ptoks = toks + q->ptokens;
@@ -229,14 +231,12 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch)
                        return skb;
                }
 
-               if (!netif_queue_stopped(sch->dev)) {
-                       long delay = PSCHED_US2JIFFIE(max_t(long, -toks, -ptoks));
+               delay = PSCHED_US2JIFFIE(max_t(long, -toks, -ptoks));
 
-                       if (delay == 0)
-                               delay = 1;
+               if (delay == 0)
+                       delay = 1;
 
-                       mod_timer(&q->wd_timer, jiffies+delay);
-               }
+               mod_timer(&q->wd_timer, jiffies+delay);
 
                /* Maybe we have a shorter packet in the queue,
                   which can be sent now. It sounds cool,
@@ -252,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;
@@ -302,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;
@@ -310,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;
@@ -341,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;
@@ -368,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;
@@ -385,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);
 
@@ -395,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;
@@ -429,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;
@@ -443,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;
@@ -459,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;
 }