diff options
Diffstat (limited to '')
| -rw-r--r-- | include/net/sch_generic.h | 11 | ||||
| -rw-r--r-- | net/core/dev.c | 15 |
2 files changed, 16 insertions, 10 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 79501499dafb..b8092d0378a0 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -1105,6 +1105,17 @@ static inline void tcf_set_drop_reason(const struct sk_buff *skb, tc_skb_cb(skb)->drop_reason = reason; } +static inline void tcf_kfree_skb_list(struct sk_buff *skb) +{ + while (unlikely(skb)) { + struct sk_buff *next = skb->next; + + prefetch(next); + kfree_skb_reason(skb, tcf_get_drop_reason(skb)); + skb = next; + } +} + /* Instead of calling kfree_skb() while root qdisc lock is held, * queue the skb for future freeing at end of __dev_xmit_skb() */ diff --git a/net/core/dev.c b/net/core/dev.c index 10042139dbb0..e865cdb9b696 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4162,7 +4162,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, __qdisc_run(q); qdisc_run_end(q); - goto no_lock_out; + goto free_skbs; } qdisc_bstats_cpu_update(q, skb); @@ -4176,12 +4176,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, rc = dev_qdisc_enqueue(skb, q, &to_free, txq); qdisc_run(q); - -no_lock_out: - if (unlikely(to_free)) - kfree_skb_list_reason(to_free, - tcf_get_drop_reason(to_free)); - return rc; + goto free_skbs; } /* Open code llist_add(&skb->ll_node, &q->defer_list) + queue limit. @@ -4257,9 +4252,9 @@ no_lock_out: } unlock: spin_unlock(root_lock); - if (unlikely(to_free)) - kfree_skb_list_reason(to_free, - tcf_get_drop_reason(to_free)); + +free_skbs: + tcf_kfree_skb_list(to_free); return rc; } |
