|
@@ -286,8 +286,7 @@ no_skb:
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- __skb_fill_page_desc(skb, 0, page, 0, 0);
|
|
|
- skb_shinfo(skb)->nr_frags = 1;
|
|
|
+ skb_add_rx_frag(skb, 0, page, 0, 0, PAGE_SIZE);
|
|
|
__skb_queue_tail(&np->rx_batch, skb);
|
|
|
}
|
|
|
|
|
@@ -831,7 +830,6 @@ static RING_IDX xennet_fill_frags(struct netfront_info *np,
|
|
|
struct sk_buff_head *list)
|
|
|
{
|
|
|
struct skb_shared_info *shinfo = skb_shinfo(skb);
|
|
|
- int nr_frags = shinfo->nr_frags;
|
|
|
RING_IDX cons = np->rx.rsp_cons;
|
|
|
struct sk_buff *nskb;
|
|
|
|
|
@@ -840,19 +838,21 @@ static RING_IDX xennet_fill_frags(struct netfront_info *np,
|
|
|
RING_GET_RESPONSE(&np->rx, ++cons);
|
|
|
skb_frag_t *nfrag = &skb_shinfo(nskb)->frags[0];
|
|
|
|
|
|
- __skb_fill_page_desc(skb, nr_frags,
|
|
|
- skb_frag_page(nfrag),
|
|
|
- rx->offset, rx->status);
|
|
|
+ if (shinfo->nr_frags == MAX_SKB_FRAGS) {
|
|
|
+ unsigned int pull_to = NETFRONT_SKB_CB(skb)->pull_to;
|
|
|
|
|
|
- skb->data_len += rx->status;
|
|
|
+ BUG_ON(pull_to <= skb_headlen(skb));
|
|
|
+ __pskb_pull_tail(skb, pull_to - skb_headlen(skb));
|
|
|
+ }
|
|
|
+ BUG_ON(shinfo->nr_frags >= MAX_SKB_FRAGS);
|
|
|
+
|
|
|
+ skb_add_rx_frag(skb, shinfo->nr_frags, skb_frag_page(nfrag),
|
|
|
+ rx->offset, rx->status, PAGE_SIZE);
|
|
|
|
|
|
skb_shinfo(nskb)->nr_frags = 0;
|
|
|
kfree_skb(nskb);
|
|
|
-
|
|
|
- nr_frags++;
|
|
|
}
|
|
|
|
|
|
- shinfo->nr_frags = nr_frags;
|
|
|
return cons;
|
|
|
}
|
|
|
|
|
@@ -933,7 +933,8 @@ static int handle_incoming_queue(struct net_device *dev,
|
|
|
while ((skb = __skb_dequeue(rxq)) != NULL) {
|
|
|
int pull_to = NETFRONT_SKB_CB(skb)->pull_to;
|
|
|
|
|
|
- __pskb_pull_tail(skb, pull_to - skb_headlen(skb));
|
|
|
+ if (pull_to > skb_headlen(skb))
|
|
|
+ __pskb_pull_tail(skb, pull_to - skb_headlen(skb));
|
|
|
|
|
|
/* Ethernet work: Delayed to here as it peeks the header. */
|
|
|
skb->protocol = eth_type_trans(skb, dev);
|
|
@@ -1019,16 +1020,10 @@ err:
|
|
|
skb_shinfo(skb)->frags[0].page_offset = rx->offset;
|
|
|
skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status);
|
|
|
skb->data_len = rx->status;
|
|
|
+ skb->len += rx->status;
|
|
|
|
|
|
i = xennet_fill_frags(np, skb, &tmpq);
|
|
|
|
|
|
- /*
|
|
|
- * Truesize is the actual allocation size, even if the
|
|
|
- * allocation is only partially used.
|
|
|
- */
|
|
|
- skb->truesize += PAGE_SIZE * skb_shinfo(skb)->nr_frags;
|
|
|
- skb->len += skb->data_len;
|
|
|
-
|
|
|
if (rx->flags & XEN_NETRXF_csum_blank)
|
|
|
skb->ip_summed = CHECKSUM_PARTIAL;
|
|
|
else if (rx->flags & XEN_NETRXF_data_validated)
|