aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHadar Hen Zion <hadarh@mellanox.co.il>2012-07-05 00:03:44 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-07 19:23:05 -0400
commitc96d97f4d127b61def87b3ee056bec20cfc265d1 (patch)
tree84c89ead71dd4f7a0795aa703b60bb5c5eb2d5a4
parent6d19993788e080edb557178cc6aba2d963edce4e (diff)
net/mlx4: Set steering mode according to device capabilities
Instead of checking the firmware supported steering mode in various places in the code, add a dedicated field in the mlx4 device capabilities structure which is written once during the initialization flow and read across the code. This also set the grounds for add new steering modes. Currently two modes are supported, and are named after the ConnectX HW versions A0 and B0. A0 steering uses mac_index, vlan_index and priority to steer traffic into pre-defined range of QPs. B0 steering uses Ethernet L2 hashing rules and is enabled only if the firmware supports both unicast and multicast B0 steering, The current steering modes are relevant for Ethernet traffic only, such that Infiniband steering remains untouched. Signed-off-by: Hadar Hen Zion <hadarh@mellanox.co.il> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c108
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c16
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mcg.c70
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/port.c9
-rw-r--r--include/linux/mlx4/device.h24
6 files changed, 148 insertions, 81 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index bedcbb30d38f..44ff7cdb15e5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -265,7 +265,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
265 struct mlx4_en_mc_list *mclist, *tmp; 265 struct mlx4_en_mc_list *mclist, *tmp;
266 u64 mcast_addr = 0; 266 u64 mcast_addr = 0;
267 u8 mc_list[16] = {0}; 267 u8 mc_list[16] = {0};
268 int err; 268 int err = 0;
269 269
270 mutex_lock(&mdev->state_lock); 270 mutex_lock(&mdev->state_lock);
271 if (!mdev->device_up) { 271 if (!mdev->device_up) {
@@ -300,16 +300,36 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
300 priv->flags |= MLX4_EN_FLAG_PROMISC; 300 priv->flags |= MLX4_EN_FLAG_PROMISC;
301 301
302 /* Enable promiscouos mode */ 302 /* Enable promiscouos mode */
303 if (!(mdev->dev->caps.flags & 303 switch (mdev->dev->caps.steering_mode) {
304 MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) 304 case MLX4_STEERING_MODE_B0:
305 err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, 305 err = mlx4_unicast_promisc_add(mdev->dev,
306 priv->base_qpn, 1); 306 priv->base_qpn,
307 else
308 err = mlx4_unicast_promisc_add(mdev->dev, priv->base_qpn,
309 priv->port); 307 priv->port);
310 if (err) 308 if (err)
311 en_err(priv, "Failed enabling " 309 en_err(priv, "Failed enabling unicast promiscuous mode\n");
312 "promiscuous mode\n"); 310
311 /* Add the default qp number as multicast
312 * promisc
313 */
314 if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
315 err = mlx4_multicast_promisc_add(mdev->dev,
316 priv->base_qpn,
317 priv->port);
318 if (err)
319 en_err(priv, "Failed enabling multicast promiscuous mode\n");
320 priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
321 }
322 break;
323
324 case MLX4_STEERING_MODE_A0:
325 err = mlx4_SET_PORT_qpn_calc(mdev->dev,
326 priv->port,
327 priv->base_qpn,
328 1);
329 if (err)
330 en_err(priv, "Failed enabling promiscuous mode\n");
331 break;
332 }
313 333
314 /* Disable port multicast filter (unconditionally) */ 334 /* Disable port multicast filter (unconditionally) */
315 err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 335 err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
@@ -318,15 +338,6 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
318 en_err(priv, "Failed disabling " 338 en_err(priv, "Failed disabling "
319 "multicast filter\n"); 339 "multicast filter\n");
320 340
321 /* Add the default qp number as multicast promisc */
322 if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
323 err = mlx4_multicast_promisc_add(mdev->dev, priv->base_qpn,
324 priv->port);
325 if (err)
326 en_err(priv, "Failed entering multicast promisc mode\n");
327 priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
328 }
329
330 /* Disable port VLAN filter */ 341 /* Disable port VLAN filter */
331 err = mlx4_SET_VLAN_FLTR(mdev->dev, priv); 342 err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
332 if (err) 343 if (err)
@@ -345,22 +356,31 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
345 priv->flags &= ~MLX4_EN_FLAG_PROMISC; 356 priv->flags &= ~MLX4_EN_FLAG_PROMISC;
346 357
347 /* Disable promiscouos mode */ 358 /* Disable promiscouos mode */
348 if (!(mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) 359 switch (mdev->dev->caps.steering_mode) {
349 err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, 360 case MLX4_STEERING_MODE_B0:
350 priv->base_qpn, 0); 361 err = mlx4_unicast_promisc_remove(mdev->dev,
351 else 362 priv->base_qpn,
352 err = mlx4_unicast_promisc_remove(mdev->dev, priv->base_qpn,
353 priv->port); 363 priv->port);
354 if (err) 364 if (err)
355 en_err(priv, "Failed disabling promiscuous mode\n"); 365 en_err(priv, "Failed disabling unicast promiscuous mode\n");
366 /* Disable Multicast promisc */
367 if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
368 err = mlx4_multicast_promisc_remove(mdev->dev,
369 priv->base_qpn,
370 priv->port);
371 if (err)
372 en_err(priv, "Failed disabling multicast promiscuous mode\n");
373 priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
374 }
375 break;
356 376
357 /* Disable Multicast promisc */ 377 case MLX4_STEERING_MODE_A0:
358 if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) { 378 err = mlx4_SET_PORT_qpn_calc(mdev->dev,
359 err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn, 379 priv->port,
360 priv->port); 380 priv->base_qpn, 0);
361 if (err) 381 if (err)
362 en_err(priv, "Failed disabling multicast promiscuous mode\n"); 382 en_err(priv, "Failed disabling promiscuous mode\n");
363 priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC; 383 break;
364 } 384 }
365 385
366 /* Enable port VLAN filter */ 386 /* Enable port VLAN filter */
@@ -378,8 +398,16 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
378 398
379 /* Add the default qp number as multicast promisc */ 399 /* Add the default qp number as multicast promisc */
380 if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) { 400 if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
381 err = mlx4_multicast_promisc_add(mdev->dev, priv->base_qpn, 401 switch (mdev->dev->caps.steering_mode) {
382 priv->port); 402 case MLX4_STEERING_MODE_B0:
403 err = mlx4_multicast_promisc_add(mdev->dev,
404 priv->base_qpn,
405 priv->port);
406 break;
407
408 case MLX4_STEERING_MODE_A0:
409 break;
410 }
383 if (err) 411 if (err)
384 en_err(priv, "Failed entering multicast promisc mode\n"); 412 en_err(priv, "Failed entering multicast promisc mode\n");
385 priv->flags |= MLX4_EN_FLAG_MC_PROMISC; 413 priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
@@ -387,8 +415,16 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
387 } else { 415 } else {
388 /* Disable Multicast promisc */ 416 /* Disable Multicast promisc */
389 if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) { 417 if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
390 err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn, 418 switch (mdev->dev->caps.steering_mode) {
391 priv->port); 419 case MLX4_STEERING_MODE_B0:
420 err = mlx4_multicast_promisc_remove(mdev->dev,
421 priv->base_qpn,
422 priv->port);
423 break;
424
425 case MLX4_STEERING_MODE_A0:
426 break;
427 }
392 if (err) 428 if (err)
393 en_err(priv, "Failed disabling multicast promiscuous mode\n"); 429 en_err(priv, "Failed disabling multicast promiscuous mode\n");
394 priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC; 430 priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index 9c83bb8151ea..40e048bac024 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -1124,7 +1124,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
1124 MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET); 1124 MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET);
1125 MLX4_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); 1125 MLX4_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
1126 MLX4_PUT(inbox, param->log_mc_hash_sz, INIT_HCA_LOG_MC_HASH_SZ_OFFSET); 1126 MLX4_PUT(inbox, param->log_mc_hash_sz, INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
1127 if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) 1127 if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0)
1128 MLX4_PUT(inbox, (u8) (1 << 3), INIT_HCA_UC_STEERING_OFFSET); 1128 MLX4_PUT(inbox, (u8) (1 << 3), INIT_HCA_UC_STEERING_OFFSET);
1129 MLX4_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); 1129 MLX4_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
1130 1130
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 14d9c762b60f..f8125a82c0cb 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -244,7 +244,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
244 dev->caps.reserved_srqs = dev_cap->reserved_srqs; 244 dev->caps.reserved_srqs = dev_cap->reserved_srqs;
245 dev->caps.max_sq_desc_sz = dev_cap->max_sq_desc_sz; 245 dev->caps.max_sq_desc_sz = dev_cap->max_sq_desc_sz;
246 dev->caps.max_rq_desc_sz = dev_cap->max_rq_desc_sz; 246 dev->caps.max_rq_desc_sz = dev_cap->max_rq_desc_sz;
247 dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev);
248 /* 247 /*
249 * Subtract 1 from the limit because we need to allocate a 248 * Subtract 1 from the limit because we need to allocate a
250 * spare CQE so the HCA HW can tell the difference between an 249 * spare CQE so the HCA HW can tell the difference between an
@@ -275,6 +274,21 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
275 dev->caps.max_gso_sz = dev_cap->max_gso_sz; 274 dev->caps.max_gso_sz = dev_cap->max_gso_sz;
276 dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz; 275 dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz;
277 276
277 if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER &&
278 dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) {
279 dev->caps.steering_mode = MLX4_STEERING_MODE_B0;
280 } else {
281 dev->caps.steering_mode = MLX4_STEERING_MODE_A0;
282
283 if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER ||
284 dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)
285 mlx4_warn(dev, "Must have UC_STEER and MC_STEER flags "
286 "set to use B0 steering. Falling back to A0 steering mode.\n");
287 }
288 mlx4_dbg(dev, "Steering mode is: %s\n",
289 mlx4_steering_mode_str(dev->caps.steering_mode));
290 dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev);
291
278 /* Sense port always allowed on supported devices for ConnectX1 and 2 */ 292 /* Sense port always allowed on supported devices for ConnectX1 and 2 */
279 if (dev->pdev->device != 0x1003) 293 if (dev->pdev->device != 0x1003)
280 dev->caps.flags |= MLX4_DEV_CAP_FLAG_SENSE_SUPPORT; 294 dev->caps.flags |= MLX4_DEV_CAP_FLAG_SENSE_SUPPORT;
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c
index f4a8f98e402a..319c9d45d59a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mcg.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c
@@ -868,36 +868,50 @@ static int mlx4_QP_ATTACH(struct mlx4_dev *dev, struct mlx4_qp *qp,
868int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], 868int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
869 int block_mcast_loopback, enum mlx4_protocol prot) 869 int block_mcast_loopback, enum mlx4_protocol prot)
870{ 870{
871 if (prot == MLX4_PROT_ETH &&
872 !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
873 return 0;
874 871
875 if (prot == MLX4_PROT_ETH) 872 switch (dev->caps.steering_mode) {
876 gid[7] |= (MLX4_MC_STEER << 1); 873 case MLX4_STEERING_MODE_A0:
874 if (prot == MLX4_PROT_ETH)
875 return 0;
877 876
878 if (mlx4_is_mfunc(dev)) 877 case MLX4_STEERING_MODE_B0:
879 return mlx4_QP_ATTACH(dev, qp, gid, 1, 878 if (prot == MLX4_PROT_ETH)
880 block_mcast_loopback, prot); 879 gid[7] |= (MLX4_MC_STEER << 1);
881 880
882 return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback, 881 if (mlx4_is_mfunc(dev))
883 prot, MLX4_MC_STEER); 882 return mlx4_QP_ATTACH(dev, qp, gid, 1,
883 block_mcast_loopback, prot);
884 return mlx4_qp_attach_common(dev, qp, gid,
885 block_mcast_loopback, prot,
886 MLX4_MC_STEER);
887
888 default:
889 return -EINVAL;
890 }
884} 891}
885EXPORT_SYMBOL_GPL(mlx4_multicast_attach); 892EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
886 893
887int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], 894int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
888 enum mlx4_protocol prot) 895 enum mlx4_protocol prot)
889{ 896{
890 if (prot == MLX4_PROT_ETH && 897 switch (dev->caps.steering_mode) {
891 !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) 898 case MLX4_STEERING_MODE_A0:
892 return 0; 899 if (prot == MLX4_PROT_ETH)
900 return 0;
893 901
894 if (prot == MLX4_PROT_ETH) 902 case MLX4_STEERING_MODE_B0:
895 gid[7] |= (MLX4_MC_STEER << 1); 903 if (prot == MLX4_PROT_ETH)
904 gid[7] |= (MLX4_MC_STEER << 1);
896 905
897 if (mlx4_is_mfunc(dev)) 906 if (mlx4_is_mfunc(dev))
898 return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot); 907 return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot);
908
909 return mlx4_qp_detach_common(dev, qp, gid, prot,
910 MLX4_MC_STEER);
899 911
900 return mlx4_qp_detach_common(dev, qp, gid, prot, MLX4_MC_STEER); 912 default:
913 return -EINVAL;
914 }
901} 915}
902EXPORT_SYMBOL_GPL(mlx4_multicast_detach); 916EXPORT_SYMBOL_GPL(mlx4_multicast_detach);
903 917
@@ -905,10 +919,6 @@ int mlx4_unicast_attach(struct mlx4_dev *dev,
905 struct mlx4_qp *qp, u8 gid[16], 919 struct mlx4_qp *qp, u8 gid[16],
906 int block_mcast_loopback, enum mlx4_protocol prot) 920 int block_mcast_loopback, enum mlx4_protocol prot)
907{ 921{
908 if (prot == MLX4_PROT_ETH &&
909 !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
910 return 0;
911
912 if (prot == MLX4_PROT_ETH) 922 if (prot == MLX4_PROT_ETH)
913 gid[7] |= (MLX4_UC_STEER << 1); 923 gid[7] |= (MLX4_UC_STEER << 1);
914 924
@@ -924,10 +934,6 @@ EXPORT_SYMBOL_GPL(mlx4_unicast_attach);
924int mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, 934int mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp,
925 u8 gid[16], enum mlx4_protocol prot) 935 u8 gid[16], enum mlx4_protocol prot)
926{ 936{
927 if (prot == MLX4_PROT_ETH &&
928 !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
929 return 0;
930
931 if (prot == MLX4_PROT_ETH) 937 if (prot == MLX4_PROT_ETH)
932 gid[7] |= (MLX4_UC_STEER << 1); 938 gid[7] |= (MLX4_UC_STEER << 1);
933 939
@@ -968,9 +974,6 @@ static int mlx4_PROMISC(struct mlx4_dev *dev, u32 qpn,
968 974
969int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port) 975int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
970{ 976{
971 if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
972 return 0;
973
974 if (mlx4_is_mfunc(dev)) 977 if (mlx4_is_mfunc(dev))
975 return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 1, port); 978 return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 1, port);
976 979
@@ -980,9 +983,6 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add);
980 983
981int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port) 984int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
982{ 985{
983 if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
984 return 0;
985
986 if (mlx4_is_mfunc(dev)) 986 if (mlx4_is_mfunc(dev))
987 return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 0, port); 987 return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 0, port);
988 988
@@ -992,9 +992,6 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove);
992 992
993int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port) 993int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
994{ 994{
995 if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
996 return 0;
997
998 if (mlx4_is_mfunc(dev)) 995 if (mlx4_is_mfunc(dev))
999 return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 1, port); 996 return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 1, port);
1000 997
@@ -1004,9 +1001,6 @@ EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add);
1004 1001
1005int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port) 1002int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
1006{ 1003{
1007 if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
1008 return 0;
1009
1010 if (mlx4_is_mfunc(dev)) 1004 if (mlx4_is_mfunc(dev))
1011 return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 0, port); 1005 return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 0, port);
1012 1006
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c
index a8fb52992c64..58de7237f57a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/port.c
@@ -155,7 +155,7 @@ int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn)
155 return err; 155 return err;
156 } 156 }
157 157
158 if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) { 158 if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
159 *qpn = info->base_qpn + index; 159 *qpn = info->base_qpn + index;
160 return 0; 160 return 0;
161 } 161 }
@@ -206,7 +206,7 @@ void mlx4_put_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int qpn)
206 (unsigned long long) mac); 206 (unsigned long long) mac);
207 mlx4_unregister_mac(dev, port, mac); 207 mlx4_unregister_mac(dev, port, mac);
208 208
209 if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { 209 if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) {
210 entry = radix_tree_lookup(&info->mac_tree, qpn); 210 entry = radix_tree_lookup(&info->mac_tree, qpn);
211 if (entry) { 211 if (entry) {
212 mlx4_dbg(dev, "Releasing qp: port %d, mac 0x%llx," 212 mlx4_dbg(dev, "Releasing qp: port %d, mac 0x%llx,"
@@ -359,7 +359,7 @@ int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac)
359 int index = qpn - info->base_qpn; 359 int index = qpn - info->base_qpn;
360 int err = 0; 360 int err = 0;
361 361
362 if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { 362 if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) {
363 entry = radix_tree_lookup(&info->mac_tree, qpn); 363 entry = radix_tree_lookup(&info->mac_tree, qpn);
364 if (!entry) 364 if (!entry)
365 return -EINVAL; 365 return -EINVAL;
@@ -803,8 +803,7 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
803 u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ? 803 u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ?
804 MCAST_DIRECT : MCAST_DEFAULT; 804 MCAST_DIRECT : MCAST_DEFAULT;
805 805
806 if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER && 806 if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0)
807 dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)
808 return 0; 807 return 0;
809 808
810 mailbox = mlx4_alloc_cmd_mailbox(dev); 809 mailbox = mlx4_alloc_cmd_mailbox(dev);
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 6a8f002b8ed3..7f5c9ee42f96 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -70,6 +70,29 @@ enum {
70 MLX4_MFUNC_EQE_MASK = (MLX4_MFUNC_MAX_EQES - 1) 70 MLX4_MFUNC_EQE_MASK = (MLX4_MFUNC_MAX_EQES - 1)
71}; 71};
72 72
73/* Driver supports 2 diffrent device methods to manage traffic steering:
74 * - B0 steering mode - Common low level API for ib and (if supported) eth.
75 * - A0 steering mode - Limited low level API for eth. In case of IB,
76 * B0 mode is in use.
77 */
78enum {
79 MLX4_STEERING_MODE_A0,
80 MLX4_STEERING_MODE_B0
81};
82
83static inline const char *mlx4_steering_mode_str(int steering_mode)
84{
85 switch (steering_mode) {
86 case MLX4_STEERING_MODE_A0:
87 return "A0 steering";
88
89 case MLX4_STEERING_MODE_B0:
90 return "B0 steering";
91 default:
92 return "Unrecognize steering mode";
93 }
94}
95
73enum { 96enum {
74 MLX4_DEV_CAP_FLAG_RC = 1LL << 0, 97 MLX4_DEV_CAP_FLAG_RC = 1LL << 0,
75 MLX4_DEV_CAP_FLAG_UC = 1LL << 1, 98 MLX4_DEV_CAP_FLAG_UC = 1LL << 1,
@@ -295,6 +318,7 @@ struct mlx4_caps {
295 int num_amgms; 318 int num_amgms;
296 int reserved_mcgs; 319 int reserved_mcgs;
297 int num_qp_per_mgm; 320 int num_qp_per_mgm;
321 int steering_mode;
298 int num_pds; 322 int num_pds;
299 int reserved_pds; 323 int reserved_pds;
300 int max_xrcds; 324 int max_xrcds;