net: Fix for initial link state in 2.6.28
[safe/jmp/linux-2.6] / net / sched / sch_hfsc.c
index d90b165..45c31b1 100644 (file)
@@ -184,7 +184,6 @@ struct hfsc_sched
        struct rb_root eligible;                /* eligible tree */
        struct list_head droplist;              /* active leaf class list (for
                                                   dropping) */
-       struct sk_buff_head requeue;            /* requeued packet */
        struct qdisc_watchdog watchdog;         /* watchdog timer */
 };
 
@@ -1019,6 +1018,14 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
                }
                cur_time = psched_get_time();
 
+               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 (rsc != NULL)
                        hfsc_change_rsc(cl, rsc, cur_time);
@@ -1035,10 +1042,6 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
                }
                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;
        }
 
@@ -1064,6 +1067,16 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        if (cl == NULL)
                return -ENOBUFS;
 
+       if (tca[TCA_RATE]) {
+               err = gen_new_estimator(&cl->bstats, &cl->rate_est,
+                                       qdisc_root_sleeping_lock(sch),
+                                       tca[TCA_RATE]);
+               if (err) {
+                       kfree(cl);
+                       return err;
+               }
+       }
+
        if (rsc != NULL)
                hfsc_change_rsc(cl, rsc, 0);
        if (fsc != NULL)
@@ -1094,9 +1107,6 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 
        qdisc_class_hash_grow(sch, &q->clhash);
 
-       if (tca[TCA_RATE])
-               gen_new_estimator(&cl->bstats, &cl->rate_est,
-                                 qdisc_root_sleeping_lock(sch), tca[TCA_RATE]);
        *arg = (unsigned long)cl;
        return 0;
 }
@@ -1203,7 +1213,8 @@ hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
 
        sch_tree_lock(sch);
        hfsc_purge_queue(sch, cl);
-       *old = xchg(&cl->qdisc, new);
+       *old = cl->qdisc;
+       cl->qdisc = new;
        sch_tree_unlock(sch);
        return 0;
 }
@@ -1432,7 +1443,6 @@ hfsc_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
                return err;
        q->eligible = RB_ROOT;
        INIT_LIST_HEAD(&q->droplist);
-       skb_queue_head_init(&q->requeue);
 
        q->root.cl_common.classid = sch->handle;
        q->root.refcnt  = 1;
@@ -1517,7 +1527,6 @@ hfsc_reset_qdisc(struct Qdisc *sch)
                hlist_for_each_entry(cl, n, &q->clhash.hash[i], cl_common.hnode)
                        hfsc_reset_class(cl);
        }
-       __skb_queue_purge(&q->requeue);
        q->eligible = RB_ROOT;
        INIT_LIST_HEAD(&q->droplist);
        qdisc_watchdog_cancel(&q->watchdog);
@@ -1542,7 +1551,6 @@ hfsc_destroy_qdisc(struct Qdisc *sch)
                        hfsc_destroy_class(sch, cl);
        }
        qdisc_class_hash_destroy(&q->clhash);
-       __skb_queue_purge(&q->requeue);
        qdisc_watchdog_cancel(&q->watchdog);
 }
 
@@ -1566,7 +1574,7 @@ static int
 hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
        struct hfsc_class *cl;
-       int err;
+       int uninitialized_var(err);
 
        cl = hfsc_classify(skb, sch, &err);
        if (cl == NULL) {
@@ -1609,8 +1617,6 @@ hfsc_dequeue(struct Qdisc *sch)
 
        if (sch->q.qlen == 0)
                return NULL;
-       if ((skb = __skb_dequeue(&q->requeue)))
-               goto out;
 
        cur_time = psched_get_time();
 
@@ -1659,24 +1665,12 @@ hfsc_dequeue(struct Qdisc *sch)
                set_passive(cl);
        }
 
- out:
        sch->flags &= ~TCQ_F_THROTTLED;
        sch->q.qlen--;
 
        return skb;
 }
 
-static int
-hfsc_requeue(struct sk_buff *skb, struct Qdisc *sch)
-{
-       struct hfsc_sched *q = qdisc_priv(sch);
-
-       __skb_queue_head(&q->requeue, skb);
-       sch->q.qlen++;
-       sch->qstats.requeues++;
-       return NET_XMIT_SUCCESS;
-}
-
 static unsigned int
 hfsc_drop(struct Qdisc *sch)
 {
@@ -1728,7 +1722,6 @@ static struct Qdisc_ops hfsc_qdisc_ops __read_mostly = {
        .enqueue        = hfsc_enqueue,
        .dequeue        = hfsc_dequeue,
        .peek           = qdisc_peek_dequeued,
-       .requeue        = hfsc_requeue,
        .drop           = hfsc_drop,
        .cl_ops         = &hfsc_class_ops,
        .priv_size      = sizeof(struct hfsc_sched),