@@ -1202,15 +1202,19 @@ static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb,
/* Copy data in the first descriptor of this completion */
curr_frag_len = min(rxcp->pkt_size, rx_frag_size);
- /* Copy the header portion into skb_data */
- hdr_len = min(BE_HDR_LEN, curr_frag_len);
+ /* If frame is small enough to fit in skb->head, pull it completely.
+ * If not, only pull ethernet header so that splice() or TCP coalesce
+ * are more efficient.
+ */
+ hdr_len = (curr_frag_len <= skb_tailroom(skb)) ?
+ curr_frag_len : ETH_HLEN;
+
memcpy(skb->data, start, hdr_len);
skb->len = curr_frag_len;
- if (curr_frag_len <= BE_HDR_LEN) { /* tiny packet */
+ skb->tail += hdr_len;
+ if (hdr_len == curr_frag_len) { /* tiny packet */
/* Complete packet has now been moved to data */
put_page(page_info->page);
- skb->data_len = 0;
- skb->tail += curr_frag_len;
} else {
skb_shinfo(skb)->nr_frags = 1;
skb_frag_set_page(skb, 0, page_info->page);
@@ -1219,7 +1223,6 @@ static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb,
skb_frag_size_set(&skb_shinfo(skb)->frags[0], curr_frag_len - hdr_len);
skb->data_len = curr_frag_len - hdr_len;
skb->truesize += rx_frag_size;
- skb->tail += hdr_len;
}
page_info->page = NULL;