Skip to content

Commit 0ff1fb6

Browse files
Hadar Hen Ziondavem330
authored andcommitted
{NET, IB}/mlx4: Add device managed flow steering firmware API
The driver is modified to support three operation modes. If supported by firmware use the device managed flow steering API, that which we call device managed steering mode. Else, if the firmware supports the B0 steering mode use it, and finally, if none of the above, use the A0 steering mode. When the steering mode is device managed, the code is modified such that L2 based rules set by the mlx4_en driver for Ethernet unicast and multicast, and the IB stack multicast attach calls done through the mlx4_ib driver are all routed to use the device managed API. When attaching rule using device managed flow steering API, the firmware returns a 64 bit registration id, which is to be provided during detach. Currently the firmware is always programmed during HCA initialization to use standard L2 hashing. Future work should be done to allow configuring the flow-steering hash function with common, non proprietary means. 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 8fcfb4d commit 0ff1fb6

File tree

14 files changed

+758
-81
lines changed

14 files changed

+758
-81
lines changed

drivers/infiniband/hw/mlx4/main.c

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -718,26 +718,53 @@ int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp,
718718
return ret;
719719
}
720720

721+
struct mlx4_ib_steering {
722+
struct list_head list;
723+
u64 reg_id;
724+
union ib_gid gid;
725+
};
726+
721727
static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
722728
{
723729
int err;
724730
struct mlx4_ib_dev *mdev = to_mdev(ibqp->device);
725731
struct mlx4_ib_qp *mqp = to_mqp(ibqp);
732+
u64 reg_id;
733+
struct mlx4_ib_steering *ib_steering = NULL;
734+
735+
if (mdev->dev->caps.steering_mode ==
736+
MLX4_STEERING_MODE_DEVICE_MANAGED) {
737+
ib_steering = kmalloc(sizeof(*ib_steering), GFP_KERNEL);
738+
if (!ib_steering)
739+
return -ENOMEM;
740+
}
726741

727-
err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw,
728-
!!(mqp->flags & MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK),
729-
MLX4_PROT_IB_IPV6);
742+
err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, mqp->port,
743+
!!(mqp->flags &
744+
MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK),
745+
MLX4_PROT_IB_IPV6, &reg_id);
730746
if (err)
731-
return err;
747+
goto err_malloc;
732748

733749
err = add_gid_entry(ibqp, gid);
734750
if (err)
735751
goto err_add;
736752

753+
if (ib_steering) {
754+
memcpy(ib_steering->gid.raw, gid->raw, 16);
755+
ib_steering->reg_id = reg_id;
756+
mutex_lock(&mqp->mutex);
757+
list_add(&ib_steering->list, &mqp->steering_rules);
758+
mutex_unlock(&mqp->mutex);
759+
}
737760
return 0;
738761

739762
err_add:
740-
mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, MLX4_PROT_IB_IPV6);
763+
mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw,
764+
MLX4_PROT_IB_IPV6, reg_id);
765+
err_malloc:
766+
kfree(ib_steering);
767+
741768
return err;
742769
}
743770

@@ -765,9 +792,30 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
765792
u8 mac[6];
766793
struct net_device *ndev;
767794
struct mlx4_ib_gid_entry *ge;
795+
u64 reg_id = 0;
796+
797+
if (mdev->dev->caps.steering_mode ==
798+
MLX4_STEERING_MODE_DEVICE_MANAGED) {
799+
struct mlx4_ib_steering *ib_steering;
800+
801+
mutex_lock(&mqp->mutex);
802+
list_for_each_entry(ib_steering, &mqp->steering_rules, list) {
803+
if (!memcmp(ib_steering->gid.raw, gid->raw, 16)) {
804+
list_del(&ib_steering->list);
805+
break;
806+
}
807+
}
808+
mutex_unlock(&mqp->mutex);
809+
if (&ib_steering->list == &mqp->steering_rules) {
810+
pr_err("Couldn't find reg_id for mgid. Steering rule is left attached\n");
811+
return -EINVAL;
812+
}
813+
reg_id = ib_steering->reg_id;
814+
kfree(ib_steering);
815+
}
768816

769-
err = mlx4_multicast_detach(mdev->dev,
770-
&mqp->mqp, gid->raw, MLX4_PROT_IB_IPV6);
817+
err = mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw,
818+
MLX4_PROT_IB_IPV6, reg_id);
771819
if (err)
772820
return err;
773821

drivers/infiniband/hw/mlx4/mlx4_ib.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ struct mlx4_ib_qp {
163163
u8 state;
164164
int mlx_type;
165165
struct list_head gid_list;
166+
struct list_head steering_rules;
166167
};
167168

168169
struct mlx4_ib_srq {

drivers/infiniband/hw/mlx4/qp.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
495495
spin_lock_init(&qp->sq.lock);
496496
spin_lock_init(&qp->rq.lock);
497497
INIT_LIST_HEAD(&qp->gid_list);
498+
INIT_LIST_HEAD(&qp->steering_rules);
498499

499500
qp->state = IB_QPS_RESET;
500501
if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,8 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
463463
err = mlx4_multicast_detach(mdev->dev,
464464
&priv->rss_map.indir_qp,
465465
mc_list,
466-
MLX4_PROT_ETH);
466+
MLX4_PROT_ETH,
467+
mclist->reg_id);
467468
if (err)
468469
en_err(priv, "Fail to detach multicast address\n");
469470

@@ -475,11 +476,14 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
475476
if (mclist->action == MCLIST_ADD) {
476477
/* attach the address */
477478
memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
479+
/* needed for B0 steering support */
478480
mc_list[5] = priv->port;
479481
err = mlx4_multicast_attach(mdev->dev,
480482
&priv->rss_map.indir_qp,
481-
mc_list, 0,
482-
MLX4_PROT_ETH);
483+
mc_list,
484+
priv->port, 0,
485+
MLX4_PROT_ETH,
486+
&mclist->reg_id);
483487
if (err)
484488
en_err(priv, "Fail to attach multicast address\n");
485489

@@ -827,9 +831,10 @@ int mlx4_en_start_port(struct net_device *dev)
827831

828832
/* Attach rx QP to bradcast address */
829833
memset(&mc_list[10], 0xff, ETH_ALEN);
830-
mc_list[5] = priv->port;
834+
mc_list[5] = priv->port; /* needed for B0 steering support */
831835
if (mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
832-
0, MLX4_PROT_ETH))
836+
priv->port, 0, MLX4_PROT_ETH,
837+
&priv->broadcast_id))
833838
mlx4_warn(mdev, "Failed Attaching Broadcast\n");
834839

835840
/* Must redo promiscuous mode setup. */
@@ -886,14 +891,14 @@ void mlx4_en_stop_port(struct net_device *dev)
886891

887892
/* Detach All multicasts */
888893
memset(&mc_list[10], 0xff, ETH_ALEN);
889-
mc_list[5] = priv->port;
894+
mc_list[5] = priv->port; /* needed for B0 steering support */
890895
mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
891-
MLX4_PROT_ETH);
896+
MLX4_PROT_ETH, priv->broadcast_id);
892897
list_for_each_entry(mclist, &priv->curr_list, list) {
893898
memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
894899
mc_list[5] = priv->port;
895900
mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
896-
mc_list, MLX4_PROT_ETH);
901+
mc_list, MLX4_PROT_ETH, mclist->reg_id);
897902
}
898903
mlx4_en_clear_list(dev);
899904
list_for_each_entry_safe(mclist, tmp, &priv->curr_list, list) {

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

Lines changed: 74 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
123123
static const char * const fname[] = {
124124
[0] = "RSS support",
125125
[1] = "RSS Toeplitz Hash Function support",
126-
[2] = "RSS XOR Hash Function support"
126+
[2] = "RSS XOR Hash Function support",
127+
[3] = "Device manage flow steering support"
127128
};
128129
int i;
129130

@@ -391,6 +392,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
391392
#define QUERY_DEV_CAP_RSVD_XRC_OFFSET 0x66
392393
#define QUERY_DEV_CAP_MAX_XRC_OFFSET 0x67
393394
#define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET 0x68
395+
#define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET 0x76
396+
#define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET 0x77
394397
#define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80
395398
#define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82
396399
#define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84
@@ -474,6 +477,12 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
474477
dev_cap->num_ports = field & 0xf;
475478
MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET);
476479
dev_cap->max_msg_sz = 1 << (field & 0x1f);
480+
MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
481+
if (field & 0x80)
482+
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FS_EN;
483+
dev_cap->fs_log_max_ucast_qp_range_size = field & 0x1f;
484+
MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET);
485+
dev_cap->fs_max_num_qp_per_entry = field;
477486
MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
478487
dev_cap->stat_rate_support = stat_rate;
479488
MLX4_GET(ext_flags, outbox, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
@@ -1061,6 +1070,15 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
10611070
#define INIT_HCA_LOG_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x16)
10621071
#define INIT_HCA_UC_STEERING_OFFSET (INIT_HCA_MCAST_OFFSET + 0x18)
10631072
#define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b)
1073+
#define INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN 0x6
1074+
#define INIT_HCA_FS_PARAM_OFFSET 0x1d0
1075+
#define INIT_HCA_FS_BASE_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x00)
1076+
#define INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x12)
1077+
#define INIT_HCA_FS_LOG_TABLE_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x1b)
1078+
#define INIT_HCA_FS_ETH_BITS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x21)
1079+
#define INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x22)
1080+
#define INIT_HCA_FS_IB_BITS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x25)
1081+
#define INIT_HCA_FS_IB_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x26)
10641082
#define INIT_HCA_TPT_OFFSET 0x0f0
10651083
#define INIT_HCA_DMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00)
10661084
#define INIT_HCA_LOG_MPT_SZ_OFFSET (INIT_HCA_TPT_OFFSET + 0x0b)
@@ -1119,14 +1137,44 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
11191137
MLX4_PUT(inbox, param->rdmarc_base, INIT_HCA_RDMARC_BASE_OFFSET);
11201138
MLX4_PUT(inbox, param->log_rd_per_qp, INIT_HCA_LOG_RD_OFFSET);
11211139

1122-
/* multicast attributes */
1123-
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);
1126-
MLX4_PUT(inbox, param->log_mc_hash_sz, INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
1127-
if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0)
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);
1140+
/* steering attributes */
1141+
if (dev->caps.steering_mode ==
1142+
MLX4_STEERING_MODE_DEVICE_MANAGED) {
1143+
*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |=
1144+
cpu_to_be32(1 <<
1145+
INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN);
1146+
1147+
MLX4_PUT(inbox, param->mc_base, INIT_HCA_FS_BASE_OFFSET);
1148+
MLX4_PUT(inbox, param->log_mc_entry_sz,
1149+
INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
1150+
MLX4_PUT(inbox, param->log_mc_table_sz,
1151+
INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
1152+
/* Enable Ethernet flow steering
1153+
* with udp unicast and tcp unicast
1154+
*/
1155+
MLX4_PUT(inbox, param->fs_hash_enable_bits,
1156+
INIT_HCA_FS_ETH_BITS_OFFSET);
1157+
MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR,
1158+
INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET);
1159+
/* Enable IPoIB flow steering
1160+
* with udp unicast and tcp unicast
1161+
*/
1162+
MLX4_PUT(inbox, param->fs_hash_enable_bits,
1163+
INIT_HCA_FS_IB_BITS_OFFSET);
1164+
MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR,
1165+
INIT_HCA_FS_IB_NUM_ADDRS_OFFSET);
1166+
} else {
1167+
MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET);
1168+
MLX4_PUT(inbox, param->log_mc_entry_sz,
1169+
INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
1170+
MLX4_PUT(inbox, param->log_mc_hash_sz,
1171+
INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
1172+
MLX4_PUT(inbox, param->log_mc_table_sz,
1173+
INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
1174+
if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0)
1175+
MLX4_PUT(inbox, (u8) (1 << 3),
1176+
INIT_HCA_UC_STEERING_OFFSET);
1177+
}
11301178

11311179
/* TPT attributes */
11321180

@@ -1188,15 +1236,24 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
11881236
MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET);
11891237
MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET);
11901238

1191-
/* multicast attributes */
1239+
/* steering attributes */
1240+
if (dev->caps.steering_mode ==
1241+
MLX4_STEERING_MODE_DEVICE_MANAGED) {
11921242

1193-
MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET);
1194-
MLX4_GET(param->log_mc_entry_sz, outbox,
1195-
INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
1196-
MLX4_GET(param->log_mc_hash_sz, outbox,
1197-
INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
1198-
MLX4_GET(param->log_mc_table_sz, outbox,
1199-
INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
1243+
MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET);
1244+
MLX4_GET(param->log_mc_entry_sz, outbox,
1245+
INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
1246+
MLX4_GET(param->log_mc_table_sz, outbox,
1247+
INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
1248+
} else {
1249+
MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET);
1250+
MLX4_GET(param->log_mc_entry_sz, outbox,
1251+
INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
1252+
MLX4_GET(param->log_mc_hash_sz, outbox,
1253+
INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
1254+
MLX4_GET(param->log_mc_table_sz, outbox,
1255+
INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
1256+
}
12001257

12011258
/* TPT attributes */
12021259

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ struct mlx4_dev_cap {
7878
u16 wavelength[MLX4_MAX_PORTS + 1];
7979
u64 trans_code[MLX4_MAX_PORTS + 1];
8080
u16 stat_rate_support;
81+
int fs_log_max_ucast_qp_range_size;
82+
int fs_max_num_qp_per_entry;
8183
u64 flags;
8284
u64 flags2;
8385
int reserved_uars;
@@ -165,6 +167,7 @@ struct mlx4_init_hca_param {
165167
u8 log_mpt_sz;
166168
u8 log_uar_sz;
167169
u8 uar_page_sz; /* log pg sz in 4k chunks */
170+
u8 fs_hash_enable_bits;
168171
};
169172

170173
struct mlx4_init_ib_param {

0 commit comments

Comments
 (0)