diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index a87264f95f1a..43294a148f8a 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -904,114 +904,40 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata) } } -static void xgbe_disable_vxlan_offloads(struct xgbe_prv_data *pdata) +static int xgbe_vxlan_set_port(struct net_device *netdev, unsigned int table, + unsigned int entry, struct udp_tunnel_info *ti) { - struct net_device *netdev = pdata->netdev; + struct xgbe_prv_data *pdata = netdev_priv(netdev); - if (!pdata->vxlan_offloads_set) - return; + pdata->vxlan_port = be16_to_cpu(ti->port); + pdata->hw_if.enable_vxlan(pdata); - netdev_info(netdev, "disabling VXLAN offloads\n"); - - netdev->hw_enc_features &= ~(NETIF_F_SG | - NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | - NETIF_F_TSO | - NETIF_F_TSO6 | - NETIF_F_GRO | - NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_UDP_TUNNEL_CSUM); - - netdev->features &= ~(NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_UDP_TUNNEL_CSUM); - - pdata->vxlan_offloads_set = 0; + return 0; } -static void xgbe_disable_vxlan_hw(struct xgbe_prv_data *pdata) +static int xgbe_vxlan_unset_port(struct net_device *netdev, unsigned int table, + unsigned int entry, struct udp_tunnel_info *ti) { - if (!pdata->vxlan_port_set) - return; + struct xgbe_prv_data *pdata = netdev_priv(netdev); pdata->hw_if.disable_vxlan(pdata); - - pdata->vxlan_port_set = 0; pdata->vxlan_port = 0; + + return 0; } -static void xgbe_disable_vxlan_accel(struct xgbe_prv_data *pdata) +static const struct udp_tunnel_nic_info xgbe_udp_tunnels = { + .set_port = xgbe_vxlan_set_port, + .unset_port = xgbe_vxlan_unset_port, + .flags = UDP_TUNNEL_NIC_INFO_OPEN_ONLY, + .tables = { + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, }, + }, +}; + +const struct udp_tunnel_nic_info *xgbe_get_udp_tunnel_info(void) { - xgbe_disable_vxlan_offloads(pdata); - - xgbe_disable_vxlan_hw(pdata); -} - -static void xgbe_enable_vxlan_offloads(struct xgbe_prv_data *pdata) -{ - struct net_device *netdev = pdata->netdev; - - if (pdata->vxlan_offloads_set) - return; - - netdev_info(netdev, "enabling VXLAN offloads\n"); - - netdev->hw_enc_features |= NETIF_F_SG | - NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | - NETIF_F_TSO | - NETIF_F_TSO6 | - NETIF_F_GRO | - pdata->vxlan_features; - - netdev->features |= pdata->vxlan_features; - - pdata->vxlan_offloads_set = 1; -} - -static void xgbe_enable_vxlan_hw(struct xgbe_prv_data *pdata) -{ - struct xgbe_vxlan_data *vdata; - - if (pdata->vxlan_port_set) - return; - - if (list_empty(&pdata->vxlan_ports)) - return; - - vdata = list_first_entry(&pdata->vxlan_ports, - struct xgbe_vxlan_data, list); - - pdata->vxlan_port_set = 1; - pdata->vxlan_port = be16_to_cpu(vdata->port); - - pdata->hw_if.enable_vxlan(pdata); -} - -static void xgbe_enable_vxlan_accel(struct xgbe_prv_data *pdata) -{ - /* VXLAN acceleration desired? */ - if (!pdata->vxlan_features) - return; - - /* VXLAN acceleration possible? */ - if (pdata->vxlan_force_disable) - return; - - xgbe_enable_vxlan_hw(pdata); - - xgbe_enable_vxlan_offloads(pdata); -} - -static void xgbe_reset_vxlan_accel(struct xgbe_prv_data *pdata) -{ - xgbe_disable_vxlan_hw(pdata); - - if (pdata->vxlan_features) - xgbe_enable_vxlan_offloads(pdata); - - pdata->vxlan_force_disable = 0; + return &xgbe_udp_tunnels; } static void xgbe_napi_enable(struct xgbe_prv_data *pdata, unsigned int add) @@ -1406,7 +1332,7 @@ static int xgbe_start(struct xgbe_prv_data *pdata) hw_if->enable_tx(pdata); hw_if->enable_rx(pdata); - udp_tunnel_get_rx_info(netdev); + udp_tunnel_nic_reset_ntf(netdev); netif_tx_start_all_queues(netdev); @@ -1447,7 +1373,7 @@ static void xgbe_stop(struct xgbe_prv_data *pdata) xgbe_stop_timers(pdata); flush_workqueue(pdata->dev_workqueue); - xgbe_reset_vxlan_accel(pdata); + xgbe_vxlan_unset_port(netdev, 0, 0, NULL); hw_if->disable_tx(pdata); hw_if->disable_rx(pdata); @@ -1773,13 +1699,8 @@ static int xgbe_prep_tso(struct sk_buff *skb, struct xgbe_packet_data *packet) return 0; } -static bool xgbe_is_vxlan(struct xgbe_prv_data *pdata, struct sk_buff *skb) +static bool xgbe_is_vxlan(struct sk_buff *skb) { - struct xgbe_vxlan_data *vdata; - - if (pdata->vxlan_force_disable) - return false; - if (!skb->encapsulation) return false; @@ -1801,19 +1722,13 @@ static bool xgbe_is_vxlan(struct xgbe_prv_data *pdata, struct sk_buff *skb) return false; } - /* See if we have the UDP port in our list */ - list_for_each_entry(vdata, &pdata->vxlan_ports, list) { - if ((skb->protocol == htons(ETH_P_IP)) && - (vdata->sa_family == AF_INET) && - (vdata->port == udp_hdr(skb)->dest)) - return true; - else if ((skb->protocol == htons(ETH_P_IPV6)) && - (vdata->sa_family == AF_INET6) && - (vdata->port == udp_hdr(skb)->dest)) - return true; - } + if (skb->inner_protocol_type != ENCAP_TYPE_ETHER || + skb->inner_protocol != htons(ETH_P_TEB) || + (skb_inner_mac_header(skb) - skb_transport_header(skb) != + sizeof(struct udphdr) + sizeof(struct vxlanhdr))) + return false; - return false; + return true; } static int xgbe_is_tso(struct sk_buff *skb) @@ -1864,7 +1779,7 @@ static void xgbe_packet_info(struct xgbe_prv_data *pdata, XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, CSUM_ENABLE, 1); - if (xgbe_is_vxlan(pdata, skb)) + if (xgbe_is_vxlan(skb)) XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, VXLAN, 1); @@ -2271,23 +2186,12 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev, netdev_features_t features) { struct xgbe_prv_data *pdata = netdev_priv(netdev); - netdev_features_t vxlan_base, vxlan_mask; + netdev_features_t vxlan_base; vxlan_base = NETIF_F_GSO_UDP_TUNNEL | NETIF_F_RX_UDP_TUNNEL_PORT; - vxlan_mask = vxlan_base | NETIF_F_GSO_UDP_TUNNEL_CSUM; - pdata->vxlan_features = features & vxlan_mask; - - /* Only fix VXLAN-related features */ - if (!pdata->vxlan_features) - return features; - - /* If VXLAN isn't supported then clear any features: - * This is needed because NETIF_F_RX_UDP_TUNNEL_PORT gets - * automatically set if ndo_udp_tunnel_add is set. - */ if (!pdata->hw_feat.vxn) - return features & ~vxlan_mask; + return features; /* VXLAN CSUM requires VXLAN base */ if ((features & NETIF_F_GSO_UDP_TUNNEL_CSUM) && @@ -2318,15 +2222,6 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev, } } - pdata->vxlan_features = features & vxlan_mask; - - /* Adjust UDP Tunnel based on current state */ - if (pdata->vxlan_force_disable) { - netdev_notice(netdev, - "VXLAN acceleration disabled, turning off udp tunnel features\n"); - features &= ~vxlan_mask; - } - return features; } @@ -2336,14 +2231,12 @@ static int xgbe_set_features(struct net_device *netdev, struct xgbe_prv_data *pdata = netdev_priv(netdev); struct xgbe_hw_if *hw_if = &pdata->hw_if; netdev_features_t rxhash, rxcsum, rxvlan, rxvlan_filter; - netdev_features_t udp_tunnel; int ret = 0; rxhash = pdata->netdev_features & NETIF_F_RXHASH; rxcsum = pdata->netdev_features & NETIF_F_RXCSUM; rxvlan = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_RX; rxvlan_filter = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_FILTER; - udp_tunnel = pdata->netdev_features & NETIF_F_GSO_UDP_TUNNEL; if ((features & NETIF_F_RXHASH) && !rxhash) ret = hw_if->enable_rss(pdata); @@ -2367,11 +2260,6 @@ static int xgbe_set_features(struct net_device *netdev, else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) && rxvlan_filter) hw_if->disable_rx_vlan_filtering(pdata); - if ((features & NETIF_F_GSO_UDP_TUNNEL) && !udp_tunnel) - xgbe_enable_vxlan_accel(pdata); - else if (!(features & NETIF_F_GSO_UDP_TUNNEL) && udp_tunnel) - xgbe_disable_vxlan_accel(pdata); - pdata->netdev_features = features; DBGPR("<--xgbe_set_features\n"); @@ -2379,101 +2267,6 @@ static int xgbe_set_features(struct net_device *netdev, return 0; } -static void xgbe_udp_tunnel_add(struct net_device *netdev, - struct udp_tunnel_info *ti) -{ - struct xgbe_prv_data *pdata = netdev_priv(netdev); - struct xgbe_vxlan_data *vdata; - - if (!pdata->hw_feat.vxn) - return; - - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) - return; - - pdata->vxlan_port_count++; - - netif_dbg(pdata, drv, netdev, - "adding VXLAN tunnel, family=%hx/port=%hx\n", - ti->sa_family, be16_to_cpu(ti->port)); - - if (pdata->vxlan_force_disable) - return; - - vdata = kzalloc(sizeof(*vdata), GFP_ATOMIC); - if (!vdata) { - /* Can no longer properly track VXLAN ports */ - pdata->vxlan_force_disable = 1; - netif_dbg(pdata, drv, netdev, - "internal error, disabling VXLAN accelerations\n"); - - xgbe_disable_vxlan_accel(pdata); - - return; - } - vdata->sa_family = ti->sa_family; - vdata->port = ti->port; - - list_add_tail(&vdata->list, &pdata->vxlan_ports); - - /* First port added? */ - if (pdata->vxlan_port_count == 1) { - xgbe_enable_vxlan_accel(pdata); - - return; - } -} - -static void xgbe_udp_tunnel_del(struct net_device *netdev, - struct udp_tunnel_info *ti) -{ - struct xgbe_prv_data *pdata = netdev_priv(netdev); - struct xgbe_vxlan_data *vdata; - - if (!pdata->hw_feat.vxn) - return; - - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) - return; - - netif_dbg(pdata, drv, netdev, - "deleting VXLAN tunnel, family=%hx/port=%hx\n", - ti->sa_family, be16_to_cpu(ti->port)); - - /* Don't need safe version since loop terminates with deletion */ - list_for_each_entry(vdata, &pdata->vxlan_ports, list) { - if (vdata->sa_family != ti->sa_family) - continue; - - if (vdata->port != ti->port) - continue; - - list_del(&vdata->list); - kfree(vdata); - - break; - } - - pdata->vxlan_port_count--; - if (!pdata->vxlan_port_count) { - xgbe_reset_vxlan_accel(pdata); - - return; - } - - if (pdata->vxlan_force_disable) - return; - - /* See if VXLAN tunnel id needs to be changed */ - vdata = list_first_entry(&pdata->vxlan_ports, - struct xgbe_vxlan_data, list); - if (pdata->vxlan_port == be16_to_cpu(vdata->port)) - return; - - pdata->vxlan_port = be16_to_cpu(vdata->port); - pdata->hw_if.set_vxlan_id(pdata); -} - static netdev_features_t xgbe_features_check(struct sk_buff *skb, struct net_device *netdev, netdev_features_t features) @@ -2503,8 +2296,8 @@ static const struct net_device_ops xgbe_netdev_ops = { .ndo_setup_tc = xgbe_setup_tc, .ndo_fix_features = xgbe_fix_features, .ndo_set_features = xgbe_set_features, - .ndo_udp_tunnel_add = xgbe_udp_tunnel_add, - .ndo_udp_tunnel_del = xgbe_udp_tunnel_del, + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, .ndo_features_check = xgbe_features_check, }; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index 2a70714a791d..a218dc6f2edd 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c @@ -192,7 +192,6 @@ struct xgbe_prv_data *xgbe_alloc_pdata(struct device *dev) mutex_init(&pdata->i2c_mutex); init_completion(&pdata->i2c_complete); init_completion(&pdata->mdio_complete); - INIT_LIST_HEAD(&pdata->vxlan_ports); pdata->msg_enable = netif_msg_init(debug, default_msg_level); @@ -366,17 +365,12 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata) NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_UDP_TUNNEL_CSUM | - NETIF_F_RX_UDP_TUNNEL_PORT; + NETIF_F_GSO_UDP_TUNNEL_CSUM; netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_UDP_TUNNEL_CSUM | - NETIF_F_RX_UDP_TUNNEL_PORT; + NETIF_F_GSO_UDP_TUNNEL_CSUM; - pdata->vxlan_offloads_set = 1; - pdata->vxlan_features = NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_UDP_TUNNEL_CSUM | - NETIF_F_RX_UDP_TUNNEL_PORT; + netdev->udp_tunnel_nic_info = xgbe_get_udp_tunnel_info(); } netdev->vlan_features |= NETIF_F_SG | diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 5897e46faca5..ba8321ec1ee7 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -1014,12 +1014,6 @@ struct xgbe_version_data { unsigned int an_cdr_workaround; }; -struct xgbe_vxlan_data { - struct list_head list; - sa_family_t sa_family; - __be16 port; -}; - struct xgbe_prv_data { struct net_device *netdev; struct pci_dev *pcidev; @@ -1172,13 +1166,7 @@ struct xgbe_prv_data { u32 rss_options; /* VXLAN settings */ - unsigned int vxlan_port_set; - unsigned int vxlan_offloads_set; - unsigned int vxlan_force_disable; - unsigned int vxlan_port_count; - struct list_head vxlan_ports; u16 vxlan_port; - netdev_features_t vxlan_features; /* Netdev related settings */ unsigned char mac_addr[ETH_ALEN]; @@ -1321,6 +1309,7 @@ void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *); void xgbe_init_function_ptrs_i2c(struct xgbe_i2c_if *); const struct net_device_ops *xgbe_get_netdev_ops(void); const struct ethtool_ops *xgbe_get_ethtool_ops(void); +const struct udp_tunnel_nic_info *xgbe_get_udp_tunnel_info(void); #ifdef CONFIG_AMD_XGBE_DCB const struct dcbnl_rtnl_ops *xgbe_get_dcbnl_ops(void); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index dee61d96680e..d04994840b87 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1287,7 +1287,6 @@ enum sp_rtnl_flag { BNX2X_SP_RTNL_HYPERVISOR_VLAN, BNX2X_SP_RTNL_TX_STOP, BNX2X_SP_RTNL_GET_DRV_VERSION, - BNX2X_SP_RTNL_CHANGE_UDP_PORT, BNX2X_SP_RTNL_UPDATE_SVID, }; @@ -1343,11 +1342,6 @@ enum bnx2x_udp_port_type { BNX2X_UDP_PORT_MAX, }; -struct bnx2x_udp_tunnel { - u16 dst_port; - u8 count; -}; - struct bnx2x { /* Fields used in the tx and intr/napi performance paths * are grouped together in the beginning of the structure @@ -1855,7 +1849,7 @@ struct bnx2x { bool accept_any_vlan; /* Vxlan/Geneve related information */ - struct bnx2x_udp_tunnel udp_tunnel_ports[BNX2X_UDP_PORT_MAX]; + u16 udp_tunnel_ports[BNX2X_UDP_PORT_MAX]; }; /* Tx queues may be less or equal to Rx queues */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index a9817cd283fe..7e4c93be4451 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -960,12 +960,12 @@ static inline int bnx2x_func_start(struct bnx2x *bp) start_params->network_cos_mode = STATIC_COS; else /* CHIP_IS_E1X */ start_params->network_cos_mode = FW_WRR; - if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN].count) { - port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN].dst_port; + if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN]) { + port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN]; start_params->vxlan_dst_port = port; } - if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE].count) { - port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE].dst_port; + if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE]) { + port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE]; start_params->geneve_dst_port = port; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index fd957212bc1b..7f24d2689fdd 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -10152,7 +10152,6 @@ static int bnx2x_udp_port_update(struct bnx2x *bp) { struct bnx2x_func_switch_update_params *switch_update_params; struct bnx2x_func_state_params func_params = {NULL}; - struct bnx2x_udp_tunnel *udp_tunnel; u16 vxlan_port = 0, geneve_port = 0; int rc; @@ -10169,15 +10168,13 @@ static int bnx2x_udp_port_update(struct bnx2x *bp) __set_bit(BNX2X_F_UPDATE_TUNNEL_CFG_CHNG, &switch_update_params->changes); - if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE].count) { - udp_tunnel = &bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE]; - geneve_port = udp_tunnel->dst_port; + if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE]) { + geneve_port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE]; switch_update_params->geneve_dst_port = geneve_port; } - if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN].count) { - udp_tunnel = &bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN]; - vxlan_port = udp_tunnel->dst_port; + if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN]) { + vxlan_port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN]; switch_update_params->vxlan_dst_port = vxlan_port; } @@ -10197,93 +10194,26 @@ static int bnx2x_udp_port_update(struct bnx2x *bp) return rc; } -static void __bnx2x_add_udp_port(struct bnx2x *bp, u16 port, - enum bnx2x_udp_port_type type) -{ - struct bnx2x_udp_tunnel *udp_port = &bp->udp_tunnel_ports[type]; - - if (!netif_running(bp->dev) || !IS_PF(bp) || CHIP_IS_E1x(bp)) - return; - - if (udp_port->count && udp_port->dst_port == port) { - udp_port->count++; - return; - } - - if (udp_port->count) { - DP(BNX2X_MSG_SP, - "UDP tunnel [%d] - destination port limit reached\n", - type); - return; - } - - udp_port->dst_port = port; - udp_port->count = 1; - bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_CHANGE_UDP_PORT, 0); -} - -static void __bnx2x_del_udp_port(struct bnx2x *bp, u16 port, - enum bnx2x_udp_port_type type) -{ - struct bnx2x_udp_tunnel *udp_port = &bp->udp_tunnel_ports[type]; - - if (!IS_PF(bp) || CHIP_IS_E1x(bp)) - return; - - if (!udp_port->count || udp_port->dst_port != port) { - DP(BNX2X_MSG_SP, "Invalid UDP tunnel [%d] port\n", - type); - return; - } - - /* Remove reference, and make certain it's no longer in use */ - udp_port->count--; - if (udp_port->count) - return; - udp_port->dst_port = 0; - - if (netif_running(bp->dev)) - bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_CHANGE_UDP_PORT, 0); - else - DP(BNX2X_MSG_SP, "Deleted UDP tunnel [%d] port %d\n", - type, port); -} - -static void bnx2x_udp_tunnel_add(struct net_device *netdev, - struct udp_tunnel_info *ti) +static int bnx2x_udp_tunnel_sync(struct net_device *netdev, unsigned int table) { struct bnx2x *bp = netdev_priv(netdev); - u16 t_port = ntohs(ti->port); + struct udp_tunnel_info ti; - switch (ti->type) { - case UDP_TUNNEL_TYPE_VXLAN: - __bnx2x_add_udp_port(bp, t_port, BNX2X_UDP_PORT_VXLAN); - break; - case UDP_TUNNEL_TYPE_GENEVE: - __bnx2x_add_udp_port(bp, t_port, BNX2X_UDP_PORT_GENEVE); - break; - default: - break; - } + udp_tunnel_nic_get_port(netdev, table, 0, &ti); + bp->udp_tunnel_ports[table] = be16_to_cpu(ti.port); + + return bnx2x_udp_port_update(bp); } -static void bnx2x_udp_tunnel_del(struct net_device *netdev, - struct udp_tunnel_info *ti) -{ - struct bnx2x *bp = netdev_priv(netdev); - u16 t_port = ntohs(ti->port); - - switch (ti->type) { - case UDP_TUNNEL_TYPE_VXLAN: - __bnx2x_del_udp_port(bp, t_port, BNX2X_UDP_PORT_VXLAN); - break; - case UDP_TUNNEL_TYPE_GENEVE: - __bnx2x_del_udp_port(bp, t_port, BNX2X_UDP_PORT_GENEVE); - break; - default: - break; - } -} +static const struct udp_tunnel_nic_info bnx2x_udp_tunnels = { + .sync_table = bnx2x_udp_tunnel_sync, + .flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP | + UDP_TUNNEL_NIC_INFO_OPEN_ONLY, + .tables = { + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, }, + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_GENEVE, }, + }, +}; static int bnx2x_close(struct net_device *dev); @@ -10407,24 +10337,6 @@ sp_rtnl_not_reset: if (test_and_clear_bit(BNX2X_SP_RTNL_UPDATE_SVID, &bp->sp_rtnl_state)) bnx2x_handle_update_svid_cmd(bp); - if (test_and_clear_bit(BNX2X_SP_RTNL_CHANGE_UDP_PORT, - &bp->sp_rtnl_state)) { - if (bnx2x_udp_port_update(bp)) { - /* On error, forget configuration */ - memset(bp->udp_tunnel_ports, 0, - sizeof(struct bnx2x_udp_tunnel) * - BNX2X_UDP_PORT_MAX); - } else { - /* Since we don't store additional port information, - * if no ports are configured for any feature ask for - * information about currently configured ports. - */ - if (!bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN].count && - !bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE].count) - udp_tunnel_get_rx_info(bp->dev); - } - } - /* work which needs rtnl lock not-taken (as it takes the lock itself and * can be called from other contexts as well) */ @@ -12620,9 +12532,6 @@ static int bnx2x_open(struct net_device *dev) if (rc) return rc; - if (IS_PF(bp)) - udp_tunnel_get_rx_info(dev); - return 0; } @@ -13162,8 +13071,8 @@ static const struct net_device_ops bnx2x_netdev_ops = { .ndo_get_phys_port_id = bnx2x_get_phys_port_id, .ndo_set_vf_link_state = bnx2x_set_vf_link_state, .ndo_features_check = bnx2x_features_check, - .ndo_udp_tunnel_add = bnx2x_udp_tunnel_add, - .ndo_udp_tunnel_del = bnx2x_udp_tunnel_del, + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, }; static int bnx2x_set_coherency_mask(struct bnx2x *bp) @@ -13358,6 +13267,9 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev, dev->gso_partial_features = NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL_CSUM; + + if (IS_PF(bp)) + dev->udp_tunnel_nic_info = &bnx2x_udp_tunnels; } dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index 19689d72bc4e..e73bc211779a 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -2670,6 +2670,35 @@ static int liquidio_vxlan_port_command(struct net_device *netdev, int command, return ret; } +static int liquidio_udp_tunnel_set_port(struct net_device *netdev, + unsigned int table, unsigned int entry, + struct udp_tunnel_info *ti) +{ + return liquidio_vxlan_port_command(netdev, + OCTNET_CMD_VXLAN_PORT_CONFIG, + htons(ti->port), + OCTNET_CMD_VXLAN_PORT_ADD); +} + +static int liquidio_udp_tunnel_unset_port(struct net_device *netdev, + unsigned int table, + unsigned int entry, + struct udp_tunnel_info *ti) +{ + return liquidio_vxlan_port_command(netdev, + OCTNET_CMD_VXLAN_PORT_CONFIG, + htons(ti->port), + OCTNET_CMD_VXLAN_PORT_DEL); +} + +static const struct udp_tunnel_nic_info liquidio_udp_tunnels = { + .set_port = liquidio_udp_tunnel_set_port, + .unset_port = liquidio_udp_tunnel_unset_port, + .tables = { + { .n_entries = 1024, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, }, + }, +}; + /** \brief Net device fix features * @param netdev pointer to network device * @param request features requested @@ -2758,30 +2787,6 @@ static int liquidio_set_features(struct net_device *netdev, return 0; } -static void liquidio_add_vxlan_port(struct net_device *netdev, - struct udp_tunnel_info *ti) -{ - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) - return; - - liquidio_vxlan_port_command(netdev, - OCTNET_CMD_VXLAN_PORT_CONFIG, - htons(ti->port), - OCTNET_CMD_VXLAN_PORT_ADD); -} - -static void liquidio_del_vxlan_port(struct net_device *netdev, - struct udp_tunnel_info *ti) -{ - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) - return; - - liquidio_vxlan_port_command(netdev, - OCTNET_CMD_VXLAN_PORT_CONFIG, - htons(ti->port), - OCTNET_CMD_VXLAN_PORT_DEL); -} - static int __liquidio_set_vf_mac(struct net_device *netdev, int vfidx, u8 *mac, bool is_admin_assigned) { @@ -3208,8 +3213,8 @@ static const struct net_device_ops lionetdevops = { .ndo_do_ioctl = liquidio_ioctl, .ndo_fix_features = liquidio_fix_features, .ndo_set_features = liquidio_set_features, - .ndo_udp_tunnel_add = liquidio_add_vxlan_port, - .ndo_udp_tunnel_del = liquidio_del_vxlan_port, + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, .ndo_set_vf_mac = liquidio_set_vf_mac, .ndo_set_vf_vlan = liquidio_set_vf_vlan, .ndo_get_vf_config = liquidio_get_vf_config, @@ -3564,6 +3569,8 @@ static int setup_nic_devices(struct octeon_device *octeon_dev) netdev->hw_enc_features = (lio->enc_dev_capability & ~NETIF_F_LRO); + netdev->udp_tunnel_nic_info = &liquidio_udp_tunnels; + lio->dev_capability |= NETIF_F_GSO_UDP_TUNNEL; netdev->vlan_features = lio->dev_capability; diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c index bbd9bfa4a989..90ef21086f27 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c @@ -1767,6 +1767,35 @@ static int liquidio_vxlan_port_command(struct net_device *netdev, int command, return ret; } +static int liquidio_udp_tunnel_set_port(struct net_device *netdev, + unsigned int table, unsigned int entry, + struct udp_tunnel_info *ti) +{ + return liquidio_vxlan_port_command(netdev, + OCTNET_CMD_VXLAN_PORT_CONFIG, + htons(ti->port), + OCTNET_CMD_VXLAN_PORT_ADD); +} + +static int liquidio_udp_tunnel_unset_port(struct net_device *netdev, + unsigned int table, + unsigned int entry, + struct udp_tunnel_info *ti) +{ + return liquidio_vxlan_port_command(netdev, + OCTNET_CMD_VXLAN_PORT_CONFIG, + htons(ti->port), + OCTNET_CMD_VXLAN_PORT_DEL); +} + +static const struct udp_tunnel_nic_info liquidio_udp_tunnels = { + .set_port = liquidio_udp_tunnel_set_port, + .unset_port = liquidio_udp_tunnel_unset_port, + .tables = { + { .n_entries = 1024, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, }, + }, +}; + /** \brief Net device fix features * @param netdev pointer to network device * @param request features requested @@ -1835,30 +1864,6 @@ static int liquidio_set_features(struct net_device *netdev, return 0; } -static void liquidio_add_vxlan_port(struct net_device *netdev, - struct udp_tunnel_info *ti) -{ - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) - return; - - liquidio_vxlan_port_command(netdev, - OCTNET_CMD_VXLAN_PORT_CONFIG, - htons(ti->port), - OCTNET_CMD_VXLAN_PORT_ADD); -} - -static void liquidio_del_vxlan_port(struct net_device *netdev, - struct udp_tunnel_info *ti) -{ - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) - return; - - liquidio_vxlan_port_command(netdev, - OCTNET_CMD_VXLAN_PORT_CONFIG, - htons(ti->port), - OCTNET_CMD_VXLAN_PORT_DEL); -} - static const struct net_device_ops lionetdevops = { .ndo_open = liquidio_open, .ndo_stop = liquidio_stop, @@ -1873,8 +1878,8 @@ static const struct net_device_ops lionetdevops = { .ndo_do_ioctl = liquidio_ioctl, .ndo_fix_features = liquidio_fix_features, .ndo_set_features = liquidio_set_features, - .ndo_udp_tunnel_add = liquidio_add_vxlan_port, - .ndo_udp_tunnel_del = liquidio_del_vxlan_port, + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, }; static int lio_nic_info(struct octeon_recv_info *recv_info, void *buf) @@ -2095,6 +2100,8 @@ static int setup_nic_devices(struct octeon_device *octeon_dev) netdev->hw_enc_features = (lio->enc_dev_capability & ~NETIF_F_LRO); + netdev->udp_tunnel_nic_info = &liquidio_udp_tunnels; + netdev->vlan_features = lio->dev_capability; /* Add any unchangeable hw features */ lio->dev_capability |= NETIF_F_HW_VLAN_CTAG_FILTER | diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index ff53c78307c5..c59e9ccc2f18 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -1109,9 +1109,7 @@ struct adapter { int msg_enable; __be16 vxlan_port; - u8 vxlan_port_cnt; __be16 geneve_port; - u8 geneve_port_cnt; struct adapter_params params; struct cxgb4_virt_res vres; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 0991631f3a91..de078a5bf23e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -3732,129 +3732,71 @@ static int cxgb_setup_tc(struct net_device *dev, enum tc_setup_type type, } } -static void cxgb_del_udp_tunnel(struct net_device *netdev, - struct udp_tunnel_info *ti) +static int cxgb_udp_tunnel_unset_port(struct net_device *netdev, + unsigned int table, unsigned int entry, + struct udp_tunnel_info *ti) { struct port_info *pi = netdev_priv(netdev); struct adapter *adapter = pi->adapter; - unsigned int chip_ver = CHELSIO_CHIP_VERSION(adapter->params.chip); u8 match_all_mac[] = { 0, 0, 0, 0, 0, 0 }; int ret = 0, i; - if (chip_ver < CHELSIO_T6) - return; - switch (ti->type) { case UDP_TUNNEL_TYPE_VXLAN: - if (!adapter->vxlan_port_cnt || - adapter->vxlan_port != ti->port) - return; /* Invalid VxLAN destination port */ - - adapter->vxlan_port_cnt--; - if (adapter->vxlan_port_cnt) - return; - adapter->vxlan_port = 0; t4_write_reg(adapter, MPS_RX_VXLAN_TYPE_A, 0); break; case UDP_TUNNEL_TYPE_GENEVE: - if (!adapter->geneve_port_cnt || - adapter->geneve_port != ti->port) - return; /* Invalid GENEVE destination port */ - - adapter->geneve_port_cnt--; - if (adapter->geneve_port_cnt) - return; - adapter->geneve_port = 0; t4_write_reg(adapter, MPS_RX_GENEVE_TYPE_A, 0); break; default: - return; + return -EINVAL; } /* Matchall mac entries can be deleted only after all tunnel ports * are brought down or removed. */ if (!adapter->rawf_cnt) - return; + return 0; for_each_port(adapter, i) { pi = adap2pinfo(adapter, i); ret = t4_free_raw_mac_filt(adapter, pi->viid, match_all_mac, match_all_mac, - adapter->rawf_start + - pi->port_id, + adapter->rawf_start + pi->port_id, 1, pi->port_id, false); if (ret < 0) { netdev_info(netdev, "Failed to free mac filter entry, for port %d\n", i); - return; + return ret; } } + + return 0; } -static void cxgb_add_udp_tunnel(struct net_device *netdev, - struct udp_tunnel_info *ti) +static int cxgb_udp_tunnel_set_port(struct net_device *netdev, + unsigned int table, unsigned int entry, + struct udp_tunnel_info *ti) { struct port_info *pi = netdev_priv(netdev); struct adapter *adapter = pi->adapter; - unsigned int chip_ver = CHELSIO_CHIP_VERSION(adapter->params.chip); u8 match_all_mac[] = { 0, 0, 0, 0, 0, 0 }; int i, ret; - if (chip_ver < CHELSIO_T6 || !adapter->rawf_cnt) - return; - switch (ti->type) { case UDP_TUNNEL_TYPE_VXLAN: - /* Callback for adding vxlan port can be called with the same - * port for both IPv4 and IPv6. We should not disable the - * offloading when the same port for both protocols is added - * and later one of them is removed. - */ - if (adapter->vxlan_port_cnt && - adapter->vxlan_port == ti->port) { - adapter->vxlan_port_cnt++; - return; - } - - /* We will support only one VxLAN port */ - if (adapter->vxlan_port_cnt) { - netdev_info(netdev, "UDP port %d already offloaded, not adding port %d\n", - be16_to_cpu(adapter->vxlan_port), - be16_to_cpu(ti->port)); - return; - } - adapter->vxlan_port = ti->port; - adapter->vxlan_port_cnt = 1; - t4_write_reg(adapter, MPS_RX_VXLAN_TYPE_A, VXLAN_V(be16_to_cpu(ti->port)) | VXLAN_EN_F); break; case UDP_TUNNEL_TYPE_GENEVE: - if (adapter->geneve_port_cnt && - adapter->geneve_port == ti->port) { - adapter->geneve_port_cnt++; - return; - } - - /* We will support only one GENEVE port */ - if (adapter->geneve_port_cnt) { - netdev_info(netdev, "UDP port %d already offloaded, not adding port %d\n", - be16_to_cpu(adapter->geneve_port), - be16_to_cpu(ti->port)); - return; - } - adapter->geneve_port = ti->port; - adapter->geneve_port_cnt = 1; - t4_write_reg(adapter, MPS_RX_GENEVE_TYPE_A, GENEVE_V(be16_to_cpu(ti->port)) | GENEVE_EN_F); break; default: - return; + return -EINVAL; } /* Create a 'match all' mac filter entry for inner mac, @@ -3869,18 +3811,27 @@ static void cxgb_add_udp_tunnel(struct net_device *netdev, ret = t4_alloc_raw_mac_filt(adapter, pi->viid, match_all_mac, match_all_mac, - adapter->rawf_start + - pi->port_id, + adapter->rawf_start + pi->port_id, 1, pi->port_id, false); if (ret < 0) { netdev_info(netdev, "Failed to allocate a mac filter entry, not adding port %d\n", be16_to_cpu(ti->port)); - cxgb_del_udp_tunnel(netdev, ti); - return; + return ret; } } + + return 0; } +static const struct udp_tunnel_nic_info cxgb_udp_tunnels = { + .set_port = cxgb_udp_tunnel_set_port, + .unset_port = cxgb_udp_tunnel_unset_port, + .tables = { + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, }, + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_GENEVE, }, + }, +}; + static netdev_features_t cxgb_features_check(struct sk_buff *skb, struct net_device *dev, netdev_features_t features) @@ -3930,8 +3881,8 @@ static const struct net_device_ops cxgb4_netdev_ops = { #endif /* CONFIG_CHELSIO_T4_FCOE */ .ndo_set_tx_maxrate = cxgb_set_tx_maxrate, .ndo_setup_tc = cxgb_setup_tc, - .ndo_udp_tunnel_add = cxgb_add_udp_tunnel, - .ndo_udp_tunnel_del = cxgb_del_udp_tunnel, + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, .ndo_features_check = cxgb_features_check, .ndo_fix_features = cxgb_fix_features, }; @@ -6761,6 +6712,9 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_HW_TLS_RECORD; + + if (adapter->rawf_cnt) + netdev->udp_tunnel_nic_info = &cxgb_udp_tunnels; } if (highdma) diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index cd5fe4f6b54c..6bc7e7ba38c3 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -176,50 +176,18 @@ static void enic_unset_affinity_hint(struct enic *enic) irq_set_affinity_hint(enic->msix_entry[i].vector, NULL); } -static void enic_udp_tunnel_add(struct net_device *netdev, - struct udp_tunnel_info *ti) +static int enic_udp_tunnel_set_port(struct net_device *netdev, + unsigned int table, unsigned int entry, + struct udp_tunnel_info *ti) { struct enic *enic = netdev_priv(netdev); - __be16 port = ti->port; int err; spin_lock_bh(&enic->devcmd_lock); - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) { - netdev_info(netdev, "udp_tnl: only vxlan tunnel offload supported"); - goto error; - } - - switch (ti->sa_family) { - case AF_INET6: - if (!(enic->vxlan.flags & ENIC_VXLAN_OUTER_IPV6)) { - netdev_info(netdev, "vxlan: only IPv4 offload supported"); - goto error; - } - /* Fall through */ - case AF_INET: - break; - default: - goto error; - } - - if (enic->vxlan.vxlan_udp_port_number) { - if (ntohs(port) == enic->vxlan.vxlan_udp_port_number) - netdev_warn(netdev, "vxlan: udp port already offloaded"); - else - netdev_info(netdev, "vxlan: offload supported for only one UDP port"); - - goto error; - } - if ((vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ) != 1) && - !(enic->vxlan.flags & ENIC_VXLAN_MULTI_WQ)) { - netdev_info(netdev, "vxlan: vxlan offload with multi wq not supported on this adapter"); - goto error; - } - err = vnic_dev_overlay_offload_cfg(enic->vdev, OVERLAY_CFG_VXLAN_PORT_UPDATE, - ntohs(port)); + ntohs(ti->port)); if (err) goto error; @@ -228,52 +196,50 @@ static void enic_udp_tunnel_add(struct net_device *netdev, if (err) goto error; - enic->vxlan.vxlan_udp_port_number = ntohs(port); - - netdev_info(netdev, "vxlan fw-vers-%d: offload enabled for udp port: %d, sa_family: %d ", - (int)enic->vxlan.patch_level, ntohs(port), ti->sa_family); - - goto unlock; - + enic->vxlan.vxlan_udp_port_number = ntohs(ti->port); error: - netdev_info(netdev, "failed to offload udp port: %d, sa_family: %d, type: %d", - ntohs(port), ti->sa_family, ti->type); -unlock: spin_unlock_bh(&enic->devcmd_lock); + + return err; } -static void enic_udp_tunnel_del(struct net_device *netdev, - struct udp_tunnel_info *ti) +static int enic_udp_tunnel_unset_port(struct net_device *netdev, + unsigned int table, unsigned int entry, + struct udp_tunnel_info *ti) { struct enic *enic = netdev_priv(netdev); int err; spin_lock_bh(&enic->devcmd_lock); - if ((ntohs(ti->port) != enic->vxlan.vxlan_udp_port_number) || - ti->type != UDP_TUNNEL_TYPE_VXLAN) { - netdev_info(netdev, "udp_tnl: port:%d, sa_family: %d, type: %d not offloaded", - ntohs(ti->port), ti->sa_family, ti->type); - goto unlock; - } - err = vnic_dev_overlay_offload_ctrl(enic->vdev, OVERLAY_FEATURE_VXLAN, OVERLAY_OFFLOAD_DISABLE); - if (err) { - netdev_err(netdev, "vxlan: del offload udp port: %d failed", - ntohs(ti->port)); + if (err) goto unlock; - } enic->vxlan.vxlan_udp_port_number = 0; - netdev_info(netdev, "vxlan: del offload udp port %d, family %d\n", - ntohs(ti->port), ti->sa_family); - unlock: spin_unlock_bh(&enic->devcmd_lock); + + return err; } +static const struct udp_tunnel_nic_info enic_udp_tunnels = { + .set_port = enic_udp_tunnel_set_port, + .unset_port = enic_udp_tunnel_unset_port, + .tables = { + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, }, + }, +}, enic_udp_tunnels_v4 = { + .set_port = enic_udp_tunnel_set_port, + .unset_port = enic_udp_tunnel_unset_port, + .flags = UDP_TUNNEL_NIC_INFO_IPV4_ONLY, + .tables = { + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, }, + }, +}; + static netdev_features_t enic_features_check(struct sk_buff *skb, struct net_device *dev, netdev_features_t features) @@ -2526,8 +2492,8 @@ static const struct net_device_ops enic_netdev_dynamic_ops = { #ifdef CONFIG_RFS_ACCEL .ndo_rx_flow_steer = enic_rx_flow_steer, #endif - .ndo_udp_tunnel_add = enic_udp_tunnel_add, - .ndo_udp_tunnel_del = enic_udp_tunnel_del, + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, .ndo_features_check = enic_features_check, }; @@ -2552,8 +2518,8 @@ static const struct net_device_ops enic_netdev_ops = { #ifdef CONFIG_RFS_ACCEL .ndo_rx_flow_steer = enic_rx_flow_steer, #endif - .ndo_udp_tunnel_add = enic_udp_tunnel_add, - .ndo_udp_tunnel_del = enic_udp_tunnel_del, + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, .ndo_features_check = enic_features_check, }; @@ -2963,6 +2929,13 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) patch_level = fls(patch_level); patch_level = patch_level ? patch_level - 1 : 0; enic->vxlan.patch_level = patch_level; + + if (vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ) == 1 || + enic->vxlan.flags & ENIC_VXLAN_MULTI_WQ) { + netdev->udp_tunnel_nic_info = &enic_udp_tunnels_v4; + if (enic->vxlan.flags & ENIC_VXLAN_OUTER_IPV6) + netdev->udp_tunnel_nic_info = &enic_udp_tunnels; + } } netdev->features |= netdev->hw_features; diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 6e9022083004..8689d4a51fe5 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -654,8 +654,6 @@ struct be_adapter { u8 hba_port_num; u16 pvid; __be16 vxlan_port; /* offloaded vxlan port num */ - int vxlan_port_count; /* active vxlan port count */ - struct list_head vxlan_port_list; /* vxlan port list */ struct phy_info phy; u8 wol_cap; bool wol_en; @@ -679,9 +677,6 @@ struct be_adapter { struct be_cmd_work { struct work_struct work; struct be_adapter *adapter; - union { - __be16 vxlan_port; - } info; }; #define be_physfn(adapter) (!adapter->virtfn) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index e26f59336cfd..676e437d78f6 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -3829,8 +3829,8 @@ static int be_open(struct net_device *netdev) be_link_status_update(adapter, link_status); netif_tx_start_all_queues(netdev); - if (skyhawk_chip(adapter)) - udp_tunnel_get_rx_info(netdev); + + udp_tunnel_nic_reset_ntf(netdev); return 0; err: @@ -3967,18 +3967,23 @@ static void be_cancel_err_detection(struct be_adapter *adapter) } } -static int be_enable_vxlan_offloads(struct be_adapter *adapter) +/* 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. If other (non + * VxLAN) tunnels are configured while VxLAN offloads are enabled, offloads for + * those other tunnels are unexported on the fly through ndo_features_check(). + */ +static int be_vxlan_set_port(struct net_device *netdev, unsigned int table, + unsigned int entry, struct udp_tunnel_info *ti) { - struct net_device *netdev = adapter->netdev; + struct be_adapter *adapter = netdev_priv(netdev); struct device *dev = &adapter->pdev->dev; - struct be_vxlan_port *vxlan_port; - __be16 port; int status; - vxlan_port = list_first_entry(&adapter->vxlan_port_list, - struct be_vxlan_port, list); - port = vxlan_port->port; - status = be_cmd_manage_iface(adapter, adapter->if_handle, OP_CONVERT_NORMAL_TO_TUNNEL); if (status) { @@ -3987,25 +3992,26 @@ static int be_enable_vxlan_offloads(struct be_adapter *adapter) } adapter->flags |= BE_FLAGS_VXLAN_OFFLOADS; - status = be_cmd_set_vxlan_port(adapter, port); + status = be_cmd_set_vxlan_port(adapter, ti->port); if (status) { dev_warn(dev, "Failed to add VxLAN port\n"); return status; } - adapter->vxlan_port = port; + adapter->vxlan_port = ti->port; netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_UDP_TUNNEL; dev_info(dev, "Enabled VxLAN offloads for UDP port %d\n", - be16_to_cpu(port)); + be16_to_cpu(ti->port)); return 0; } -static void be_disable_vxlan_offloads(struct be_adapter *adapter) +static int be_vxlan_unset_port(struct net_device *netdev, unsigned int table, + unsigned int entry, struct udp_tunnel_info *ti) { - struct net_device *netdev = adapter->netdev; + struct be_adapter *adapter = netdev_priv(netdev); if (adapter->flags & BE_FLAGS_VXLAN_OFFLOADS) be_cmd_manage_iface(adapter, adapter->if_handle, @@ -4018,8 +4024,19 @@ static void be_disable_vxlan_offloads(struct be_adapter *adapter) adapter->vxlan_port = 0; netdev->hw_enc_features = 0; + return 0; } +static const struct udp_tunnel_nic_info be_udp_tunnels = { + .set_port = be_vxlan_set_port, + .unset_port = be_vxlan_unset_port, + .flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP | + UDP_TUNNEL_NIC_INFO_OPEN_ONLY, + .tables = { + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, }, + }, +}; + static void be_calculate_vf_res(struct be_adapter *adapter, u16 num_vfs, struct be_resources *vft_res) { @@ -4135,7 +4152,7 @@ static int be_clear(struct be_adapter *adapter) &vft_res); } - be_disable_vxlan_offloads(adapter); + be_vxlan_unset_port(adapter->netdev, 0, 0, NULL); be_if_destroy(adapter); @@ -5053,147 +5070,6 @@ static struct be_cmd_work *be_alloc_work(struct be_adapter *adapter, return work; } -/* 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. If other (non - * VxLAN) tunnels are configured while VxLAN offloads are enabled, offloads for - * those other tunnels are unexported on the fly through ndo_features_check(). - * - * Skyhawk supports VxLAN offloads only for one UDP dport. So, if the stack - * adds more than one port, disable offloads and re-enable them again when - * there's only one port left. We maintain a list of ports for this purpose. - */ -static void be_work_add_vxlan_port(struct work_struct *work) -{ - struct be_cmd_work *cmd_work = - container_of(work, struct be_cmd_work, work); - struct be_adapter *adapter = cmd_work->adapter; - struct device *dev = &adapter->pdev->dev; - __be16 port = cmd_work->info.vxlan_port; - struct be_vxlan_port *vxlan_port; - int status; - - /* Bump up the alias count if it is an existing port */ - list_for_each_entry(vxlan_port, &adapter->vxlan_port_list, list) { - if (vxlan_port->port == port) { - vxlan_port->port_aliases++; - goto done; - } - } - - /* Add a new port to our list. We don't need a lock here since port - * add/delete are done only in the context of a single-threaded work - * queue (be_wq). - */ - vxlan_port = kzalloc(sizeof(*vxlan_port), GFP_KERNEL); - if (!vxlan_port) - goto done; - - vxlan_port->port = port; - INIT_LIST_HEAD(&vxlan_port->list); - list_add_tail(&vxlan_port->list, &adapter->vxlan_port_list); - adapter->vxlan_port_count++; - - if (adapter->flags & BE_FLAGS_VXLAN_OFFLOADS) { - dev_info(dev, - "Only one UDP port supported for VxLAN offloads\n"); - dev_info(dev, "Disabling VxLAN offloads\n"); - goto err; - } - - if (adapter->vxlan_port_count > 1) - goto done; - - status = be_enable_vxlan_offloads(adapter); - if (!status) - goto done; - -err: - be_disable_vxlan_offloads(adapter); -done: - kfree(cmd_work); - return; -} - -static void be_work_del_vxlan_port(struct work_struct *work) -{ - struct be_cmd_work *cmd_work = - container_of(work, struct be_cmd_work, work); - struct be_adapter *adapter = cmd_work->adapter; - __be16 port = cmd_work->info.vxlan_port; - struct be_vxlan_port *vxlan_port; - - /* Nothing to be done if a port alias is being deleted */ - list_for_each_entry(vxlan_port, &adapter->vxlan_port_list, list) { - if (vxlan_port->port == port) { - if (vxlan_port->port_aliases) { - vxlan_port->port_aliases--; - goto done; - } - break; - } - } - - /* No port aliases left; delete the port from the list */ - list_del(&vxlan_port->list); - adapter->vxlan_port_count--; - - /* Disable VxLAN offload if this is the offloaded port */ - if (adapter->vxlan_port == vxlan_port->port) { - WARN_ON(adapter->vxlan_port_count); - be_disable_vxlan_offloads(adapter); - dev_info(&adapter->pdev->dev, - "Disabled VxLAN offloads for UDP port %d\n", - be16_to_cpu(port)); - goto out; - } - - /* If only 1 port is left, re-enable VxLAN offload */ - if (adapter->vxlan_port_count == 1) - be_enable_vxlan_offloads(adapter); - -out: - kfree(vxlan_port); -done: - kfree(cmd_work); -} - -static void be_cfg_vxlan_port(struct net_device *netdev, - struct udp_tunnel_info *ti, - void (*func)(struct work_struct *)) -{ - struct be_adapter *adapter = netdev_priv(netdev); - struct be_cmd_work *cmd_work; - - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) - return; - - if (lancer_chip(adapter) || BEx_chip(adapter) || be_is_mc(adapter)) - return; - - cmd_work = be_alloc_work(adapter, func); - if (cmd_work) { - cmd_work->info.vxlan_port = ti->port; - queue_work(be_wq, &cmd_work->work); - } -} - -static void be_del_vxlan_port(struct net_device *netdev, - struct udp_tunnel_info *ti) -{ - be_cfg_vxlan_port(netdev, ti, be_work_del_vxlan_port); -} - -static void be_add_vxlan_port(struct net_device *netdev, - struct udp_tunnel_info *ti) -{ - be_cfg_vxlan_port(netdev, ti, be_work_add_vxlan_port); -} - static netdev_features_t be_features_check(struct sk_buff *skb, struct net_device *dev, netdev_features_t features) @@ -5309,8 +5185,8 @@ static const struct net_device_ops be_netdev_ops = { #endif .ndo_bridge_setlink = be_ndo_bridge_setlink, .ndo_bridge_getlink = be_ndo_bridge_getlink, - .ndo_udp_tunnel_add = be_add_vxlan_port, - .ndo_udp_tunnel_del = be_del_vxlan_port, + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, .ndo_features_check = be_features_check, .ndo_get_phys_port_id = be_get_phys_port_id, }; @@ -5342,6 +5218,9 @@ static void be_netdev_init(struct net_device *netdev) netdev->ethtool_ops = &be_ethtool_ops; + if (!lancer_chip(adapter) && !BEx_chip(adapter) && !be_is_mc(adapter)) + netdev->udp_tunnel_nic_info = &be_udp_tunnels; + /* MTU range: 256 - 9000 */ netdev->min_mtu = BE_MIN_MTU; netdev->max_mtu = BE_MAX_MTU; @@ -5819,7 +5698,6 @@ static int be_drv_init(struct be_adapter *adapter) /* Must be a power of 2 or else MODULO will BUG_ON */ adapter->be_get_temp_freq = 64; - INIT_LIST_HEAD(&adapter->vxlan_port_list); return 0; free_rx_filter: diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h index f9be10a04dd6..6119a4108838 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k.h @@ -221,12 +221,6 @@ struct fm10k_iov_data { struct fm10k_vf_info vf_info[]; }; -struct fm10k_udp_port { - struct list_head list; - sa_family_t sa_family; - __be16 port; -}; - enum fm10k_macvlan_request_type { FM10K_UC_MAC_REQUEST, FM10K_MC_MAC_REQUEST, @@ -370,8 +364,8 @@ struct fm10k_intfc { u32 rssrk[FM10K_RSSRK_SIZE]; /* UDP encapsulation port tracking information */ - struct list_head vxlan_port; - struct list_head geneve_port; + __be16 vxlan_port; + __be16 geneve_port; /* MAC/VLAN update queue */ struct list_head macvlan_requests; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index 34f1f5350f68..d88dd41a9442 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -635,15 +635,8 @@ static int fm10k_clean_rx_irq(struct fm10k_q_vector *q_vector, static struct ethhdr *fm10k_port_is_vxlan(struct sk_buff *skb) { struct fm10k_intfc *interface = netdev_priv(skb->dev); - struct fm10k_udp_port *vxlan_port; - /* we can only offload a vxlan if we recognize it as such */ - vxlan_port = list_first_entry_or_null(&interface->vxlan_port, - struct fm10k_udp_port, list); - - if (!vxlan_port) - return NULL; - if (vxlan_port->port != udp_hdr(skb)->dest) + if (interface->vxlan_port != udp_hdr(skb)->dest) return NULL; /* return offset of udp_hdr plus 8 bytes for VXLAN header */ diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 1450a9f98c5a..5c19ff452558 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -366,39 +366,6 @@ static void fm10k_request_glort_range(struct fm10k_intfc *interface) } } -/** - * fm10k_free_udp_port_info - * @interface: board private structure - * - * This function frees both geneve_port and vxlan_port structures - **/ -static void fm10k_free_udp_port_info(struct fm10k_intfc *interface) -{ - struct fm10k_udp_port *port; - - /* flush all entries from vxlan list */ - port = list_first_entry_or_null(&interface->vxlan_port, - struct fm10k_udp_port, list); - while (port) { - list_del(&port->list); - kfree(port); - port = list_first_entry_or_null(&interface->vxlan_port, - struct fm10k_udp_port, - list); - } - - /* flush all entries from geneve list */ - port = list_first_entry_or_null(&interface->geneve_port, - struct fm10k_udp_port, list); - while (port) { - list_del(&port->list); - kfree(port); - port = list_first_entry_or_null(&interface->vxlan_port, - struct fm10k_udp_port, - list); - } -} - /** * fm10k_restore_udp_port_info * @interface: board private structure @@ -408,131 +375,52 @@ static void fm10k_free_udp_port_info(struct fm10k_intfc *interface) static void fm10k_restore_udp_port_info(struct fm10k_intfc *interface) { struct fm10k_hw *hw = &interface->hw; - struct fm10k_udp_port *port; /* only the PF supports configuring tunnels */ if (hw->mac.type != fm10k_mac_pf) return; - port = list_first_entry_or_null(&interface->vxlan_port, - struct fm10k_udp_port, list); - /* restore tunnel configuration register */ fm10k_write_reg(hw, FM10K_TUNNEL_CFG, - (port ? ntohs(port->port) : 0) | + ntohs(interface->vxlan_port) | (ETH_P_TEB << FM10K_TUNNEL_CFG_NVGRE_SHIFT)); - port = list_first_entry_or_null(&interface->geneve_port, - struct fm10k_udp_port, list); - /* restore Geneve tunnel configuration register */ fm10k_write_reg(hw, FM10K_TUNNEL_CFG_GENEVE, - (port ? ntohs(port->port) : 0)); -} - -static struct fm10k_udp_port * -fm10k_remove_tunnel_port(struct list_head *ports, - struct udp_tunnel_info *ti) -{ - struct fm10k_udp_port *port; - - list_for_each_entry(port, ports, list) { - if ((port->port == ti->port) && - (port->sa_family == ti->sa_family)) { - list_del(&port->list); - return port; - } - } - - return NULL; -} - -static void fm10k_insert_tunnel_port(struct list_head *ports, - struct udp_tunnel_info *ti) -{ - struct fm10k_udp_port *port; - - /* remove existing port entry from the list so that the newest items - * are always at the tail of the list. - */ - port = fm10k_remove_tunnel_port(ports, ti); - if (!port) { - port = kmalloc(sizeof(*port), GFP_ATOMIC); - if (!port) - return; - port->port = ti->port; - port->sa_family = ti->sa_family; - } - - list_add_tail(&port->list, ports); + ntohs(interface->geneve_port)); } /** - * fm10k_udp_tunnel_add + * fm10k_udp_tunnel_sync - Called when UDP tunnel ports change * @dev: network interface device structure - * @ti: Tunnel endpoint information + * @table: Tunnel table (according to tables of @fm10k_udp_tunnels) * - * This function is called when a new UDP tunnel port has been added. + * This function is called when a new UDP tunnel port is added or deleted. * Due to hardware restrictions, only one port per type can be offloaded at - * once. + * once. Core will send to the driver a port of its choice. **/ -static void fm10k_udp_tunnel_add(struct net_device *dev, - struct udp_tunnel_info *ti) +static int fm10k_udp_tunnel_sync(struct net_device *dev, unsigned int table) { struct fm10k_intfc *interface = netdev_priv(dev); + struct udp_tunnel_info ti; - /* only the PF supports configuring tunnels */ - if (interface->hw.mac.type != fm10k_mac_pf) - return; - - switch (ti->type) { - case UDP_TUNNEL_TYPE_VXLAN: - fm10k_insert_tunnel_port(&interface->vxlan_port, ti); - break; - case UDP_TUNNEL_TYPE_GENEVE: - fm10k_insert_tunnel_port(&interface->geneve_port, ti); - break; - default: - return; - } + udp_tunnel_nic_get_port(dev, table, 0, &ti); + if (!table) + interface->vxlan_port = ti.port; + else + interface->geneve_port = ti.port; fm10k_restore_udp_port_info(interface); + return 0; } -/** - * fm10k_udp_tunnel_del - * @dev: network interface device structure - * @ti: Tunnel end point information - * - * This function is called when a new UDP tunnel port is deleted. The freed - * port will be removed from the list, then we reprogram the offloaded port - * based on the head of the list. - **/ -static void fm10k_udp_tunnel_del(struct net_device *dev, - struct udp_tunnel_info *ti) -{ - struct fm10k_intfc *interface = netdev_priv(dev); - struct fm10k_udp_port *port = NULL; - - if (interface->hw.mac.type != fm10k_mac_pf) - return; - - switch (ti->type) { - case UDP_TUNNEL_TYPE_VXLAN: - port = fm10k_remove_tunnel_port(&interface->vxlan_port, ti); - break; - case UDP_TUNNEL_TYPE_GENEVE: - port = fm10k_remove_tunnel_port(&interface->geneve_port, ti); - break; - default: - return; - } - - /* if we did remove a port we need to free its memory */ - kfree(port); - - fm10k_restore_udp_port_info(interface); -} +static const struct udp_tunnel_nic_info fm10k_udp_tunnels = { + .sync_table = fm10k_udp_tunnel_sync, + .tables = { + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, }, + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_GENEVE, }, + }, +}; /** * fm10k_open - Called when a network interface is made active @@ -580,8 +468,6 @@ int fm10k_open(struct net_device *netdev) if (err) goto err_set_queues; - udp_tunnel_get_rx_info(netdev); - fm10k_up(interface); return 0; @@ -615,8 +501,6 @@ int fm10k_close(struct net_device *netdev) fm10k_qv_free_irq(interface); - fm10k_free_udp_port_info(interface); - fm10k_free_all_tx_resources(interface); fm10k_free_all_rx_resources(interface); @@ -1647,8 +1531,8 @@ static const struct net_device_ops fm10k_netdev_ops = { .ndo_set_vf_rate = fm10k_ndo_set_vf_bw, .ndo_get_vf_config = fm10k_ndo_get_vf_config, .ndo_get_vf_stats = fm10k_ndo_get_vf_stats, - .ndo_udp_tunnel_add = fm10k_udp_tunnel_add, - .ndo_udp_tunnel_del = fm10k_udp_tunnel_del, + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, .ndo_dfwd_add_station = fm10k_dfwd_add_station, .ndo_dfwd_del_station = fm10k_dfwd_del_station, .ndo_features_check = fm10k_features_check, @@ -1695,6 +1579,8 @@ struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info) NETIF_F_SG; dev->features |= NETIF_F_GSO_UDP_TUNNEL; + + dev->udp_tunnel_nic_info = &fm10k_udp_tunnels; } /* all features defined to this point should be changeable */ diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index d122d0087191..140212bfe08b 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -2066,10 +2066,6 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, interface->tx_itr = FM10K_TX_ITR_DEFAULT; interface->rx_itr = FM10K_ITR_ADAPTIVE | FM10K_RX_ITR_DEFAULT; - /* initialize udp port lists */ - INIT_LIST_HEAD(&interface->vxlan_port); - INIT_LIST_HEAD(&interface->geneve_port); - /* Initialize the MAC/VLAN queue */ INIT_LIST_HEAD(&interface->macvlan_requests); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h index ff4438478ea9..df5b748be068 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h @@ -575,8 +575,6 @@ struct nfp_net_dp { * @rx_coalesce_max_frames: RX interrupt moderation frame count parameter * @tx_coalesce_usecs: TX interrupt moderation usecs delay parameter * @tx_coalesce_max_frames: TX interrupt moderation frame count parameter - * @vxlan_ports: VXLAN ports for RX inner csum offload communicated to HW - * @vxlan_usecnt: IPv4/IPv6 VXLAN port use counts * @qcp_cfg: Pointer to QCP queue used for configuration notification * @tx_bar: Pointer to mapped TX queues * @rx_bar: Pointer to mapped FL/RX queues @@ -661,9 +659,6 @@ struct nfp_net { u32 tx_coalesce_usecs; u32 tx_coalesce_max_frames; - __be16 vxlan_ports[NFP_NET_N_VXLAN_PORTS]; - u8 vxlan_usecnt[NFP_NET_N_VXLAN_PORTS]; - u8 __iomem *qcp_cfg; u8 __iomem *tx_bar; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 83ff18140bfe..44608873d3d9 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -2867,15 +2867,6 @@ static int nfp_net_set_config_and_enable(struct nfp_net *nn) for (r = 0; r < nn->dp.num_rx_rings; r++) nfp_net_rx_ring_fill_freelist(&nn->dp, &nn->dp.rx_rings[r]); - /* Since reconfiguration requests while NFP is down are ignored we - * have to wipe the entire VXLAN configuration and reinitialize it. - */ - if (nn->dp.ctrl & NFP_NET_CFG_CTRL_VXLAN) { - memset(&nn->vxlan_ports, 0, sizeof(nn->vxlan_ports)); - memset(&nn->vxlan_usecnt, 0, sizeof(nn->vxlan_usecnt)); - udp_tunnel_get_rx_info(nn->dp.netdev); - } - return 0; } @@ -3566,87 +3557,6 @@ nfp_net_get_phys_port_name(struct net_device *netdev, char *name, size_t len) return 0; } -/** - * nfp_net_set_vxlan_port() - set vxlan port in SW and reconfigure HW - * @nn: NFP Net device to reconfigure - * @idx: Index into the port table where new port should be written - * @port: UDP port to configure (pass zero to remove VXLAN port) - */ -static void nfp_net_set_vxlan_port(struct nfp_net *nn, int idx, __be16 port) -{ - int i; - - nn->vxlan_ports[idx] = port; - - if (!(nn->dp.ctrl & NFP_NET_CFG_CTRL_VXLAN)) - return; - - BUILD_BUG_ON(NFP_NET_N_VXLAN_PORTS & 1); - for (i = 0; i < NFP_NET_N_VXLAN_PORTS; i += 2) - nn_writel(nn, NFP_NET_CFG_VXLAN_PORT + i * sizeof(port), - be16_to_cpu(nn->vxlan_ports[i + 1]) << 16 | - be16_to_cpu(nn->vxlan_ports[i])); - - nfp_net_reconfig_post(nn, NFP_NET_CFG_UPDATE_VXLAN); -} - -/** - * nfp_net_find_vxlan_idx() - find table entry of the port or a free one - * @nn: NFP Network structure - * @port: UDP port to look for - * - * Return: if the port is already in the table -- it's position; - * if the port is not in the table -- free position to use; - * if the table is full -- -ENOSPC. - */ -static int nfp_net_find_vxlan_idx(struct nfp_net *nn, __be16 port) -{ - int i, free_idx = -ENOSPC; - - for (i = 0; i < NFP_NET_N_VXLAN_PORTS; i++) { - if (nn->vxlan_ports[i] == port) - return i; - if (!nn->vxlan_usecnt[i]) - free_idx = i; - } - - return free_idx; -} - -static void nfp_net_add_vxlan_port(struct net_device *netdev, - struct udp_tunnel_info *ti) -{ - struct nfp_net *nn = netdev_priv(netdev); - int idx; - - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) - return; - - idx = nfp_net_find_vxlan_idx(nn, ti->port); - if (idx == -ENOSPC) - return; - - if (!nn->vxlan_usecnt[idx]++) - nfp_net_set_vxlan_port(nn, idx, ti->port); -} - -static void nfp_net_del_vxlan_port(struct net_device *netdev, - struct udp_tunnel_info *ti) -{ - struct nfp_net *nn = netdev_priv(netdev); - int idx; - - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) - return; - - idx = nfp_net_find_vxlan_idx(nn, ti->port); - if (idx == -ENOSPC || !nn->vxlan_usecnt[idx]) - return; - - if (!--nn->vxlan_usecnt[idx]) - nfp_net_set_vxlan_port(nn, idx, 0); -} - static int nfp_net_xdp_setup_drv(struct nfp_net *nn, struct netdev_bpf *bpf) { struct bpf_prog *prog = bpf->prog; @@ -3757,12 +3667,43 @@ const struct net_device_ops nfp_net_netdev_ops = { .ndo_set_features = nfp_net_set_features, .ndo_features_check = nfp_net_features_check, .ndo_get_phys_port_name = nfp_net_get_phys_port_name, - .ndo_udp_tunnel_add = nfp_net_add_vxlan_port, - .ndo_udp_tunnel_del = nfp_net_del_vxlan_port, + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, .ndo_bpf = nfp_net_xdp, .ndo_get_devlink_port = nfp_devlink_get_devlink_port, }; +static int nfp_udp_tunnel_sync(struct net_device *netdev, unsigned int table) +{ + struct nfp_net *nn = netdev_priv(netdev); + int i; + + BUILD_BUG_ON(NFP_NET_N_VXLAN_PORTS & 1); + for (i = 0; i < NFP_NET_N_VXLAN_PORTS; i += 2) { + struct udp_tunnel_info ti0, ti1; + + udp_tunnel_nic_get_port(netdev, table, i, &ti0); + udp_tunnel_nic_get_port(netdev, table, i + 1, &ti1); + + nn_writel(nn, NFP_NET_CFG_VXLAN_PORT + i * sizeof(ti0.port), + be16_to_cpu(ti1.port) << 16 | be16_to_cpu(ti0.port)); + } + + return nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_VXLAN); +} + +static const struct udp_tunnel_nic_info nfp_udp_tunnels = { + .sync_table = nfp_udp_tunnel_sync, + .flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP | + UDP_TUNNEL_NIC_INFO_OPEN_ONLY, + .tables = { + { + .n_entries = NFP_NET_N_VXLAN_PORTS, + .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, + }, + }, +}; + /** * nfp_net_info() - Print general info about the NIC * @nn: NFP Net device to reconfigure @@ -4010,6 +3951,7 @@ static void nfp_net_netdev_init(struct nfp_net *nn) if (nn->cap & NFP_NET_CFG_CTRL_VXLAN) { if (nn->cap & NFP_NET_CFG_CTRL_LSO) netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL; + netdev->udp_tunnel_nic_info = &nfp_udp_tunnels; nn->dp.ctrl |= NFP_NET_CFG_CTRL_VXLAN; } if (nn->cap & NFP_NET_CFG_CTRL_NVGRE) { diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 591dd4051d06..8adda5dc9e88 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -543,6 +543,7 @@ void qede_set_dcbnl_ops(struct net_device *ndev); void qede_config_debug(uint debug, u32 *p_dp_module, u8 *p_dp_level); void qede_set_ethtool_ops(struct net_device *netdev); +void qede_set_udp_tunnels(struct qede_dev *edev); void qede_reload(struct qede_dev *edev, struct qede_reload_args *args, bool is_locked); int qede_change_mtu(struct net_device *dev, int new_mtu); diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c index d8100434e340..b7d0b6ccebd3 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_filter.c +++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c @@ -953,115 +953,67 @@ int qede_set_features(struct net_device *dev, netdev_features_t features) return 0; } -void qede_udp_tunnel_add(struct net_device *dev, struct udp_tunnel_info *ti) +static int qede_udp_tunnel_sync(struct net_device *dev, unsigned int table) { struct qede_dev *edev = netdev_priv(dev); struct qed_tunn_params tunn_params; - u16 t_port = ntohs(ti->port); + struct udp_tunnel_info ti; + u16 *save_port; int rc; memset(&tunn_params, 0, sizeof(tunn_params)); - switch (ti->type) { - case UDP_TUNNEL_TYPE_VXLAN: - if (!edev->dev_info.common.vxlan_enable) - return; - - if (edev->vxlan_dst_port) - return; - + udp_tunnel_nic_get_port(dev, table, 0, &ti); + if (ti.type == UDP_TUNNEL_TYPE_VXLAN) { tunn_params.update_vxlan_port = 1; - tunn_params.vxlan_port = t_port; - - __qede_lock(edev); - rc = edev->ops->tunn_config(edev->cdev, &tunn_params); - __qede_unlock(edev); - - if (!rc) { - edev->vxlan_dst_port = t_port; - DP_VERBOSE(edev, QED_MSG_DEBUG, "Added vxlan port=%d\n", - t_port); - } else { - DP_NOTICE(edev, "Failed to add vxlan UDP port=%d\n", - t_port); - } - - break; - case UDP_TUNNEL_TYPE_GENEVE: - if (!edev->dev_info.common.geneve_enable) - return; - - if (edev->geneve_dst_port) - return; - + tunn_params.vxlan_port = ntohs(ti.port); + save_port = &edev->vxlan_dst_port; + } else { tunn_params.update_geneve_port = 1; - tunn_params.geneve_port = t_port; - - __qede_lock(edev); - rc = edev->ops->tunn_config(edev->cdev, &tunn_params); - __qede_unlock(edev); - - if (!rc) { - edev->geneve_dst_port = t_port; - DP_VERBOSE(edev, QED_MSG_DEBUG, - "Added geneve port=%d\n", t_port); - } else { - DP_NOTICE(edev, "Failed to add geneve UDP port=%d\n", - t_port); - } - - break; - default: - return; + tunn_params.geneve_port = ntohs(ti.port); + save_port = &edev->geneve_dst_port; } + + __qede_lock(edev); + rc = edev->ops->tunn_config(edev->cdev, &tunn_params); + __qede_unlock(edev); + if (rc) + return rc; + + *save_port = ntohs(ti.port); + return 0; } -void qede_udp_tunnel_del(struct net_device *dev, - struct udp_tunnel_info *ti) +static const struct udp_tunnel_nic_info qede_udp_tunnels_both = { + .sync_table = qede_udp_tunnel_sync, + .flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP, + .tables = { + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, }, + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_GENEVE, }, + }, +}, qede_udp_tunnels_vxlan = { + .sync_table = qede_udp_tunnel_sync, + .flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP, + .tables = { + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, }, + }, +}, qede_udp_tunnels_geneve = { + .sync_table = qede_udp_tunnel_sync, + .flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP, + .tables = { + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_GENEVE, }, + }, +}; + +void qede_set_udp_tunnels(struct qede_dev *edev) { - struct qede_dev *edev = netdev_priv(dev); - struct qed_tunn_params tunn_params; - u16 t_port = ntohs(ti->port); - - memset(&tunn_params, 0, sizeof(tunn_params)); - - switch (ti->type) { - case UDP_TUNNEL_TYPE_VXLAN: - if (t_port != edev->vxlan_dst_port) - return; - - tunn_params.update_vxlan_port = 1; - tunn_params.vxlan_port = 0; - - __qede_lock(edev); - edev->ops->tunn_config(edev->cdev, &tunn_params); - __qede_unlock(edev); - - edev->vxlan_dst_port = 0; - - DP_VERBOSE(edev, QED_MSG_DEBUG, "Deleted vxlan port=%d\n", - t_port); - - break; - case UDP_TUNNEL_TYPE_GENEVE: - if (t_port != edev->geneve_dst_port) - return; - - tunn_params.update_geneve_port = 1; - tunn_params.geneve_port = 0; - - __qede_lock(edev); - edev->ops->tunn_config(edev->cdev, &tunn_params); - __qede_unlock(edev); - - edev->geneve_dst_port = 0; - - DP_VERBOSE(edev, QED_MSG_DEBUG, "Deleted geneve port=%d\n", - t_port); - break; - default: - return; - } + if (edev->dev_info.common.vxlan_enable && + edev->dev_info.common.geneve_enable) + edev->ndev->udp_tunnel_nic_info = &qede_udp_tunnels_both; + else if (edev->dev_info.common.vxlan_enable) + edev->ndev->udp_tunnel_nic_info = &qede_udp_tunnels_vxlan; + else if (edev->dev_info.common.geneve_enable) + edev->ndev->udp_tunnel_nic_info = &qede_udp_tunnels_geneve; } static void qede_xdp_reload_func(struct qede_dev *edev, diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 8cd27f8f1b3a..a653dd0e5c22 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -663,8 +663,8 @@ static const struct net_device_ops qede_netdev_ops = { .ndo_get_vf_config = qede_get_vf_config, .ndo_set_vf_rate = qede_set_vf_rate, #endif - .ndo_udp_tunnel_add = qede_udp_tunnel_add, - .ndo_udp_tunnel_del = qede_udp_tunnel_del, + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, .ndo_features_check = qede_features_check, .ndo_bpf = qede_xdp, #ifdef CONFIG_RFS_ACCEL @@ -687,8 +687,8 @@ static const struct net_device_ops qede_netdev_vf_ops = { .ndo_fix_features = qede_fix_features, .ndo_set_features = qede_set_features, .ndo_get_stats64 = qede_get_stats64, - .ndo_udp_tunnel_add = qede_udp_tunnel_add, - .ndo_udp_tunnel_del = qede_udp_tunnel_del, + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, .ndo_features_check = qede_features_check, }; @@ -706,8 +706,8 @@ static const struct net_device_ops qede_netdev_vf_xdp_ops = { .ndo_fix_features = qede_fix_features, .ndo_set_features = qede_set_features, .ndo_get_stats64 = qede_get_stats64, - .ndo_udp_tunnel_add = qede_udp_tunnel_add, - .ndo_udp_tunnel_del = qede_udp_tunnel_del, + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, .ndo_features_check = qede_features_check, .ndo_bpf = qede_xdp, }; @@ -822,6 +822,8 @@ static void qede_init_ndev(struct qede_dev *edev) NETIF_F_GSO_UDP_TUNNEL_CSUM); ndev->hw_enc_features |= (NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM); + + qede_set_udp_tunnels(edev); } if (edev->dev_info.common.gre_enable) { @@ -2421,7 +2423,7 @@ static int qede_open(struct net_device *ndev) if (rc) return rc; - udp_tunnel_get_rx_info(ndev); + udp_tunnel_nic_reset_ntf(ndev); edev->ops->common->update_drv_state(edev->cdev, true); @@ -2523,7 +2525,7 @@ static void qede_recovery_handler(struct qede_dev *edev) goto err; qede_config_rx_mode(edev->ndev); - udp_tunnel_get_rx_info(edev->ndev); + udp_tunnel_nic_reset_ntf(edev->ndev); } edev->state = curr_state; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index d838774af5a6..d67f8265724a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -536,8 +536,6 @@ struct qlcnic_hardware_context { u8 extend_lb_time; u8 phys_port_id[ETH_ALEN]; u8 lb_mode; - u8 vxlan_port_count; - u16 vxlan_port; struct device *hwmon_dev; u32 post_mode; bool run_post; @@ -1026,9 +1024,6 @@ struct qlcnic_ipaddr { #define QLCNIC_HAS_PHYS_PORT_ID 0x40000 #define QLCNIC_TSS_RSS 0x80000 -#define QLCNIC_ADD_VXLAN_PORT 0x100000 -#define QLCNIC_DEL_VXLAN_PORT 0x200000 - #define QLCNIC_VLAN_FILTERING 0x800000 #define QLCNIC_IS_MSI_FAMILY(adapter) \ @@ -1700,6 +1695,8 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *); int qlcnic_set_default_offload_settings(struct qlcnic_adapter *); int qlcnic_reset_npar_config(struct qlcnic_adapter *); int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *); +int qlcnic_set_vxlan_port(struct qlcnic_adapter *adapter, u16 port); +int qlcnic_set_vxlan_parsing(struct qlcnic_adapter *adapter, u16 port); int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter); int qlcnic_read_mac_addr(struct qlcnic_adapter *); int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index cda5b0a9e948..0e2f2fb6c3a9 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c @@ -1028,9 +1028,8 @@ static int qlcnic_83xx_idc_check_state_validity(struct qlcnic_adapter *adapter, #define QLCNIC_ENABLE_INGRESS_ENCAP_PARSING 1 #define QLCNIC_DISABLE_INGRESS_ENCAP_PARSING 0 -static int qlcnic_set_vxlan_port(struct qlcnic_adapter *adapter) +int qlcnic_set_vxlan_port(struct qlcnic_adapter *adapter, u16 port) { - u16 port = adapter->ahw->vxlan_port; struct qlcnic_cmd_args cmd; int ret = 0; @@ -1057,10 +1056,8 @@ static int qlcnic_set_vxlan_port(struct qlcnic_adapter *adapter) return ret; } -static int qlcnic_set_vxlan_parsing(struct qlcnic_adapter *adapter, - bool state) +int qlcnic_set_vxlan_parsing(struct qlcnic_adapter *adapter, u16 port) { - u16 vxlan_port = adapter->ahw->vxlan_port; struct qlcnic_cmd_args cmd; int ret = 0; @@ -1071,18 +1068,18 @@ static int qlcnic_set_vxlan_parsing(struct qlcnic_adapter *adapter, if (ret) return ret; - cmd.req.arg[1] = state ? QLCNIC_ENABLE_INGRESS_ENCAP_PARSING : - QLCNIC_DISABLE_INGRESS_ENCAP_PARSING; + cmd.req.arg[1] = port ? QLCNIC_ENABLE_INGRESS_ENCAP_PARSING : + QLCNIC_DISABLE_INGRESS_ENCAP_PARSING; ret = qlcnic_issue_cmd(adapter, &cmd); if (ret) netdev_err(adapter->netdev, "Failed to %s VXLAN parsing for port %d\n", - state ? "enable" : "disable", vxlan_port); + port ? "enable" : "disable", port); else netdev_info(adapter->netdev, "%s VXLAN parsing for port %d\n", - state ? "Enabled" : "Disabled", vxlan_port); + port ? "Enabled" : "Disabled", port); qlcnic_free_mbx_args(&cmd); @@ -1093,22 +1090,6 @@ static void qlcnic_83xx_periodic_tasks(struct qlcnic_adapter *adapter) { if (adapter->fhash.fnum) qlcnic_prune_lb_filters(adapter); - - if (adapter->flags & QLCNIC_ADD_VXLAN_PORT) { - if (qlcnic_set_vxlan_port(adapter)) - return; - - if (qlcnic_set_vxlan_parsing(adapter, true)) - return; - - adapter->flags &= ~QLCNIC_ADD_VXLAN_PORT; - } else if (adapter->flags & QLCNIC_DEL_VXLAN_PORT) { - if (qlcnic_set_vxlan_parsing(adapter, false)) - return; - - adapter->ahw->vxlan_port = 0; - adapter->flags &= ~QLCNIC_DEL_VXLAN_PORT; - } } /** diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index e52af092a793..173c7300cdf7 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -471,48 +471,29 @@ static int qlcnic_get_phys_port_id(struct net_device *netdev, return 0; } -static void qlcnic_add_vxlan_port(struct net_device *netdev, - struct udp_tunnel_info *ti) +static int qlcnic_udp_tunnel_sync(struct net_device *dev, unsigned int table) { - struct qlcnic_adapter *adapter = netdev_priv(netdev); - struct qlcnic_hardware_context *ahw = adapter->ahw; + struct qlcnic_adapter *adapter = netdev_priv(dev); + struct udp_tunnel_info ti; + int err; - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) - return; - - /* Adapter supports only one VXLAN port. Use very first port - * for enabling offload - */ - if (!qlcnic_encap_rx_offload(adapter)) - return; - if (!ahw->vxlan_port_count) { - ahw->vxlan_port_count = 1; - ahw->vxlan_port = ntohs(ti->port); - adapter->flags |= QLCNIC_ADD_VXLAN_PORT; - return; + udp_tunnel_nic_get_port(dev, table, 0, &ti); + if (ti.port) { + err = qlcnic_set_vxlan_port(adapter, ntohs(ti.port)); + if (err) + return err; } - if (ahw->vxlan_port == ntohs(ti->port)) - ahw->vxlan_port_count++; + return qlcnic_set_vxlan_parsing(adapter, ntohs(ti.port)); } -static void qlcnic_del_vxlan_port(struct net_device *netdev, - struct udp_tunnel_info *ti) -{ - struct qlcnic_adapter *adapter = netdev_priv(netdev); - struct qlcnic_hardware_context *ahw = adapter->ahw; - - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) - return; - - if (!qlcnic_encap_rx_offload(adapter) || !ahw->vxlan_port_count || - (ahw->vxlan_port != ntohs(ti->port))) - return; - - ahw->vxlan_port_count--; - if (!ahw->vxlan_port_count) - adapter->flags |= QLCNIC_DEL_VXLAN_PORT; -} +static const struct udp_tunnel_nic_info qlcnic_udp_tunnels = { + .sync_table = qlcnic_udp_tunnel_sync, + .flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP, + .tables = { + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, }, + }, +}; static netdev_features_t qlcnic_features_check(struct sk_buff *skb, struct net_device *dev, @@ -540,8 +521,8 @@ static const struct net_device_ops qlcnic_netdev_ops = { .ndo_fdb_del = qlcnic_fdb_del, .ndo_fdb_dump = qlcnic_fdb_dump, .ndo_get_phys_port_id = qlcnic_get_phys_port_id, - .ndo_udp_tunnel_add = qlcnic_add_vxlan_port, - .ndo_udp_tunnel_del = qlcnic_del_vxlan_port, + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, .ndo_features_check = qlcnic_features_check, #ifdef CONFIG_QLCNIC_SRIOV .ndo_set_vf_mac = qlcnic_sriov_set_vf_mac, @@ -2017,7 +1998,7 @@ qlcnic_attach(struct qlcnic_adapter *adapter) qlcnic_create_sysfs_entries(adapter); if (qlcnic_encap_rx_offload(adapter)) - udp_tunnel_get_rx_info(netdev); + udp_tunnel_nic_reset_ntf(netdev); adapter->is_up = QLCNIC_ADAPTER_UP_MAGIC; return 0; @@ -2335,9 +2316,12 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev, NETIF_F_TSO6; } - if (qlcnic_encap_rx_offload(adapter)) + if (qlcnic_encap_rx_offload(adapter)) { netdev->hw_enc_features |= NETIF_F_RXCSUM; + netdev->udp_tunnel_nic_info = &qlcnic_udp_tunnels; + } + netdev->hw_features = netdev->features; netdev->priv_flags |= IFF_UNICAST_FLT; netdev->irq = adapter->msix_entries[0].vector;