History

IB/mlx5: Add RSS QP support

Add support for Raw Ethernet RX HASH QP. Currently, creation and destruction of such a QP are supported. This QP is implemented as a simple TIR object which points to the receive RQ indirection table. The given hashing configuration is used to configure the TIR and by that it chooses the right RQ from the RQ indirection table.

Yishai Hadas committed 10 years ago

Commit 28d61371 parent c70285f3 files · +239 −0Browse files

Unified · Split

3 files
  1. drivers/infiniband/hw/mlx5/mlx5_ib.h +5 −0
  2. drivers/infiniband/hw/mlx5/qp.c +200 −0
  3. drivers/infiniband/hw/mlx5/user.h +34 −0
drivers/infiniband/hw/mlx5/mlx5_ib.h+5−0
@@ -295,6 +295,10 @@ struct mlx5_ib_qp_trans { · 294 unmodified lines
295295 u8 resp_depth;
296296 };
297297
298+struct mlx5_ib_rss_qp {
299+ u32 tirn;
300+};
301+
298302 struct mlx5_ib_rq {
299303 struct mlx5_ib_qp_base base;
300304 struct mlx5_ib_wq *rq;
@@ -323,6 +327,7 @@ struct mlx5_ib_qp { · 22 unmodified lines
323327 union {
324328 struct mlx5_ib_qp_trans trans_qp;
325329 struct mlx5_ib_raw_packet_qp raw_packet_qp;
330+ struct mlx5_ib_rss_qp rss_qp;
326331 };
327332 struct mlx5_buf buf;
328333
drivers/infiniband/hw/mlx5/qp.c+200−0
@@ -1266,6 +1266,187 @@ static void raw_packet_qp_copy_info(struct mlx5_ib_qp *qp, · 1265 unmodified lines
12661266 rq->doorbell = &qp->db;
12671267 }
12681268
1269+static void destroy_rss_raw_qp_tir(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
1270+{
1271+ mlx5_core_destroy_tir(dev->mdev, qp->rss_qp.tirn);
1272+}
1273+
1274+static int create_rss_raw_qp_tir(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
1275+ struct ib_pd *pd,
1276+ struct ib_qp_init_attr *init_attr,
1277+ struct ib_udata *udata)
1278+{
1279+ struct ib_uobject *uobj = pd->uobject;
1280+ struct ib_ucontext *ucontext = uobj->context;
1281+ struct mlx5_ib_ucontext *mucontext = to_mucontext(ucontext);
1282+ struct mlx5_ib_create_qp_resp resp = {};
1283+ int inlen;
1284+ int err;
1285+ u32 *in;
1286+ void *tirc;
1287+ void *hfso;
1288+ u32 selected_fields = 0;
1289+ size_t min_resp_len;
1290+ u32 tdn = mucontext->tdn;
1291+ struct mlx5_ib_create_qp_rss ucmd = {};
1292+ size_t required_cmd_sz;
1293+
1294+ if (init_attr->qp_type != IB_QPT_RAW_PACKET)
1295+ return -EOPNOTSUPP;
1296+
1297+ if (init_attr->create_flags || init_attr->send_cq)
1298+ return -EINVAL;
1299+
1300+ min_resp_len = offsetof(typeof(resp), uuar_index) + sizeof(resp.uuar_index);
1301+ if (udata->outlen < min_resp_len)
1302+ return -EINVAL;
1303+
1304+ required_cmd_sz = offsetof(typeof(ucmd), reserved1) + sizeof(ucmd.reserved1);
1305+ if (udata->inlen < required_cmd_sz) {
1306+ mlx5_ib_dbg(dev, "invalid inlen\n");
1307+ return -EINVAL;
1308+ }
1309+
1310+ if (udata->inlen > sizeof(ucmd) &&
1311+ !ib_is_udata_cleared(udata, sizeof(ucmd),
1312+ udata->inlen - sizeof(ucmd))) {
1313+ mlx5_ib_dbg(dev, "inlen is not supported\n");
1314+ return -EOPNOTSUPP;
1315+ }
1316+
1317+ if (ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata->inlen))) {
1318+ mlx5_ib_dbg(dev, "copy failed\n");
1319+ return -EFAULT;
1320+ }
1321+
1322+ if (ucmd.comp_mask) {
1323+ mlx5_ib_dbg(dev, "invalid comp mask\n");
1324+ return -EOPNOTSUPP;
1325+ }
1326+
1327+ if (memchr_inv(ucmd.reserved, 0, sizeof(ucmd.reserved)) || ucmd.reserved1) {
1328+ mlx5_ib_dbg(dev, "invalid reserved\n");
1329+ return -EOPNOTSUPP;
1330+ }
1331+
1332+ err = ib_copy_to_udata(udata, &resp, min_resp_len);
1333+ if (err) {
1334+ mlx5_ib_dbg(dev, "copy failed\n");
1335+ return -EINVAL;
1336+ }
1337+
1338+ inlen = MLX5_ST_SZ_BYTES(create_tir_in);
1339+ in = mlx5_vzalloc(inlen);
1340+ if (!in)
1341+ return -ENOMEM;
1342+
1343+ tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
1344+ MLX5_SET(tirc, tirc, disp_type,
1345+ MLX5_TIRC_DISP_TYPE_INDIRECT);
1346+ MLX5_SET(tirc, tirc, indirect_table,
1347+ init_attr->rwq_ind_tbl->ind_tbl_num);
1348+ MLX5_SET(tirc, tirc, transport_domain, tdn);
1349+
1350+ hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
1351+ switch (ucmd.rx_hash_function) {
1352+ case MLX5_RX_HASH_FUNC_TOEPLITZ:
1353+ {
1354+ void *rss_key = MLX5_ADDR_OF(tirc, tirc, rx_hash_toeplitz_key);
1355+ size_t len = MLX5_FLD_SZ_BYTES(tirc, rx_hash_toeplitz_key);
1356+
1357+ if (len != ucmd.rx_key_len) {
1358+ err = -EINVAL;
1359+ goto err;
1360+ }
1361+
1362+ MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_TOEPLITZ);
1363+ MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
1364+ memcpy(rss_key, ucmd.rx_hash_key, len);
1365+ break;
1366+ }
1367+ default:
1368+ err = -EOPNOTSUPP;
1369+ goto err;
1370+ }
1371+
1372+ if (!ucmd.rx_hash_fields_mask) {
1373+ /* special case when this TIR serves as steering entry without hashing */
1374+ if (!init_attr->rwq_ind_tbl->log_ind_tbl_size)
1375+ goto create_tir;
1376+ err = -EINVAL;
1377+ goto err;
1378+ }
1379+
1380+ if (((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV4) ||
1381+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV4)) &&
1382+ ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV6) ||
1383+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV6))) {
1384+ err = -EINVAL;
1385+ goto err;
1386+ }
1387+
1388+ /* If none of IPV4 & IPV6 SRC/DST was set - this bit field is ignored */
1389+ if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV4) ||
1390+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV4))
1391+ MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
1392+ MLX5_L3_PROT_TYPE_IPV4);
1393+ else if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV6) ||
1394+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV6))
1395+ MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
1396+ MLX5_L3_PROT_TYPE_IPV6);
1397+
1398+ if (((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_TCP) ||
1399+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_TCP)) &&
1400+ ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_UDP) ||
1401+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_UDP))) {
1402+ err = -EINVAL;
1403+ goto err;
1404+ }
1405+
1406+ /* If none of TCP & UDP SRC/DST was set - this bit field is ignored */
1407+ if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_TCP) ||
1408+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_TCP))
1409+ MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
1410+ MLX5_L4_PROT_TYPE_TCP);
1411+ else if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_UDP) ||
1412+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_UDP))
1413+ MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
1414+ MLX5_L4_PROT_TYPE_UDP);
1415+
1416+ if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV4) ||
1417+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV6))
1418+ selected_fields |= MLX5_HASH_FIELD_SEL_SRC_IP;
1419+
1420+ if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV4) ||
1421+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV6))
1422+ selected_fields |= MLX5_HASH_FIELD_SEL_DST_IP;
1423+
1424+ if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_TCP) ||
1425+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_UDP))
1426+ selected_fields |= MLX5_HASH_FIELD_SEL_L4_SPORT;
1427+
1428+ if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_TCP) ||
1429+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_UDP))
1430+ selected_fields |= MLX5_HASH_FIELD_SEL_L4_DPORT;
1431+
1432+ MLX5_SET(rx_hash_field_select, hfso, selected_fields, selected_fields);
1433+
1434+create_tir:
1435+ err = mlx5_core_create_tir(dev->mdev, in, inlen, &qp->rss_qp.tirn);
1436+
1437+ if (err)
1438+ goto err;
1439+
1440+ kvfree(in);
1441+ /* qpn is reserved for that QP */
1442+ qp->trans_qp.base.mqp.qpn = 0;
1443+ return 0;
1444+
1445+err:
1446+ kvfree(in);
1447+ return err;
1448+}
1449+
12691450 static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
12701451 struct ib_qp_init_attr *init_attr,
12711452 struct ib_udata *udata, struct mlx5_ib_qp *qp)
@@ -1292,6 +1473,14 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, · 20 unmodified lines
12921473 spin_lock_init(&qp->sq.lock);
12931474 spin_lock_init(&qp->rq.lock);
12941475
1476+ if (init_attr->rwq_ind_tbl) {
1477+ if (!udata)
1478+ return -ENOSYS;
1479+
1480+ err = create_rss_raw_qp_tir(dev, qp, pd, init_attr, udata);
1481+ return err;
1482+ }
1483+
12951484 if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {
12961485 if (!MLX5_CAP_GEN(mdev, block_lb_mc)) {
12971486 mlx5_ib_dbg(dev, "block multicast loopback isn't supported\n");
@@ -1644,6 +1833,11 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp) · 346 unmodified lines
16441833 struct mlx5_modify_qp_mbox_in *in;
16451834 int err;
16461835
1836+ if (qp->ibqp.rwq_ind_tbl) {
1837+ destroy_rss_raw_qp_tir(dev, qp);
1838+ return;
1839+ }
1840+
16471841 base = qp->ibqp.qp_type == IB_QPT_RAW_PACKET ?
16481842 &qp->raw_packet_qp.rq.base :
16491843 &qp->trans_qp.base;
@@ -2504,6 +2698,9 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, · 854 unmodified lines
25042698 int port;
25052699 enum rdma_link_layer ll = IB_LINK_LAYER_UNSPECIFIED;
25062700
2701+ if (ibqp->rwq_ind_tbl)
2702+ return -ENOSYS;
2703+
25072704 if (unlikely(ibqp->qp_type == IB_QPT_GSI))
25082705 return mlx5_ib_gsi_modify_qp(ibqp, attr, attr_mask);
25092706
@@ -4119,6 +4316,9 @@ int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, · 1609 unmodified lines
41194316 int err = 0;
41204317 u8 raw_packet_qp_state;
41214318
4319+ if (ibqp->rwq_ind_tbl)
4320+ return -ENOSYS;
4321+
41224322 if (unlikely(ibqp->qp_type == IB_QPT_GSI))
41234323 return mlx5_ib_gsi_query_qp(ibqp, qp_attr, qp_attr_mask,
41244324 qp_init_attr);
drivers/infiniband/hw/mlx5/user.h+34−0
@@ -152,6 +152,40 @@ struct mlx5_ib_create_qp { · 151 unmodified lines
152152 __u64 sq_buf_addr;
153153 };
154154
155+/* RX Hash function flags */
156+enum mlx5_rx_hash_function_flags {
157+ MLX5_RX_HASH_FUNC_TOEPLITZ = 1 << 0,
158+};
159+
160+/*
161+ * RX Hash flags, these flags allows to set which incoming packet's field should
162+ * participates in RX Hash. Each flag represent certain packet's field,
163+ * when the flag is set the field that is represented by the flag will
164+ * participate in RX Hash calculation.
165+ * Note: *IPV4 and *IPV6 flags can't be enabled together on the same QP
166+ * and *TCP and *UDP flags can't be enabled together on the same QP.
167+*/
168+enum mlx5_rx_hash_fields {
169+ MLX5_RX_HASH_SRC_IPV4 = 1 << 0,
170+ MLX5_RX_HASH_DST_IPV4 = 1 << 1,
171+ MLX5_RX_HASH_SRC_IPV6 = 1 << 2,
172+ MLX5_RX_HASH_DST_IPV6 = 1 << 3,
173+ MLX5_RX_HASH_SRC_PORT_TCP = 1 << 4,
174+ MLX5_RX_HASH_DST_PORT_TCP = 1 << 5,
175+ MLX5_RX_HASH_SRC_PORT_UDP = 1 << 6,
176+ MLX5_RX_HASH_DST_PORT_UDP = 1 << 7
177+};
178+
179+struct mlx5_ib_create_qp_rss {
180+ __u64 rx_hash_fields_mask; /* enum mlx5_rx_hash_fields */
181+ __u8 rx_hash_function; /* enum mlx5_rx_hash_function_flags */
182+ __u8 rx_key_len; /* valid only for Toeplitz */
183+ __u8 reserved[6];
184+ __u8 rx_hash_key[128]; /* valid only for Toeplitz */
185+ __u32 comp_mask;
186+ __u32 reserved1;
187+};
188+
155189 struct mlx5_ib_create_qp_resp {
156190 __u32 uuar_index;
157191 };

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t