aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorOr Gerlitz <ogerlitz@mellanox.com>2014-03-27 08:02:04 -0400
committerDavid S. Miller <davem@davemloft.net>2014-03-28 16:29:35 -0400
commit1b136de120dda625109f2afe1e3d04e256be9ec1 (patch)
tree321fa0738eb04cffe07abb89b7f06759f062f64c /drivers
parentd18f141a1a7cfa5ffad8433e43062b05a8d1b82a (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')
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c86
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_en.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/port.c5
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
2270static 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);
2282out:
2283 if (ret)
2284 en_err(priv, "failed setting L2 tunnel configuration ret %d\n", ret);
2285}
2286
2287static 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
2301static 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
2324static 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
2267static const struct net_device_ops mlx4_netdev_ops = { 2345static 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
2295static const struct net_device_ops mlx4_netdev_ops_master = { 2375static 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
590enum mlx4_en_wol { 593enum 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
991int mlx4_SET_PORT_VXLAN(struct mlx4_dev *dev, u8 port, u8 steering) 991int 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;