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
295 u8 resp_depth;295 u8 resp_depth;
296};296};
297 297
298struct mlx5_ib_rss_qp {
299 u32 tirn;
300};
301
298struct mlx5_ib_rq {302struct mlx5_ib_rq {
299 struct mlx5_ib_qp_base base;303 struct mlx5_ib_qp_base base;
300 struct mlx5_ib_wq *rq;304 struct mlx5_ib_wq *rq;
@@ -323,6 +327,7 @@ struct mlx5_ib_qp { · 22 unmodified lines
323 union {327 union {
324 struct mlx5_ib_qp_trans trans_qp;328 struct mlx5_ib_qp_trans trans_qp;
325 struct mlx5_ib_raw_packet_qp raw_packet_qp;329 struct mlx5_ib_raw_packet_qp raw_packet_qp;
330 struct mlx5_ib_rss_qp rss_qp;
326 };331 };
327 struct mlx5_buf buf;332 struct mlx5_buf buf;
328 333
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
1266 rq->doorbell = &qp->db;1266 rq->doorbell = &qp->db;
1267}1267}
1268 1268
1269static 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
1274static 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
1434create_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
1445err:
1446 kvfree(in);
1447 return err;
1448}
1449
1269static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,1450static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
1270 struct ib_qp_init_attr *init_attr,1451 struct ib_qp_init_attr *init_attr,
1271 struct ib_udata *udata, struct mlx5_ib_qp *qp)1452 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
1292 spin_lock_init(&qp->sq.lock);1473 spin_lock_init(&qp->sq.lock);
1293 spin_lock_init(&qp->rq.lock);1474 spin_lock_init(&qp->rq.lock);
1294 1475
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
1295 if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {1484 if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {
1296 if (!MLX5_CAP_GEN(mdev, block_lb_mc)) {1485 if (!MLX5_CAP_GEN(mdev, block_lb_mc)) {
1297 mlx5_ib_dbg(dev, "block multicast loopback isn't supported\n");1486 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
1644 struct mlx5_modify_qp_mbox_in *in;1833 struct mlx5_modify_qp_mbox_in *in;
1645 int err;1834 int err;
1646 1835
1836 if (qp->ibqp.rwq_ind_tbl) {
1837 destroy_rss_raw_qp_tir(dev, qp);
1838 return;
1839 }
1840
1647 base = qp->ibqp.qp_type == IB_QPT_RAW_PACKET ?1841 base = qp->ibqp.qp_type == IB_QPT_RAW_PACKET ?
1648 &qp->raw_packet_qp.rq.base :1842 &qp->raw_packet_qp.rq.base :
1649 &qp->trans_qp.base;1843 &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
2504 int port;2698 int port;
2505 enum rdma_link_layer ll = IB_LINK_LAYER_UNSPECIFIED;2699 enum rdma_link_layer ll = IB_LINK_LAYER_UNSPECIFIED;
2506 2700
2701 if (ibqp->rwq_ind_tbl)
2702 return -ENOSYS;
2703
2507 if (unlikely(ibqp->qp_type == IB_QPT_GSI))2704 if (unlikely(ibqp->qp_type == IB_QPT_GSI))
2508 return mlx5_ib_gsi_modify_qp(ibqp, attr, attr_mask);2705 return mlx5_ib_gsi_modify_qp(ibqp, attr, attr_mask);
2509 2706
@@ -4119,6 +4316,9 @@ int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, · 1609 unmodified lines
4119 int err = 0;4316 int err = 0;
4120 u8 raw_packet_qp_state;4317 u8 raw_packet_qp_state;
4121 4318
4319 if (ibqp->rwq_ind_tbl)
4320 return -ENOSYS;
4321
4122 if (unlikely(ibqp->qp_type == IB_QPT_GSI))4322 if (unlikely(ibqp->qp_type == IB_QPT_GSI))
4123 return mlx5_ib_gsi_query_qp(ibqp, qp_attr, qp_attr_mask,4323 return mlx5_ib_gsi_query_qp(ibqp, qp_attr, qp_attr_mask,
4124 qp_init_attr);4324 qp_init_attr);
drivers/infiniband/hw/mlx5/user.h+34−0
@@ -152,6 +152,40 @@ struct mlx5_ib_create_qp { · 151 unmodified lines
152 __u64 sq_buf_addr;152 __u64 sq_buf_addr;
153};153};
154 154
155/* RX Hash function flags */
156enum 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*/
168enum 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
179struct 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
155struct mlx5_ib_create_qp_resp {189struct mlx5_ib_create_qp_resp {
156 __u32 uuar_index;190 __u32 uuar_index;
157};191};

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