mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-14 22:56:41 +07:00
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:
commit
4ff91fa0a3
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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 |
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 @@ static void bnx2x_sp_rtnl_task(struct work_struct *work)
|
||||
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 |
|
||||
|
@ -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;
|
||||
|
@ -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 |
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user