/* 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)
        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)
 {
        struct virtnet_info *vi = svq->vdev->priv;
        }
        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);
                if (vi->big_packets) {
                        for (i = 0; i < MAX_SKB_FRAGS; i++) {
                                skb_frag_t *f = &skb_shinfo(skb)->frags[i];
-                               f->page = alloc_page(GFP_ATOMIC);
+                               f->page = get_a_page(vi, GFP_ATOMIC);
                                if (!f->page)
                                        break;
 
        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. */
        vdev->config->del_vq(vi->svq);
        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);
 }