Merge branches 'pm-sleep', 'pm-cpufreq', 'pm-core' and 'pm-opp'
[deliverable/linux.git] / net / sched / sch_fq.c
index 3c6a47d66a047da8765c9e90b808629a87afc0ea..e5458b99e09cb4d4226a1ef49a7ec81f2e20d94a 100644 (file)
@@ -368,18 +368,19 @@ static void flow_queue_add(struct fq_flow *flow, struct sk_buff *skb)
        }
 }
 
-static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+                     struct sk_buff **to_free)
 {
        struct fq_sched_data *q = qdisc_priv(sch);
        struct fq_flow *f;
 
        if (unlikely(sch->q.qlen >= sch->limit))
-               return qdisc_drop(skb, sch);
+               return qdisc_drop(skb, sch, to_free);
 
        f = fq_classify(skb, q);
        if (unlikely(f->qlen >= q->flow_plimit && f != &q->internal)) {
                q->stat_flows_plimit++;
-               return qdisc_drop(skb, sch);
+               return qdisc_drop(skb, sch, to_free);
        }
 
        f->qlen++;
@@ -445,8 +446,7 @@ begin:
                if (!head->first) {
                        if (q->time_next_delayed_flow != ~0ULL)
                                qdisc_watchdog_schedule_ns(&q->watchdog,
-                                                          q->time_next_delayed_flow,
-                                                          false);
+                                                          q->time_next_delayed_flow);
                        return NULL;
                }
        }
@@ -515,17 +515,25 @@ out:
        return skb;
 }
 
+static void fq_flow_purge(struct fq_flow *flow)
+{
+       rtnl_kfree_skbs(flow->head, flow->tail);
+       flow->head = NULL;
+       flow->qlen = 0;
+}
+
 static void fq_reset(struct Qdisc *sch)
 {
        struct fq_sched_data *q = qdisc_priv(sch);
        struct rb_root *root;
-       struct sk_buff *skb;
        struct rb_node *p;
        struct fq_flow *f;
        unsigned int idx;
 
-       while ((skb = fq_dequeue_head(sch, &q->internal)) != NULL)
-               kfree_skb(skb);
+       sch->q.qlen = 0;
+       sch->qstats.backlog = 0;
+
+       fq_flow_purge(&q->internal);
 
        if (!q->fq_root)
                return;
@@ -536,8 +544,7 @@ static void fq_reset(struct Qdisc *sch)
                        f = container_of(p, struct fq_flow, fq_node);
                        rb_erase(p, root);
 
-                       while ((skb = fq_dequeue_head(sch, f)) != NULL)
-                               kfree_skb(skb);
+                       fq_flow_purge(f);
 
                        kmem_cache_free(fq_flow_cachep, f);
                }
@@ -738,7 +745,7 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt)
                if (!skb)
                        break;
                drop_len += qdisc_pkt_len(skb);
-               kfree_skb(skb);
+               rtnl_kfree_skbs(skb, skb);
                drop_count++;
        }
        qdisc_tree_reduce_backlog(sch, drop_count, drop_len);
This page took 0.044595 seconds and 5 git commands to generate.