aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2020-07-14 12:18:20 -0700
committerDavid S. Miller <davem@davemloft.net>2020-07-14 17:04:27 -0700
commit8f0545d232ca4eb1449584c68725d02f03a1d1a9 (patch)
treef8c25b1edc8c23deee5a3799cd920e1639f1d894
parentnfp: convert to new udp_tunnel_nic infra (diff)
downloadlinux-dev-8f0545d232ca4eb1449584c68725d02f03a1d1a9.tar.xz
linux-dev-8f0545d232ca4eb1449584c68725d02f03a1d1a9.zip
be2net: convert to new udp_tunnel_nic infra
Convert be2net to new udp_tunnel_nic infra. NIC only takes one VxLAN port. Remove the port tracking using a list. The warning in be_work_del_vxlan_port() looked suspicious - like the driver expected ports to be removed in order of addition. be2net unregisters ports when going down and re-registers them (for skyhawk) when coming up, but it never checks if the device is up in the add_port / del_port callbacks. Make it use UDP_TUNNEL_NIC_INFO_OPEN_ONLY. Sadly this driver calls its own open/close functions directly so the udp_tunnel_nic_reset_ntf() workaround is needed. Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h5
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c198
2 files changed, 38 insertions, 165 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 6e9022083004..8689d4a51fe5 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -654,8 +654,6 @@ struct be_adapter {
u8 hba_port_num;
u16 pvid;
__be16 vxlan_port; /* offloaded vxlan port num */
- int vxlan_port_count; /* active vxlan port count */
- struct list_head vxlan_port_list; /* vxlan port list */
struct phy_info phy;
u8 wol_cap;
bool wol_en;
@@ -679,9 +677,6 @@ struct be_adapter {
struct be_cmd_work {
struct work_struct work;
struct be_adapter *adapter;
- union {
- __be16 vxlan_port;
- } info;
};
#define be_physfn(adapter) (!adapter->virtfn)
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index e26f59336cfd..676e437d78f6 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -3829,8 +3829,8 @@ static int be_open(struct net_device *netdev)
be_link_status_update(adapter, link_status);
netif_tx_start_all_queues(netdev);
- if (skyhawk_chip(adapter))
- udp_tunnel_get_rx_info(netdev);
+
+ udp_tunnel_nic_reset_ntf(netdev);
return 0;
err:
@@ -3967,18 +3967,23 @@ static void be_cancel_err_detection(struct be_adapter *adapter)
}
}
-static int be_enable_vxlan_offloads(struct be_adapter *adapter)
+/* VxLAN offload Notes:
+ *
+ * The stack defines tunnel offload flags (hw_enc_features) for IP and doesn't
+ * distinguish various types of transports (VxLAN, GRE, NVGRE ..). So, offload
+ * is expected to work across all types of IP tunnels once exported. Skyhawk
+ * supports offloads for either VxLAN or NVGRE, exclusively. So we export VxLAN
+ * offloads in hw_enc_features only when a VxLAN port is added. If other (non
+ * VxLAN) tunnels are configured while VxLAN offloads are enabled, offloads for
+ * those other tunnels are unexported on the fly through ndo_features_check().
+ */
+static int be_vxlan_set_port(struct net_device *netdev, unsigned int table,
+ unsigned int entry, struct udp_tunnel_info *ti)
{
- struct net_device *netdev = adapter->netdev;
+ struct be_adapter *adapter = netdev_priv(netdev);
struct device *dev = &adapter->pdev->dev;
- struct be_vxlan_port *vxlan_port;
- __be16 port;
int status;
- vxlan_port = list_first_entry(&adapter->vxlan_port_list,
- struct be_vxlan_port, list);
- port = vxlan_port->port;
-
status = be_cmd_manage_iface(adapter, adapter->if_handle,
OP_CONVERT_NORMAL_TO_TUNNEL);
if (status) {
@@ -3987,25 +3992,26 @@ static int be_enable_vxlan_offloads(struct be_adapter *adapter)
}
adapter->flags |= BE_FLAGS_VXLAN_OFFLOADS;
- status = be_cmd_set_vxlan_port(adapter, port);
+ status = be_cmd_set_vxlan_port(adapter, ti->port);
if (status) {
dev_warn(dev, "Failed to add VxLAN port\n");
return status;
}
- adapter->vxlan_port = port;
+ adapter->vxlan_port = ti->port;
netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_TSO | NETIF_F_TSO6 |
NETIF_F_GSO_UDP_TUNNEL;
dev_info(dev, "Enabled VxLAN offloads for UDP port %d\n",
- be16_to_cpu(port));
+ be16_to_cpu(ti->port));
return 0;
}
-static void be_disable_vxlan_offloads(struct be_adapter *adapter)
+static int be_vxlan_unset_port(struct net_device *netdev, unsigned int table,
+ unsigned int entry, struct udp_tunnel_info *ti)
{
- struct net_device *netdev = adapter->netdev;
+ struct be_adapter *adapter = netdev_priv(netdev);
if (adapter->flags & BE_FLAGS_VXLAN_OFFLOADS)
be_cmd_manage_iface(adapter, adapter->if_handle,
@@ -4018,8 +4024,19 @@ static void be_disable_vxlan_offloads(struct be_adapter *adapter)
adapter->vxlan_port = 0;
netdev->hw_enc_features = 0;
+ return 0;
}
+static const struct udp_tunnel_nic_info be_udp_tunnels = {
+ .set_port = be_vxlan_set_port,
+ .unset_port = be_vxlan_unset_port,
+ .flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP |
+ UDP_TUNNEL_NIC_INFO_OPEN_ONLY,
+ .tables = {
+ { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, },
+ },
+};
+
static void be_calculate_vf_res(struct be_adapter *adapter, u16 num_vfs,
struct be_resources *vft_res)
{
@@ -4135,7 +4152,7 @@ static int be_clear(struct be_adapter *adapter)
&vft_res);
}
- be_disable_vxlan_offloads(adapter);
+ be_vxlan_unset_port(adapter->netdev, 0, 0, NULL);
be_if_destroy(adapter);
@@ -5053,147 +5070,6 @@ static struct be_cmd_work *be_alloc_work(struct be_adapter *adapter,
return work;
}
-/* VxLAN offload Notes:
- *
- * The stack defines tunnel offload flags (hw_enc_features) for IP and doesn't
- * distinguish various types of transports (VxLAN, GRE, NVGRE ..). So, offload
- * is expected to work across all types of IP tunnels once exported. Skyhawk
- * supports offloads for either VxLAN or NVGRE, exclusively. So we export VxLAN
- * offloads in hw_enc_features only when a VxLAN port is added. If other (non
- * VxLAN) tunnels are configured while VxLAN offloads are enabled, offloads for
- * those other tunnels are unexported on the fly through ndo_features_check().
- *
- * Skyhawk supports VxLAN offloads only for one UDP dport. So, if the stack
- * adds more than one port, disable offloads and re-enable them again when
- * there's only one port left. We maintain a list of ports for this purpose.
- */
-static void be_work_add_vxlan_port(struct work_struct *work)
-{
- struct be_cmd_work *cmd_work =
- container_of(work, struct be_cmd_work, work);
- struct be_adapter *adapter = cmd_work->adapter;
- struct device *dev = &adapter->pdev->dev;
- __be16 port = cmd_work->info.vxlan_port;
- struct be_vxlan_port *vxlan_port;
- int status;
-
- /* Bump up the alias count if it is an existing port */
- list_for_each_entry(vxlan_port, &adapter->vxlan_port_list, list) {
- if (vxlan_port->port == port) {
- vxlan_port->port_aliases++;
- goto done;
- }
- }
-
- /* Add a new port to our list. We don't need a lock here since port
- * add/delete are done only in the context of a single-threaded work
- * queue (be_wq).
- */
- vxlan_port = kzalloc(sizeof(*vxlan_port), GFP_KERNEL);
- if (!vxlan_port)
- goto done;
-
- vxlan_port->port = port;
- INIT_LIST_HEAD(&vxlan_port->list);
- list_add_tail(&vxlan_port->list, &adapter->vxlan_port_list);
- adapter->vxlan_port_count++;
-
- if (adapter->flags & BE_FLAGS_VXLAN_OFFLOADS) {
- dev_info(dev,
- "Only one UDP port supported for VxLAN offloads\n");
- dev_info(dev, "Disabling VxLAN offloads\n");
- goto err;
- }
-
- if (adapter->vxlan_port_count > 1)
- goto done;
-
- status = be_enable_vxlan_offloads(adapter);
- if (!status)
- goto done;
-
-err:
- be_disable_vxlan_offloads(adapter);
-done:
- kfree(cmd_work);
- return;
-}
-
-static void be_work_del_vxlan_port(struct work_struct *work)
-{
- struct be_cmd_work *cmd_work =
- container_of(work, struct be_cmd_work, work);
- struct be_adapter *adapter = cmd_work->adapter;
- __be16 port = cmd_work->info.vxlan_port;
- struct be_vxlan_port *vxlan_port;
-
- /* Nothing to be done if a port alias is being deleted */
- list_for_each_entry(vxlan_port, &adapter->vxlan_port_list, list) {
- if (vxlan_port->port == port) {
- if (vxlan_port->port_aliases) {
- vxlan_port->port_aliases--;
- goto done;
- }
- break;
- }
- }
-
- /* No port aliases left; delete the port from the list */
- list_del(&vxlan_port->list);
- adapter->vxlan_port_count--;
-
- /* Disable VxLAN offload if this is the offloaded port */
- if (adapter->vxlan_port == vxlan_port->port) {
- WARN_ON(adapter->vxlan_port_count);
- be_disable_vxlan_offloads(adapter);
- dev_info(&adapter->pdev->dev,
- "Disabled VxLAN offloads for UDP port %d\n",
- be16_to_cpu(port));
- goto out;
- }
-
- /* If only 1 port is left, re-enable VxLAN offload */
- if (adapter->vxlan_port_count == 1)
- be_enable_vxlan_offloads(adapter);
-
-out:
- kfree(vxlan_port);
-done:
- kfree(cmd_work);
-}
-
-static void be_cfg_vxlan_port(struct net_device *netdev,
- struct udp_tunnel_info *ti,
- void (*func)(struct work_struct *))
-{
- struct be_adapter *adapter = netdev_priv(netdev);
- struct be_cmd_work *cmd_work;
-
- if (ti->type != UDP_TUNNEL_TYPE_VXLAN)
- return;
-
- if (lancer_chip(adapter) || BEx_chip(adapter) || be_is_mc(adapter))
- return;
-
- cmd_work = be_alloc_work(adapter, func);
- if (cmd_work) {
- cmd_work->info.vxlan_port = ti->port;
- queue_work(be_wq, &cmd_work->work);
- }
-}
-
-static void be_del_vxlan_port(struct net_device *netdev,
- struct udp_tunnel_info *ti)
-{
- be_cfg_vxlan_port(netdev, ti, be_work_del_vxlan_port);
-}
-
-static void be_add_vxlan_port(struct net_device *netdev,
- struct udp_tunnel_info *ti)
-{
- be_cfg_vxlan_port(netdev, ti, be_work_add_vxlan_port);
-}
-
static netdev_features_t be_features_check(struct sk_buff *skb,
struct net_device *dev,
netdev_features_t features)
@@ -5309,8 +5185,8 @@ static const struct net_device_ops be_netdev_ops = {
#endif
.ndo_bridge_setlink = be_ndo_bridge_setlink,
.ndo_bridge_getlink = be_ndo_bridge_getlink,
- .ndo_udp_tunnel_add = be_add_vxlan_port,
- .ndo_udp_tunnel_del = be_del_vxlan_port,
+ .ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
+ .ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
.ndo_features_check = be_features_check,
.ndo_get_phys_port_id = be_get_phys_port_id,
};
@@ -5342,6 +5218,9 @@ static void be_netdev_init(struct net_device *netdev)
netdev->ethtool_ops = &be_ethtool_ops;
+ if (!lancer_chip(adapter) && !BEx_chip(adapter) && !be_is_mc(adapter))
+ netdev->udp_tunnel_nic_info = &be_udp_tunnels;
+
/* MTU range: 256 - 9000 */
netdev->min_mtu = BE_MIN_MTU;
netdev->max_mtu = BE_MAX_MTU;
@@ -5819,7 +5698,6 @@ static int be_drv_init(struct be_adapter *adapter)
/* Must be a power of 2 or else MODULO will BUG_ON */
adapter->be_get_temp_freq = 64;
- INIT_LIST_HEAD(&adapter->vxlan_port_list);
return 0;
free_rx_filter: