be2net: Export tunnel offloads only when a VxLAN tunnel is created
[cascardo/linux.git] / drivers / net / ethernet / emulex / benet / be_main.c
index 9461ad8..2aacd47 100644 (file)
@@ -3124,6 +3124,8 @@ static void be_mac_clear(struct be_adapter *adapter)
 #ifdef CONFIG_BE2NET_VXLAN
 static void be_disable_vxlan_offloads(struct be_adapter *adapter)
 {
+       struct net_device *netdev = adapter->netdev;
+
        if (adapter->flags & BE_FLAGS_VXLAN_OFFLOADS)
                be_cmd_manage_iface(adapter, adapter->if_handle,
                                    OP_CONVERT_TUNNEL_TO_NORMAL);
@@ -3133,6 +3135,9 @@ static void be_disable_vxlan_offloads(struct be_adapter *adapter)
 
        adapter->flags &= ~BE_FLAGS_VXLAN_OFFLOADS;
        adapter->vxlan_port = 0;
+
+       netdev->hw_enc_features = 0;
+       netdev->hw_features &= ~(NETIF_F_GSO_UDP_TUNNEL);
 }
 #endif
 
@@ -4371,6 +4376,19 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
 }
 
 #ifdef CONFIG_BE2NET_VXLAN
+/* VxLAN offload Notes:
+ *
+ * The stack defines tunnel offload flags (hw_enc_features) for IP and doesn't
+ * distinguish various types of transports (VxLAN, GRE, NVGRE ..). So, offload
+ * is expected to work across all types of IP tunnels once exported. Skyhawk
+ * supports offloads for either VxLAN or NVGRE, exclusively. So we export VxLAN
+ * offloads in hw_enc_features only when a VxLAN port is added. Note this only
+ * ensures that other tunnels work fine while VxLAN offloads are not enabled.
+ *
+ * Skyhawk supports VxLAN offloads only for one UDP dport. So, if the stack
+ * adds more than one port, disable offloads and don't re-enable them again
+ * until after all the tunnels are removed.
+ */
 static void be_add_vxlan_port(struct net_device *netdev, sa_family_t sa_family,
                              __be16 port)
 {
@@ -4382,13 +4400,16 @@ static void be_add_vxlan_port(struct net_device *netdev, sa_family_t sa_family,
                return;
 
        if (adapter->flags & BE_FLAGS_VXLAN_OFFLOADS) {
-               dev_warn(dev, "Cannot add UDP port %d for VxLAN offloads\n",
-                        be16_to_cpu(port));
                dev_info(dev,
                         "Only one UDP port supported for VxLAN offloads\n");
-               return;
+               dev_info(dev, "Disabling VxLAN offloads\n");
+               adapter->vxlan_port_count++;
+               goto err;
        }
 
+       if (adapter->vxlan_port_count++ >= 1)
+               return;
+
        status = be_cmd_manage_iface(adapter, adapter->if_handle,
                                     OP_CONVERT_NORMAL_TO_TUNNEL);
        if (status) {
@@ -4404,6 +4425,11 @@ static void be_add_vxlan_port(struct net_device *netdev, sa_family_t sa_family,
        adapter->flags |= BE_FLAGS_VXLAN_OFFLOADS;
        adapter->vxlan_port = port;
 
+       netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+                                  NETIF_F_TSO | NETIF_F_TSO6 |
+                                  NETIF_F_GSO_UDP_TUNNEL;
+       netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
+
        dev_info(dev, "Enabled VxLAN offloads for UDP port %d\n",
                 be16_to_cpu(port));
        return;
@@ -4420,13 +4446,15 @@ static void be_del_vxlan_port(struct net_device *netdev, sa_family_t sa_family,
                return;
 
        if (adapter->vxlan_port != port)
-               return;
+               goto done;
 
        be_disable_vxlan_offloads(adapter);
 
        dev_info(&adapter->pdev->dev,
                 "Disabled VxLAN offloads for UDP port %d\n",
                 be16_to_cpu(port));
+done:
+       adapter->vxlan_port_count--;
 }
 
 static bool be_gso_check(struct sk_buff *skb, struct net_device *dev)
@@ -4470,12 +4498,6 @@ static void be_netdev_init(struct net_device *netdev)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
 
-       if (skyhawk_chip(adapter)) {
-               netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-                                          NETIF_F_TSO | NETIF_F_TSO6 |
-                                          NETIF_F_GSO_UDP_TUNNEL;
-               netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
-       }
        netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
                NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |
                NETIF_F_HW_VLAN_CTAG_TX;