TG3_TX_RING_SIZE)
 #define NEXT_TX(N)             (((N) + 1) & (TG3_TX_RING_SIZE - 1))
 
+#define TG3_RX_DMA_ALIGN               16
+#define TG3_RX_HEADROOM                        ALIGN(VLAN_HLEN, TG3_RX_DMA_ALIGN)
+
 #define TG3_DMA_BYTE_ENAB              64
 
 #define TG3_RX_STD_DMA_SZ              1536
                struct sk_buff *skb;
                dma_addr_t dma_addr;
                u32 opaque_key, desc_idx, *post_ptr;
+               bool hw_vlan __maybe_unused = false;
+               u16 vtag __maybe_unused = 0;
 
                desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
                opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
                        tg3_recycle_rx(tnapi, tpr, opaque_key,
                                       desc_idx, *post_ptr);
 
-                       copy_skb = netdev_alloc_skb(tp->dev,
-                                                   len + TG3_RAW_IP_ALIGN);
+                       copy_skb = netdev_alloc_skb(tp->dev, len + VLAN_HLEN +
+                                                   TG3_RAW_IP_ALIGN);
                        if (copy_skb == NULL)
                                goto drop_it_no_recycle;
 
-                       skb_reserve(copy_skb, TG3_RAW_IP_ALIGN);
+                       skb_reserve(copy_skb, TG3_RAW_IP_ALIGN + VLAN_HLEN);
                        skb_put(copy_skb, len);
                        pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE);
                        skb_copy_from_linear_data(skb, copy_skb->data, len);
                        goto next_pkt;
                }
 
+               if (desc->type_flags & RXD_FLAG_VLAN &&
+                   !(tp->rx_mode & RX_MODE_KEEP_VLAN_TAG)) {
+                       vtag = desc->err_vlan & RXD_VLAN_MASK;
 #if TG3_VLAN_TAG_USED
-               if (tp->vlgrp != NULL &&
-                   desc->type_flags & RXD_FLAG_VLAN) {
-                       vlan_gro_receive(&tnapi->napi, tp->vlgrp,
-                                        desc->err_vlan & RXD_VLAN_MASK, skb);
-               } else
+                       if (tp->vlgrp)
+                               hw_vlan = true;
+                       else
+#endif
+                       {
+                               struct vlan_ethhdr *ve = (struct vlan_ethhdr *)
+                                                   __skb_push(skb, VLAN_HLEN);
+
+                               memmove(ve, skb->data + VLAN_HLEN,
+                                       ETH_ALEN * 2);
+                               ve->h_vlan_proto = htons(ETH_P_8021Q);
+                               ve->h_vlan_TCI = htons(vtag);
+                       }
+               }
+
+#if TG3_VLAN_TAG_USED
+               if (hw_vlan)
+                       vlan_gro_receive(&tnapi->napi, tp->vlgrp, vtag, skb);
+               else
 #endif
                        napi_gro_receive(&tnapi->napi, skb);
 
        else
                tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
 
-       tp->rx_offset = NET_IP_ALIGN;
+       tp->rx_offset = NET_IP_ALIGN + TG3_RX_HEADROOM;
        tp->rx_copy_thresh = TG3_RX_COPY_THRESHOLD;
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
            (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) {
-               tp->rx_offset = 0;
+               tp->rx_offset -= NET_IP_ALIGN;
 #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-               tp->rx_copy_thresh = ~0;
+               tp->rx_copy_thresh = ~(u16)0;
 #endif
        }