|
@@ -57,8 +57,7 @@
|
|
|
static const struct ethtool_ops xennet_ethtool_ops;
|
|
|
|
|
|
struct netfront_cb {
|
|
|
- struct page *page;
|
|
|
- unsigned offset;
|
|
|
+ int pull_to;
|
|
|
};
|
|
|
|
|
|
#define NETFRONT_SKB_CB(skb) ((struct netfront_cb *)((skb)->cb))
|
|
@@ -867,15 +866,9 @@ static int handle_incoming_queue(struct net_device *dev,
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
while ((skb = __skb_dequeue(rxq)) != NULL) {
|
|
|
- struct page *page = NETFRONT_SKB_CB(skb)->page;
|
|
|
- void *vaddr = page_address(page);
|
|
|
- unsigned offset = NETFRONT_SKB_CB(skb)->offset;
|
|
|
-
|
|
|
- memcpy(skb->data, vaddr + offset,
|
|
|
- skb_headlen(skb));
|
|
|
+ int pull_to = NETFRONT_SKB_CB(skb)->pull_to;
|
|
|
|
|
|
- if (page != skb_frag_page(&skb_shinfo(skb)->frags[0]))
|
|
|
- __free_page(page);
|
|
|
+ __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);
|
|
@@ -913,7 +906,6 @@ static int xennet_poll(struct napi_struct *napi, int budget)
|
|
|
struct sk_buff_head errq;
|
|
|
struct sk_buff_head tmpq;
|
|
|
unsigned long flags;
|
|
|
- unsigned int len;
|
|
|
int err;
|
|
|
|
|
|
spin_lock(&np->rx_lock);
|
|
@@ -955,24 +947,13 @@ err:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- NETFRONT_SKB_CB(skb)->page =
|
|
|
- skb_frag_page(&skb_shinfo(skb)->frags[0]);
|
|
|
- NETFRONT_SKB_CB(skb)->offset = rx->offset;
|
|
|
-
|
|
|
- len = rx->status;
|
|
|
- if (len > RX_COPY_THRESHOLD)
|
|
|
- len = RX_COPY_THRESHOLD;
|
|
|
- skb_put(skb, len);
|
|
|
+ NETFRONT_SKB_CB(skb)->pull_to = rx->status;
|
|
|
+ if (NETFRONT_SKB_CB(skb)->pull_to > RX_COPY_THRESHOLD)
|
|
|
+ NETFRONT_SKB_CB(skb)->pull_to = RX_COPY_THRESHOLD;
|
|
|
|
|
|
- if (rx->status > len) {
|
|
|
- skb_shinfo(skb)->frags[0].page_offset =
|
|
|
- rx->offset + len;
|
|
|
- skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status - len);
|
|
|
- skb->data_len = rx->status - len;
|
|
|
- } else {
|
|
|
- __skb_fill_page_desc(skb, 0, NULL, 0, 0);
|
|
|
- skb_shinfo(skb)->nr_frags = 0;
|
|
|
- }
|
|
|
+ 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;
|
|
|
|
|
|
i = xennet_fill_frags(np, skb, &tmpq);
|
|
|
|
|
@@ -999,7 +980,7 @@ err:
|
|
|
* receive throughout using the standard receive
|
|
|
* buffer size was cut by 25%(!!!).
|
|
|
*/
|
|
|
- skb->truesize += skb->data_len - (RX_COPY_THRESHOLD - len);
|
|
|
+ skb->truesize += skb->data_len - RX_COPY_THRESHOLD;
|
|
|
skb->len += skb->data_len;
|
|
|
|
|
|
if (rx->flags & XEN_NETRXF_csum_blank)
|