| @@ -1266,6 +1266,187 @@ static void raw_packet_qp_copy_info(struct mlx5_ib_qp *qp, · 1265 unmodified lines |
| 1266 | 1266 | rq->doorbell = &qp->db; |
| 1267 | 1267 | } |
| 1268 | 1268 | |
| 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 | + |
| 1269 | 1450 | static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, |
| 1270 | 1451 | struct ib_qp_init_attr *init_attr, |
| 1271 | 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 | 1473 | spin_lock_init(&qp->sq.lock); |
| 1293 | 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 | 1484 | if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) { |
| 1296 | 1485 | if (!MLX5_CAP_GEN(mdev, block_lb_mc)) { |
| 1297 | 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 | 1833 | struct mlx5_modify_qp_mbox_in *in; |
| 1645 | 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 | 1841 | base = qp->ibqp.qp_type == IB_QPT_RAW_PACKET ? |
| 1648 | 1842 | &qp->raw_packet_qp.rq.base : |
| 1649 | 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 | 2698 | int port; |
| 2505 | 2699 | enum rdma_link_layer ll = IB_LINK_LAYER_UNSPECIFIED; |
| 2506 | 2700 | |
| 2701 | + if (ibqp->rwq_ind_tbl) |
| 2702 | + return -ENOSYS; |
| 2703 | + |
| 2507 | 2704 | if (unlikely(ibqp->qp_type == IB_QPT_GSI)) |
| 2508 | 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 | 4316 | int err = 0; |
| 4120 | 4317 | u8 raw_packet_qp_state; |
| 4121 | 4318 | |
| 4319 | + if (ibqp->rwq_ind_tbl) |
| 4320 | + return -ENOSYS; |
| 4321 | + |
| 4122 | 4322 | if (unlikely(ibqp->qp_type == IB_QPT_GSI)) |
| 4123 | 4323 | return mlx5_ib_gsi_query_qp(ibqp, qp_attr, qp_attr_mask, |
| 4124 | 4324 | qp_init_attr); |