diff options
author | Or Gerlitz <ogerlitz@mellanox.com> | 2014-03-27 08:02:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-03-28 16:29:35 -0400 |
commit | 1b136de120dda625109f2afe1e3d04e256be9ec1 (patch) | |
tree | 321fa0738eb04cffe07abb89b7f06759f062f64c /drivers/net/ethernet/mellanox/mlx4 | |
parent | d18f141a1a7cfa5ffad8433e43062b05a8d1b82a (diff) |
net/mlx4: Implement vxlan ndo calls
Add implementation for the add/del vxlan port ndo calls, using the
CONFIG_DEV firmware command.
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 86 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/port.c | 5 |
3 files changed, 90 insertions, 4 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index fa5ee719e04b..82d7eb5b79cc 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/hash.h> | 39 | #include <linux/hash.h> |
40 | #include <net/ip.h> | 40 | #include <net/ip.h> |
41 | #include <net/busy_poll.h> | 41 | #include <net/busy_poll.h> |
42 | #include <net/vxlan.h> | ||
42 | 43 | ||
43 | #include <linux/mlx4/driver.h> | 44 | #include <linux/mlx4/driver.h> |
44 | #include <linux/mlx4/device.h> | 45 | #include <linux/mlx4/device.h> |
@@ -1665,7 +1666,7 @@ int mlx4_en_start_port(struct net_device *dev) | |||
1665 | } | 1666 | } |
1666 | 1667 | ||
1667 | if (mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) { | 1668 | if (mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) { |
1668 | err = mlx4_SET_PORT_VXLAN(mdev->dev, priv->port, VXLAN_STEER_BY_OUTER_MAC); | 1669 | err = mlx4_SET_PORT_VXLAN(mdev->dev, priv->port, VXLAN_STEER_BY_OUTER_MAC, 1); |
1669 | if (err) { | 1670 | if (err) { |
1670 | en_err(priv, "Failed setting port L2 tunnel configuration, err %d\n", | 1671 | en_err(priv, "Failed setting port L2 tunnel configuration, err %d\n", |
1671 | err); | 1672 | err); |
@@ -1697,6 +1698,8 @@ int mlx4_en_start_port(struct net_device *dev) | |||
1697 | 1698 | ||
1698 | mlx4_set_stats_bitmap(mdev->dev, &priv->stats_bitmap); | 1699 | mlx4_set_stats_bitmap(mdev->dev, &priv->stats_bitmap); |
1699 | 1700 | ||
1701 | if (priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS) | ||
1702 | vxlan_get_rx_port(dev); | ||
1700 | priv->port_up = true; | 1703 | priv->port_up = true; |
1701 | netif_tx_start_all_queues(dev); | 1704 | netif_tx_start_all_queues(dev); |
1702 | netif_device_attach(dev); | 1705 | netif_device_attach(dev); |
@@ -2264,6 +2267,81 @@ static int mlx4_en_get_phys_port_id(struct net_device *dev, | |||
2264 | return 0; | 2267 | return 0; |
2265 | } | 2268 | } |
2266 | 2269 | ||
2270 | static void mlx4_en_add_vxlan_offloads(struct work_struct *work) | ||
2271 | { | ||
2272 | int ret; | ||
2273 | struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, | ||
2274 | vxlan_add_task); | ||
2275 | |||
2276 | ret = mlx4_config_vxlan_port(priv->mdev->dev, priv->vxlan_port); | ||
2277 | if (ret) | ||
2278 | goto out; | ||
2279 | |||
2280 | ret = mlx4_SET_PORT_VXLAN(priv->mdev->dev, priv->port, | ||
2281 | VXLAN_STEER_BY_OUTER_MAC, 1); | ||
2282 | out: | ||
2283 | if (ret) | ||
2284 | en_err(priv, "failed setting L2 tunnel configuration ret %d\n", ret); | ||
2285 | } | ||
2286 | |||
2287 | static void mlx4_en_del_vxlan_offloads(struct work_struct *work) | ||
2288 | { | ||
2289 | int ret; | ||
2290 | struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, | ||
2291 | vxlan_del_task); | ||
2292 | |||
2293 | ret = mlx4_SET_PORT_VXLAN(priv->mdev->dev, priv->port, | ||
2294 | VXLAN_STEER_BY_OUTER_MAC, 0); | ||
2295 | if (ret) | ||
2296 | en_err(priv, "failed setting L2 tunnel configuration ret %d\n", ret); | ||
2297 | |||
2298 | priv->vxlan_port = 0; | ||
2299 | } | ||
2300 | |||
2301 | static void mlx4_en_add_vxlan_port(struct net_device *dev, | ||
2302 | sa_family_t sa_family, __be16 port) | ||
2303 | { | ||
2304 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
2305 | __be16 current_port; | ||
2306 | |||
2307 | if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS)) | ||
2308 | return; | ||
2309 | |||
2310 | if (sa_family == AF_INET6) | ||
2311 | return; | ||
2312 | |||
2313 | current_port = priv->vxlan_port; | ||
2314 | if (current_port && current_port != port) { | ||
2315 | en_warn(priv, "vxlan port %d configured, can't add port %d\n", | ||
2316 | ntohs(current_port), ntohs(port)); | ||
2317 | return; | ||
2318 | } | ||
2319 | |||
2320 | priv->vxlan_port = port; | ||
2321 | queue_work(priv->mdev->workqueue, &priv->vxlan_add_task); | ||
2322 | } | ||
2323 | |||
2324 | static void mlx4_en_del_vxlan_port(struct net_device *dev, | ||
2325 | sa_family_t sa_family, __be16 port) | ||
2326 | { | ||
2327 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
2328 | __be16 current_port; | ||
2329 | |||
2330 | if (priv->mdev->dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) | ||
2331 | return; | ||
2332 | |||
2333 | if (sa_family == AF_INET6) | ||
2334 | return; | ||
2335 | |||
2336 | current_port = priv->vxlan_port; | ||
2337 | if (current_port != port) { | ||
2338 | en_dbg(DRV, priv, "vxlan port %d isn't configured, ignoring\n", ntohs(port)); | ||
2339 | return; | ||
2340 | } | ||
2341 | |||
2342 | queue_work(priv->mdev->workqueue, &priv->vxlan_del_task); | ||
2343 | } | ||
2344 | |||
2267 | static const struct net_device_ops mlx4_netdev_ops = { | 2345 | static const struct net_device_ops mlx4_netdev_ops = { |
2268 | .ndo_open = mlx4_en_open, | 2346 | .ndo_open = mlx4_en_open, |
2269 | .ndo_stop = mlx4_en_close, | 2347 | .ndo_stop = mlx4_en_close, |
@@ -2290,6 +2368,8 @@ static const struct net_device_ops mlx4_netdev_ops = { | |||
2290 | .ndo_busy_poll = mlx4_en_low_latency_recv, | 2368 | .ndo_busy_poll = mlx4_en_low_latency_recv, |
2291 | #endif | 2369 | #endif |
2292 | .ndo_get_phys_port_id = mlx4_en_get_phys_port_id, | 2370 | .ndo_get_phys_port_id = mlx4_en_get_phys_port_id, |
2371 | .ndo_add_vxlan_port = mlx4_en_add_vxlan_port, | ||
2372 | .ndo_del_vxlan_port = mlx4_en_del_vxlan_port, | ||
2293 | }; | 2373 | }; |
2294 | 2374 | ||
2295 | static const struct net_device_ops mlx4_netdev_ops_master = { | 2375 | static const struct net_device_ops mlx4_netdev_ops_master = { |
@@ -2381,6 +2461,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, | |||
2381 | INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate); | 2461 | INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate); |
2382 | INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats); | 2462 | INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats); |
2383 | INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task); | 2463 | INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task); |
2464 | INIT_WORK(&priv->vxlan_add_task, mlx4_en_add_vxlan_offloads); | ||
2465 | INIT_WORK(&priv->vxlan_del_task, mlx4_en_del_vxlan_offloads); | ||
2384 | #ifdef CONFIG_MLX4_EN_DCB | 2466 | #ifdef CONFIG_MLX4_EN_DCB |
2385 | if (!mlx4_is_slave(priv->mdev->dev)) { | 2467 | if (!mlx4_is_slave(priv->mdev->dev)) { |
2386 | if (mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_SET_ETH_SCHED) { | 2468 | if (mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_SET_ETH_SCHED) { |
@@ -2514,7 +2596,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, | |||
2514 | } | 2596 | } |
2515 | 2597 | ||
2516 | if (mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) { | 2598 | if (mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) { |
2517 | err = mlx4_SET_PORT_VXLAN(mdev->dev, priv->port, VXLAN_STEER_BY_OUTER_MAC); | 2599 | err = mlx4_SET_PORT_VXLAN(mdev->dev, priv->port, VXLAN_STEER_BY_OUTER_MAC, 1); |
2518 | if (err) { | 2600 | if (err) { |
2519 | en_err(priv, "Failed setting port L2 tunnel configuration, err %d\n", | 2601 | en_err(priv, "Failed setting port L2 tunnel configuration, err %d\n", |
2520 | err); | 2602 | err); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 69e1f36858e0..36fc2a2b24c3 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | |||
@@ -559,6 +559,8 @@ struct mlx4_en_priv { | |||
559 | struct work_struct linkstate_task; | 559 | struct work_struct linkstate_task; |
560 | struct delayed_work stats_task; | 560 | struct delayed_work stats_task; |
561 | struct delayed_work service_task; | 561 | struct delayed_work service_task; |
562 | struct work_struct vxlan_add_task; | ||
563 | struct work_struct vxlan_del_task; | ||
562 | struct mlx4_en_perf_stats pstats; | 564 | struct mlx4_en_perf_stats pstats; |
563 | struct mlx4_en_pkt_stats pkstats; | 565 | struct mlx4_en_pkt_stats pkstats; |
564 | struct mlx4_en_port_stats port_stats; | 566 | struct mlx4_en_port_stats port_stats; |
@@ -585,6 +587,7 @@ struct mlx4_en_priv { | |||
585 | struct hlist_head filter_hash[1 << MLX4_EN_FILTER_HASH_SHIFT]; | 587 | struct hlist_head filter_hash[1 << MLX4_EN_FILTER_HASH_SHIFT]; |
586 | #endif | 588 | #endif |
587 | u64 tunnel_reg_id; | 589 | u64 tunnel_reg_id; |
590 | __be16 vxlan_port; | ||
588 | }; | 591 | }; |
589 | 592 | ||
590 | enum mlx4_en_wol { | 593 | enum mlx4_en_wol { |
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c index 2705b9ab9463..cfcad26ed40f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/drivers/net/ethernet/mellanox/mlx4/port.c | |||
@@ -988,7 +988,7 @@ struct mlx4_set_port_vxlan_context { | |||
988 | u8 steering; | 988 | u8 steering; |
989 | }; | 989 | }; |
990 | 990 | ||
991 | int mlx4_SET_PORT_VXLAN(struct mlx4_dev *dev, u8 port, u8 steering) | 991 | int mlx4_SET_PORT_VXLAN(struct mlx4_dev *dev, u8 port, u8 steering, int enable) |
992 | { | 992 | { |
993 | int err; | 993 | int err; |
994 | u32 in_mod; | 994 | u32 in_mod; |
@@ -1002,7 +1002,8 @@ int mlx4_SET_PORT_VXLAN(struct mlx4_dev *dev, u8 port, u8 steering) | |||
1002 | memset(context, 0, sizeof(*context)); | 1002 | memset(context, 0, sizeof(*context)); |
1003 | 1003 | ||
1004 | context->modify_flags = VXLAN_ENABLE_MODIFY | VXLAN_STEERING_MODIFY; | 1004 | context->modify_flags = VXLAN_ENABLE_MODIFY | VXLAN_STEERING_MODIFY; |
1005 | context->enable_flags = VXLAN_ENABLE; | 1005 | if (enable) |
1006 | context->enable_flags = VXLAN_ENABLE; | ||
1006 | context->steering = steering; | 1007 | context->steering = steering; |
1007 | 1008 | ||
1008 | in_mod = MLX4_SET_PORT_VXLAN << 8 | port; | 1009 | in_mod = MLX4_SET_PORT_VXLAN << 8 | port; |