{
        struct dma_desc *desc, *first, *mss_desc = NULL;
        struct stmmac_priv *priv = netdev_priv(dev);
-       int nfrags = skb_shinfo(skb)->nr_frags;
-       u32 queue = skb_get_queue_mapping(skb);
+       int tmp_pay_len = 0, first_tx, nfrags;
        unsigned int first_entry, tx_packets;
        struct stmmac_txq_stats *txq_stats;
-       int tmp_pay_len = 0, first_tx;
        struct stmmac_tx_queue *tx_q;
-       bool has_vlan, set_ic;
+       u32 pay_len, mss, queue;
        u8 proto_hdr_len, hdr;
-       u32 pay_len, mss;
        dma_addr_t des;
+       bool set_ic;
        int i;
 
+       /* Always insert VLAN tag to SKB payload for TSO frames.
+        *
+        * Never insert VLAN tag by HW, since segments splited by
+        * TSO engine will be un-tagged by mistake.
+        */
+       if (skb_vlan_tag_present(skb)) {
+               skb = __vlan_hwaccel_push_inside(skb);
+               if (unlikely(!skb)) {
+                       priv->xstats.tx_dropped++;
+                       return NETDEV_TX_OK;
+               }
+       }
+
+       nfrags = skb_shinfo(skb)->nr_frags;
+       queue = skb_get_queue_mapping(skb);
+
        tx_q = &priv->dma_conf.tx_queue[queue];
        txq_stats = &priv->xstats.txq_stats[queue];
        first_tx = tx_q->cur_tx;
                        skb->data_len);
        }
 
-       /* Check if VLAN can be inserted by HW */
-       has_vlan = stmmac_vlan_insert(priv, skb, tx_q);
-
        first_entry = tx_q->cur_tx;
        WARN_ON(tx_q->tx_skbuff[first_entry]);
 
                desc = &tx_q->dma_tx[first_entry];
        first = desc;
 
-       if (has_vlan)
-               stmmac_set_desc_vlan(priv, first, STMMAC_VLAN_INSERT);
-
        /* first descriptor: fill Headers on Buf1 */
        des = dma_map_single(priv->device, skb->data, skb_headlen(skb),
                             DMA_TO_DEVICE);
                ndev->features |= NETIF_F_RXHASH;
 
        ndev->vlan_features |= ndev->features;
-       /* TSO doesn't work on VLANs yet */
-       ndev->vlan_features &= ~NETIF_F_TSO;
 
        /* MTU range: 46 - hw-specific max */
        ndev->min_mtu = ETH_ZLEN - ETH_HLEN;