fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / net / sched / sch_hfsc.c
index 91132f6..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>
@@ -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;
@@ -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;
@@ -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,