]> Pileus Git - ~andy/linux/blobdiff - net/sched/sch_qfq.c
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
[~andy/linux] / net / sched / sch_qfq.c
index 7b0325459e718c6c0fb8d259ef7e10ecc6353130..e68cb440756a4c33ce1108d464ea51b1c0b95631 100644 (file)
@@ -211,6 +211,7 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        struct nlattr *tb[TCA_QFQ_MAX + 1];
        u32 weight, lmax, inv_w;
        int i, err;
+       int delta_w;
 
        if (tca[TCA_OPTIONS] == NULL) {
                pr_notice("qfq: no options\n");
@@ -232,9 +233,10 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 
        inv_w = ONE_FP / weight;
        weight = ONE_FP / inv_w;
-       if (q->wsum + weight > QFQ_MAX_WSUM) {
+       delta_w = weight - (cl ? ONE_FP / cl->inv_w : 0);
+       if (q->wsum + delta_w > QFQ_MAX_WSUM) {
                pr_notice("qfq: total weight out of range (%u + %u)\n",
-                         weight, q->wsum);
+                         delta_w, q->wsum);
                return -EINVAL;
        }
 
@@ -256,13 +258,12 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
                                return err;
                }
 
-               sch_tree_lock(sch);
-               if (tb[TCA_QFQ_WEIGHT]) {
-                       q->wsum = weight - ONE_FP / cl->inv_w;
+               if (inv_w != cl->inv_w) {
+                       sch_tree_lock(sch);
+                       q->wsum += delta_w;
                        cl->inv_w = inv_w;
+                       sch_tree_unlock(sch);
                }
-               sch_tree_unlock(sch);
-
                return 0;
        }
 
@@ -277,7 +278,6 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        i = qfq_calc_index(cl->inv_w, cl->lmax);
 
        cl->grp = &q->groups[i];
-       q->wsum += weight;
 
        cl->qdisc = qdisc_create_dflt(sch->dev_queue,
                                      &pfifo_qdisc_ops, classid);
@@ -294,6 +294,7 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
                        return err;
                }
        }
+       q->wsum += weight;
 
        sch_tree_lock(sch);
        qdisc_class_hash_insert(&q->clhash, &cl->common);