]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/sched/sch_htb.c
net: convert BUG_TRAP to generic WARN_ON
[linux-2.6-omap-h63xx.git] / net / sched / sch_htb.c
index e7461a17d71e042e9548cb2618349a64b9297fa3..75a40951c4f24edc68684462980e74dfd7123214 100644 (file)
@@ -81,9 +81,8 @@ struct htb_class {
 
        /* topology */
        int level;              /* our level (see above) */
+       unsigned int children;
        struct htb_class *parent;       /* parent class */
-       struct list_head sibling;       /* sibling list item */
-       struct list_head children;      /* children list */
 
        union {
                struct htb_class_leaf {
@@ -138,7 +137,6 @@ static inline long L2T(struct htb_class *cl, struct qdisc_rate_table *rate,
 }
 
 struct htb_sched {
-       struct list_head root;  /* root classes list */
        struct Qdisc_class_hash clhash;
        struct list_head drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */
 
@@ -161,7 +159,6 @@ struct htb_sched {
 
        /* filters for qdisc itself */
        struct tcf_proto *filter_list;
-       int filter_cnt;
 
        int rate2quantum;       /* quant = rate / rate2quantum */
        psched_time_t now;      /* cached dequeue time */
@@ -527,7 +524,7 @@ htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, long *diff)
  */
 static inline void htb_activate(struct htb_sched *q, struct htb_class *cl)
 {
-       BUG_TRAP(!cl->level && cl->un.leaf.q && cl->un.leaf.q->q.qlen);
+       WARN_ON(cl->level || !cl->un.leaf.q || !cl->un.leaf.q->q.qlen);
 
        if (!cl->prio_activity) {
                cl->prio_activity = 1 << (cl->un.leaf.aprio = cl->un.leaf.prio);
@@ -545,7 +542,7 @@ static inline void htb_activate(struct htb_sched *q, struct htb_class *cl)
  */
 static inline void htb_deactivate(struct htb_sched *q, struct htb_class *cl)
 {
-       BUG_TRAP(cl->prio_activity);
+       WARN_ON(!cl->prio_activity);
 
        htb_deactivate_prios(q, cl);
        cl->prio_activity = 0;
@@ -575,21 +572,20 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                kfree_skb(skb);
                return ret;
 #endif
-       } else if (cl->un.leaf.q->enqueue(skb, cl->un.leaf.q) !=
-                  NET_XMIT_SUCCESS) {
+       } else if (qdisc_enqueue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) {
                sch->qstats.drops++;
                cl->qstats.drops++;
                return NET_XMIT_DROP;
        } else {
                cl->bstats.packets +=
                        skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
-               cl->bstats.bytes += skb->len;
+               cl->bstats.bytes += qdisc_pkt_len(skb);
                htb_activate(q, cl);
        }
 
        sch->q.qlen++;
        sch->bstats.packets += skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
-       sch->bstats.bytes += skb->len;
+       sch->bstats.bytes += qdisc_pkt_len(skb);
        return NET_XMIT_SUCCESS;
 }
 
@@ -646,7 +642,7 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch)
 static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
                             int level, struct sk_buff *skb)
 {
-       int bytes = skb->len;
+       int bytes = qdisc_pkt_len(skb);
        long toks, diff;
        enum htb_cmode old_mode;
 
@@ -761,7 +757,7 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio,
                u32 *pid;
        } stk[TC_HTB_MAXDEPTH], *sp = stk;
 
-       BUG_TRAP(tree->rb_node);
+       WARN_ON(!tree->rb_node);
        sp->root = tree->rb_node;
        sp->pptr = pptr;
        sp->pid = pid;
@@ -781,7 +777,7 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio,
                                *sp->pptr = (*sp->pptr)->rb_left;
                        if (sp > stk) {
                                sp--;
-                               BUG_TRAP(*sp->pptr);
+                               WARN_ON(!*sp->pptr);
                                if (!*sp->pptr)
                                        return NULL;
                                htb_next_rb_node(sp->pptr);
@@ -796,7 +792,7 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio,
                        sp->pid = cl->un.inner.last_ptr_id + prio;
                }
        }
-       BUG_TRAP(0);
+       WARN_ON(1);
        return NULL;
 }
 
@@ -814,7 +810,7 @@ static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio,
 
        do {
 next:
-               BUG_TRAP(cl);
+               WARN_ON(!cl);
                if (!cl)
                        return NULL;
 
@@ -859,7 +855,8 @@ next:
        } while (cl != start);
 
        if (likely(skb != NULL)) {
-               if ((cl->un.leaf.deficit[level] -= skb->len) < 0) {
+               cl->un.leaf.deficit[level] -= qdisc_pkt_len(skb);
+               if (cl->un.leaf.deficit[level] < 0) {
                        cl->un.leaf.deficit[level] += cl->un.leaf.quantum;
                        htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
                                          ptr[0]) + prio);
@@ -1020,7 +1017,6 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
                return -EINVAL;
        }
 
-       INIT_LIST_HEAD(&q->root);
        err = qdisc_class_hash_init(&q->clhash);
        if (err < 0)
                return err;
@@ -1030,7 +1026,7 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
        qdisc_watchdog_init(&q->watchdog, sch);
        skb_queue_head_init(&q->direct_queue);
 
-       q->direct_qlen = sch->dev->tx_queue_len;
+       q->direct_qlen = qdisc_dev(sch)->tx_queue_len;
        if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */
                q->direct_qlen = 2;
 
@@ -1043,11 +1039,12 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
 
 static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
+       spinlock_t *root_lock = qdisc_root_lock(sch);
        struct htb_sched *q = qdisc_priv(sch);
        struct nlattr *nest;
        struct tc_htb_glob gopt;
 
-       spin_lock_bh(&sch->dev->queue_lock);
+       spin_lock_bh(root_lock);
 
        gopt.direct_pkts = q->direct_pkts;
        gopt.version = HTB_VER;
@@ -1061,11 +1058,11 @@ static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
        NLA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt);
        nla_nest_end(skb, nest);
 
-       spin_unlock_bh(&sch->dev->queue_lock);
+       spin_unlock_bh(root_lock);
        return skb->len;
 
 nla_put_failure:
-       spin_unlock_bh(&sch->dev->queue_lock);
+       spin_unlock_bh(root_lock);
        nla_nest_cancel(skb, nest);
        return -1;
 }
@@ -1074,10 +1071,11 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
                          struct sk_buff *skb, struct tcmsg *tcm)
 {
        struct htb_class *cl = (struct htb_class *)arg;
+       spinlock_t *root_lock = qdisc_root_lock(sch);
        struct nlattr *nest;
        struct tc_htb_opt opt;
 
-       spin_lock_bh(&sch->dev->queue_lock);
+       spin_lock_bh(root_lock);
        tcm->tcm_parent = cl->parent ? cl->parent->common.classid : TC_H_ROOT;
        tcm->tcm_handle = cl->common.classid;
        if (!cl->level && cl->un.leaf.q)
@@ -1099,11 +1097,11 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
        NLA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt);
 
        nla_nest_end(skb, nest);
-       spin_unlock_bh(&sch->dev->queue_lock);
+       spin_unlock_bh(root_lock);
        return skb->len;
 
 nla_put_failure:
-       spin_unlock_bh(&sch->dev->queue_lock);
+       spin_unlock_bh(root_lock);
        nla_nest_cancel(skb, nest);
        return -1;
 }
@@ -1133,7 +1131,8 @@ static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
 
        if (cl && !cl->level) {
                if (new == NULL &&
-                   (new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+                   (new = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
+                                            &pfifo_qdisc_ops,
                                             cl->common.classid))
                    == NULL)
                        return -ENOBUFS;
@@ -1175,12 +1174,9 @@ static inline int htb_parent_last_child(struct htb_class *cl)
        if (!cl->parent)
                /* the root class */
                return 0;
-
-       if (!(cl->parent->children.next == &cl->sibling &&
-               cl->parent->children.prev == &cl->sibling))
+       if (cl->parent->children > 1)
                /* not the last child */
                return 0;
-
        return 1;
 }
 
@@ -1189,7 +1185,7 @@ static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl,
 {
        struct htb_class *parent = cl->parent;
 
-       BUG_TRAP(!cl->level && cl->un.leaf.q && !cl->prio_activity);
+       WARN_ON(cl->level || !cl->un.leaf.q || cl->prio_activity);
 
        if (parent->cmode != HTB_CAN_SEND)
                htb_safe_rb_erase(&parent->pq_node, q->wait_pq + parent->level);
@@ -1209,7 +1205,7 @@ static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl,
 static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
 {
        if (!cl->level) {
-               BUG_TRAP(cl->un.leaf.q);
+               WARN_ON(!cl->un.leaf.q);
                qdisc_destroy(cl->un.leaf.q);
        }
        gen_kill_estimator(&cl->bstats, &cl->rate_est);
@@ -1259,12 +1255,13 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
        // TODO: why don't allow to delete subtree ? references ? does
        // tc subsys quarantee us that in htb_destroy it holds no class
        // refs so that we can remove children safely there ?
-       if (!list_empty(&cl->children) || cl->filter_cnt)
+       if (cl->children || cl->filter_cnt)
                return -EBUSY;
 
        if (!cl->level && htb_parent_last_child(cl)) {
-               new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
-                                               cl->parent->common.classid);
+               new_q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
+                                         &pfifo_qdisc_ops,
+                                         cl->parent->common.classid);
                last_child = 1;
        }
 
@@ -1278,7 +1275,7 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
 
        /* delete from hash and active; remainder in destroy_class */
        qdisc_class_hash_remove(&q->clhash, &cl->common);
-       list_del(&cl->sibling);
+       cl->parent->children--;
 
        if (cl->prio_activity)
                htb_deactivate(q, cl);
@@ -1370,11 +1367,10 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
                        goto failure;
 
                gen_new_estimator(&cl->bstats, &cl->rate_est,
-                                 &sch->dev->queue_lock,
+                                 qdisc_root_lock(sch),
                                  tca[TCA_RATE] ? : &est.nla);
                cl->refcnt = 1;
-               INIT_LIST_HEAD(&cl->sibling);
-               INIT_LIST_HEAD(&cl->children);
+               cl->children = 0;
                INIT_LIST_HEAD(&cl->un.leaf.drop_list);
                RB_CLEAR_NODE(&cl->pq_node);
 
@@ -1384,7 +1380,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
                /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL)
                   so that can't be used inside of sch_tree_lock
                   -- thanks to Karlis Peisenieks */
-               new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid);
+               new_q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
+                                         &pfifo_qdisc_ops, classid);
                sch_tree_lock(sch);
                if (parent && !parent->level) {
                        unsigned int qlen = parent->un.leaf.q->q.qlen;
@@ -1420,12 +1417,12 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
 
                /* attach to the hash list and parent's family */
                qdisc_class_hash_insert(&q->clhash, &cl->common);
-               list_add_tail(&cl->sibling,
-                             parent ? &parent->children : &q->root);
+               if (parent)
+                       parent->children++;
        } else {
                if (tca[TCA_RATE])
                        gen_replace_estimator(&cl->bstats, &cl->rate_est,
-                                             &sch->dev->queue_lock,
+                                             qdisc_root_lock(sch),
                                              tca[TCA_RATE]);
                sch_tree_lock(sch);
        }
@@ -1491,7 +1488,6 @@ static struct tcf_proto **htb_find_tcf(struct Qdisc *sch, unsigned long arg)
 static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent,
                                     u32 classid)
 {
-       struct htb_sched *q = qdisc_priv(sch);
        struct htb_class *cl = htb_find(classid, sch);
 
        /*if (cl && !cl->level) return 0;
@@ -1505,20 +1501,15 @@ static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent,
         */
        if (cl)
                cl->filter_cnt++;
-       else
-               q->filter_cnt++;
        return (unsigned long)cl;
 }
 
 static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg)
 {
-       struct htb_sched *q = qdisc_priv(sch);
        struct htb_class *cl = (struct htb_class *)arg;
 
        if (cl)
                cl->filter_cnt--;
-       else
-               q->filter_cnt--;
 }
 
 static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg)