/* Local includes */
 #include "i40e.h"
 #include "i40e_diag.h"
-#ifdef CONFIG_I40E_VXLAN
+#if IS_ENABLED(CONFIG_VXLAN)
 #include <net/vxlan.h>
 #endif
+#if IS_ENABLED(CONFIG_GENEVE)
+#include <net/geneve.h>
+#endif
 
 const char i40e_driver_name[] = "i40e";
 static const char i40e_driver_string[] =
        i40e_flush(hw);
 }
 
-#ifdef CONFIG_I40E_VXLAN
 /**
- * i40e_sync_vxlan_filters_subtask - Sync the VSI filter list with HW
+ * i40e_sync_udp_filters_subtask - Sync the VSI filter list with HW
  * @pf: board private structure
  **/
-static void i40e_sync_vxlan_filters_subtask(struct i40e_pf *pf)
+static void i40e_sync_udp_filters_subtask(struct i40e_pf *pf)
 {
+#if IS_ENABLED(CONFIG_VXLAN) || IS_ENABLED(CONFIG_GENEVE)
        struct i40e_hw *hw = &pf->hw;
        i40e_status ret;
        __be16 port;
        int i;
 
-       if (!(pf->flags & I40E_FLAG_VXLAN_FILTER_SYNC))
+       if (!(pf->flags & I40E_FLAG_UDP_FILTER_SYNC))
                return;
 
-       pf->flags &= ~I40E_FLAG_VXLAN_FILTER_SYNC;
+       pf->flags &= ~I40E_FLAG_UDP_FILTER_SYNC;
 
        for (i = 0; i < I40E_MAX_PF_UDP_OFFLOAD_PORTS; i++) {
-               if (pf->pending_vxlan_bitmap & BIT_ULL(i)) {
-                       pf->pending_vxlan_bitmap &= ~BIT_ULL(i);
-                       port = pf->vxlan_ports[i];
+               if (pf->pending_udp_bitmap & BIT_ULL(i)) {
+                       pf->pending_udp_bitmap &= ~BIT_ULL(i);
+                       port = pf->udp_ports[i].index;
                        if (port)
                                ret = i40e_aq_add_udp_tunnel(hw, ntohs(port),
-                                                    I40E_AQC_TUNNEL_TYPE_VXLAN,
+                                                    pf->udp_ports[i].type,
                                                     NULL, NULL);
                        else
                                ret = i40e_aq_del_udp_tunnel(hw, i, NULL);
                                         i40e_stat_str(&pf->hw, ret),
                                         i40e_aq_str(&pf->hw,
                                                    pf->hw.aq.asq_last_status));
-                               pf->vxlan_ports[i] = 0;
+                               pf->udp_ports[i].index = 0;
                        }
                }
        }
+#endif
 }
 
-#endif
 /**
  * i40e_service_task - Run the driver's async subtasks
  * @work: pointer to work_struct containing our data
        i40e_watchdog_subtask(pf);
        i40e_fdir_reinit_subtask(pf);
        i40e_sync_filters_subtask(pf);
-#ifdef CONFIG_I40E_VXLAN
-       i40e_sync_vxlan_filters_subtask(pf);
+#if IS_ENABLED(CONFIG_VXLAN) || IS_ENABLED(CONFIG_GENEVE)
+       i40e_sync_udp_filters_subtask(pf);
 #endif
        i40e_clean_adminq_subtask(pf);
 
                             I40E_FLAG_HW_ATR_EVICT_CAPABLE |
                             I40E_FLAG_OUTER_UDP_CSUM_CAPABLE |
                             I40E_FLAG_WB_ON_ITR_CAPABLE |
-                            I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE;
+                            I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE |
+                            I40E_FLAG_GENEVE_OFFLOAD_CAPABLE;
        }
        pf->eeprom_version = 0xDEAD;
        pf->lan_veb = I40E_NO_VEB;
        return 0;
 }
 
-#ifdef CONFIG_I40E_VXLAN
+#if IS_ENABLED(CONFIG_VXLAN) || IS_ENABLED(CONFIG_GENEVE)
 /**
- * i40e_get_vxlan_port_idx - Lookup a possibly offloaded for Rx UDP port
+ * i40e_get_udp_port_idx - Lookup a possibly offloaded for Rx UDP port
  * @pf: board private structure
  * @port: The UDP port to look up
  *
  * Returns the index number or I40E_MAX_PF_UDP_OFFLOAD_PORTS if port not found
  **/
-static u8 i40e_get_vxlan_port_idx(struct i40e_pf *pf, __be16 port)
+static u8 i40e_get_udp_port_idx(struct i40e_pf *pf, __be16 port)
 {
        u8 i;
 
        for (i = 0; i < I40E_MAX_PF_UDP_OFFLOAD_PORTS; i++) {
-               if (pf->vxlan_ports[i] == port)
+               if (pf->udp_ports[i].index == port)
                        return i;
        }
 
        return i;
 }
 
+#endif
 /**
  * i40e_add_vxlan_port - Get notifications about VXLAN ports that come up
  * @netdev: This physical port's netdev
 static void i40e_add_vxlan_port(struct net_device *netdev,
                                sa_family_t sa_family, __be16 port)
 {
+#if IS_ENABLED(CONFIG_VXLAN)
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_vsi *vsi = np->vsi;
        struct i40e_pf *pf = vsi->back;
        if (sa_family == AF_INET6)
                return;
 
-       idx = i40e_get_vxlan_port_idx(pf, port);
+       idx = i40e_get_udp_port_idx(pf, port);
 
        /* Check if port already exists */
        if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
        }
 
        /* Now check if there is space to add the new port */
-       next_idx = i40e_get_vxlan_port_idx(pf, 0);
+       next_idx = i40e_get_udp_port_idx(pf, 0);
 
        if (next_idx == I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
                netdev_info(netdev, "maximum number of vxlan UDP ports reached, not adding port %d\n",
        }
 
        /* New port: add it and mark its index in the bitmap */
-       pf->vxlan_ports[next_idx] = port;
-       pf->pending_vxlan_bitmap |= BIT_ULL(next_idx);
-       pf->flags |= I40E_FLAG_VXLAN_FILTER_SYNC;
+       pf->udp_ports[next_idx].index = port;
+       pf->udp_ports[next_idx].type = I40E_AQC_TUNNEL_TYPE_VXLAN;
+       pf->pending_udp_bitmap |= BIT_ULL(next_idx);
+       pf->flags |= I40E_FLAG_UDP_FILTER_SYNC;
+#endif
 }
 
 /**
 static void i40e_del_vxlan_port(struct net_device *netdev,
                                sa_family_t sa_family, __be16 port)
 {
+#if IS_ENABLED(CONFIG_VXLAN)
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_vsi *vsi = np->vsi;
        struct i40e_pf *pf = vsi->back;
        if (sa_family == AF_INET6)
                return;
 
-       idx = i40e_get_vxlan_port_idx(pf, port);
+       idx = i40e_get_udp_port_idx(pf, port);
 
        /* Check if port already exists */
        if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
                /* if port exists, set it to 0 (mark for deletion)
                 * and make it pending
                 */
-               pf->vxlan_ports[idx] = 0;
-               pf->pending_vxlan_bitmap |= BIT_ULL(idx);
-               pf->flags |= I40E_FLAG_VXLAN_FILTER_SYNC;
+               pf->udp_ports[idx].index = 0;
+               pf->pending_udp_bitmap |= BIT_ULL(idx);
+               pf->flags |= I40E_FLAG_UDP_FILTER_SYNC;
        } else {
                netdev_warn(netdev, "vxlan port %d was not found, not deleting\n",
                            ntohs(port));
        }
+#endif
+}
+
+/**
+ * i40e_add_geneve_port - Get notifications about GENEVE ports that come up
+ * @netdev: This physical port's netdev
+ * @sa_family: Socket Family that GENEVE is notifying us about
+ * @port: New UDP port number that GENEVE started listening to
+ **/
+static void i40e_add_geneve_port(struct net_device *netdev,
+                                sa_family_t sa_family, __be16 port)
+{
+#if IS_ENABLED(CONFIG_GENEVE)
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_vsi *vsi = np->vsi;
+       struct i40e_pf *pf = vsi->back;
+       u8 next_idx;
+       u8 idx;
+
+       if (sa_family == AF_INET6)
+               return;
+
+       idx = i40e_get_udp_port_idx(pf, port);
+
+       /* Check if port already exists */
+       if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
+               netdev_info(netdev, "udp port %d already offloaded\n",
+                           ntohs(port));
+               return;
+       }
+
+       /* Now check if there is space to add the new port */
+       next_idx = i40e_get_udp_port_idx(pf, 0);
+
+       if (next_idx == I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
+               netdev_info(netdev, "maximum number of UDP ports reached, not adding port %d\n",
+                           ntohs(port));
+               return;
+       }
+
+       /* New port: add it and mark its index in the bitmap */
+       pf->udp_ports[next_idx].index = port;
+       pf->udp_ports[next_idx].type = I40E_AQC_TUNNEL_TYPE_NGE;
+       pf->pending_udp_bitmap |= BIT_ULL(next_idx);
+       pf->flags |= I40E_FLAG_UDP_FILTER_SYNC;
+
+       dev_info(&pf->pdev->dev, "adding geneve port %d\n", ntohs(port));
+#endif
 }
 
+/**
+ * i40e_del_geneve_port - Get notifications about GENEVE ports that go away
+ * @netdev: This physical port's netdev
+ * @sa_family: Socket Family that GENEVE is notifying us about
+ * @port: UDP port number that GENEVE stopped listening to
+ **/
+static void i40e_del_geneve_port(struct net_device *netdev,
+                                sa_family_t sa_family, __be16 port)
+{
+#if IS_ENABLED(CONFIG_GENEVE)
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_vsi *vsi = np->vsi;
+       struct i40e_pf *pf = vsi->back;
+       u8 idx;
+
+       if (sa_family == AF_INET6)
+               return;
+
+       idx = i40e_get_udp_port_idx(pf, port);
+
+       /* Check if port already exists */
+       if (idx < I40E_MAX_PF_UDP_OFFLOAD_PORTS) {
+               /* if port exists, set it to 0 (mark for deletion)
+                * and make it pending
+                */
+               pf->udp_ports[idx].index = 0;
+               pf->pending_udp_bitmap |= BIT_ULL(idx);
+               pf->flags |= I40E_FLAG_UDP_FILTER_SYNC;
+
+               dev_info(&pf->pdev->dev, "deleting geneve port %d\n",
+                        ntohs(port));
+       } else {
+               netdev_warn(netdev, "geneve port %d was not found, not deleting\n",
+                           ntohs(port));
+       }
 #endif
+}
+
 static int i40e_get_phys_port_id(struct net_device *netdev,
                                 struct netdev_phys_item_id *ppid)
 {
                                       nlflags, 0, 0, filter_mask, NULL);
 }
 
-#define I40E_MAX_TUNNEL_HDR_LEN 80
+/* Hardware supports L4 tunnel length of 128B (=2^7) which includes
+ * inner mac plus all inner ethertypes.
+ */
+#define I40E_MAX_TUNNEL_HDR_LEN 128
 /**
  * i40e_features_check - Validate encapsulated packet conforms to limits
  * @skb: skb buff
                                             netdev_features_t features)
 {
        if (skb->encapsulation &&
-           (skb_inner_mac_header(skb) - skb_transport_header(skb) >
+           ((skb_inner_network_header(skb) - skb_transport_header(skb)) >
             I40E_MAX_TUNNEL_HDR_LEN))
                return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
 
        .ndo_get_vf_config      = i40e_ndo_get_vf_config,
        .ndo_set_vf_link_state  = i40e_ndo_set_vf_link_state,
        .ndo_set_vf_spoofchk    = i40e_ndo_set_vf_spoofchk,
-#ifdef CONFIG_I40E_VXLAN
+#if IS_ENABLED(CONFIG_VXLAN)
        .ndo_add_vxlan_port     = i40e_add_vxlan_port,
        .ndo_del_vxlan_port     = i40e_del_vxlan_port,
+#endif
+#if IS_ENABLED(CONFIG_GENEVE)
+       .ndo_add_geneve_port    = i40e_add_geneve_port,
+       .ndo_del_geneve_port    = i40e_del_geneve_port,
 #endif
        .ndo_get_phys_port_id   = i40e_get_phys_port_id,
        .ndo_fdb_add            = i40e_ndo_fdb_add,
        np->vsi = vsi;
 
        netdev->hw_enc_features |= NETIF_F_IP_CSUM       |
+                                 NETIF_F_RXCSUM         |
                                  NETIF_F_GSO_UDP_TUNNEL |
                                  NETIF_F_GSO_GRE        |
                                  NETIF_F_TSO;
                i += snprintf(&buf[i], REMAIN(i), " DCB");
 #if IS_ENABLED(CONFIG_VXLAN)
        i += snprintf(&buf[i], REMAIN(i), " VxLAN");
+#endif
+#if IS_ENABLED(CONFIG_GENEVE)
+       i += snprintf(&buf[i], REMAIN(i), " Geneve");
 #endif
        if (pf->flags & I40E_FLAG_PTP)
                i += snprintf(&buf[i], REMAIN(i), " PTP");