support for Virtual eXtensible Local Area Network (VXLAN)
          in the driver.
 
+config QEDE_GENEVE
+       bool "Generic Network Virtualization Encapsulation (GENEVE) support"
+       depends on QEDE && GENEVE && !(QEDE=y && GENEVE=m)
+       ---help---
+         This allows one to create GENEVE virtual interfaces that provide
+         Layer 2 Networks over Layer 3 Networks. GENEVE is often used
+         to tunnel virtual network infrastructure in virtualized environments.
+         Say Y here if you want to enable hardware offload support for
+         Generic Network Virtualization Encapsulation (GENEVE) in the driver.
+
 endif # NET_VENDOR_QLOGIC
 
        data = cdev->firmware->data;
 
        memset(&tunn_info, 0, sizeof(tunn_info));
-       tunn_info.tunn_mode |=  1 << QED_MODE_VXLAN_TUNN;
+       tunn_info.tunn_mode |=  1 << QED_MODE_VXLAN_TUNN |
+                               1 << QED_MODE_L2GENEVE_TUNN |
+                               1 << QED_MODE_IPGENEVE_TUNN;
+
        tunn_info.tunn_clss_vxlan = QED_TUNN_CLSS_MAC_VLAN;
 
        rc = qed_hw_init(cdev, &tunn_info, true,
 
 #ifdef CONFIG_QEDE_VXLAN
 #include <net/vxlan.h>
 #endif
+#ifdef CONFIG_QEDE_GENEVE
+#include <net/geneve.h>
+#endif
 #include <linux/ip.h>
 #include <net/ipv6.h>
 #include <net/tcp.h>
 }
 #endif
 
+#ifdef CONFIG_QEDE_GENEVE
+static void qede_add_geneve_port(struct net_device *dev,
+                                sa_family_t sa_family, __be16 port)
+{
+       struct qede_dev *edev = netdev_priv(dev);
+       u16 t_port = ntohs(port);
+
+       if (edev->geneve_dst_port)
+               return;
+
+       edev->geneve_dst_port = t_port;
+
+       DP_VERBOSE(edev, QED_MSG_DEBUG, "Added geneve port=%d", t_port);
+       set_bit(QEDE_SP_GENEVE_PORT_CONFIG, &edev->sp_flags);
+       schedule_delayed_work(&edev->sp_task, 0);
+}
+
+static void qede_del_geneve_port(struct net_device *dev,
+                                sa_family_t sa_family, __be16 port)
+{
+       struct qede_dev *edev = netdev_priv(dev);
+       u16 t_port = ntohs(port);
+
+       if (t_port != edev->geneve_dst_port)
+               return;
+
+       edev->geneve_dst_port = 0;
+
+       DP_VERBOSE(edev, QED_MSG_DEBUG, "Deleted geneve port=%d", t_port);
+       set_bit(QEDE_SP_GENEVE_PORT_CONFIG, &edev->sp_flags);
+       schedule_delayed_work(&edev->sp_task, 0);
+}
+#endif
+
 static const struct net_device_ops qede_netdev_ops = {
        .ndo_open = qede_open,
        .ndo_stop = qede_close,
        .ndo_add_vxlan_port = qede_add_vxlan_port,
        .ndo_del_vxlan_port = qede_del_vxlan_port,
 #endif
+#ifdef CONFIG_QEDE_GENEVE
+       .ndo_add_geneve_port = qede_add_geneve_port,
+       .ndo_del_geneve_port = qede_del_geneve_port,
+#endif
 };
 
 /* -------------------------------------------------------------------------
                qed_ops->tunn_config(cdev, &tunn_params);
        }
 
+       if (test_and_clear_bit(QEDE_SP_GENEVE_PORT_CONFIG, &edev->sp_flags)) {
+               struct qed_tunn_params tunn_params;
+
+               memset(&tunn_params, 0, sizeof(tunn_params));
+               tunn_params.update_geneve_port = 1;
+               tunn_params.geneve_port = edev->geneve_dst_port;
+               qed_ops->tunn_config(cdev, &tunn_params);
+       }
+
        mutex_unlock(&edev->qede_lock);
 }
 
 
 #ifdef CONFIG_QEDE_VXLAN
        vxlan_get_rx_port(ndev);
+#endif
+#ifdef CONFIG_QEDE_GENEVE
+       geneve_get_rx_port(ndev);
 #endif
        return 0;
 }