Commit fc9a7def authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller

enic: convert to new udp_tunnel_nic infra

Convert to new infra, now the refcounting will be correct,
and driver gets port replay of other ports when offloaded
port gets removed.
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ad166a8e
...@@ -176,50 +176,18 @@ static void enic_unset_affinity_hint(struct enic *enic) ...@@ -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, ...@@ -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 = { ...@@ -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 = { ...@@ -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) ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment