static inline bool skb_gro_may_pull(const struct sk_buff *skb,
                                    unsigned int hlen)
 {
-       return hlen <= NAPI_GRO_CB(skb)->frag0_len;
+       return likely(hlen <= NAPI_GRO_CB(skb)->frag0_len);
 }
 
 static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen,
 
 
 static inline void skb_gro_reset_offset(struct sk_buff *skb, u32 nhoff)
 {
-       const struct skb_shared_info *pinfo = skb_shinfo(skb);
-       const skb_frag_t *frag0 = &pinfo->frags[0];
+       const struct skb_shared_info *pinfo;
+       const skb_frag_t *frag0;
+       unsigned int headlen;
 
        NAPI_GRO_CB(skb)->data_offset = 0;
-       NAPI_GRO_CB(skb)->frag0 = NULL;
-       NAPI_GRO_CB(skb)->frag0_len = 0;
+       headlen = skb_headlen(skb);
+       NAPI_GRO_CB(skb)->frag0 = skb->data;
+       NAPI_GRO_CB(skb)->frag0_len = headlen;
+       if (headlen)
+               return;
+
+       pinfo = skb_shinfo(skb);
+       frag0 = &pinfo->frags[0];
 
-       if (!skb_headlen(skb) && pinfo->nr_frags &&
-           !PageHighMem(skb_frag_page(frag0)) &&
+       if (pinfo->nr_frags && !PageHighMem(skb_frag_page(frag0)) &&
            (!NET_IP_ALIGN || !((skb_frag_off(frag0) + nhoff) & 3))) {
                NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0);
                NAPI_GRO_CB(skb)->frag0_len = min_t(unsigned int,
                }
        } else {
                eth = (const struct ethhdr *)skb->data;
-               gro_pull_from_frag0(skb, hlen);
+
+               if (NAPI_GRO_CB(skb)->frag0 != skb->data)
+                       gro_pull_from_frag0(skb, hlen);
+
                NAPI_GRO_CB(skb)->frag0 += hlen;
                NAPI_GRO_CB(skb)->frag0_len -= hlen;
        }