---
 drivers/net/virtio_net.c |   78 +++++++++--------------------------------------
 1 file changed, 16 insertions(+), 62 deletions(-)

diff -r 13a0567af694 drivers/net/virtio_net.c
--- a/drivers/net/virtio_net.c	Mon Aug 25 19:31:37 2008 +1000
+++ b/drivers/net/virtio_net.c	Mon Aug 25 19:44:43 2008 +1000
@@ -61,9 +61,6 @@ struct virtnet_info
 	/* Receive & send queues. */
 	struct sk_buff_head recv;
 	struct sk_buff_head send;
-
-	/* Chain pages by the private ptr. */
-	struct page *pages;
 };
 
 static inline struct virtio_net_hdr *skb_vnet_hdr(struct sk_buff *skb)
@@ -74,23 +71,6 @@ static inline void vnet_hdr_to_sg(struct
 static inline void vnet_hdr_to_sg(struct scatterlist *sg, struct sk_buff *skb)
 {
 	sg_init_one(sg, skb_vnet_hdr(skb), sizeof(struct virtio_net_hdr));
-}
-
-static void give_a_page(struct virtnet_info *vi, struct page *page)
-{
-	page->private = (unsigned long)vi->pages;
-	vi->pages = page;
-}
-
-static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask)
-{
-	struct page *p = vi->pages;
-
-	if (p)
-		vi->pages = (struct page *)p->private;
-	else
-		p = alloc_page(gfp_mask);
-	return p;
 }
 
 static void skb_xmit_done(struct virtqueue *svq)
@@ -112,7 +92,6 @@ static void receive_skb(struct net_devic
 			unsigned len)
 {
 	struct virtio_net_hdr *hdr = skb_vnet_hdr(skb);
-	int err;
 
 	if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) {
 		pr_debug("%s: short packet %i\n", dev->name, len);
@@ -121,22 +100,11 @@ static void receive_skb(struct net_devic
 	}
 	len -= sizeof(struct virtio_net_hdr);
 
-	if (len <= MAX_PACKET_LEN) {
-		unsigned int i;
-
-		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-			give_a_page(dev->priv, skb_shinfo(skb)->frags[i].page);
-		skb->data_len = 0;
-		skb_shinfo(skb)->nr_frags = 0;
-	}
-
-	err = pskb_trim(skb, len);
-	if (err) {
-		pr_debug("%s: pskb_trim failed %i %d\n", dev->name, len, err);
-		dev->stats.rx_dropped++;
-		goto drop;
-	}
-	skb->truesize += skb->data_len;
+	printk("before: skb->len = %u, totlen = %u.  nr_frags = %u\n",
+	       skb->len, len, skb_shinfo(skb)->nr_frags);
+	trim_alloced_pskb(skb, len);
+	printk("after: skb->len = %u. nr_frags = %u\n",
+	       skb->len, skb_shinfo(skb)->nr_frags);
 	dev->stats.rx_bytes += skb->len;
 	dev->stats.rx_packets++;
 
@@ -198,34 +166,24 @@ static void try_fill_recv(struct virtnet
 {
 	struct sk_buff *skb;
 	struct scatterlist sg[2+MAX_SKB_FRAGS];
-	int num, err, i;
+	int num, err;
 
 	sg_init_table(sg, 2+MAX_SKB_FRAGS);
 	for (;;) {
-		skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN);
+		if (vi->big_packets) {
+			skb = alloc_pskb(MAX_PACKET_LEN,
+					 MAX_SKB_FRAGS*PAGE_SIZE,
+					 GFP_ATOMIC);
+		} else {
+			skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN);
+			if (skb)
+				skb_put(skb, MAX_PACKET_LEN);
+		}
+
 		if (unlikely(!skb))
 			break;
 
-		skb_put(skb, MAX_PACKET_LEN);
 		vnet_hdr_to_sg(sg, skb);
-
-		if (vi->big_packets) {
-			for (i = 0; i < MAX_SKB_FRAGS; i++) {
-				skb_frag_t *f = &skb_shinfo(skb)->frags[i];
-				f->page = get_a_page(vi, GFP_ATOMIC);
-				if (!f->page)
-					break;
-
-				f->page_offset = 0;
-				f->size = PAGE_SIZE;
-
-				skb->data_len += PAGE_SIZE;
-				skb->len += PAGE_SIZE;
-
-				skb_shinfo(skb)->nr_frags++;
-			}
-		}
-
 		num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
 		skb_queue_head(&vi->recv, skb);
 
@@ -535,7 +493,6 @@ static int virtnet_probe(struct virtio_d
 	vi->dev = dev;
 	vi->vdev = vdev;
 	vdev->priv = vi;
-	vi->pages = NULL;
 
 	/* If they give us a callback when all buffers are done, we don't need
 	 * the timer. */
@@ -622,9 +579,6 @@ static void virtnet_remove(struct virtio
 	vdev->config->del_vq(vi->rvq);
 	unregister_netdev(vi->dev);
 
-	while (vi->pages)
-		__free_pages(get_a_page(vi, GFP_KERNEL), 0);
-
 	free_netdev(vi->dev);
 }
 
