aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/sched/sch_qfq.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index 103343408593..2c5ff6148589 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -211,6 +211,7 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
211 struct nlattr *tb[TCA_QFQ_MAX + 1]; 211 struct nlattr *tb[TCA_QFQ_MAX + 1];
212 u32 weight, lmax, inv_w; 212 u32 weight, lmax, inv_w;
213 int i, err; 213 int i, err;
214 int delta_w;
214 215
215 if (tca[TCA_OPTIONS] == NULL) { 216 if (tca[TCA_OPTIONS] == NULL) {
216 pr_notice("qfq: no options\n"); 217 pr_notice("qfq: no options\n");
@@ -232,9 +233,10 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
232 233
233 inv_w = ONE_FP / weight; 234 inv_w = ONE_FP / weight;
234 weight = ONE_FP / inv_w; 235 weight = ONE_FP / inv_w;
235 if (q->wsum + weight > QFQ_MAX_WSUM) { 236 delta_w = weight - (cl ? ONE_FP / cl->inv_w : 0);
237 if (q->wsum + delta_w > QFQ_MAX_WSUM) {
236 pr_notice("qfq: total weight out of range (%u + %u)\n", 238 pr_notice("qfq: total weight out of range (%u + %u)\n",
237 weight, q->wsum); 239 delta_w, q->wsum);
238 return -EINVAL; 240 return -EINVAL;
239 } 241 }
240 242
@@ -256,13 +258,12 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
256 return err; 258 return err;
257 } 259 }
258 260
259 sch_tree_lock(sch); 261 if (inv_w != cl->inv_w) {
260 if (tb[TCA_QFQ_WEIGHT]) { 262 sch_tree_lock(sch);
261 q->wsum = weight - ONE_FP / cl->inv_w; 263 q->wsum += delta_w;
262 cl->inv_w = inv_w; 264 cl->inv_w = inv_w;
265 sch_tree_unlock(sch);
263 } 266 }
264 sch_tree_unlock(sch);
265
266 return 0; 267 return 0;
267 } 268 }
268 269
@@ -277,7 +278,6 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
277 i = qfq_calc_index(cl->inv_w, cl->lmax); 278 i = qfq_calc_index(cl->inv_w, cl->lmax);
278 279
279 cl->grp = &q->groups[i]; 280 cl->grp = &q->groups[i];
280 q->wsum += weight;
281 281
282 cl->qdisc = qdisc_create_dflt(sch->dev_queue, 282 cl->qdisc = qdisc_create_dflt(sch->dev_queue,
283 &pfifo_qdisc_ops, classid); 283 &pfifo_qdisc_ops, classid);
@@ -294,6 +294,7 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
294 return err; 294 return err;
295 } 295 }
296 } 296 }
297 q->wsum += weight;
297 298
298 sch_tree_lock(sch); 299 sch_tree_lock(sch);
299 qdisc_class_hash_insert(&q->clhash, &cl->common); 300 qdisc_class_hash_insert(&q->clhash, &cl->common);