#endif /* CONFIG_DEBUG_FS */
 #include <linux/net_tstamp.h>
 #include <linux/phylink.h>
+#include <linux/udp.h>
 #include <net/pkt_cls.h>
 #include "stmmac_ptp.h"
 #include "stmmac.h"
        u32 queue = skb_get_queue_mapping(skb);
        struct stmmac_tx_queue *tx_q;
        unsigned int first_entry;
+       u8 proto_hdr_len, hdr;
        int tmp_pay_len = 0;
        u32 pay_len, mss;
-       u8 proto_hdr_len;
        dma_addr_t des;
        bool has_vlan;
        int i;
        tx_q = &priv->tx_queue[queue];
 
        /* Compute header lengths */
-       proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+       if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
+               proto_hdr_len = skb_transport_offset(skb) + sizeof(struct udphdr);
+               hdr = sizeof(struct udphdr);
+       } else {
+               proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+               hdr = tcp_hdrlen(skb);
+       }
 
        /* Desc availability based on threshold should be enough safe */
        if (unlikely(stmmac_tx_avail(priv, queue) <
        }
 
        if (netif_msg_tx_queued(priv)) {
-               pr_info("%s: tcphdrlen %d, hdr_len %d, pay_len %d, mss %d\n",
-                       __func__, tcp_hdrlen(skb), proto_hdr_len, pay_len, mss);
+               pr_info("%s: hdrlen %d, hdr_len %d, pay_len %d, mss %d\n",
+                       __func__, hdr, proto_hdr_len, pay_len, mss);
                pr_info("\tskb->len %d, skb->data_len %d\n", skb->len,
                        skb->data_len);
        }
                        proto_hdr_len,
                        pay_len,
                        1, tx_q->tx_skbuff_dma[first_entry].last_segment,
-                       tcp_hdrlen(skb) / 4, (skb->len - proto_hdr_len));
+                       hdr / 4, (skb->len - proto_hdr_len));
 
        /* If context desc is used to change MSS */
        if (mss_desc) {
        int i, csum_insertion = 0, is_jumbo = 0;
        u32 queue = skb_get_queue_mapping(skb);
        int nfrags = skb_shinfo(skb)->nr_frags;
+       int gso = skb_shinfo(skb)->gso_type;
        struct dma_desc *desc, *first;
        struct stmmac_tx_queue *tx_q;
        unsigned int first_entry;
 
        /* Manage oversized TCP frames for GMAC4 device */
        if (skb_is_gso(skb) && priv->tso) {
-               if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))
+               if (gso & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))
+                       return stmmac_tso_xmit(skb, dev);
+               if (priv->plat->has_gmac4 && (gso & SKB_GSO_UDP_L4))
                        return stmmac_tso_xmit(skb, dev);
        }
 
 static u16 stmmac_select_queue(struct net_device *dev, struct sk_buff *skb,
                               struct net_device *sb_dev)
 {
-       if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
+       int gso = skb_shinfo(skb)->gso_type;
+
+       if (gso & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6 | SKB_GSO_UDP_L4)) {
                /*
-                * There is no way to determine the number of TSO
+                * There is no way to determine the number of TSO/USO
                 * capable Queues. Let's use always the Queue 0
-                * because if TSO is supported then at least this
+                * because if TSO/USO is supported then at least this
                 * one will be capable.
                 */
                return 0;
 
        if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) {
                ndev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
+               if (priv->plat->has_gmac4)
+                       ndev->hw_features |= NETIF_F_GSO_UDP_L4;
                priv->tso = true;
                dev_info(priv->device, "TSO feature enabled\n");
        }