On Thu, 2014-02-27 at 13:51 -0800, Ben Greear wrote: > That said, the code below appears to work, even if it is > not as efficient as it might be? > > if (msdu_chaining) { > struct sk_buff *next = msdu_head->next; > struct sk_buff *to_free = next; > int space; > static int do_once = 1; > msdu_head->next = NULL; > > if (unlikely(do_once)) { > ath10k_warn("htt rx msdu_chaining detected %d\n", > msdu_chaining); > do_once = 0; > } > > while (next) { > space = next->len - skb_tailroom(msdu_head); > > if ((space > 0) && > (pskb_expand_head(msdu_head, 0, space, GFP_ATOMIC) < 0)) { > /* TODO: bump some rx-oom error stat */ > goto outside_continue; > } > skb_copy_from_linear_data(next, skb_put(msdu_head, next->len), > next->len); > next = next->next; > } Yep, this is very inefficient , you might copy data very often in pskb_expand_head(), then in skb_copy_from_linear_data() Also, if total length is big, you end up doing high order allocations, since you generate a linear skb. This might fail under memory pressure. What is the maximal skb->len of resulting skb ? -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html