Merge branch 'udp_tunnel-NIC-RX-port-offload-infrastructure'

Jakub Kicinski says:

====================
udp_tunnel: NIC RX port offload infrastructure

This set of patches converts further drivers to use the new
infrastructure to UDP tunnel port offload merged in
commit 0ea460474d ("Merge branch 'udp_tunnel-add-NIC-RX-port-offload-infrastructure'").

v3:
 - fix a W=1 build warning in qede.
v2:
 - fix a W=1 build warning in xgbe,
 - expand the size of tables for lio.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2020-07-14 17:04:28 -07:00
commit 4ff91fa0a3
25 changed files with 396 additions and 1179 deletions

View File

@ -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) pdata->vxlan_port = be16_to_cpu(ti->port);
return; pdata->hw_if.enable_vxlan(pdata);
netdev_info(netdev, "disabling VXLAN offloads\n"); return 0;
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;
} }
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) struct xgbe_prv_data *pdata = netdev_priv(netdev);
return;
pdata->hw_if.disable_vxlan(pdata); pdata->hw_if.disable_vxlan(pdata);
pdata->vxlan_port_set = 0;
pdata->vxlan_port = 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); return &xgbe_udp_tunnels;
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;
} }
static void xgbe_napi_enable(struct xgbe_prv_data *pdata, unsigned int add) 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_tx(pdata);
hw_if->enable_rx(pdata); hw_if->enable_rx(pdata);
udp_tunnel_get_rx_info(netdev); udp_tunnel_nic_reset_ntf(netdev);
netif_tx_start_all_queues(netdev); netif_tx_start_all_queues(netdev);
@ -1447,7 +1373,7 @@ static void xgbe_stop(struct xgbe_prv_data *pdata)
xgbe_stop_timers(pdata); xgbe_stop_timers(pdata);
flush_workqueue(pdata->dev_workqueue); 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_tx(pdata);
hw_if->disable_rx(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; 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) if (!skb->encapsulation)
return false; return false;
@ -1801,19 +1722,13 @@ static bool xgbe_is_vxlan(struct xgbe_prv_data *pdata, struct sk_buff *skb)
return false; return false;
} }
/* See if we have the UDP port in our list */ if (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
list_for_each_entry(vdata, &pdata->vxlan_ports, list) { skb->inner_protocol != htons(ETH_P_TEB) ||
if ((skb->protocol == htons(ETH_P_IP)) && (skb_inner_mac_header(skb) - skb_transport_header(skb) !=
(vdata->sa_family == AF_INET) && sizeof(struct udphdr) + sizeof(struct vxlanhdr)))
(vdata->port == udp_hdr(skb)->dest)) return false;
return true;
else if ((skb->protocol == htons(ETH_P_IPV6)) &&
(vdata->sa_family == AF_INET6) &&
(vdata->port == udp_hdr(skb)->dest))
return true;
}
return false; return true;
} }
static int xgbe_is_tso(struct sk_buff *skb) 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, XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES,
CSUM_ENABLE, 1); CSUM_ENABLE, 1);
if (xgbe_is_vxlan(pdata, skb)) if (xgbe_is_vxlan(skb))
XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES,
VXLAN, 1); VXLAN, 1);
@ -2271,23 +2186,12 @@ static netdev_features_t xgbe_fix_features(struct net_device *netdev,
netdev_features_t features) netdev_features_t features)
{ {
struct xgbe_prv_data *pdata = netdev_priv(netdev); 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_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) if (!pdata->hw_feat.vxn)
return features & ~vxlan_mask; return features;
/* VXLAN CSUM requires VXLAN base */ /* VXLAN CSUM requires VXLAN base */
if ((features & NETIF_F_GSO_UDP_TUNNEL_CSUM) && 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; 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_prv_data *pdata = netdev_priv(netdev);
struct xgbe_hw_if *hw_if = &pdata->hw_if; struct xgbe_hw_if *hw_if = &pdata->hw_if;
netdev_features_t rxhash, rxcsum, rxvlan, rxvlan_filter; netdev_features_t rxhash, rxcsum, rxvlan, rxvlan_filter;
netdev_features_t udp_tunnel;
int ret = 0; int ret = 0;
rxhash = pdata->netdev_features & NETIF_F_RXHASH; rxhash = pdata->netdev_features & NETIF_F_RXHASH;
rxcsum = pdata->netdev_features & NETIF_F_RXCSUM; rxcsum = pdata->netdev_features & NETIF_F_RXCSUM;
rxvlan = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_RX; rxvlan = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_RX;
rxvlan_filter = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_FILTER; 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) if ((features & NETIF_F_RXHASH) && !rxhash)
ret = hw_if->enable_rss(pdata); 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) else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) && rxvlan_filter)
hw_if->disable_rx_vlan_filtering(pdata); 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; pdata->netdev_features = features;
DBGPR("<--xgbe_set_features\n"); DBGPR("<--xgbe_set_features\n");
@ -2379,101 +2267,6 @@ static int xgbe_set_features(struct net_device *netdev,
return 0; 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, static netdev_features_t xgbe_features_check(struct sk_buff *skb,
struct net_device *netdev, struct net_device *netdev,
netdev_features_t features) netdev_features_t features)
@ -2503,8 +2296,8 @@ static const struct net_device_ops xgbe_netdev_ops = {
.ndo_setup_tc = xgbe_setup_tc, .ndo_setup_tc = xgbe_setup_tc,
.ndo_fix_features = xgbe_fix_features, .ndo_fix_features = xgbe_fix_features,
.ndo_set_features = xgbe_set_features, .ndo_set_features = xgbe_set_features,
.ndo_udp_tunnel_add = xgbe_udp_tunnel_add, .ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
.ndo_udp_tunnel_del = xgbe_udp_tunnel_del, .ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
.ndo_features_check = xgbe_features_check, .ndo_features_check = xgbe_features_check,
}; };

View File

@ -192,7 +192,6 @@ struct xgbe_prv_data *xgbe_alloc_pdata(struct device *dev)
mutex_init(&pdata->i2c_mutex); mutex_init(&pdata->i2c_mutex);
init_completion(&pdata->i2c_complete); init_completion(&pdata->i2c_complete);
init_completion(&pdata->mdio_complete); init_completion(&pdata->mdio_complete);
INIT_LIST_HEAD(&pdata->vxlan_ports);
pdata->msg_enable = netif_msg_init(debug, default_msg_level); 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_TSO6 |
NETIF_F_GRO | NETIF_F_GRO |
NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_UDP_TUNNEL_CSUM;
NETIF_F_RX_UDP_TUNNEL_PORT;
netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL | netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_UDP_TUNNEL_CSUM;
NETIF_F_RX_UDP_TUNNEL_PORT;
pdata->vxlan_offloads_set = 1; netdev->udp_tunnel_nic_info = xgbe_get_udp_tunnel_info();
pdata->vxlan_features = NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_GSO_UDP_TUNNEL_CSUM |
NETIF_F_RX_UDP_TUNNEL_PORT;
} }
netdev->vlan_features |= NETIF_F_SG | netdev->vlan_features |= NETIF_F_SG |

View File

@ -1014,12 +1014,6 @@ struct xgbe_version_data {
unsigned int an_cdr_workaround; 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 xgbe_prv_data {
struct net_device *netdev; struct net_device *netdev;
struct pci_dev *pcidev; struct pci_dev *pcidev;
@ -1172,13 +1166,7 @@ struct xgbe_prv_data {
u32 rss_options; u32 rss_options;
/* VXLAN settings */ /* 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; u16 vxlan_port;
netdev_features_t vxlan_features;
/* Netdev related settings */ /* Netdev related settings */
unsigned char mac_addr[ETH_ALEN]; 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 *); void xgbe_init_function_ptrs_i2c(struct xgbe_i2c_if *);
const struct net_device_ops *xgbe_get_netdev_ops(void); const struct net_device_ops *xgbe_get_netdev_ops(void);
const struct ethtool_ops *xgbe_get_ethtool_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 #ifdef CONFIG_AMD_XGBE_DCB
const struct dcbnl_rtnl_ops *xgbe_get_dcbnl_ops(void); const struct dcbnl_rtnl_ops *xgbe_get_dcbnl_ops(void);

View File

@ -1287,7 +1287,6 @@ enum sp_rtnl_flag {
BNX2X_SP_RTNL_HYPERVISOR_VLAN, BNX2X_SP_RTNL_HYPERVISOR_VLAN,
BNX2X_SP_RTNL_TX_STOP, BNX2X_SP_RTNL_TX_STOP,
BNX2X_SP_RTNL_GET_DRV_VERSION, BNX2X_SP_RTNL_GET_DRV_VERSION,
BNX2X_SP_RTNL_CHANGE_UDP_PORT,
BNX2X_SP_RTNL_UPDATE_SVID, BNX2X_SP_RTNL_UPDATE_SVID,
}; };
@ -1343,11 +1342,6 @@ enum bnx2x_udp_port_type {
BNX2X_UDP_PORT_MAX, BNX2X_UDP_PORT_MAX,
}; };
struct bnx2x_udp_tunnel {
u16 dst_port;
u8 count;
};
struct bnx2x { struct bnx2x {
/* Fields used in the tx and intr/napi performance paths /* Fields used in the tx and intr/napi performance paths
* are grouped together in the beginning of the structure * are grouped together in the beginning of the structure
@ -1855,7 +1849,7 @@ struct bnx2x {
bool accept_any_vlan; bool accept_any_vlan;
/* Vxlan/Geneve related information */ /* 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 */ /* Tx queues may be less or equal to Rx queues */

View File

@ -960,12 +960,12 @@ static inline int bnx2x_func_start(struct bnx2x *bp)
start_params->network_cos_mode = STATIC_COS; start_params->network_cos_mode = STATIC_COS;
else /* CHIP_IS_E1X */ else /* CHIP_IS_E1X */
start_params->network_cos_mode = FW_WRR; start_params->network_cos_mode = FW_WRR;
if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN].count) { if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN]) {
port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN].dst_port; port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN];
start_params->vxlan_dst_port = port; start_params->vxlan_dst_port = port;
} }
if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE].count) { if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE]) {
port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE].dst_port; port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE];
start_params->geneve_dst_port = port; start_params->geneve_dst_port = port;
} }

View File

@ -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_switch_update_params *switch_update_params;
struct bnx2x_func_state_params func_params = {NULL}; struct bnx2x_func_state_params func_params = {NULL};
struct bnx2x_udp_tunnel *udp_tunnel;
u16 vxlan_port = 0, geneve_port = 0; u16 vxlan_port = 0, geneve_port = 0;
int rc; int rc;
@ -10169,15 +10168,13 @@ static int bnx2x_udp_port_update(struct bnx2x *bp)
__set_bit(BNX2X_F_UPDATE_TUNNEL_CFG_CHNG, __set_bit(BNX2X_F_UPDATE_TUNNEL_CFG_CHNG,
&switch_update_params->changes); &switch_update_params->changes);
if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE].count) { if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE]) {
udp_tunnel = &bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE]; geneve_port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE];
geneve_port = udp_tunnel->dst_port;
switch_update_params->geneve_dst_port = geneve_port; switch_update_params->geneve_dst_port = geneve_port;
} }
if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN].count) { if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN]) {
udp_tunnel = &bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN]; vxlan_port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN];
vxlan_port = udp_tunnel->dst_port;
switch_update_params->vxlan_dst_port = vxlan_port; switch_update_params->vxlan_dst_port = vxlan_port;
} }
@ -10197,93 +10194,26 @@ static int bnx2x_udp_port_update(struct bnx2x *bp)
return rc; return rc;
} }
static void __bnx2x_add_udp_port(struct bnx2x *bp, u16 port, static int bnx2x_udp_tunnel_sync(struct net_device *netdev, unsigned int table)
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)
{ {
struct bnx2x *bp = netdev_priv(netdev); struct bnx2x *bp = netdev_priv(netdev);
u16 t_port = ntohs(ti->port); struct udp_tunnel_info ti;
switch (ti->type) { udp_tunnel_nic_get_port(netdev, table, 0, &ti);
case UDP_TUNNEL_TYPE_VXLAN: bp->udp_tunnel_ports[table] = be16_to_cpu(ti.port);
__bnx2x_add_udp_port(bp, t_port, BNX2X_UDP_PORT_VXLAN);
break; return bnx2x_udp_port_update(bp);
case UDP_TUNNEL_TYPE_GENEVE:
__bnx2x_add_udp_port(bp, t_port, BNX2X_UDP_PORT_GENEVE);
break;
default:
break;
}
} }
static void bnx2x_udp_tunnel_del(struct net_device *netdev, static const struct udp_tunnel_nic_info bnx2x_udp_tunnels = {
struct udp_tunnel_info *ti) .sync_table = bnx2x_udp_tunnel_sync,
{ .flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP |
struct bnx2x *bp = netdev_priv(netdev); UDP_TUNNEL_NIC_INFO_OPEN_ONLY,
u16 t_port = ntohs(ti->port); .tables = {
{ .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, },
switch (ti->type) { { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_GENEVE, },
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 int bnx2x_close(struct net_device *dev); static int bnx2x_close(struct net_device *dev);
@ -10407,24 +10337,6 @@ static void bnx2x_sp_rtnl_task(struct work_struct *work)
if (test_and_clear_bit(BNX2X_SP_RTNL_UPDATE_SVID, &bp->sp_rtnl_state)) if (test_and_clear_bit(BNX2X_SP_RTNL_UPDATE_SVID, &bp->sp_rtnl_state))
bnx2x_handle_update_svid_cmd(bp); 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 /* work which needs rtnl lock not-taken (as it takes the lock itself and
* can be called from other contexts as well) * can be called from other contexts as well)
*/ */
@ -12620,9 +12532,6 @@ static int bnx2x_open(struct net_device *dev)
if (rc) if (rc)
return rc; return rc;
if (IS_PF(bp))
udp_tunnel_get_rx_info(dev);
return 0; 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_get_phys_port_id = bnx2x_get_phys_port_id,
.ndo_set_vf_link_state = bnx2x_set_vf_link_state, .ndo_set_vf_link_state = bnx2x_set_vf_link_state,
.ndo_features_check = bnx2x_features_check, .ndo_features_check = bnx2x_features_check,
.ndo_udp_tunnel_add = bnx2x_udp_tunnel_add, .ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
.ndo_udp_tunnel_del = bnx2x_udp_tunnel_del, .ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
}; };
static int bnx2x_set_coherency_mask(struct bnx2x *bp) 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 | dev->gso_partial_features = NETIF_F_GSO_GRE_CSUM |
NETIF_F_GSO_UDP_TUNNEL_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 | dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |

View File

@ -2670,6 +2670,35 @@ static int liquidio_vxlan_port_command(struct net_device *netdev, int command,
return ret; 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 /** \brief Net device fix features
* @param netdev pointer to network device * @param netdev pointer to network device
* @param request features requested * @param request features requested
@ -2758,30 +2787,6 @@ static int liquidio_set_features(struct net_device *netdev,
return 0; 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, static int __liquidio_set_vf_mac(struct net_device *netdev, int vfidx,
u8 *mac, bool is_admin_assigned) u8 *mac, bool is_admin_assigned)
{ {
@ -3208,8 +3213,8 @@ static const struct net_device_ops lionetdevops = {
.ndo_do_ioctl = liquidio_ioctl, .ndo_do_ioctl = liquidio_ioctl,
.ndo_fix_features = liquidio_fix_features, .ndo_fix_features = liquidio_fix_features,
.ndo_set_features = liquidio_set_features, .ndo_set_features = liquidio_set_features,
.ndo_udp_tunnel_add = liquidio_add_vxlan_port, .ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
.ndo_udp_tunnel_del = liquidio_del_vxlan_port, .ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
.ndo_set_vf_mac = liquidio_set_vf_mac, .ndo_set_vf_mac = liquidio_set_vf_mac,
.ndo_set_vf_vlan = liquidio_set_vf_vlan, .ndo_set_vf_vlan = liquidio_set_vf_vlan,
.ndo_get_vf_config = liquidio_get_vf_config, .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 & netdev->hw_enc_features = (lio->enc_dev_capability &
~NETIF_F_LRO); ~NETIF_F_LRO);
netdev->udp_tunnel_nic_info = &liquidio_udp_tunnels;
lio->dev_capability |= NETIF_F_GSO_UDP_TUNNEL; lio->dev_capability |= NETIF_F_GSO_UDP_TUNNEL;
netdev->vlan_features = lio->dev_capability; netdev->vlan_features = lio->dev_capability;

View File

@ -1767,6 +1767,35 @@ static int liquidio_vxlan_port_command(struct net_device *netdev, int command,
return ret; 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 /** \brief Net device fix features
* @param netdev pointer to network device * @param netdev pointer to network device
* @param request features requested * @param request features requested
@ -1835,30 +1864,6 @@ static int liquidio_set_features(struct net_device *netdev,
return 0; 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 = { static const struct net_device_ops lionetdevops = {
.ndo_open = liquidio_open, .ndo_open = liquidio_open,
.ndo_stop = liquidio_stop, .ndo_stop = liquidio_stop,
@ -1873,8 +1878,8 @@ static const struct net_device_ops lionetdevops = {
.ndo_do_ioctl = liquidio_ioctl, .ndo_do_ioctl = liquidio_ioctl,
.ndo_fix_features = liquidio_fix_features, .ndo_fix_features = liquidio_fix_features,
.ndo_set_features = liquidio_set_features, .ndo_set_features = liquidio_set_features,
.ndo_udp_tunnel_add = liquidio_add_vxlan_port, .ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
.ndo_udp_tunnel_del = liquidio_del_vxlan_port, .ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
}; };
static int lio_nic_info(struct octeon_recv_info *recv_info, void *buf) 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 = netdev->hw_enc_features =
(lio->enc_dev_capability & ~NETIF_F_LRO); (lio->enc_dev_capability & ~NETIF_F_LRO);
netdev->udp_tunnel_nic_info = &liquidio_udp_tunnels;
netdev->vlan_features = lio->dev_capability; netdev->vlan_features = lio->dev_capability;
/* Add any unchangeable hw features */ /* Add any unchangeable hw features */
lio->dev_capability |= NETIF_F_HW_VLAN_CTAG_FILTER | lio->dev_capability |= NETIF_F_HW_VLAN_CTAG_FILTER |

View File

@ -1109,9 +1109,7 @@ struct adapter {
int msg_enable; int msg_enable;
__be16 vxlan_port; __be16 vxlan_port;
u8 vxlan_port_cnt;
__be16 geneve_port; __be16 geneve_port;
u8 geneve_port_cnt;
struct adapter_params params; struct adapter_params params;
struct cxgb4_virt_res vres; struct cxgb4_virt_res vres;

View File

@ -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, static int cxgb_udp_tunnel_unset_port(struct net_device *netdev,
struct udp_tunnel_info *ti) unsigned int table, unsigned int entry,
struct udp_tunnel_info *ti)
{ {
struct port_info *pi = netdev_priv(netdev); struct port_info *pi = netdev_priv(netdev);
struct adapter *adapter = pi->adapter; 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 }; u8 match_all_mac[] = { 0, 0, 0, 0, 0, 0 };
int ret = 0, i; int ret = 0, i;
if (chip_ver < CHELSIO_T6)
return;
switch (ti->type) { switch (ti->type) {
case UDP_TUNNEL_TYPE_VXLAN: 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; adapter->vxlan_port = 0;
t4_write_reg(adapter, MPS_RX_VXLAN_TYPE_A, 0); t4_write_reg(adapter, MPS_RX_VXLAN_TYPE_A, 0);
break; break;
case UDP_TUNNEL_TYPE_GENEVE: 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; adapter->geneve_port = 0;
t4_write_reg(adapter, MPS_RX_GENEVE_TYPE_A, 0); t4_write_reg(adapter, MPS_RX_GENEVE_TYPE_A, 0);
break; break;
default: default:
return; return -EINVAL;
} }
/* Matchall mac entries can be deleted only after all tunnel ports /* Matchall mac entries can be deleted only after all tunnel ports
* are brought down or removed. * are brought down or removed.
*/ */
if (!adapter->rawf_cnt) if (!adapter->rawf_cnt)
return; return 0;
for_each_port(adapter, i) { for_each_port(adapter, i) {
pi = adap2pinfo(adapter, i); pi = adap2pinfo(adapter, i);
ret = t4_free_raw_mac_filt(adapter, pi->viid, ret = t4_free_raw_mac_filt(adapter, pi->viid,
match_all_mac, match_all_mac, match_all_mac, match_all_mac,
adapter->rawf_start + adapter->rawf_start + pi->port_id,
pi->port_id,
1, pi->port_id, false); 1, pi->port_id, false);
if (ret < 0) { if (ret < 0) {
netdev_info(netdev, "Failed to free mac filter entry, for port %d\n", netdev_info(netdev, "Failed to free mac filter entry, for port %d\n",
i); i);
return; return ret;
} }
} }
return 0;
} }
static void cxgb_add_udp_tunnel(struct net_device *netdev, static int cxgb_udp_tunnel_set_port(struct net_device *netdev,
struct udp_tunnel_info *ti) unsigned int table, unsigned int entry,
struct udp_tunnel_info *ti)
{ {
struct port_info *pi = netdev_priv(netdev); struct port_info *pi = netdev_priv(netdev);
struct adapter *adapter = pi->adapter; 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 }; u8 match_all_mac[] = { 0, 0, 0, 0, 0, 0 };
int i, ret; int i, ret;
if (chip_ver < CHELSIO_T6 || !adapter->rawf_cnt)
return;
switch (ti->type) { switch (ti->type) {
case UDP_TUNNEL_TYPE_VXLAN: 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 = ti->port;
adapter->vxlan_port_cnt = 1;
t4_write_reg(adapter, MPS_RX_VXLAN_TYPE_A, t4_write_reg(adapter, MPS_RX_VXLAN_TYPE_A,
VXLAN_V(be16_to_cpu(ti->port)) | VXLAN_EN_F); VXLAN_V(be16_to_cpu(ti->port)) | VXLAN_EN_F);
break; break;
case UDP_TUNNEL_TYPE_GENEVE: 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 = ti->port;
adapter->geneve_port_cnt = 1;
t4_write_reg(adapter, MPS_RX_GENEVE_TYPE_A, t4_write_reg(adapter, MPS_RX_GENEVE_TYPE_A,
GENEVE_V(be16_to_cpu(ti->port)) | GENEVE_EN_F); GENEVE_V(be16_to_cpu(ti->port)) | GENEVE_EN_F);
break; break;
default: default:
return; return -EINVAL;
} }
/* Create a 'match all' mac filter entry for inner mac, /* 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, ret = t4_alloc_raw_mac_filt(adapter, pi->viid,
match_all_mac, match_all_mac,
match_all_mac, match_all_mac,
adapter->rawf_start + adapter->rawf_start + pi->port_id,
pi->port_id,
1, pi->port_id, false); 1, pi->port_id, false);
if (ret < 0) { if (ret < 0) {
netdev_info(netdev, "Failed to allocate a mac filter entry, not adding port %d\n", netdev_info(netdev, "Failed to allocate a mac filter entry, not adding port %d\n",
be16_to_cpu(ti->port)); be16_to_cpu(ti->port));
cxgb_del_udp_tunnel(netdev, ti); return ret;
return;
} }
} }
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, static netdev_features_t cxgb_features_check(struct sk_buff *skb,
struct net_device *dev, struct net_device *dev,
netdev_features_t features) netdev_features_t features)
@ -3930,8 +3881,8 @@ static const struct net_device_ops cxgb4_netdev_ops = {
#endif /* CONFIG_CHELSIO_T4_FCOE */ #endif /* CONFIG_CHELSIO_T4_FCOE */
.ndo_set_tx_maxrate = cxgb_set_tx_maxrate, .ndo_set_tx_maxrate = cxgb_set_tx_maxrate,
.ndo_setup_tc = cxgb_setup_tc, .ndo_setup_tc = cxgb_setup_tc,
.ndo_udp_tunnel_add = cxgb_add_udp_tunnel, .ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
.ndo_udp_tunnel_del = cxgb_del_udp_tunnel, .ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
.ndo_features_check = cxgb_features_check, .ndo_features_check = cxgb_features_check,
.ndo_fix_features = cxgb_fix_features, .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 | netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_UDP_TUNNEL_CSUM |
NETIF_F_HW_TLS_RECORD; NETIF_F_HW_TLS_RECORD;
if (adapter->rawf_cnt)
netdev->udp_tunnel_nic_info = &cxgb_udp_tunnels;
} }
if (highdma) if (highdma)

View File

@ -176,50 +176,18 @@ static void enic_unset_affinity_hint(struct enic *enic)
irq_set_affinity_hint(enic->msix_entry[i].vector, NULL); irq_set_affinity_hint(enic->msix_entry[i].vector, NULL);
} }
static void enic_udp_tunnel_add(struct net_device *netdev, static int enic_udp_tunnel_set_port(struct net_device *netdev,
struct udp_tunnel_info *ti) unsigned int table, unsigned int entry,
struct udp_tunnel_info *ti)
{ {
struct enic *enic = netdev_priv(netdev); struct enic *enic = netdev_priv(netdev);
__be16 port = ti->port;
int err; int err;
spin_lock_bh(&enic->devcmd_lock); 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, err = vnic_dev_overlay_offload_cfg(enic->vdev,
OVERLAY_CFG_VXLAN_PORT_UPDATE, OVERLAY_CFG_VXLAN_PORT_UPDATE,
ntohs(port)); ntohs(ti->port));
if (err) if (err)
goto error; goto error;
@ -228,52 +196,50 @@ static void enic_udp_tunnel_add(struct net_device *netdev,
if (err) if (err)
goto error; goto error;
enic->vxlan.vxlan_udp_port_number = ntohs(port); enic->vxlan.vxlan_udp_port_number = ntohs(ti->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;
error: 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); spin_unlock_bh(&enic->devcmd_lock);
return err;
} }
static void enic_udp_tunnel_del(struct net_device *netdev, static int enic_udp_tunnel_unset_port(struct net_device *netdev,
struct udp_tunnel_info *ti) unsigned int table, unsigned int entry,
struct udp_tunnel_info *ti)
{ {
struct enic *enic = netdev_priv(netdev); struct enic *enic = netdev_priv(netdev);
int err; int err;
spin_lock_bh(&enic->devcmd_lock); 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, err = vnic_dev_overlay_offload_ctrl(enic->vdev, OVERLAY_FEATURE_VXLAN,
OVERLAY_OFFLOAD_DISABLE); OVERLAY_OFFLOAD_DISABLE);
if (err) { if (err)
netdev_err(netdev, "vxlan: del offload udp port: %d failed",
ntohs(ti->port));
goto unlock; goto unlock;
}
enic->vxlan.vxlan_udp_port_number = 0; 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: unlock:
spin_unlock_bh(&enic->devcmd_lock); 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, static netdev_features_t enic_features_check(struct sk_buff *skb,
struct net_device *dev, struct net_device *dev,
netdev_features_t features) netdev_features_t features)
@ -2526,8 +2492,8 @@ static const struct net_device_ops enic_netdev_dynamic_ops = {
#ifdef CONFIG_RFS_ACCEL #ifdef CONFIG_RFS_ACCEL
.ndo_rx_flow_steer = enic_rx_flow_steer, .ndo_rx_flow_steer = enic_rx_flow_steer,
#endif #endif
.ndo_udp_tunnel_add = enic_udp_tunnel_add, .ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
.ndo_udp_tunnel_del = enic_udp_tunnel_del, .ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
.ndo_features_check = enic_features_check, .ndo_features_check = enic_features_check,
}; };
@ -2552,8 +2518,8 @@ static const struct net_device_ops enic_netdev_ops = {
#ifdef CONFIG_RFS_ACCEL #ifdef CONFIG_RFS_ACCEL
.ndo_rx_flow_steer = enic_rx_flow_steer, .ndo_rx_flow_steer = enic_rx_flow_steer,
#endif #endif
.ndo_udp_tunnel_add = enic_udp_tunnel_add, .ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
.ndo_udp_tunnel_del = enic_udp_tunnel_del, .ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
.ndo_features_check = enic_features_check, .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 = fls(patch_level);
patch_level = patch_level ? patch_level - 1 : 0; patch_level = patch_level ? patch_level - 1 : 0;
enic->vxlan.patch_level = patch_level; 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; netdev->features |= netdev->hw_features;

View File

@ -654,8 +654,6 @@ struct be_adapter {
u8 hba_port_num; u8 hba_port_num;
u16 pvid; u16 pvid;
__be16 vxlan_port; /* offloaded vxlan port num */ __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; struct phy_info phy;
u8 wol_cap; u8 wol_cap;
bool wol_en; bool wol_en;
@ -679,9 +677,6 @@ struct be_adapter {
struct be_cmd_work { struct be_cmd_work {
struct work_struct work; struct work_struct work;
struct be_adapter *adapter; struct be_adapter *adapter;
union {
__be16 vxlan_port;
} info;
}; };
#define be_physfn(adapter) (!adapter->virtfn) #define be_physfn(adapter) (!adapter->virtfn)

View File

@ -3829,8 +3829,8 @@ static int be_open(struct net_device *netdev)
be_link_status_update(adapter, link_status); be_link_status_update(adapter, link_status);
netif_tx_start_all_queues(netdev); netif_tx_start_all_queues(netdev);
if (skyhawk_chip(adapter))
udp_tunnel_get_rx_info(netdev); udp_tunnel_nic_reset_ntf(netdev);
return 0; return 0;
err: 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 device *dev = &adapter->pdev->dev;
struct be_vxlan_port *vxlan_port;
__be16 port;
int status; 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, status = be_cmd_manage_iface(adapter, adapter->if_handle,
OP_CONVERT_NORMAL_TO_TUNNEL); OP_CONVERT_NORMAL_TO_TUNNEL);
if (status) { if (status) {
@ -3987,25 +3992,26 @@ static int be_enable_vxlan_offloads(struct be_adapter *adapter)
} }
adapter->flags |= BE_FLAGS_VXLAN_OFFLOADS; 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) { if (status) {
dev_warn(dev, "Failed to add VxLAN port\n"); dev_warn(dev, "Failed to add VxLAN port\n");
return status; return status;
} }
adapter->vxlan_port = port; adapter->vxlan_port = ti->port;
netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO | NETIF_F_TSO6 |
NETIF_F_GSO_UDP_TUNNEL; NETIF_F_GSO_UDP_TUNNEL;
dev_info(dev, "Enabled VxLAN offloads for UDP port %d\n", dev_info(dev, "Enabled VxLAN offloads for UDP port %d\n",
be16_to_cpu(port)); be16_to_cpu(ti->port));
return 0; 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) if (adapter->flags & BE_FLAGS_VXLAN_OFFLOADS)
be_cmd_manage_iface(adapter, adapter->if_handle, 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; adapter->vxlan_port = 0;
netdev->hw_enc_features = 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, static void be_calculate_vf_res(struct be_adapter *adapter, u16 num_vfs,
struct be_resources *vft_res) struct be_resources *vft_res)
{ {
@ -4135,7 +4152,7 @@ static int be_clear(struct be_adapter *adapter)
&vft_res); &vft_res);
} }
be_disable_vxlan_offloads(adapter); be_vxlan_unset_port(adapter->netdev, 0, 0, NULL);
be_if_destroy(adapter); be_if_destroy(adapter);
@ -5053,147 +5070,6 @@ static struct be_cmd_work *be_alloc_work(struct be_adapter *adapter,
return work; 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, static netdev_features_t be_features_check(struct sk_buff *skb,
struct net_device *dev, struct net_device *dev,
netdev_features_t features) netdev_features_t features)
@ -5309,8 +5185,8 @@ static const struct net_device_ops be_netdev_ops = {
#endif #endif
.ndo_bridge_setlink = be_ndo_bridge_setlink, .ndo_bridge_setlink = be_ndo_bridge_setlink,
.ndo_bridge_getlink = be_ndo_bridge_getlink, .ndo_bridge_getlink = be_ndo_bridge_getlink,
.ndo_udp_tunnel_add = be_add_vxlan_port, .ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
.ndo_udp_tunnel_del = be_del_vxlan_port, .ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
.ndo_features_check = be_features_check, .ndo_features_check = be_features_check,
.ndo_get_phys_port_id = be_get_phys_port_id, .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; 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 */ /* MTU range: 256 - 9000 */
netdev->min_mtu = BE_MIN_MTU; netdev->min_mtu = BE_MIN_MTU;
netdev->max_mtu = BE_MAX_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 */ /* Must be a power of 2 or else MODULO will BUG_ON */
adapter->be_get_temp_freq = 64; adapter->be_get_temp_freq = 64;
INIT_LIST_HEAD(&adapter->vxlan_port_list);
return 0; return 0;
free_rx_filter: free_rx_filter:

View File

@ -221,12 +221,6 @@ struct fm10k_iov_data {
struct fm10k_vf_info vf_info[]; 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 { enum fm10k_macvlan_request_type {
FM10K_UC_MAC_REQUEST, FM10K_UC_MAC_REQUEST,
FM10K_MC_MAC_REQUEST, FM10K_MC_MAC_REQUEST,
@ -370,8 +364,8 @@ struct fm10k_intfc {
u32 rssrk[FM10K_RSSRK_SIZE]; u32 rssrk[FM10K_RSSRK_SIZE];
/* UDP encapsulation port tracking information */ /* UDP encapsulation port tracking information */
struct list_head vxlan_port; __be16 vxlan_port;
struct list_head geneve_port; __be16 geneve_port;
/* MAC/VLAN update queue */ /* MAC/VLAN update queue */
struct list_head macvlan_requests; struct list_head macvlan_requests;

View File

@ -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) static struct ethhdr *fm10k_port_is_vxlan(struct sk_buff *skb)
{ {
struct fm10k_intfc *interface = netdev_priv(skb->dev); 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 */ if (interface->vxlan_port != udp_hdr(skb)->dest)
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)
return NULL; return NULL;
/* return offset of udp_hdr plus 8 bytes for VXLAN header */ /* return offset of udp_hdr plus 8 bytes for VXLAN header */

View File

@ -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 * fm10k_restore_udp_port_info
* @interface: board private structure * @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) static void fm10k_restore_udp_port_info(struct fm10k_intfc *interface)
{ {
struct fm10k_hw *hw = &interface->hw; struct fm10k_hw *hw = &interface->hw;
struct fm10k_udp_port *port;
/* only the PF supports configuring tunnels */ /* only the PF supports configuring tunnels */
if (hw->mac.type != fm10k_mac_pf) if (hw->mac.type != fm10k_mac_pf)
return; return;
port = list_first_entry_or_null(&interface->vxlan_port,
struct fm10k_udp_port, list);
/* restore tunnel configuration register */ /* restore tunnel configuration register */
fm10k_write_reg(hw, FM10K_TUNNEL_CFG, fm10k_write_reg(hw, FM10K_TUNNEL_CFG,
(port ? ntohs(port->port) : 0) | ntohs(interface->vxlan_port) |
(ETH_P_TEB << FM10K_TUNNEL_CFG_NVGRE_SHIFT)); (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 */ /* restore Geneve tunnel configuration register */
fm10k_write_reg(hw, FM10K_TUNNEL_CFG_GENEVE, fm10k_write_reg(hw, FM10K_TUNNEL_CFG_GENEVE,
(port ? ntohs(port->port) : 0)); ntohs(interface->geneve_port));
}
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);
} }
/** /**
* fm10k_udp_tunnel_add * fm10k_udp_tunnel_sync - Called when UDP tunnel ports change
* @dev: network interface device structure * @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 * 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, static int fm10k_udp_tunnel_sync(struct net_device *dev, unsigned int table)
struct udp_tunnel_info *ti)
{ {
struct fm10k_intfc *interface = netdev_priv(dev); struct fm10k_intfc *interface = netdev_priv(dev);
struct udp_tunnel_info ti;
/* only the PF supports configuring tunnels */ udp_tunnel_nic_get_port(dev, table, 0, &ti);
if (interface->hw.mac.type != fm10k_mac_pf) if (!table)
return; interface->vxlan_port = ti.port;
else
switch (ti->type) { interface->geneve_port = ti.port;
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;
}
fm10k_restore_udp_port_info(interface); fm10k_restore_udp_port_info(interface);
return 0;
} }
/** static const struct udp_tunnel_nic_info fm10k_udp_tunnels = {
* fm10k_udp_tunnel_del .sync_table = fm10k_udp_tunnel_sync,
* @dev: network interface device structure .tables = {
* @ti: Tunnel end point information { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, },
* { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_GENEVE, },
* 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);
}
/** /**
* fm10k_open - Called when a network interface is made active * fm10k_open - Called when a network interface is made active
@ -580,8 +468,6 @@ int fm10k_open(struct net_device *netdev)
if (err) if (err)
goto err_set_queues; goto err_set_queues;
udp_tunnel_get_rx_info(netdev);
fm10k_up(interface); fm10k_up(interface);
return 0; return 0;
@ -615,8 +501,6 @@ int fm10k_close(struct net_device *netdev)
fm10k_qv_free_irq(interface); fm10k_qv_free_irq(interface);
fm10k_free_udp_port_info(interface);
fm10k_free_all_tx_resources(interface); fm10k_free_all_tx_resources(interface);
fm10k_free_all_rx_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_set_vf_rate = fm10k_ndo_set_vf_bw,
.ndo_get_vf_config = fm10k_ndo_get_vf_config, .ndo_get_vf_config = fm10k_ndo_get_vf_config,
.ndo_get_vf_stats = fm10k_ndo_get_vf_stats, .ndo_get_vf_stats = fm10k_ndo_get_vf_stats,
.ndo_udp_tunnel_add = fm10k_udp_tunnel_add, .ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
.ndo_udp_tunnel_del = fm10k_udp_tunnel_del, .ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
.ndo_dfwd_add_station = fm10k_dfwd_add_station, .ndo_dfwd_add_station = fm10k_dfwd_add_station,
.ndo_dfwd_del_station = fm10k_dfwd_del_station, .ndo_dfwd_del_station = fm10k_dfwd_del_station,
.ndo_features_check = fm10k_features_check, .ndo_features_check = fm10k_features_check,
@ -1695,6 +1579,8 @@ struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info)
NETIF_F_SG; NETIF_F_SG;
dev->features |= NETIF_F_GSO_UDP_TUNNEL; dev->features |= NETIF_F_GSO_UDP_TUNNEL;
dev->udp_tunnel_nic_info = &fm10k_udp_tunnels;
} }
/* all features defined to this point should be changeable */ /* all features defined to this point should be changeable */

View File

@ -2066,10 +2066,6 @@ static int fm10k_sw_init(struct fm10k_intfc *interface,
interface->tx_itr = FM10K_TX_ITR_DEFAULT; interface->tx_itr = FM10K_TX_ITR_DEFAULT;
interface->rx_itr = FM10K_ITR_ADAPTIVE | FM10K_RX_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 */ /* Initialize the MAC/VLAN queue */
INIT_LIST_HEAD(&interface->macvlan_requests); INIT_LIST_HEAD(&interface->macvlan_requests);

View File

@ -575,8 +575,6 @@ struct nfp_net_dp {
* @rx_coalesce_max_frames: RX interrupt moderation frame count parameter * @rx_coalesce_max_frames: RX interrupt moderation frame count parameter
* @tx_coalesce_usecs: TX interrupt moderation usecs delay parameter * @tx_coalesce_usecs: TX interrupt moderation usecs delay parameter
* @tx_coalesce_max_frames: TX interrupt moderation frame count 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 * @qcp_cfg: Pointer to QCP queue used for configuration notification
* @tx_bar: Pointer to mapped TX queues * @tx_bar: Pointer to mapped TX queues
* @rx_bar: Pointer to mapped FL/RX queues * @rx_bar: Pointer to mapped FL/RX queues
@ -661,9 +659,6 @@ struct nfp_net {
u32 tx_coalesce_usecs; u32 tx_coalesce_usecs;
u32 tx_coalesce_max_frames; 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 *qcp_cfg;
u8 __iomem *tx_bar; u8 __iomem *tx_bar;

View File

@ -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++) for (r = 0; r < nn->dp.num_rx_rings; r++)
nfp_net_rx_ring_fill_freelist(&nn->dp, &nn->dp.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; return 0;
} }
@ -3566,87 +3557,6 @@ nfp_net_get_phys_port_name(struct net_device *netdev, char *name, size_t len)
return 0; 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) static int nfp_net_xdp_setup_drv(struct nfp_net *nn, struct netdev_bpf *bpf)
{ {
struct bpf_prog *prog = bpf->prog; 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_set_features = nfp_net_set_features,
.ndo_features_check = nfp_net_features_check, .ndo_features_check = nfp_net_features_check,
.ndo_get_phys_port_name = nfp_net_get_phys_port_name, .ndo_get_phys_port_name = nfp_net_get_phys_port_name,
.ndo_udp_tunnel_add = nfp_net_add_vxlan_port, .ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
.ndo_udp_tunnel_del = nfp_net_del_vxlan_port, .ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
.ndo_bpf = nfp_net_xdp, .ndo_bpf = nfp_net_xdp,
.ndo_get_devlink_port = nfp_devlink_get_devlink_port, .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 * nfp_net_info() - Print general info about the NIC
* @nn: NFP Net device to reconfigure * @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_VXLAN) {
if (nn->cap & NFP_NET_CFG_CTRL_LSO) if (nn->cap & NFP_NET_CFG_CTRL_LSO)
netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL; netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
netdev->udp_tunnel_nic_info = &nfp_udp_tunnels;
nn->dp.ctrl |= NFP_NET_CFG_CTRL_VXLAN; nn->dp.ctrl |= NFP_NET_CFG_CTRL_VXLAN;
} }
if (nn->cap & NFP_NET_CFG_CTRL_NVGRE) { if (nn->cap & NFP_NET_CFG_CTRL_NVGRE) {

View File

@ -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_config_debug(uint debug, u32 *p_dp_module, u8 *p_dp_level);
void qede_set_ethtool_ops(struct net_device *netdev); 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, void qede_reload(struct qede_dev *edev,
struct qede_reload_args *args, bool is_locked); struct qede_reload_args *args, bool is_locked);
int qede_change_mtu(struct net_device *dev, int new_mtu); int qede_change_mtu(struct net_device *dev, int new_mtu);

View File

@ -953,115 +953,67 @@ int qede_set_features(struct net_device *dev, netdev_features_t features)
return 0; 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 qede_dev *edev = netdev_priv(dev);
struct qed_tunn_params tunn_params; struct qed_tunn_params tunn_params;
u16 t_port = ntohs(ti->port); struct udp_tunnel_info ti;
u16 *save_port;
int rc; int rc;
memset(&tunn_params, 0, sizeof(tunn_params)); memset(&tunn_params, 0, sizeof(tunn_params));
switch (ti->type) { udp_tunnel_nic_get_port(dev, table, 0, &ti);
case UDP_TUNNEL_TYPE_VXLAN: if (ti.type == UDP_TUNNEL_TYPE_VXLAN) {
if (!edev->dev_info.common.vxlan_enable)
return;
if (edev->vxlan_dst_port)
return;
tunn_params.update_vxlan_port = 1; tunn_params.update_vxlan_port = 1;
tunn_params.vxlan_port = t_port; tunn_params.vxlan_port = ntohs(ti.port);
save_port = &edev->vxlan_dst_port;
__qede_lock(edev); } else {
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.update_geneve_port = 1; tunn_params.update_geneve_port = 1;
tunn_params.geneve_port = t_port; 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) {
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;
} }
__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, static const struct udp_tunnel_nic_info qede_udp_tunnels_both = {
struct udp_tunnel_info *ti) .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); if (edev->dev_info.common.vxlan_enable &&
struct qed_tunn_params tunn_params; edev->dev_info.common.geneve_enable)
u16 t_port = ntohs(ti->port); edev->ndev->udp_tunnel_nic_info = &qede_udp_tunnels_both;
else if (edev->dev_info.common.vxlan_enable)
memset(&tunn_params, 0, sizeof(tunn_params)); edev->ndev->udp_tunnel_nic_info = &qede_udp_tunnels_vxlan;
else if (edev->dev_info.common.geneve_enable)
switch (ti->type) { edev->ndev->udp_tunnel_nic_info = &qede_udp_tunnels_geneve;
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;
}
} }
static void qede_xdp_reload_func(struct qede_dev *edev, static void qede_xdp_reload_func(struct qede_dev *edev,

View File

@ -663,8 +663,8 @@ static const struct net_device_ops qede_netdev_ops = {
.ndo_get_vf_config = qede_get_vf_config, .ndo_get_vf_config = qede_get_vf_config,
.ndo_set_vf_rate = qede_set_vf_rate, .ndo_set_vf_rate = qede_set_vf_rate,
#endif #endif
.ndo_udp_tunnel_add = qede_udp_tunnel_add, .ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
.ndo_udp_tunnel_del = qede_udp_tunnel_del, .ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
.ndo_features_check = qede_features_check, .ndo_features_check = qede_features_check,
.ndo_bpf = qede_xdp, .ndo_bpf = qede_xdp,
#ifdef CONFIG_RFS_ACCEL #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_fix_features = qede_fix_features,
.ndo_set_features = qede_set_features, .ndo_set_features = qede_set_features,
.ndo_get_stats64 = qede_get_stats64, .ndo_get_stats64 = qede_get_stats64,
.ndo_udp_tunnel_add = qede_udp_tunnel_add, .ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
.ndo_udp_tunnel_del = qede_udp_tunnel_del, .ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
.ndo_features_check = qede_features_check, .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_fix_features = qede_fix_features,
.ndo_set_features = qede_set_features, .ndo_set_features = qede_set_features,
.ndo_get_stats64 = qede_get_stats64, .ndo_get_stats64 = qede_get_stats64,
.ndo_udp_tunnel_add = qede_udp_tunnel_add, .ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
.ndo_udp_tunnel_del = qede_udp_tunnel_del, .ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
.ndo_features_check = qede_features_check, .ndo_features_check = qede_features_check,
.ndo_bpf = qede_xdp, .ndo_bpf = qede_xdp,
}; };
@ -822,6 +822,8 @@ static void qede_init_ndev(struct qede_dev *edev)
NETIF_F_GSO_UDP_TUNNEL_CSUM); NETIF_F_GSO_UDP_TUNNEL_CSUM);
ndev->hw_enc_features |= (NETIF_F_GSO_UDP_TUNNEL | ndev->hw_enc_features |= (NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_GSO_UDP_TUNNEL_CSUM); NETIF_F_GSO_UDP_TUNNEL_CSUM);
qede_set_udp_tunnels(edev);
} }
if (edev->dev_info.common.gre_enable) { if (edev->dev_info.common.gre_enable) {
@ -2421,7 +2423,7 @@ static int qede_open(struct net_device *ndev)
if (rc) if (rc)
return rc; return rc;
udp_tunnel_get_rx_info(ndev); udp_tunnel_nic_reset_ntf(ndev);
edev->ops->common->update_drv_state(edev->cdev, true); edev->ops->common->update_drv_state(edev->cdev, true);
@ -2523,7 +2525,7 @@ static void qede_recovery_handler(struct qede_dev *edev)
goto err; goto err;
qede_config_rx_mode(edev->ndev); qede_config_rx_mode(edev->ndev);
udp_tunnel_get_rx_info(edev->ndev); udp_tunnel_nic_reset_ntf(edev->ndev);
} }
edev->state = curr_state; edev->state = curr_state;

View File

@ -536,8 +536,6 @@ struct qlcnic_hardware_context {
u8 extend_lb_time; u8 extend_lb_time;
u8 phys_port_id[ETH_ALEN]; u8 phys_port_id[ETH_ALEN];
u8 lb_mode; u8 lb_mode;
u8 vxlan_port_count;
u16 vxlan_port;
struct device *hwmon_dev; struct device *hwmon_dev;
u32 post_mode; u32 post_mode;
bool run_post; bool run_post;
@ -1026,9 +1024,6 @@ struct qlcnic_ipaddr {
#define QLCNIC_HAS_PHYS_PORT_ID 0x40000 #define QLCNIC_HAS_PHYS_PORT_ID 0x40000
#define QLCNIC_TSS_RSS 0x80000 #define QLCNIC_TSS_RSS 0x80000
#define QLCNIC_ADD_VXLAN_PORT 0x100000
#define QLCNIC_DEL_VXLAN_PORT 0x200000
#define QLCNIC_VLAN_FILTERING 0x800000 #define QLCNIC_VLAN_FILTERING 0x800000
#define QLCNIC_IS_MSI_FAMILY(adapter) \ #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_set_default_offload_settings(struct qlcnic_adapter *);
int qlcnic_reset_npar_config(struct qlcnic_adapter *); int qlcnic_reset_npar_config(struct qlcnic_adapter *);
int qlcnic_set_eswitch_port_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_83xx_configure_opmode(struct qlcnic_adapter *adapter);
int qlcnic_read_mac_addr(struct qlcnic_adapter *); int qlcnic_read_mac_addr(struct qlcnic_adapter *);
int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int); int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int);

View File

@ -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_ENABLE_INGRESS_ENCAP_PARSING 1
#define QLCNIC_DISABLE_INGRESS_ENCAP_PARSING 0 #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; struct qlcnic_cmd_args cmd;
int ret = 0; int ret = 0;
@ -1057,10 +1056,8 @@ static int qlcnic_set_vxlan_port(struct qlcnic_adapter *adapter)
return ret; return ret;
} }
static int qlcnic_set_vxlan_parsing(struct qlcnic_adapter *adapter, int qlcnic_set_vxlan_parsing(struct qlcnic_adapter *adapter, u16 port)
bool state)
{ {
u16 vxlan_port = adapter->ahw->vxlan_port;
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
int ret = 0; int ret = 0;
@ -1071,18 +1068,18 @@ static int qlcnic_set_vxlan_parsing(struct qlcnic_adapter *adapter,
if (ret) if (ret)
return ret; return ret;
cmd.req.arg[1] = state ? QLCNIC_ENABLE_INGRESS_ENCAP_PARSING : cmd.req.arg[1] = port ? QLCNIC_ENABLE_INGRESS_ENCAP_PARSING :
QLCNIC_DISABLE_INGRESS_ENCAP_PARSING; QLCNIC_DISABLE_INGRESS_ENCAP_PARSING;
ret = qlcnic_issue_cmd(adapter, &cmd); ret = qlcnic_issue_cmd(adapter, &cmd);
if (ret) if (ret)
netdev_err(adapter->netdev, netdev_err(adapter->netdev,
"Failed to %s VXLAN parsing for port %d\n", "Failed to %s VXLAN parsing for port %d\n",
state ? "enable" : "disable", vxlan_port); port ? "enable" : "disable", port);
else else
netdev_info(adapter->netdev, netdev_info(adapter->netdev,
"%s VXLAN parsing for port %d\n", "%s VXLAN parsing for port %d\n",
state ? "Enabled" : "Disabled", vxlan_port); port ? "Enabled" : "Disabled", port);
qlcnic_free_mbx_args(&cmd); qlcnic_free_mbx_args(&cmd);
@ -1093,22 +1090,6 @@ static void qlcnic_83xx_periodic_tasks(struct qlcnic_adapter *adapter)
{ {
if (adapter->fhash.fnum) if (adapter->fhash.fnum)
qlcnic_prune_lb_filters(adapter); 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;
}
} }
/** /**

View File

@ -471,48 +471,29 @@ static int qlcnic_get_phys_port_id(struct net_device *netdev,
return 0; return 0;
} }
static void qlcnic_add_vxlan_port(struct net_device *netdev, static int qlcnic_udp_tunnel_sync(struct net_device *dev, unsigned int table)
struct udp_tunnel_info *ti)
{ {
struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_adapter *adapter = netdev_priv(dev);
struct qlcnic_hardware_context *ahw = adapter->ahw; struct udp_tunnel_info ti;
int err;
if (ti->type != UDP_TUNNEL_TYPE_VXLAN) udp_tunnel_nic_get_port(dev, table, 0, &ti);
return; if (ti.port) {
err = qlcnic_set_vxlan_port(adapter, ntohs(ti.port));
/* Adapter supports only one VXLAN port. Use very first port if (err)
* for enabling offload return err;
*/
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;
} }
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, static const struct udp_tunnel_nic_info qlcnic_udp_tunnels = {
struct udp_tunnel_info *ti) .sync_table = qlcnic_udp_tunnel_sync,
{ .flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP,
struct qlcnic_adapter *adapter = netdev_priv(netdev); .tables = {
struct qlcnic_hardware_context *ahw = adapter->ahw; { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, },
},
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 netdev_features_t qlcnic_features_check(struct sk_buff *skb, static netdev_features_t qlcnic_features_check(struct sk_buff *skb,
struct net_device *dev, 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_del = qlcnic_fdb_del,
.ndo_fdb_dump = qlcnic_fdb_dump, .ndo_fdb_dump = qlcnic_fdb_dump,
.ndo_get_phys_port_id = qlcnic_get_phys_port_id, .ndo_get_phys_port_id = qlcnic_get_phys_port_id,
.ndo_udp_tunnel_add = qlcnic_add_vxlan_port, .ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
.ndo_udp_tunnel_del = qlcnic_del_vxlan_port, .ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
.ndo_features_check = qlcnic_features_check, .ndo_features_check = qlcnic_features_check,
#ifdef CONFIG_QLCNIC_SRIOV #ifdef CONFIG_QLCNIC_SRIOV
.ndo_set_vf_mac = qlcnic_sriov_set_vf_mac, .ndo_set_vf_mac = qlcnic_sriov_set_vf_mac,
@ -2017,7 +1998,7 @@ qlcnic_attach(struct qlcnic_adapter *adapter)
qlcnic_create_sysfs_entries(adapter); qlcnic_create_sysfs_entries(adapter);
if (qlcnic_encap_rx_offload(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; adapter->is_up = QLCNIC_ADAPTER_UP_MAGIC;
return 0; return 0;
@ -2335,9 +2316,12 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
NETIF_F_TSO6; NETIF_F_TSO6;
} }
if (qlcnic_encap_rx_offload(adapter)) if (qlcnic_encap_rx_offload(adapter)) {
netdev->hw_enc_features |= NETIF_F_RXCSUM; netdev->hw_enc_features |= NETIF_F_RXCSUM;
netdev->udp_tunnel_nic_info = &qlcnic_udp_tunnels;
}
netdev->hw_features = netdev->features; netdev->hw_features = netdev->features;
netdev->priv_flags |= IFF_UNICAST_FLT; netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->irq = adapter->msix_entries[0].vector; netdev->irq = adapter->msix_entries[0].vector;