struct tasklet_struct tasklet;
        bool free_in_tasklet;
 
+       /* I like... big packets and I cannot lie! */
+       bool big_packets;
+
        /* Receive & send queues. */
        struct sk_buff_head recv;
        struct sk_buff_head send;
                        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);
                goto drop;
        }
        len -= sizeof(struct virtio_net_hdr);
-       BUG_ON(len > MAX_PACKET_LEN);
-
-       skb_trim(skb, len);
 
+       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;
        dev->stats.rx_bytes += skb->len;
        dev->stats.rx_packets++;
 
 {
        struct sk_buff *skb;
        struct scatterlist sg[2+MAX_SKB_FRAGS];
-       int num, err;
+       int num, err, i;
 
        sg_init_table(sg, 2+MAX_SKB_FRAGS);
        for (;;) {
 
                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 = alloc_page(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);
 
         * the timer. */
        vi->free_in_tasklet = virtio_has_feature(vdev,VIRTIO_F_NOTIFY_ON_EMPTY);
 
+       /* If we can receive ANY GSO packets, we must allocate large ones. */
+       if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4)
+           || virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6)
+           || virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN))
+               vi->big_packets = true;
+
        /* We expect two virtqueues, receive then send. */
        vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done);
        if (IS_ERR(vi->rvq)) {
        VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM,
        VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC,
        VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
-       VIRTIO_NET_F_HOST_ECN, VIRTIO_F_NOTIFY_ON_EMPTY,
+       VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
+       VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */
+       VIRTIO_F_NOTIFY_ON_EMPTY,
 };
 
 static struct virtio_driver virtio_net = {