]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/core/skbuff.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6-omap-h63xx.git] / net / core / skbuff.c
index b8d0abb264334d6d5589d107c8cf4007e393ffd4..65eac77390337e9857c73736618a60ff09737d84 100644 (file)
@@ -2594,6 +2594,23 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
 
        if (skb_shinfo(p)->frag_list)
                goto merge;
+       else if (!skb_headlen(p) && !skb_headlen(skb) &&
+                skb_shinfo(p)->nr_frags + skb_shinfo(skb)->nr_frags <
+                MAX_SKB_FRAGS) {
+               memcpy(skb_shinfo(p)->frags + skb_shinfo(p)->nr_frags,
+                      skb_shinfo(skb)->frags,
+                      skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t));
+
+               skb_shinfo(p)->nr_frags += skb_shinfo(skb)->nr_frags;
+               skb_shinfo(skb)->nr_frags = 0;
+
+               skb->truesize -= skb->data_len;
+               skb->len -= skb->data_len;
+               skb->data_len = 0;
+
+               NAPI_GRO_CB(skb)->free = 1;
+               goto done;
+       }
 
        headroom = skb_headroom(p);
        nskb = netdev_alloc_skb(p->dev, headroom);
@@ -2613,6 +2630,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
 
        *NAPI_GRO_CB(nskb) = *NAPI_GRO_CB(p);
        skb_shinfo(nskb)->frag_list = p;
+       skb_shinfo(nskb)->gso_size = skb_shinfo(p)->gso_size;
        skb_header_release(p);
        nskb->prev = p;
 
@@ -2627,11 +2645,12 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
        p = nskb;
 
 merge:
-       NAPI_GRO_CB(p)->count++;
        p->prev->next = skb;
        p->prev = skb;
        skb_header_release(skb);
 
+done:
+       NAPI_GRO_CB(p)->count++;
        p->data_len += skb->len;
        p->truesize += skb->len;
        p->len += skb->len;