Skip to content

Commit c96d97f

Browse files
Hadar Hen Ziondavem330
authored andcommitted
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 <[email protected]> Signed-off-by: Or Gerlitz <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6d19993 commit c96d97f

File tree

6 files changed

+148
-81
lines changed

6 files changed

+148
-81
lines changed

drivers/net/ethernet/mellanox/mlx4/en_netdev.c

Lines changed: 72 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
265265
struct mlx4_en_mc_list *mclist, *tmp;
266266
u64 mcast_addr = 0;
267267
u8 mc_list[16] = {0};
268-
int err;
268+
int err = 0;
269269

270270
mutex_lock(&mdev->state_lock);
271271
if (!mdev->device_up) {
@@ -300,16 +300,36 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
300300
priv->flags |= MLX4_EN_FLAG_PROMISC;
301301

302302
/* Enable promiscouos mode */
303-
if (!(mdev->dev->caps.flags &
304-
MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
305-
err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
306-
priv->base_qpn, 1);
307-
else
308-
err = mlx4_unicast_promisc_add(mdev->dev, priv->base_qpn,
303+
switch (mdev->dev->caps.steering_mode) {
304+
case MLX4_STEERING_MODE_B0:
305+
err = mlx4_unicast_promisc_add(mdev->dev,
306+
priv->base_qpn,
309307
priv->port);
310-
if (err)
311-
en_err(priv, "Failed enabling "
312-
"promiscuous mode\n");
308+
if (err)
309+
en_err(priv, "Failed enabling unicast 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+
}
313333

314334
/* Disable port multicast filter (unconditionally) */
315335
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)
318338
en_err(priv, "Failed disabling "
319339
"multicast filter\n");
320340

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-
330341
/* Disable port VLAN filter */
331342
err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
332343
if (err)
@@ -345,22 +356,31 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
345356
priv->flags &= ~MLX4_EN_FLAG_PROMISC;
346357

347358
/* Disable promiscouos mode */
348-
if (!(mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
349-
err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
350-
priv->base_qpn, 0);
351-
else
352-
err = mlx4_unicast_promisc_remove(mdev->dev, priv->base_qpn,
359+
switch (mdev->dev->caps.steering_mode) {
360+
case MLX4_STEERING_MODE_B0:
361+
err = mlx4_unicast_promisc_remove(mdev->dev,
362+
priv->base_qpn,
353363
priv->port);
354-
if (err)
355-
en_err(priv, "Failed disabling promiscuous mode\n");
364+
if (err)
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;
356376

357-
/* Disable Multicast promisc */
358-
if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
359-
err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
360-
priv->port);
377+
case MLX4_STEERING_MODE_A0:
378+
err = mlx4_SET_PORT_qpn_calc(mdev->dev,
379+
priv->port,
380+
priv->base_qpn, 0);
361381
if (err)
362-
en_err(priv, "Failed disabling multicast promiscuous mode\n");
363-
priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
382+
en_err(priv, "Failed disabling promiscuous mode\n");
383+
break;
364384
}
365385

366386
/* Enable port VLAN filter */
@@ -378,17 +398,33 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
378398

379399
/* Add the default qp number as multicast promisc */
380400
if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
381-
err = mlx4_multicast_promisc_add(mdev->dev, priv->base_qpn,
382-
priv->port);
401+
switch (mdev->dev->caps.steering_mode) {
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+
}
383411
if (err)
384412
en_err(priv, "Failed entering multicast promisc mode\n");
385413
priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
386414
}
387415
} else {
388416
/* Disable Multicast promisc */
389417
if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
390-
err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
391-
priv->port);
418+
switch (mdev->dev->caps.steering_mode) {
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+
}
392428
if (err)
393429
en_err(priv, "Failed disabling multicast promiscuous mode\n");
394430
priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;

drivers/net/ethernet/mellanox/mlx4/fw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
11241124
MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET);
11251125
MLX4_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
11261126
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)
11281128
MLX4_PUT(inbox, (u8) (1 << 3), INIT_HCA_UC_STEERING_OFFSET);
11291129
MLX4_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
11301130

drivers/net/ethernet/mellanox/mlx4/main.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
244244
dev->caps.reserved_srqs = dev_cap->reserved_srqs;
245245
dev->caps.max_sq_desc_sz = dev_cap->max_sq_desc_sz;
246246
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);
248247
/*
249248
* Subtract 1 from the limit because we need to allocate a
250249
* 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)
275274
dev->caps.max_gso_sz = dev_cap->max_gso_sz;
276275
dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz;
277276

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+
278292
/* Sense port always allowed on supported devices for ConnectX1 and 2 */
279293
if (dev->pdev->device != 0x1003)
280294
dev->caps.flags |= MLX4_DEV_CAP_FLAG_SENSE_SUPPORT;

drivers/net/ethernet/mellanox/mlx4/mcg.c

Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -868,47 +868,57 @@ static int mlx4_QP_ATTACH(struct mlx4_dev *dev, struct mlx4_qp *qp,
868868
int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
869869
int block_mcast_loopback, enum mlx4_protocol prot)
870870
{
871-
if (prot == MLX4_PROT_ETH &&
872-
!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
873-
return 0;
874871

875-
if (prot == MLX4_PROT_ETH)
876-
gid[7] |= (MLX4_MC_STEER << 1);
872+
switch (dev->caps.steering_mode) {
873+
case MLX4_STEERING_MODE_A0:
874+
if (prot == MLX4_PROT_ETH)
875+
return 0;
877876

878-
if (mlx4_is_mfunc(dev))
879-
return mlx4_QP_ATTACH(dev, qp, gid, 1,
880-
block_mcast_loopback, prot);
877+
case MLX4_STEERING_MODE_B0:
878+
if (prot == MLX4_PROT_ETH)
879+
gid[7] |= (MLX4_MC_STEER << 1);
881880

882-
return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback,
883-
prot, MLX4_MC_STEER);
881+
if (mlx4_is_mfunc(dev))
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+
}
884891
}
885892
EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
886893

887894
int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
888895
enum mlx4_protocol prot)
889896
{
890-
if (prot == MLX4_PROT_ETH &&
891-
!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
892-
return 0;
897+
switch (dev->caps.steering_mode) {
898+
case MLX4_STEERING_MODE_A0:
899+
if (prot == MLX4_PROT_ETH)
900+
return 0;
893901

894-
if (prot == MLX4_PROT_ETH)
895-
gid[7] |= (MLX4_MC_STEER << 1);
902+
case MLX4_STEERING_MODE_B0:
903+
if (prot == MLX4_PROT_ETH)
904+
gid[7] |= (MLX4_MC_STEER << 1);
896905

897-
if (mlx4_is_mfunc(dev))
898-
return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot);
906+
if (mlx4_is_mfunc(dev))
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);
899911

900-
return mlx4_qp_detach_common(dev, qp, gid, prot, MLX4_MC_STEER);
912+
default:
913+
return -EINVAL;
914+
}
901915
}
902916
EXPORT_SYMBOL_GPL(mlx4_multicast_detach);
903917

904918
int mlx4_unicast_attach(struct mlx4_dev *dev,
905919
struct mlx4_qp *qp, u8 gid[16],
906920
int block_mcast_loopback, enum mlx4_protocol prot)
907921
{
908-
if (prot == MLX4_PROT_ETH &&
909-
!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
910-
return 0;
911-
912922
if (prot == MLX4_PROT_ETH)
913923
gid[7] |= (MLX4_UC_STEER << 1);
914924

@@ -924,10 +934,6 @@ EXPORT_SYMBOL_GPL(mlx4_unicast_attach);
924934
int mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp,
925935
u8 gid[16], enum mlx4_protocol prot)
926936
{
927-
if (prot == MLX4_PROT_ETH &&
928-
!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
929-
return 0;
930-
931937
if (prot == MLX4_PROT_ETH)
932938
gid[7] |= (MLX4_UC_STEER << 1);
933939

@@ -968,9 +974,6 @@ static int mlx4_PROMISC(struct mlx4_dev *dev, u32 qpn,
968974

969975
int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
970976
{
971-
if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
972-
return 0;
973-
974977
if (mlx4_is_mfunc(dev))
975978
return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 1, port);
976979

@@ -980,9 +983,6 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add);
980983

981984
int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
982985
{
983-
if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
984-
return 0;
985-
986986
if (mlx4_is_mfunc(dev))
987987
return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 0, port);
988988

@@ -992,9 +992,6 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove);
992992

993993
int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
994994
{
995-
if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
996-
return 0;
997-
998995
if (mlx4_is_mfunc(dev))
999996
return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 1, port);
1000997

@@ -1004,9 +1001,6 @@ EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add);
10041001

10051002
int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
10061003
{
1007-
if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
1008-
return 0;
1009-
10101004
if (mlx4_is_mfunc(dev))
10111005
return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 0, port);
10121006

drivers/net/ethernet/mellanox/mlx4/port.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn)
155155
return err;
156156
}
157157

158-
if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) {
158+
if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
159159
*qpn = info->base_qpn + index;
160160
return 0;
161161
}
@@ -206,7 +206,7 @@ void mlx4_put_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int qpn)
206206
(unsigned long long) mac);
207207
mlx4_unregister_mac(dev, port, mac);
208208

209-
if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) {
209+
if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) {
210210
entry = radix_tree_lookup(&info->mac_tree, qpn);
211211
if (entry) {
212212
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)
359359
int index = qpn - info->base_qpn;
360360
int err = 0;
361361

362-
if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) {
362+
if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) {
363363
entry = radix_tree_lookup(&info->mac_tree, qpn);
364364
if (!entry)
365365
return -EINVAL;
@@ -803,8 +803,7 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
803803
u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ?
804804
MCAST_DIRECT : MCAST_DEFAULT;
805805

806-
if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER &&
807-
dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)
806+
if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0)
808807
return 0;
809808

810809
mailbox = mlx4_alloc_cmd_mailbox(dev);

include/linux/mlx4/device.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,29 @@ enum {
7070
MLX4_MFUNC_EQE_MASK = (MLX4_MFUNC_MAX_EQES - 1)
7171
};
7272

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+
*/
78+
enum {
79+
MLX4_STEERING_MODE_A0,
80+
MLX4_STEERING_MODE_B0
81+
};
82+
83+
static 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+
7396
enum {
7497
MLX4_DEV_CAP_FLAG_RC = 1LL << 0,
7598
MLX4_DEV_CAP_FLAG_UC = 1LL << 1,
@@ -295,6 +318,7 @@ struct mlx4_caps {
295318
int num_amgms;
296319
int reserved_mcgs;
297320
int num_qp_per_mgm;
321+
int steering_mode;
298322
int num_pds;
299323
int reserved_pds;
300324
int max_xrcds;

0 commit comments

Comments
 (0)