fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / net / sched / sch_hfsc.c
index c26764b..6eefa69 100644 (file)
@@ -50,7 +50,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -208,7 +207,7 @@ struct hfsc_sched
 do {                                                                   \
        struct timeval tv;                                              \
        do_gettimeofday(&tv);                                           \
-       (stamp) = 1000000ULL * tv.tv_sec + tv.tv_usec;                  \
+       (stamp) = 1ULL * USEC_PER_SEC * tv.tv_sec + tv.tv_usec;         \
 } while (0)
 #endif
 
@@ -502,8 +501,8 @@ d2dx(u32 d)
        u64 dx;
 
        dx = ((u64)d * PSCHED_JIFFIE2US(HZ));
-       dx += 1000000 - 1;
-       do_div(dx, 1000000);
+       dx += USEC_PER_SEC - 1;
+       do_div(dx, USEC_PER_SEC);
        return dx;
 }
 
@@ -523,7 +522,7 @@ dx2d(u64 dx)
 {
        u64 d;
 
-       d = dx * 1000000;
+       d = dx * USEC_PER_SEC;
        do_div(d, PSCHED_JIFFIE2US(HZ));
        return (u32)d;
 }
@@ -947,6 +946,7 @@ qdisc_peek_len(struct Qdisc *sch)
        if (unlikely(sch->ops->requeue(skb, sch) != NET_XMIT_SUCCESS)) {
                if (net_ratelimit())
                        printk("qdisc_peek_len: failed to requeue\n");
+               qdisc_tree_decrease_qlen(sch, 1);
                return 0;
        }
        return len;
@@ -958,11 +958,7 @@ hfsc_purge_queue(struct Qdisc *sch, struct hfsc_class *cl)
        unsigned int len = cl->qdisc->q.qlen;
 
        qdisc_reset(cl->qdisc);
-       if (len > 0) {
-               update_vf(cl, 0, 0);
-               set_passive(cl);
-               sch->q.qlen -= len;
-       }
+       qdisc_tree_decrease_qlen(cl->qdisc, len);
 }
 
 static void
@@ -974,10 +970,10 @@ hfsc_adjust_levels(struct hfsc_class *cl)
        do {
                level = 0;
                list_for_each_entry(p, &cl->children, siblings) {
-                       if (p->level > level)
-                               level = p->level;
+                       if (p->level >= level)
+                               level = p->level + 1;
                }
-               cl->level = level + 1;
+               cl->level = level;
        } while ((cl = cl->cl_parent) != NULL);
 }
 
@@ -1124,10 +1120,9 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        if (rsc == NULL && fsc == NULL)
                return -EINVAL;
 
-       cl = kmalloc(sizeof(struct hfsc_class), GFP_KERNEL);
+       cl = kzalloc(sizeof(struct hfsc_class), GFP_KERNEL);
        if (cl == NULL)
                return -ENOBUFS;
-       memset(cl, 0, sizeof(struct hfsc_class));
 
        if (rsc != NULL)
                hfsc_change_rsc(cl, rsc, 0);
@@ -1140,7 +1135,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        cl->classid   = classid;
        cl->sched     = q;
        cl->cl_parent = parent;
-       cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+       cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid);
        if (cl->qdisc == NULL)
                cl->qdisc = &noop_qdisc;
        cl->stats_lock = &sch->dev->queue_lock;
@@ -1227,7 +1222,7 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
                if (cl->level == 0)
                        return cl;
 
-       *qerr = NET_XMIT_DROP;
+       *qerr = NET_XMIT_BYPASS;
        tcf = q->root.filter_list;
        while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
 #ifdef CONFIG_NET_CLS_ACT
@@ -1273,7 +1268,8 @@ hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
        if (cl->level > 0)
                return -EINVAL;
        if (new == NULL) {
-               new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+               new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+                                       cl->classid);
                if (new == NULL)
                        new = &noop_qdisc;
        }
@@ -1296,6 +1292,17 @@ hfsc_class_leaf(struct Qdisc *sch, unsigned long arg)
        return NULL;
 }
 
+static void
+hfsc_qlen_notify(struct Qdisc *sch, unsigned long arg)
+{
+       struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+       if (cl->qdisc->q.qlen == 0) {
+               update_vf(cl, 0, 0);
+               set_passive(cl);
+       }
+}
+
 static unsigned long
 hfsc_get_class(struct Qdisc *sch, u32 classid)
 {
@@ -1516,7 +1523,8 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt)
        q->root.refcnt  = 1;
        q->root.classid = sch->handle;
        q->root.sched   = q;
-       q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+       q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+                                         sch->handle);
        if (q->root.qdisc == NULL)
                q->root.qdisc = &noop_qdisc;
        q->root.stats_lock = &sch->dev->queue_lock;
@@ -1643,7 +1651,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 
        cl = hfsc_classify(skb, sch, &err);
        if (cl == NULL) {
-               if (err == NET_XMIT_DROP)
+               if (err == NET_XMIT_BYPASS)
                        sch->qstats.drops++;
                kfree_skb(skb);
                return err;
@@ -1779,6 +1787,7 @@ static struct Qdisc_class_ops hfsc_class_ops = {
        .delete         = hfsc_delete_class,
        .graft          = hfsc_graft_class,
        .leaf           = hfsc_class_leaf,
+       .qlen_notify    = hfsc_qlen_notify,
        .get            = hfsc_get_class,
        .put            = hfsc_put_class,
        .bind_tcf       = hfsc_bind_tcf,