V4L/DVB (10977): STB6100 init fix, the call to stb6100_set_bandwidth needs an argument
[safe/jmp/linux-2.6] / net / sched / sch_drr.c
index 37e6ab9..e36e94a 100644 (file)
@@ -66,11 +66,15 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 {
        struct drr_sched *q = qdisc_priv(sch);
        struct drr_class *cl = (struct drr_class *)*arg;
+       struct nlattr *opt = tca[TCA_OPTIONS];
        struct nlattr *tb[TCA_DRR_MAX + 1];
        u32 quantum;
        int err;
 
-       err = nla_parse_nested(tb, TCA_DRR_MAX, tca[TCA_OPTIONS], drr_policy);
+       if (!opt)
+               return -EINVAL;
+
+       err = nla_parse_nested(tb, TCA_DRR_MAX, opt, drr_policy);
        if (err < 0)
                return err;
 
@@ -82,15 +86,19 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
                quantum = psched_mtu(qdisc_dev(sch));
 
        if (cl != NULL) {
+               if (tca[TCA_RATE]) {
+                       err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
+                                                   qdisc_root_sleeping_lock(sch),
+                                                   tca[TCA_RATE]);
+                       if (err)
+                               return err;
+               }
+
                sch_tree_lock(sch);
                if (tb[TCA_DRR_QUANTUM])
                        cl->quantum = quantum;
                sch_tree_unlock(sch);
 
-               if (tca[TCA_RATE])
-                       gen_replace_estimator(&cl->bstats, &cl->rate_est,
-                                             qdisc_root_sleeping_lock(sch),
-                                             tca[TCA_RATE]);
                return 0;
        }
 
@@ -106,10 +114,16 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        if (cl->qdisc == NULL)
                cl->qdisc = &noop_qdisc;
 
-       if (tca[TCA_RATE])
-               gen_replace_estimator(&cl->bstats, &cl->rate_est,
-                                     qdisc_root_sleeping_lock(sch),
-                                     tca[TCA_RATE]);
+       if (tca[TCA_RATE]) {
+               err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
+                                           qdisc_root_sleeping_lock(sch),
+                                           tca[TCA_RATE]);
+               if (err) {
+                       qdisc_destroy(cl->qdisc);
+                       kfree(cl);
+                       return err;
+               }
+       }
 
        sch_tree_lock(sch);
        qdisc_class_hash_insert(&q->clhash, &cl->common);
@@ -373,11 +387,13 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch)
        struct sk_buff *skb;
        unsigned int len;
 
-       while (!list_empty(&q->active)) {
+       if (list_empty(&q->active))
+               goto out;
+       while (1) {
                cl = list_first_entry(&q->active, struct drr_class, alist);
                skb = cl->qdisc->ops->peek(cl->qdisc);
                if (skb == NULL)
-                       goto skip;
+                       goto out;
 
                len = qdisc_pkt_len(skb);
                if (len <= cl->deficit) {
@@ -390,9 +406,9 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch)
                }
 
                cl->deficit += cl->quantum;
-skip:
                list_move_tail(&cl->alist, &q->active);
        }
+out:
        return NULL;
 }