mac80211: remove pointless chanctx NULL check
[cascardo/linux.git] / net / sched / sch_netem.c
index 178f163..aaaf021 100644 (file)
@@ -368,9 +368,7 @@ static void tfifo_reset(struct Qdisc *sch)
                struct sk_buff *skb = netem_rb_to_skb(p);
 
                rb_erase(p, &q->t_root);
-               skb->next = NULL;
-               skb->prev = NULL;
-               kfree_skb(skb);
+               rtnl_kfree_skbs(skb, skb);
        }
 }
 
@@ -399,7 +397,8 @@ static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
  * when we statistically choose to corrupt one, we instead segment it, returning
  * the first packet to be corrupted, and re-enqueue the remaining frames
  */
-static struct sk_buff *netem_segment(struct sk_buff *skb, struct Qdisc *sch)
+static struct sk_buff *netem_segment(struct sk_buff *skb, struct Qdisc *sch,
+                                    struct sk_buff **to_free)
 {
        struct sk_buff *segs;
        netdev_features_t features = netif_skb_features(skb);
@@ -407,7 +406,7 @@ static struct sk_buff *netem_segment(struct sk_buff *skb, struct Qdisc *sch)
        segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
 
        if (IS_ERR_OR_NULL(segs)) {
-               qdisc_reshape_fail(skb, sch);
+               qdisc_drop(skb, sch, to_free);
                return NULL;
        }
        consume_skb(skb);
@@ -420,7 +419,8 @@ static struct sk_buff *netem_segment(struct sk_buff *skb, struct Qdisc *sch)
  *     NET_XMIT_DROP: queue length didn't change.
  *      NET_XMIT_SUCCESS: one skb was queued.
  */
-static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+                        struct sk_buff **to_free)
 {
        struct netem_sched_data *q = qdisc_priv(sch);
        /* We don't fill cb now as skb_unshare() may invalidate it */
@@ -445,7 +445,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        }
        if (count == 0) {
                qdisc_qstats_drop(sch);
-               kfree_skb(skb);
+               __qdisc_drop(skb, to_free);
                return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
        }
 
@@ -465,7 +465,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                u32 dupsave = q->duplicate; /* prevent duplicating a dup... */
 
                q->duplicate = 0;
-               rootq->enqueue(skb2, rootq);
+               rootq->enqueue(skb2, rootq, to_free);
                q->duplicate = dupsave;
        }
 
@@ -477,7 +477,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
         */
        if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) {
                if (skb_is_gso(skb)) {
-                       segs = netem_segment(skb, sch);
+                       segs = netem_segment(skb, sch, to_free);
                        if (!segs)
                                return NET_XMIT_DROP;
                } else {
@@ -487,10 +487,14 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                skb = segs;
                segs = segs->next;
 
-               if (!(skb = skb_unshare(skb, GFP_ATOMIC)) ||
-                   (skb->ip_summed == CHECKSUM_PARTIAL &&
-                    skb_checksum_help(skb))) {
-                       rc = qdisc_drop(skb, sch);
+               skb = skb_unshare(skb, GFP_ATOMIC);
+               if (unlikely(!skb)) {
+                       qdisc_qstats_drop(sch);
+                       goto finish_segs;
+               }
+               if (skb->ip_summed == CHECKSUM_PARTIAL &&
+                   skb_checksum_help(skb)) {
+                       qdisc_drop(skb, sch, to_free);
                        goto finish_segs;
                }
 
@@ -499,7 +503,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        }
 
        if (unlikely(skb_queue_len(&sch->q) >= sch->limit))
-               return qdisc_reshape_fail(skb, sch);
+               return qdisc_drop(skb, sch, to_free);
 
        qdisc_qstats_backlog_inc(sch, skb);
 
@@ -559,7 +563,7 @@ finish_segs:
                        segs->next = NULL;
                        qdisc_skb_cb(segs)->pkt_len = segs->len;
                        last_len = segs->len;
-                       rc = qdisc_enqueue(segs, sch);
+                       rc = qdisc_enqueue(segs, sch, to_free);
                        if (rc != NET_XMIT_SUCCESS) {
                                if (net_xmit_drop_count(rc))
                                        qdisc_qstats_drop(sch);
@@ -576,50 +580,17 @@ finish_segs:
        return NET_XMIT_SUCCESS;
 }
 
-static unsigned int netem_drop(struct Qdisc *sch)
-{
-       struct netem_sched_data *q = qdisc_priv(sch);
-       unsigned int len;
-
-       len = qdisc_queue_drop(sch);
-
-       if (!len) {
-               struct rb_node *p = rb_first(&q->t_root);
-
-               if (p) {
-                       struct sk_buff *skb = netem_rb_to_skb(p);
-
-                       rb_erase(p, &q->t_root);
-                       sch->q.qlen--;
-                       skb->next = NULL;
-                       skb->prev = NULL;
-                       qdisc_qstats_backlog_dec(sch, skb);
-                       kfree_skb(skb);
-               }
-       }
-       if (!len && q->qdisc && q->qdisc->ops->drop)
-           len = q->qdisc->ops->drop(q->qdisc);
-       if (len)
-               qdisc_qstats_drop(sch);
-
-       return len;
-}
-
 static struct sk_buff *netem_dequeue(struct Qdisc *sch)
 {
        struct netem_sched_data *q = qdisc_priv(sch);
        struct sk_buff *skb;
        struct rb_node *p;
 
-       if (qdisc_is_throttled(sch))
-               return NULL;
-
 tfifo_dequeue:
        skb = __skb_dequeue(&sch->q);
        if (skb) {
                qdisc_qstats_backlog_dec(sch, skb);
 deliver:
-               qdisc_unthrottled(sch);
                qdisc_bstats_update(sch, skb);
                return skb;
        }
@@ -651,8 +622,11 @@ deliver:
 
                        if (q->qdisc) {
                                unsigned int pkt_len = qdisc_pkt_len(skb);
-                               int err = qdisc_enqueue(skb, q->qdisc);
+                               struct sk_buff *to_free = NULL;
+                               int err;
 
+                               err = qdisc_enqueue(skb, q->qdisc, &to_free);
+                               kfree_skb_list(to_free);
                                if (err != NET_XMIT_SUCCESS &&
                                    net_xmit_drop_count(err)) {
                                        qdisc_qstats_drop(sch);
@@ -1143,7 +1117,6 @@ static struct Qdisc_ops netem_qdisc_ops __read_mostly = {
        .enqueue        =       netem_enqueue,
        .dequeue        =       netem_dequeue,
        .peek           =       qdisc_peek_dequeued,
-       .drop           =       netem_drop,
        .init           =       netem_init,
        .reset          =       netem_reset,
        .destroy        =       netem_destroy,