1 /* 2 * Copyright (c) 2012 Mellanox Technologies, Inc. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 33 #include <config.h> 34 35 #include <stdlib.h> 36 #include <stdio.h> 37 #include <string.h> 38 #include <pthread.h> 39 #include <errno.h> 40 #include <limits.h> 41 #include <sys/types.h> 42 #include <sys/stat.h> 43 #include <fcntl.h> 44 #include <unistd.h> 45 #include <sys/mman.h> 46 47 #include "mlx5.h" 48 #include "mlx5-abi.h" 49 #include "wqe.h" 50 51 int mlx5_single_threaded = 0; 52 53 static inline int is_xrc_tgt(int type) 54 { 55 return type == IBV_QPT_XRC_RECV; 56 } 57 58 int mlx5_query_device(struct ibv_context *context, struct ibv_device_attr *attr) 59 { 60 struct ibv_query_device cmd; 61 uint64_t raw_fw_ver; 62 unsigned major, minor, sub_minor; 63 int ret; 64 65 ret = ibv_cmd_query_device(context, attr, &raw_fw_ver, &cmd, sizeof cmd); 66 if (ret) 67 return ret; 68 69 major = (raw_fw_ver >> 32) & 0xffff; 70 minor = (raw_fw_ver >> 16) & 0xffff; 71 sub_minor = raw_fw_ver & 0xffff; 72 73 snprintf(attr->fw_ver, sizeof attr->fw_ver, 74 "%d.%d.%04d", major, minor, sub_minor); 75 76 return 0; 77 } 78 79 #define READL(ptr) (*((uint32_t *)(ptr))) 80 static int mlx5_read_clock(struct ibv_context *context, uint64_t *cycles) 81 { 82 unsigned int clockhi, clocklo, clockhi1; 83 int i; 84 struct mlx5_context *ctx = to_mctx(context); 85 86 if (!ctx->hca_core_clock) 87 return -EOPNOTSUPP; 88 89 /* Handle wraparound */ 90 for (i = 0; i < 2; i++) { 91 clockhi = be32toh(READL(ctx->hca_core_clock)); 92 clocklo = be32toh(READL(ctx->hca_core_clock + 4)); 93 clockhi1 = be32toh(READL(ctx->hca_core_clock)); 94 if (clockhi == clockhi1) 95 break; 96 } 97 98 *cycles = (uint64_t)clockhi << 32 | (uint64_t)clocklo; 99 100 return 0; 101 } 102 103 int mlx5_query_rt_values(struct ibv_context *context, 104 struct ibv_values_ex *values) 105 { 106 uint32_t comp_mask = 0; 107 int err = 0; 108 109 if (values->comp_mask & IBV_VALUES_MASK_RAW_CLOCK) { 110 uint64_t cycles; 111 112 err = mlx5_read_clock(context, &cycles); 113 if (!err) { 114 values->raw_clock.tv_sec = 0; 115 values->raw_clock.tv_nsec = cycles; 116 comp_mask |= IBV_VALUES_MASK_RAW_CLOCK; 117 } 118 } 119 120 values->comp_mask = comp_mask; 121 122 return err; 123 } 124 125 int mlx5_query_port(struct ibv_context *context, uint8_t port, 126 struct ibv_port_attr *attr) 127 { 128 struct ibv_query_port cmd; 129 130 return ibv_cmd_query_port(context, port, attr, &cmd, sizeof cmd); 131 } 132 133 struct ibv_pd *mlx5_alloc_pd(struct ibv_context *context) 134 { 135 struct ibv_alloc_pd cmd; 136 struct mlx5_alloc_pd_resp resp; 137 struct mlx5_pd *pd; 138 139 pd = calloc(1, sizeof *pd); 140 if (!pd) 141 return NULL; 142 143 if (ibv_cmd_alloc_pd(context, &pd->ibv_pd, &cmd, sizeof cmd, 144 &resp.ibv_resp, sizeof resp)) { 145 free(pd); 146 return NULL; 147 } 148 149 pd->pdn = resp.pdn; 150 151 return &pd->ibv_pd; 152 } 153 154 int mlx5_free_pd(struct ibv_pd *pd) 155 { 156 int ret; 157 158 ret = ibv_cmd_dealloc_pd(pd); 159 if (ret) 160 return ret; 161 162 free(to_mpd(pd)); 163 return 0; 164 } 165 166 struct ibv_mr *mlx5_reg_mr(struct ibv_pd *pd, void *addr, size_t length, 167 int acc) 168 { 169 struct mlx5_mr *mr; 170 struct ibv_reg_mr cmd; 171 int ret; 172 enum ibv_access_flags access = (enum ibv_access_flags)acc; 173 struct ibv_reg_mr_resp resp; 174 175 mr = calloc(1, sizeof(*mr)); 176 if (!mr) 177 return NULL; 178 179 ret = ibv_cmd_reg_mr(pd, addr, length, (uintptr_t)addr, access, 180 &(mr->ibv_mr), &cmd, sizeof(cmd), &resp, 181 sizeof resp); 182 if (ret) { 183 mlx5_free_buf(&(mr->buf)); 184 free(mr); 185 return NULL; 186 } 187 mr->alloc_flags = acc; 188 189 return &mr->ibv_mr; 190 } 191 192 int mlx5_rereg_mr(struct ibv_mr *ibmr, int flags, struct ibv_pd *pd, void *addr, 193 size_t length, int access) 194 { 195 struct ibv_rereg_mr cmd; 196 struct ibv_rereg_mr_resp resp; 197 198 if (flags & IBV_REREG_MR_KEEP_VALID) 199 return ENOTSUP; 200 201 return ibv_cmd_rereg_mr(ibmr, flags, addr, length, (uintptr_t)addr, 202 access, pd, &cmd, sizeof(cmd), &resp, 203 sizeof(resp)); 204 } 205 206 int mlx5_dereg_mr(struct ibv_mr *ibmr) 207 { 208 int ret; 209 struct mlx5_mr *mr = to_mmr(ibmr); 210 211 ret = ibv_cmd_dereg_mr(ibmr); 212 if (ret) 213 return ret; 214 215 free(mr); 216 return 0; 217 } 218 219 struct ibv_mw *mlx5_alloc_mw(struct ibv_pd *pd, enum ibv_mw_type type) 220 { 221 struct ibv_mw *mw; 222 struct ibv_alloc_mw cmd; 223 struct ibv_alloc_mw_resp resp; 224 int ret; 225 226 mw = malloc(sizeof(*mw)); 227 if (!mw) 228 return NULL; 229 230 memset(mw, 0, sizeof(*mw)); 231 232 ret = ibv_cmd_alloc_mw(pd, type, mw, &cmd, sizeof(cmd), &resp, 233 sizeof(resp)); 234 if (ret) { 235 free(mw); 236 return NULL; 237 } 238 239 return mw; 240 } 241 242 int mlx5_dealloc_mw(struct ibv_mw *mw) 243 { 244 int ret; 245 struct ibv_dealloc_mw cmd; 246 247 ret = ibv_cmd_dealloc_mw(mw, &cmd, sizeof(cmd)); 248 if (ret) 249 return ret; 250 251 free(mw); 252 return 0; 253 } 254 255 int mlx5_round_up_power_of_two(long long sz) 256 { 257 long long ret; 258 259 for (ret = 1; ret < sz; ret <<= 1) 260 ; /* nothing */ 261 262 if (ret > INT_MAX) { 263 fprintf(stderr, "%s: roundup overflow\n", __func__); 264 return -ENOMEM; 265 } 266 267 return (int)ret; 268 } 269 270 static int align_queue_size(long long req) 271 { 272 return mlx5_round_up_power_of_two(req); 273 } 274 275 static int get_cqe_size(void) 276 { 277 char *env; 278 int size = 64; 279 280 env = getenv("MLX5_CQE_SIZE"); 281 if (env) 282 size = atoi(env); 283 284 switch (size) { 285 case 64: 286 case 128: 287 return size; 288 289 default: 290 return -EINVAL; 291 } 292 } 293 294 static int use_scatter_to_cqe(void) 295 { 296 char *env; 297 298 env = getenv("MLX5_SCATTER_TO_CQE"); 299 if (env && !strcmp(env, "0")) 300 return 0; 301 302 return 1; 303 } 304 305 static int srq_sig_enabled(void) 306 { 307 char *env; 308 309 env = getenv("MLX5_SRQ_SIGNATURE"); 310 if (env) 311 return 1; 312 313 return 0; 314 } 315 316 static int qp_sig_enabled(void) 317 { 318 char *env; 319 320 env = getenv("MLX5_QP_SIGNATURE"); 321 if (env) 322 return 1; 323 324 return 0; 325 } 326 327 enum { 328 CREATE_CQ_SUPPORTED_WC_FLAGS = IBV_WC_STANDARD_FLAGS | 329 IBV_WC_EX_WITH_COMPLETION_TIMESTAMP | 330 IBV_WC_EX_WITH_CVLAN | 331 IBV_WC_EX_WITH_FLOW_TAG 332 }; 333 334 enum { 335 CREATE_CQ_SUPPORTED_COMP_MASK = IBV_CQ_INIT_ATTR_MASK_FLAGS 336 }; 337 338 enum { 339 CREATE_CQ_SUPPORTED_FLAGS = IBV_CREATE_CQ_ATTR_SINGLE_THREADED 340 }; 341 342 static struct ibv_cq_ex *create_cq(struct ibv_context *context, 343 const struct ibv_cq_init_attr_ex *cq_attr, 344 int cq_alloc_flags, 345 struct mlx5dv_cq_init_attr *mlx5cq_attr) 346 { 347 struct mlx5_create_cq cmd; 348 struct mlx5_create_cq_resp resp; 349 struct mlx5_cq *cq; 350 int cqe_sz; 351 int ret; 352 int ncqe; 353 struct mlx5_context *mctx = to_mctx(context); 354 FILE *fp = to_mctx(context)->dbg_fp; 355 356 if (!cq_attr->cqe) { 357 mlx5_dbg(fp, MLX5_DBG_CQ, "CQE invalid\n"); 358 errno = EINVAL; 359 return NULL; 360 } 361 362 if (cq_attr->comp_mask & ~CREATE_CQ_SUPPORTED_COMP_MASK) { 363 mlx5_dbg(fp, MLX5_DBG_CQ, 364 "Unsupported comp_mask for create_cq\n"); 365 errno = EINVAL; 366 return NULL; 367 } 368 369 if (cq_attr->comp_mask & IBV_CQ_INIT_ATTR_MASK_FLAGS && 370 cq_attr->flags & ~CREATE_CQ_SUPPORTED_FLAGS) { 371 mlx5_dbg(fp, MLX5_DBG_CQ, 372 "Unsupported creation flags requested for create_cq\n"); 373 errno = EINVAL; 374 return NULL; 375 } 376 377 if (cq_attr->wc_flags & ~CREATE_CQ_SUPPORTED_WC_FLAGS) { 378 mlx5_dbg(fp, MLX5_DBG_CQ, "\n"); 379 errno = ENOTSUP; 380 return NULL; 381 } 382 383 cq = calloc(1, sizeof *cq); 384 if (!cq) { 385 mlx5_dbg(fp, MLX5_DBG_CQ, "\n"); 386 return NULL; 387 } 388 389 memset(&cmd, 0, sizeof cmd); 390 cq->cons_index = 0; 391 392 if (mlx5_spinlock_init(&cq->lock)) 393 goto err; 394 395 ncqe = align_queue_size(cq_attr->cqe + 1); 396 if ((ncqe > (1 << 24)) || (ncqe < (cq_attr->cqe + 1))) { 397 mlx5_dbg(fp, MLX5_DBG_CQ, "ncqe %d\n", ncqe); 398 errno = EINVAL; 399 goto err_spl; 400 } 401 402 cqe_sz = get_cqe_size(); 403 if (cqe_sz < 0) { 404 mlx5_dbg(fp, MLX5_DBG_CQ, "\n"); 405 errno = -cqe_sz; 406 goto err_spl; 407 } 408 409 if (mlx5_alloc_cq_buf(to_mctx(context), cq, &cq->buf_a, ncqe, cqe_sz)) { 410 mlx5_dbg(fp, MLX5_DBG_CQ, "\n"); 411 goto err_spl; 412 } 413 414 cq->dbrec = mlx5_alloc_dbrec(to_mctx(context)); 415 if (!cq->dbrec) { 416 mlx5_dbg(fp, MLX5_DBG_CQ, "\n"); 417 goto err_buf; 418 } 419 420 cq->dbrec[MLX5_CQ_SET_CI] = 0; 421 cq->dbrec[MLX5_CQ_ARM_DB] = 0; 422 cq->arm_sn = 0; 423 cq->cqe_sz = cqe_sz; 424 cq->flags = cq_alloc_flags; 425 426 if (cq_attr->comp_mask & IBV_CQ_INIT_ATTR_MASK_FLAGS && 427 cq_attr->flags & IBV_CREATE_CQ_ATTR_SINGLE_THREADED) 428 cq->flags |= MLX5_CQ_FLAGS_SINGLE_THREADED; 429 cmd.buf_addr = (uintptr_t) cq->buf_a.buf; 430 cmd.db_addr = (uintptr_t) cq->dbrec; 431 cmd.cqe_size = cqe_sz; 432 433 if (mlx5cq_attr) { 434 if (mlx5cq_attr->comp_mask & ~(MLX5DV_CQ_INIT_ATTR_MASK_RESERVED - 1)) { 435 mlx5_dbg(fp, MLX5_DBG_CQ, 436 "Unsupported vendor comp_mask for create_cq\n"); 437 errno = EINVAL; 438 goto err_db; 439 } 440 441 if (mlx5cq_attr->comp_mask & MLX5DV_CQ_INIT_ATTR_MASK_COMPRESSED_CQE) { 442 if (mctx->cqe_comp_caps.max_num && 443 (mlx5cq_attr->cqe_comp_res_format & 444 mctx->cqe_comp_caps.supported_format)) { 445 cmd.cqe_comp_en = 1; 446 cmd.cqe_comp_res_format = mlx5cq_attr->cqe_comp_res_format; 447 } else { 448 mlx5_dbg(fp, MLX5_DBG_CQ, "CQE Compression is not supported\n"); 449 errno = EINVAL; 450 goto err_db; 451 } 452 } 453 } 454 455 ret = ibv_cmd_create_cq(context, ncqe - 1, cq_attr->channel, 456 cq_attr->comp_vector, 457 ibv_cq_ex_to_cq(&cq->ibv_cq), &cmd.ibv_cmd, 458 sizeof(cmd), &resp.ibv_resp, sizeof(resp)); 459 if (ret) { 460 mlx5_dbg(fp, MLX5_DBG_CQ, "ret %d\n", ret); 461 goto err_db; 462 } 463 464 cq->active_buf = &cq->buf_a; 465 cq->resize_buf = NULL; 466 cq->cqn = resp.cqn; 467 cq->stall_enable = to_mctx(context)->stall_enable; 468 cq->stall_adaptive_enable = to_mctx(context)->stall_adaptive_enable; 469 cq->stall_cycles = to_mctx(context)->stall_cycles; 470 471 if (cq_alloc_flags & MLX5_CQ_FLAGS_EXTENDED) 472 mlx5_cq_fill_pfns(cq, cq_attr); 473 474 return &cq->ibv_cq; 475 476 err_db: 477 mlx5_free_db(to_mctx(context), cq->dbrec); 478 479 err_buf: 480 mlx5_free_cq_buf(to_mctx(context), &cq->buf_a); 481 482 err_spl: 483 mlx5_spinlock_destroy(&cq->lock); 484 485 err: 486 free(cq); 487 488 return NULL; 489 } 490 491 struct ibv_cq *mlx5_create_cq(struct ibv_context *context, int cqe, 492 struct ibv_comp_channel *channel, 493 int comp_vector) 494 { 495 struct ibv_cq_ex *cq; 496 struct ibv_cq_init_attr_ex cq_attr = {.cqe = cqe, .channel = channel, 497 .comp_vector = comp_vector, 498 .wc_flags = IBV_WC_STANDARD_FLAGS}; 499 500 if (cqe <= 0) { 501 errno = EINVAL; 502 return NULL; 503 } 504 505 cq = create_cq(context, &cq_attr, 0, NULL); 506 return cq ? ibv_cq_ex_to_cq(cq) : NULL; 507 } 508 509 struct ibv_cq_ex *mlx5_create_cq_ex(struct ibv_context *context, 510 struct ibv_cq_init_attr_ex *cq_attr) 511 { 512 return create_cq(context, cq_attr, MLX5_CQ_FLAGS_EXTENDED, NULL); 513 } 514 515 struct ibv_cq_ex *mlx5dv_create_cq(struct ibv_context *context, 516 struct ibv_cq_init_attr_ex *cq_attr, 517 struct mlx5dv_cq_init_attr *mlx5_cq_attr) 518 { 519 struct ibv_cq_ex *cq; 520 int err = 0; 521 522 cq = create_cq(context, cq_attr, MLX5_CQ_FLAGS_EXTENDED, mlx5_cq_attr); 523 if (!cq) 524 return NULL; 525 526 err = verbs_init_cq(ibv_cq_ex_to_cq(cq), context, 527 cq_attr->channel, cq_attr->cq_context); 528 if (err) 529 goto err; 530 531 return cq; 532 533 err: 534 context->ops.destroy_cq(ibv_cq_ex_to_cq(cq)); 535 536 return NULL; 537 } 538 539 int mlx5_resize_cq(struct ibv_cq *ibcq, int cqe) 540 { 541 struct mlx5_cq *cq = to_mcq(ibcq); 542 struct mlx5_resize_cq_resp resp; 543 struct mlx5_resize_cq cmd; 544 struct mlx5_context *mctx = to_mctx(ibcq->context); 545 int err; 546 547 if (cqe < 0) { 548 errno = EINVAL; 549 return errno; 550 } 551 552 memset(&cmd, 0, sizeof(cmd)); 553 memset(&resp, 0, sizeof(resp)); 554 555 if (((long long)cqe * 64) > INT_MAX) 556 return EINVAL; 557 558 mlx5_spin_lock(&cq->lock); 559 cq->active_cqes = cq->ibv_cq.cqe; 560 if (cq->active_buf == &cq->buf_a) 561 cq->resize_buf = &cq->buf_b; 562 else 563 cq->resize_buf = &cq->buf_a; 564 565 cqe = align_queue_size(cqe + 1); 566 if (cqe == ibcq->cqe + 1) { 567 cq->resize_buf = NULL; 568 err = 0; 569 goto out; 570 } 571 572 /* currently we don't change cqe size */ 573 cq->resize_cqe_sz = cq->cqe_sz; 574 cq->resize_cqes = cqe; 575 err = mlx5_alloc_cq_buf(mctx, cq, cq->resize_buf, cq->resize_cqes, cq->resize_cqe_sz); 576 if (err) { 577 cq->resize_buf = NULL; 578 errno = ENOMEM; 579 goto out; 580 } 581 582 cmd.buf_addr = (uintptr_t)cq->resize_buf->buf; 583 cmd.cqe_size = cq->resize_cqe_sz; 584 585 err = ibv_cmd_resize_cq(ibcq, cqe - 1, &cmd.ibv_cmd, sizeof(cmd), 586 &resp.ibv_resp, sizeof(resp)); 587 if (err) 588 goto out_buf; 589 590 mlx5_cq_resize_copy_cqes(cq); 591 mlx5_free_cq_buf(mctx, cq->active_buf); 592 cq->active_buf = cq->resize_buf; 593 cq->ibv_cq.cqe = cqe - 1; 594 mlx5_spin_unlock(&cq->lock); 595 cq->resize_buf = NULL; 596 return 0; 597 598 out_buf: 599 mlx5_free_cq_buf(mctx, cq->resize_buf); 600 cq->resize_buf = NULL; 601 602 out: 603 mlx5_spin_unlock(&cq->lock); 604 return err; 605 } 606 607 int mlx5_destroy_cq(struct ibv_cq *cq) 608 { 609 int ret; 610 struct mlx5_cq *mcq = to_mcq(cq); 611 612 ret = ibv_cmd_destroy_cq(cq); 613 if (ret) 614 return ret; 615 616 verbs_cleanup_cq(cq); 617 mlx5_free_db(to_mctx(cq->context), to_mcq(cq)->dbrec); 618 mlx5_free_cq_buf(to_mctx(cq->context), to_mcq(cq)->active_buf); 619 mlx5_spinlock_destroy(&mcq->lock); 620 free(to_mcq(cq)); 621 622 return 0; 623 } 624 625 struct ibv_srq *mlx5_create_srq(struct ibv_pd *pd, 626 struct ibv_srq_init_attr *attr) 627 { 628 struct mlx5_create_srq cmd; 629 struct mlx5_create_srq_resp resp; 630 struct mlx5_srq *srq; 631 int ret; 632 struct mlx5_context *ctx; 633 int max_sge; 634 struct ibv_srq *ibsrq; 635 636 ctx = to_mctx(pd->context); 637 srq = calloc(1, sizeof *srq); 638 if (!srq) { 639 fprintf(stderr, "%s-%d:\n", __func__, __LINE__); 640 return NULL; 641 } 642 ibsrq = &srq->vsrq.srq; 643 644 memset(&cmd, 0, sizeof cmd); 645 if (mlx5_spinlock_init(&srq->lock)) { 646 fprintf(stderr, "%s-%d:\n", __func__, __LINE__); 647 goto err; 648 } 649 650 if (attr->attr.max_wr > ctx->max_srq_recv_wr) { 651 fprintf(stderr, "%s-%d:max_wr %d, max_srq_recv_wr %d\n", __func__, __LINE__, 652 attr->attr.max_wr, ctx->max_srq_recv_wr); 653 errno = EINVAL; 654 goto err_spl; 655 } 656 657 /* 658 * this calculation does not consider required control segments. The 659 * final calculation is done again later. This is done so to avoid 660 * overflows of variables 661 */ 662 max_sge = ctx->max_rq_desc_sz / sizeof(struct mlx5_wqe_data_seg); 663 if (attr->attr.max_sge > max_sge) { 664 fprintf(stderr, "%s-%d:max_wr %d, max_srq_recv_wr %d\n", __func__, __LINE__, 665 attr->attr.max_wr, ctx->max_srq_recv_wr); 666 errno = EINVAL; 667 goto err_spl; 668 } 669 670 srq->max = align_queue_size(attr->attr.max_wr + 1); 671 srq->max_gs = attr->attr.max_sge; 672 srq->counter = 0; 673 674 if (mlx5_alloc_srq_buf(pd->context, srq)) { 675 fprintf(stderr, "%s-%d:\n", __func__, __LINE__); 676 goto err_spl; 677 } 678 679 srq->db = mlx5_alloc_dbrec(to_mctx(pd->context)); 680 if (!srq->db) { 681 fprintf(stderr, "%s-%d:\n", __func__, __LINE__); 682 goto err_free; 683 } 684 685 *srq->db = 0; 686 687 cmd.buf_addr = (uintptr_t) srq->buf.buf; 688 cmd.db_addr = (uintptr_t) srq->db; 689 srq->wq_sig = srq_sig_enabled(); 690 if (srq->wq_sig) 691 cmd.flags = MLX5_SRQ_FLAG_SIGNATURE; 692 693 attr->attr.max_sge = srq->max_gs; 694 pthread_mutex_lock(&ctx->srq_table_mutex); 695 ret = ibv_cmd_create_srq(pd, ibsrq, attr, &cmd.ibv_cmd, sizeof(cmd), 696 &resp.ibv_resp, sizeof(resp)); 697 if (ret) 698 goto err_db; 699 700 ret = mlx5_store_srq(ctx, resp.srqn, srq); 701 if (ret) 702 goto err_destroy; 703 704 pthread_mutex_unlock(&ctx->srq_table_mutex); 705 706 srq->srqn = resp.srqn; 707 srq->rsc.rsn = resp.srqn; 708 srq->rsc.type = MLX5_RSC_TYPE_SRQ; 709 710 return ibsrq; 711 712 err_destroy: 713 ibv_cmd_destroy_srq(ibsrq); 714 715 err_db: 716 pthread_mutex_unlock(&ctx->srq_table_mutex); 717 mlx5_free_db(to_mctx(pd->context), srq->db); 718 719 err_free: 720 free(srq->wrid); 721 mlx5_free_buf(&srq->buf); 722 723 err_spl: 724 mlx5_spinlock_destroy(&srq->lock); 725 726 err: 727 free(srq); 728 729 return NULL; 730 } 731 732 int mlx5_modify_srq(struct ibv_srq *srq, 733 struct ibv_srq_attr *attr, 734 int attr_mask) 735 { 736 struct ibv_modify_srq cmd; 737 738 return ibv_cmd_modify_srq(srq, attr, attr_mask, &cmd, sizeof cmd); 739 } 740 741 int mlx5_query_srq(struct ibv_srq *srq, 742 struct ibv_srq_attr *attr) 743 { 744 struct ibv_query_srq cmd; 745 746 return ibv_cmd_query_srq(srq, attr, &cmd, sizeof cmd); 747 } 748 749 int mlx5_destroy_srq(struct ibv_srq *srq) 750 { 751 int ret; 752 struct mlx5_srq *msrq = to_msrq(srq); 753 struct mlx5_context *ctx = to_mctx(srq->context); 754 755 ret = ibv_cmd_destroy_srq(srq); 756 if (ret) 757 return ret; 758 759 if (ctx->cqe_version && msrq->rsc.type == MLX5_RSC_TYPE_XSRQ) 760 mlx5_clear_uidx(ctx, msrq->rsc.rsn); 761 else 762 mlx5_clear_srq(ctx, msrq->srqn); 763 764 mlx5_free_db(ctx, msrq->db); 765 mlx5_free_buf(&msrq->buf); 766 free(msrq->wrid); 767 mlx5_spinlock_destroy(&msrq->lock); 768 free(msrq); 769 770 return 0; 771 } 772 773 static int sq_overhead(enum ibv_qp_type qp_type) 774 { 775 size_t size = 0; 776 size_t mw_bind_size = 777 sizeof(struct mlx5_wqe_umr_ctrl_seg) + 778 sizeof(struct mlx5_wqe_mkey_context_seg) + 779 max_t(size_t, sizeof(struct mlx5_wqe_umr_klm_seg), 64); 780 781 switch (qp_type) { 782 case IBV_QPT_RC: 783 size += sizeof(struct mlx5_wqe_ctrl_seg) + 784 max(sizeof(struct mlx5_wqe_atomic_seg) + 785 sizeof(struct mlx5_wqe_raddr_seg), 786 mw_bind_size); 787 break; 788 789 case IBV_QPT_UC: 790 size = sizeof(struct mlx5_wqe_ctrl_seg) + 791 max(sizeof(struct mlx5_wqe_raddr_seg), 792 mw_bind_size); 793 break; 794 795 case IBV_QPT_UD: 796 size = sizeof(struct mlx5_wqe_ctrl_seg) + 797 sizeof(struct mlx5_wqe_datagram_seg); 798 break; 799 800 case IBV_QPT_XRC_SEND: 801 size = sizeof(struct mlx5_wqe_ctrl_seg) + mw_bind_size; 802 SWITCH_FALLTHROUGH; 803 804 case IBV_QPT_XRC_RECV: 805 size = max(size, sizeof(struct mlx5_wqe_ctrl_seg) + 806 sizeof(struct mlx5_wqe_xrc_seg) + 807 sizeof(struct mlx5_wqe_raddr_seg)); 808 break; 809 810 case IBV_QPT_RAW_PACKET: 811 size = sizeof(struct mlx5_wqe_ctrl_seg) + 812 sizeof(struct mlx5_wqe_eth_seg); 813 break; 814 815 default: 816 return -EINVAL; 817 } 818 819 return size; 820 } 821 822 static int mlx5_calc_send_wqe(struct mlx5_context *ctx, 823 struct ibv_qp_init_attr_ex *attr, 824 struct mlx5_qp *qp) 825 { 826 int size; 827 int inl_size = 0; 828 int max_gather; 829 int tot_size; 830 831 size = sq_overhead(attr->qp_type); 832 if (size < 0) 833 return size; 834 835 if (attr->cap.max_inline_data) { 836 inl_size = size + align(sizeof(struct mlx5_wqe_inl_data_seg) + 837 attr->cap.max_inline_data, 16); 838 } 839 840 if (attr->comp_mask & IBV_QP_INIT_ATTR_MAX_TSO_HEADER) { 841 size += align(attr->max_tso_header, 16); 842 qp->max_tso_header = attr->max_tso_header; 843 } 844 845 max_gather = (ctx->max_sq_desc_sz - size) / 846 sizeof(struct mlx5_wqe_data_seg); 847 if (attr->cap.max_send_sge > max_gather) 848 return -EINVAL; 849 850 size += attr->cap.max_send_sge * sizeof(struct mlx5_wqe_data_seg); 851 tot_size = max_int(size, inl_size); 852 853 if (tot_size > ctx->max_sq_desc_sz) 854 return -EINVAL; 855 856 return align(tot_size, MLX5_SEND_WQE_BB); 857 } 858 859 static int mlx5_calc_rcv_wqe(struct mlx5_context *ctx, 860 struct ibv_qp_init_attr_ex *attr, 861 struct mlx5_qp *qp) 862 { 863 uint32_t size; 864 int num_scatter; 865 866 if (attr->srq) 867 return 0; 868 869 num_scatter = max_t(uint32_t, attr->cap.max_recv_sge, 1); 870 size = sizeof(struct mlx5_wqe_data_seg) * num_scatter; 871 if (qp->wq_sig) 872 size += sizeof(struct mlx5_rwqe_sig); 873 874 if (size > ctx->max_rq_desc_sz) 875 return -EINVAL; 876 877 size = mlx5_round_up_power_of_two(size); 878 879 return size; 880 } 881 882 static int mlx5_calc_sq_size(struct mlx5_context *ctx, 883 struct ibv_qp_init_attr_ex *attr, 884 struct mlx5_qp *qp) 885 { 886 int wqe_size; 887 int wq_size; 888 FILE *fp = ctx->dbg_fp; 889 890 if (!attr->cap.max_send_wr) 891 return 0; 892 893 wqe_size = mlx5_calc_send_wqe(ctx, attr, qp); 894 if (wqe_size < 0) { 895 mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 896 return wqe_size; 897 } 898 899 if (wqe_size > ctx->max_sq_desc_sz) { 900 mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 901 return -EINVAL; 902 } 903 904 qp->max_inline_data = wqe_size - sq_overhead(attr->qp_type) - 905 sizeof(struct mlx5_wqe_inl_data_seg); 906 attr->cap.max_inline_data = qp->max_inline_data; 907 908 /* 909 * to avoid overflow, we limit max_send_wr so 910 * that the multiplication will fit in int 911 */ 912 if (attr->cap.max_send_wr > 0x7fffffff / ctx->max_sq_desc_sz) { 913 mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 914 return -EINVAL; 915 } 916 917 wq_size = mlx5_round_up_power_of_two(attr->cap.max_send_wr * wqe_size); 918 qp->sq.wqe_cnt = wq_size / MLX5_SEND_WQE_BB; 919 if (qp->sq.wqe_cnt > ctx->max_send_wqebb) { 920 mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 921 return -EINVAL; 922 } 923 924 qp->sq.wqe_shift = mlx5_ilog2(MLX5_SEND_WQE_BB); 925 qp->sq.max_gs = attr->cap.max_send_sge; 926 qp->sq.max_post = wq_size / wqe_size; 927 928 return wq_size; 929 } 930 931 static int mlx5_calc_rwq_size(struct mlx5_context *ctx, 932 struct mlx5_rwq *rwq, 933 struct ibv_wq_init_attr *attr) 934 { 935 size_t wqe_size; 936 int wq_size; 937 uint32_t num_scatter; 938 int scat_spc; 939 940 if (!attr->max_wr) 941 return -EINVAL; 942 943 /* TBD: check caps for RQ */ 944 num_scatter = max_t(uint32_t, attr->max_sge, 1); 945 wqe_size = sizeof(struct mlx5_wqe_data_seg) * num_scatter; 946 947 if (rwq->wq_sig) 948 wqe_size += sizeof(struct mlx5_rwqe_sig); 949 950 if (wqe_size <= 0 || wqe_size > ctx->max_rq_desc_sz) 951 return -EINVAL; 952 953 wqe_size = mlx5_round_up_power_of_two(wqe_size); 954 wq_size = mlx5_round_up_power_of_two(attr->max_wr) * wqe_size; 955 wq_size = max(wq_size, MLX5_SEND_WQE_BB); 956 rwq->rq.wqe_cnt = wq_size / wqe_size; 957 rwq->rq.wqe_shift = mlx5_ilog2(wqe_size); 958 rwq->rq.max_post = 1 << mlx5_ilog2(wq_size / wqe_size); 959 scat_spc = wqe_size - 960 ((rwq->wq_sig) ? sizeof(struct mlx5_rwqe_sig) : 0); 961 rwq->rq.max_gs = scat_spc / sizeof(struct mlx5_wqe_data_seg); 962 return wq_size; 963 } 964 965 static int mlx5_calc_rq_size(struct mlx5_context *ctx, 966 struct ibv_qp_init_attr_ex *attr, 967 struct mlx5_qp *qp) 968 { 969 int wqe_size; 970 int wq_size; 971 int scat_spc; 972 FILE *fp = ctx->dbg_fp; 973 974 if (!attr->cap.max_recv_wr) 975 return 0; 976 977 if (attr->cap.max_recv_wr > ctx->max_recv_wr) { 978 mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 979 return -EINVAL; 980 } 981 982 wqe_size = mlx5_calc_rcv_wqe(ctx, attr, qp); 983 if (wqe_size < 0 || wqe_size > ctx->max_rq_desc_sz) { 984 mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 985 return -EINVAL; 986 } 987 988 wq_size = mlx5_round_up_power_of_two(attr->cap.max_recv_wr) * wqe_size; 989 if (wqe_size) { 990 wq_size = max(wq_size, MLX5_SEND_WQE_BB); 991 qp->rq.wqe_cnt = wq_size / wqe_size; 992 qp->rq.wqe_shift = mlx5_ilog2(wqe_size); 993 qp->rq.max_post = 1 << mlx5_ilog2(wq_size / wqe_size); 994 scat_spc = wqe_size - 995 (qp->wq_sig ? sizeof(struct mlx5_rwqe_sig) : 0); 996 qp->rq.max_gs = scat_spc / sizeof(struct mlx5_wqe_data_seg); 997 } else { 998 qp->rq.wqe_cnt = 0; 999 qp->rq.wqe_shift = 0; 1000 qp->rq.max_post = 0; 1001 qp->rq.max_gs = 0; 1002 } 1003 return wq_size; 1004 } 1005 1006 static int mlx5_calc_wq_size(struct mlx5_context *ctx, 1007 struct ibv_qp_init_attr_ex *attr, 1008 struct mlx5_qp *qp) 1009 { 1010 int ret; 1011 int result; 1012 1013 ret = mlx5_calc_sq_size(ctx, attr, qp); 1014 if (ret < 0) 1015 return ret; 1016 1017 result = ret; 1018 ret = mlx5_calc_rq_size(ctx, attr, qp); 1019 if (ret < 0) 1020 return ret; 1021 1022 result += ret; 1023 1024 qp->sq.offset = ret; 1025 qp->rq.offset = 0; 1026 1027 return result; 1028 } 1029 1030 static void map_uuar(struct ibv_context *context, struct mlx5_qp *qp, 1031 int uuar_index) 1032 { 1033 struct mlx5_context *ctx = to_mctx(context); 1034 1035 qp->bf = &ctx->bfs[uuar_index]; 1036 } 1037 1038 static const char *qptype2key(enum ibv_qp_type type) 1039 { 1040 switch (type) { 1041 case IBV_QPT_RC: return "HUGE_RC"; 1042 case IBV_QPT_UC: return "HUGE_UC"; 1043 case IBV_QPT_UD: return "HUGE_UD"; 1044 case IBV_QPT_RAW_PACKET: return "HUGE_RAW_ETH"; 1045 default: return "HUGE_NA"; 1046 } 1047 } 1048 1049 static int mlx5_alloc_qp_buf(struct ibv_context *context, 1050 struct ibv_qp_init_attr_ex *attr, 1051 struct mlx5_qp *qp, 1052 int size) 1053 { 1054 int err; 1055 enum mlx5_alloc_type alloc_type; 1056 enum mlx5_alloc_type default_alloc_type = MLX5_ALLOC_TYPE_ANON; 1057 const char *qp_huge_key; 1058 1059 if (qp->sq.wqe_cnt) { 1060 qp->sq.wrid = malloc(qp->sq.wqe_cnt * sizeof(*qp->sq.wrid)); 1061 if (!qp->sq.wrid) { 1062 errno = ENOMEM; 1063 err = -1; 1064 return err; 1065 } 1066 1067 qp->sq.wr_data = malloc(qp->sq.wqe_cnt * sizeof(*qp->sq.wr_data)); 1068 if (!qp->sq.wr_data) { 1069 errno = ENOMEM; 1070 err = -1; 1071 goto ex_wrid; 1072 } 1073 } 1074 1075 qp->sq.wqe_head = malloc(qp->sq.wqe_cnt * sizeof(*qp->sq.wqe_head)); 1076 if (!qp->sq.wqe_head) { 1077 errno = ENOMEM; 1078 err = -1; 1079 goto ex_wrid; 1080 } 1081 1082 if (qp->rq.wqe_cnt) { 1083 qp->rq.wrid = malloc(qp->rq.wqe_cnt * sizeof(uint64_t)); 1084 if (!qp->rq.wrid) { 1085 errno = ENOMEM; 1086 err = -1; 1087 goto ex_wrid; 1088 } 1089 } 1090 1091 /* compatibility support */ 1092 qp_huge_key = qptype2key(qp->ibv_qp->qp_type); 1093 if (mlx5_use_huge(qp_huge_key)) 1094 default_alloc_type = MLX5_ALLOC_TYPE_HUGE; 1095 1096 mlx5_get_alloc_type(MLX5_QP_PREFIX, &alloc_type, 1097 default_alloc_type); 1098 1099 err = mlx5_alloc_prefered_buf(to_mctx(context), &qp->buf, 1100 align(qp->buf_size, to_mdev 1101 (context->device)->page_size), 1102 to_mdev(context->device)->page_size, 1103 alloc_type, 1104 MLX5_QP_PREFIX); 1105 1106 if (err) { 1107 err = -ENOMEM; 1108 goto ex_wrid; 1109 } 1110 1111 memset(qp->buf.buf, 0, qp->buf_size); 1112 1113 if (attr->qp_type == IBV_QPT_RAW_PACKET) { 1114 size_t aligned_sq_buf_size = align(qp->sq_buf_size, 1115 to_mdev(context->device)->page_size); 1116 /* For Raw Packet QP, allocate a separate buffer for the SQ */ 1117 err = mlx5_alloc_prefered_buf(to_mctx(context), &qp->sq_buf, 1118 aligned_sq_buf_size, 1119 to_mdev(context->device)->page_size, 1120 alloc_type, 1121 MLX5_QP_PREFIX); 1122 if (err) { 1123 err = -ENOMEM; 1124 goto rq_buf; 1125 } 1126 1127 memset(qp->sq_buf.buf, 0, aligned_sq_buf_size); 1128 } 1129 1130 return 0; 1131 rq_buf: 1132 mlx5_free_actual_buf(to_mctx(qp->verbs_qp.qp.context), &qp->buf); 1133 ex_wrid: 1134 if (qp->rq.wrid) 1135 free(qp->rq.wrid); 1136 1137 if (qp->sq.wqe_head) 1138 free(qp->sq.wqe_head); 1139 1140 if (qp->sq.wr_data) 1141 free(qp->sq.wr_data); 1142 if (qp->sq.wrid) 1143 free(qp->sq.wrid); 1144 1145 return err; 1146 } 1147 1148 static void mlx5_free_qp_buf(struct mlx5_qp *qp) 1149 { 1150 struct mlx5_context *ctx = to_mctx(qp->ibv_qp->context); 1151 1152 mlx5_free_actual_buf(ctx, &qp->buf); 1153 1154 if (qp->sq_buf.buf) 1155 mlx5_free_actual_buf(ctx, &qp->sq_buf); 1156 1157 if (qp->rq.wrid) 1158 free(qp->rq.wrid); 1159 1160 if (qp->sq.wqe_head) 1161 free(qp->sq.wqe_head); 1162 1163 if (qp->sq.wrid) 1164 free(qp->sq.wrid); 1165 1166 if (qp->sq.wr_data) 1167 free(qp->sq.wr_data); 1168 } 1169 1170 static int mlx5_cmd_create_rss_qp(struct ibv_context *context, 1171 struct ibv_qp_init_attr_ex *attr, 1172 struct mlx5_qp *qp) 1173 { 1174 struct mlx5_create_qp_ex_rss cmd_ex_rss = {}; 1175 struct mlx5_create_qp_resp_ex resp = {}; 1176 int ret; 1177 1178 if (attr->rx_hash_conf.rx_hash_key_len > sizeof(cmd_ex_rss.rx_hash_key)) { 1179 errno = EINVAL; 1180 return errno; 1181 } 1182 1183 cmd_ex_rss.rx_hash_fields_mask = attr->rx_hash_conf.rx_hash_fields_mask; 1184 cmd_ex_rss.rx_hash_function = attr->rx_hash_conf.rx_hash_function; 1185 cmd_ex_rss.rx_key_len = attr->rx_hash_conf.rx_hash_key_len; 1186 memcpy(cmd_ex_rss.rx_hash_key, attr->rx_hash_conf.rx_hash_key, 1187 attr->rx_hash_conf.rx_hash_key_len); 1188 1189 ret = ibv_cmd_create_qp_ex2(context, &qp->verbs_qp, 1190 sizeof(qp->verbs_qp), attr, 1191 &cmd_ex_rss.ibv_cmd, sizeof(cmd_ex_rss.ibv_cmd), 1192 sizeof(cmd_ex_rss), &resp.ibv_resp, 1193 sizeof(resp.ibv_resp), sizeof(resp)); 1194 if (ret) 1195 return ret; 1196 1197 qp->rss_qp = 1; 1198 return 0; 1199 } 1200 1201 static int mlx5_cmd_create_qp_ex(struct ibv_context *context, 1202 struct ibv_qp_init_attr_ex *attr, 1203 struct mlx5_create_qp *cmd, 1204 struct mlx5_qp *qp, 1205 struct mlx5_create_qp_resp_ex *resp) 1206 { 1207 struct mlx5_create_qp_ex cmd_ex; 1208 int ret; 1209 1210 memset(&cmd_ex, 0, sizeof(cmd_ex)); 1211 memcpy(&cmd_ex.ibv_cmd.base, &cmd->ibv_cmd.user_handle, 1212 offsetof(typeof(cmd->ibv_cmd), is_srq) + 1213 sizeof(cmd->ibv_cmd.is_srq) - 1214 offsetof(typeof(cmd->ibv_cmd), user_handle)); 1215 1216 memcpy(&cmd_ex.drv_ex, &cmd->buf_addr, 1217 offsetof(typeof(*cmd), sq_buf_addr) + 1218 sizeof(cmd->sq_buf_addr) - sizeof(cmd->ibv_cmd)); 1219 1220 ret = ibv_cmd_create_qp_ex2(context, &qp->verbs_qp, 1221 sizeof(qp->verbs_qp), attr, 1222 &cmd_ex.ibv_cmd, sizeof(cmd_ex.ibv_cmd), 1223 sizeof(cmd_ex), &resp->ibv_resp, 1224 sizeof(resp->ibv_resp), sizeof(*resp)); 1225 1226 return ret; 1227 } 1228 1229 enum { 1230 MLX5_CREATE_QP_SUP_COMP_MASK = (IBV_QP_INIT_ATTR_PD | 1231 IBV_QP_INIT_ATTR_XRCD | 1232 IBV_QP_INIT_ATTR_CREATE_FLAGS | 1233 IBV_QP_INIT_ATTR_MAX_TSO_HEADER | 1234 IBV_QP_INIT_ATTR_IND_TABLE | 1235 IBV_QP_INIT_ATTR_RX_HASH), 1236 }; 1237 1238 enum { 1239 MLX5_CREATE_QP_EX2_COMP_MASK = (IBV_QP_INIT_ATTR_CREATE_FLAGS | 1240 IBV_QP_INIT_ATTR_MAX_TSO_HEADER | 1241 IBV_QP_INIT_ATTR_IND_TABLE | 1242 IBV_QP_INIT_ATTR_RX_HASH), 1243 }; 1244 1245 static struct ibv_qp *create_qp(struct ibv_context *context, 1246 struct ibv_qp_init_attr_ex *attr) 1247 { 1248 struct mlx5_create_qp cmd; 1249 struct mlx5_create_qp_resp resp; 1250 struct mlx5_create_qp_resp_ex resp_ex; 1251 struct mlx5_qp *qp; 1252 int ret; 1253 struct mlx5_context *ctx = to_mctx(context); 1254 struct ibv_qp *ibqp; 1255 int32_t usr_idx = 0; 1256 uint32_t uuar_index; 1257 FILE *fp = ctx->dbg_fp; 1258 1259 if (attr->comp_mask & ~MLX5_CREATE_QP_SUP_COMP_MASK) 1260 return NULL; 1261 1262 if ((attr->comp_mask & IBV_QP_INIT_ATTR_MAX_TSO_HEADER) && 1263 (attr->qp_type != IBV_QPT_RAW_PACKET)) 1264 return NULL; 1265 1266 qp = calloc(1, sizeof(*qp)); 1267 if (!qp) { 1268 mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 1269 return NULL; 1270 } 1271 ibqp = (struct ibv_qp *)&qp->verbs_qp; 1272 qp->ibv_qp = ibqp; 1273 1274 memset(&cmd, 0, sizeof(cmd)); 1275 memset(&resp, 0, sizeof(resp)); 1276 memset(&resp_ex, 0, sizeof(resp_ex)); 1277 1278 if (attr->comp_mask & IBV_QP_INIT_ATTR_RX_HASH) { 1279 ret = mlx5_cmd_create_rss_qp(context, attr, qp); 1280 if (ret) 1281 goto err; 1282 1283 return ibqp; 1284 } 1285 1286 qp->wq_sig = qp_sig_enabled(); 1287 if (qp->wq_sig) 1288 cmd.flags |= MLX5_QP_FLAG_SIGNATURE; 1289 1290 if (use_scatter_to_cqe()) 1291 cmd.flags |= MLX5_QP_FLAG_SCATTER_CQE; 1292 1293 ret = mlx5_calc_wq_size(ctx, attr, qp); 1294 if (ret < 0) { 1295 errno = -ret; 1296 goto err; 1297 } 1298 1299 if (attr->qp_type == IBV_QPT_RAW_PACKET) { 1300 qp->buf_size = qp->sq.offset; 1301 qp->sq_buf_size = ret - qp->buf_size; 1302 qp->sq.offset = 0; 1303 } else { 1304 qp->buf_size = ret; 1305 qp->sq_buf_size = 0; 1306 } 1307 1308 if (mlx5_alloc_qp_buf(context, attr, qp, ret)) { 1309 mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 1310 goto err; 1311 } 1312 1313 if (attr->qp_type == IBV_QPT_RAW_PACKET) { 1314 qp->sq_start = qp->sq_buf.buf; 1315 qp->sq.qend = qp->sq_buf.buf + 1316 (qp->sq.wqe_cnt << qp->sq.wqe_shift); 1317 } else { 1318 qp->sq_start = qp->buf.buf + qp->sq.offset; 1319 qp->sq.qend = qp->buf.buf + qp->sq.offset + 1320 (qp->sq.wqe_cnt << qp->sq.wqe_shift); 1321 } 1322 1323 mlx5_init_qp_indices(qp); 1324 1325 if (mlx5_spinlock_init(&qp->sq.lock)) 1326 goto err_free_qp_buf; 1327 1328 if (mlx5_spinlock_init(&qp->rq.lock)) 1329 goto err_sq_spl; 1330 1331 qp->db = mlx5_alloc_dbrec(ctx); 1332 if (!qp->db) { 1333 mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 1334 goto err_rq_spl; 1335 } 1336 1337 qp->db[MLX5_RCV_DBR] = 0; 1338 qp->db[MLX5_SND_DBR] = 0; 1339 1340 cmd.buf_addr = (uintptr_t) qp->buf.buf; 1341 cmd.sq_buf_addr = (attr->qp_type == IBV_QPT_RAW_PACKET) ? 1342 (uintptr_t) qp->sq_buf.buf : 0; 1343 cmd.db_addr = (uintptr_t) qp->db; 1344 cmd.sq_wqe_count = qp->sq.wqe_cnt; 1345 cmd.rq_wqe_count = qp->rq.wqe_cnt; 1346 cmd.rq_wqe_shift = qp->rq.wqe_shift; 1347 1348 if (ctx->atomic_cap == IBV_ATOMIC_HCA) 1349 qp->atomics_enabled = 1; 1350 1351 if (!ctx->cqe_version) { 1352 cmd.uidx = 0xffffff; 1353 pthread_mutex_lock(&ctx->qp_table_mutex); 1354 } else if (!is_xrc_tgt(attr->qp_type)) { 1355 usr_idx = mlx5_store_uidx(ctx, qp); 1356 if (usr_idx < 0) { 1357 mlx5_dbg(fp, MLX5_DBG_QP, "Couldn't find free user index\n"); 1358 goto err_rq_db; 1359 } 1360 1361 cmd.uidx = usr_idx; 1362 } 1363 1364 if (attr->comp_mask & MLX5_CREATE_QP_EX2_COMP_MASK) 1365 ret = mlx5_cmd_create_qp_ex(context, attr, &cmd, qp, &resp_ex); 1366 else 1367 ret = ibv_cmd_create_qp_ex(context, &qp->verbs_qp, sizeof(qp->verbs_qp), 1368 attr, &cmd.ibv_cmd, sizeof(cmd), 1369 &resp.ibv_resp, sizeof(resp)); 1370 if (ret) { 1371 mlx5_dbg(fp, MLX5_DBG_QP, "ret %d\n", ret); 1372 goto err_free_uidx; 1373 } 1374 1375 uuar_index = (attr->comp_mask & MLX5_CREATE_QP_EX2_COMP_MASK) ? 1376 resp_ex.uuar_index : resp.uuar_index; 1377 if (!ctx->cqe_version) { 1378 if (qp->sq.wqe_cnt || qp->rq.wqe_cnt) { 1379 ret = mlx5_store_qp(ctx, ibqp->qp_num, qp); 1380 if (ret) { 1381 mlx5_dbg(fp, MLX5_DBG_QP, "ret %d\n", ret); 1382 goto err_destroy; 1383 } 1384 } 1385 1386 pthread_mutex_unlock(&ctx->qp_table_mutex); 1387 } 1388 1389 map_uuar(context, qp, uuar_index); 1390 1391 qp->rq.max_post = qp->rq.wqe_cnt; 1392 if (attr->sq_sig_all) 1393 qp->sq_signal_bits = MLX5_WQE_CTRL_CQ_UPDATE; 1394 else 1395 qp->sq_signal_bits = 0; 1396 1397 attr->cap.max_send_wr = qp->sq.max_post; 1398 attr->cap.max_recv_wr = qp->rq.max_post; 1399 attr->cap.max_recv_sge = qp->rq.max_gs; 1400 1401 qp->rsc.type = MLX5_RSC_TYPE_QP; 1402 qp->rsc.rsn = (ctx->cqe_version && !is_xrc_tgt(attr->qp_type)) ? 1403 usr_idx : ibqp->qp_num; 1404 1405 return ibqp; 1406 1407 err_destroy: 1408 ibv_cmd_destroy_qp(ibqp); 1409 1410 err_free_uidx: 1411 if (!ctx->cqe_version) 1412 pthread_mutex_unlock(&to_mctx(context)->qp_table_mutex); 1413 else if (!is_xrc_tgt(attr->qp_type)) 1414 mlx5_clear_uidx(ctx, usr_idx); 1415 1416 err_rq_db: 1417 mlx5_free_db(to_mctx(context), qp->db); 1418 1419 err_rq_spl: 1420 mlx5_spinlock_destroy(&qp->rq.lock); 1421 1422 err_sq_spl: 1423 mlx5_spinlock_destroy(&qp->sq.lock); 1424 1425 err_free_qp_buf: 1426 mlx5_free_qp_buf(qp); 1427 1428 err: 1429 free(qp); 1430 1431 return NULL; 1432 } 1433 1434 struct ibv_qp *mlx5_create_qp(struct ibv_pd *pd, 1435 struct ibv_qp_init_attr *attr) 1436 { 1437 struct ibv_qp *qp; 1438 struct ibv_qp_init_attr_ex attrx; 1439 1440 memset(&attrx, 0, sizeof(attrx)); 1441 memcpy(&attrx, attr, sizeof(*attr)); 1442 attrx.comp_mask = IBV_QP_INIT_ATTR_PD; 1443 attrx.pd = pd; 1444 qp = create_qp(pd->context, &attrx); 1445 if (qp) 1446 memcpy(attr, &attrx, sizeof(*attr)); 1447 1448 return qp; 1449 } 1450 1451 static void mlx5_lock_cqs(struct ibv_qp *qp) 1452 { 1453 struct mlx5_cq *send_cq = to_mcq(qp->send_cq); 1454 struct mlx5_cq *recv_cq = to_mcq(qp->recv_cq); 1455 1456 if (send_cq && recv_cq) { 1457 if (send_cq == recv_cq) { 1458 mlx5_spin_lock(&send_cq->lock); 1459 } else if (send_cq->cqn < recv_cq->cqn) { 1460 mlx5_spin_lock(&send_cq->lock); 1461 mlx5_spin_lock(&recv_cq->lock); 1462 } else { 1463 mlx5_spin_lock(&recv_cq->lock); 1464 mlx5_spin_lock(&send_cq->lock); 1465 } 1466 } else if (send_cq) { 1467 mlx5_spin_lock(&send_cq->lock); 1468 } else if (recv_cq) { 1469 mlx5_spin_lock(&recv_cq->lock); 1470 } 1471 } 1472 1473 static void mlx5_unlock_cqs(struct ibv_qp *qp) 1474 { 1475 struct mlx5_cq *send_cq = to_mcq(qp->send_cq); 1476 struct mlx5_cq *recv_cq = to_mcq(qp->recv_cq); 1477 1478 if (send_cq && recv_cq) { 1479 if (send_cq == recv_cq) { 1480 mlx5_spin_unlock(&send_cq->lock); 1481 } else if (send_cq->cqn < recv_cq->cqn) { 1482 mlx5_spin_unlock(&recv_cq->lock); 1483 mlx5_spin_unlock(&send_cq->lock); 1484 } else { 1485 mlx5_spin_unlock(&send_cq->lock); 1486 mlx5_spin_unlock(&recv_cq->lock); 1487 } 1488 } else if (send_cq) { 1489 mlx5_spin_unlock(&send_cq->lock); 1490 } else if (recv_cq) { 1491 mlx5_spin_unlock(&recv_cq->lock); 1492 } 1493 } 1494 1495 int mlx5_destroy_qp(struct ibv_qp *ibqp) 1496 { 1497 struct mlx5_qp *qp = to_mqp(ibqp); 1498 struct mlx5_context *ctx = to_mctx(ibqp->context); 1499 int ret; 1500 1501 if (qp->rss_qp) { 1502 ret = ibv_cmd_destroy_qp(ibqp); 1503 if (ret) 1504 return ret; 1505 goto free; 1506 } 1507 1508 if (!ctx->cqe_version) 1509 pthread_mutex_lock(&ctx->qp_table_mutex); 1510 1511 ret = ibv_cmd_destroy_qp(ibqp); 1512 if (ret) { 1513 if (!ctx->cqe_version) 1514 pthread_mutex_unlock(&ctx->qp_table_mutex); 1515 return ret; 1516 } 1517 1518 mlx5_lock_cqs(ibqp); 1519 1520 __mlx5_cq_clean(to_mcq(ibqp->recv_cq), qp->rsc.rsn, 1521 ibqp->srq ? to_msrq(ibqp->srq) : NULL); 1522 if (ibqp->send_cq != ibqp->recv_cq) 1523 __mlx5_cq_clean(to_mcq(ibqp->send_cq), qp->rsc.rsn, NULL); 1524 1525 if (!ctx->cqe_version) { 1526 if (qp->sq.wqe_cnt || qp->rq.wqe_cnt) 1527 mlx5_clear_qp(ctx, ibqp->qp_num); 1528 } 1529 1530 mlx5_unlock_cqs(ibqp); 1531 if (!ctx->cqe_version) 1532 pthread_mutex_unlock(&ctx->qp_table_mutex); 1533 else if (!is_xrc_tgt(ibqp->qp_type)) 1534 mlx5_clear_uidx(ctx, qp->rsc.rsn); 1535 1536 mlx5_free_db(ctx, qp->db); 1537 mlx5_spinlock_destroy(&qp->rq.lock); 1538 mlx5_spinlock_destroy(&qp->sq.lock); 1539 mlx5_free_qp_buf(qp); 1540 free: 1541 free(qp); 1542 1543 return 0; 1544 } 1545 1546 int mlx5_query_qp(struct ibv_qp *ibqp, struct ibv_qp_attr *attr, 1547 int attr_mask, struct ibv_qp_init_attr *init_attr) 1548 { 1549 struct ibv_query_qp cmd; 1550 struct mlx5_qp *qp = to_mqp(ibqp); 1551 int ret; 1552 1553 if (qp->rss_qp) 1554 return ENOSYS; 1555 1556 ret = ibv_cmd_query_qp(ibqp, attr, attr_mask, init_attr, &cmd, sizeof(cmd)); 1557 if (ret) 1558 return ret; 1559 1560 init_attr->cap.max_send_wr = qp->sq.max_post; 1561 init_attr->cap.max_send_sge = qp->sq.max_gs; 1562 init_attr->cap.max_inline_data = qp->max_inline_data; 1563 1564 attr->cap = init_attr->cap; 1565 1566 return 0; 1567 } 1568 1569 enum { 1570 MLX5_MODIFY_QP_EX_ATTR_MASK = IBV_QP_RATE_LIMIT, 1571 }; 1572 1573 int mlx5_modify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr, 1574 int attr_mask) 1575 { 1576 struct ibv_modify_qp cmd = {}; 1577 struct ibv_modify_qp_ex cmd_ex = {}; 1578 struct ibv_modify_qp_resp_ex resp = {}; 1579 struct mlx5_qp *mqp = to_mqp(qp); 1580 struct mlx5_context *context = to_mctx(qp->context); 1581 int ret; 1582 uint32_t *db; 1583 1584 if (mqp->rss_qp) 1585 return ENOSYS; 1586 1587 if (attr_mask & IBV_QP_PORT) { 1588 switch (qp->qp_type) { 1589 case IBV_QPT_RAW_PACKET: 1590 if (context->cached_link_layer[attr->port_num - 1] == 1591 IBV_LINK_LAYER_ETHERNET) { 1592 if (context->cached_device_cap_flags & 1593 IBV_DEVICE_RAW_IP_CSUM) 1594 mqp->qp_cap_cache |= 1595 MLX5_CSUM_SUPPORT_RAW_OVER_ETH | 1596 MLX5_RX_CSUM_VALID; 1597 1598 if (ibv_is_qpt_supported( 1599 context->cached_tso_caps.supported_qpts, 1600 IBV_QPT_RAW_PACKET)) 1601 mqp->max_tso = 1602 context->cached_tso_caps.max_tso; 1603 } 1604 break; 1605 default: 1606 break; 1607 } 1608 } 1609 1610 if (attr_mask & MLX5_MODIFY_QP_EX_ATTR_MASK) 1611 ret = ibv_cmd_modify_qp_ex(qp, attr, attr_mask, 1612 &cmd_ex, 1613 sizeof(cmd_ex), sizeof(cmd_ex), 1614 &resp, 1615 sizeof(resp), sizeof(resp)); 1616 else 1617 ret = ibv_cmd_modify_qp(qp, attr, attr_mask, 1618 &cmd, sizeof(cmd)); 1619 1620 if (!ret && 1621 (attr_mask & IBV_QP_STATE) && 1622 attr->qp_state == IBV_QPS_RESET) { 1623 if (qp->recv_cq) { 1624 mlx5_cq_clean(to_mcq(qp->recv_cq), mqp->rsc.rsn, 1625 qp->srq ? to_msrq(qp->srq) : NULL); 1626 } 1627 if (qp->send_cq != qp->recv_cq && qp->send_cq) 1628 mlx5_cq_clean(to_mcq(qp->send_cq), 1629 to_mqp(qp)->rsc.rsn, NULL); 1630 1631 mlx5_init_qp_indices(mqp); 1632 db = mqp->db; 1633 db[MLX5_RCV_DBR] = 0; 1634 db[MLX5_SND_DBR] = 0; 1635 } 1636 1637 /* 1638 * When the Raw Packet QP is in INIT state, its RQ 1639 * underneath is already in RDY, which means it can 1640 * receive packets. According to the IB spec, a QP can't 1641 * receive packets until moved to RTR state. To achieve this, 1642 * for Raw Packet QPs, we update the doorbell record 1643 * once the QP is moved to RTR. 1644 */ 1645 if (!ret && 1646 (attr_mask & IBV_QP_STATE) && 1647 attr->qp_state == IBV_QPS_RTR && 1648 qp->qp_type == IBV_QPT_RAW_PACKET) { 1649 mlx5_spin_lock(&mqp->rq.lock); 1650 mqp->db[MLX5_RCV_DBR] = htobe32(mqp->rq.head & 0xffff); 1651 mlx5_spin_unlock(&mqp->rq.lock); 1652 } 1653 1654 return ret; 1655 } 1656 1657 #define RROCE_UDP_SPORT_MIN 0xC000 1658 #define RROCE_UDP_SPORT_MAX 0xFFFF 1659 struct ibv_ah *mlx5_create_ah(struct ibv_pd *pd, struct ibv_ah_attr *attr) 1660 { 1661 struct mlx5_context *ctx = to_mctx(pd->context); 1662 struct ibv_port_attr port_attr; 1663 struct mlx5_ah *ah; 1664 uint32_t gid_type; 1665 uint32_t tmp; 1666 uint8_t grh; 1667 int is_eth; 1668 1669 if (attr->port_num < 1 || attr->port_num > ctx->num_ports) 1670 return NULL; 1671 1672 if (ctx->cached_link_layer[attr->port_num - 1]) { 1673 is_eth = ctx->cached_link_layer[attr->port_num - 1] == 1674 IBV_LINK_LAYER_ETHERNET; 1675 } else { 1676 if (ibv_query_port(pd->context, attr->port_num, &port_attr)) 1677 return NULL; 1678 1679 is_eth = (port_attr.link_layer == IBV_LINK_LAYER_ETHERNET); 1680 } 1681 1682 if (unlikely((!attr->is_global) && is_eth)) { 1683 errno = EINVAL; 1684 return NULL; 1685 } 1686 1687 ah = calloc(1, sizeof *ah); 1688 if (!ah) 1689 return NULL; 1690 1691 if (is_eth) { 1692 if (ibv_query_gid_type(pd->context, attr->port_num, 1693 attr->grh.sgid_index, &gid_type)) 1694 goto err; 1695 1696 if (gid_type == IBV_GID_TYPE_ROCE_V2) 1697 ah->av.rlid = htobe16(rand() % (RROCE_UDP_SPORT_MAX + 1 1698 - RROCE_UDP_SPORT_MIN) 1699 + RROCE_UDP_SPORT_MIN); 1700 /* Since RoCE packets must contain GRH, this bit is reserved 1701 * for RoCE and shouldn't be set. 1702 */ 1703 grh = 0; 1704 } else { 1705 ah->av.fl_mlid = attr->src_path_bits & 0x7f; 1706 ah->av.rlid = htobe16(attr->dlid); 1707 grh = 1; 1708 } 1709 ah->av.stat_rate_sl = (attr->static_rate << 4) | attr->sl; 1710 if (attr->is_global) { 1711 ah->av.tclass = attr->grh.traffic_class; 1712 ah->av.hop_limit = attr->grh.hop_limit; 1713 tmp = htobe32((grh << 30) | 1714 ((attr->grh.sgid_index & 0xff) << 20) | 1715 (attr->grh.flow_label & 0xfffff)); 1716 ah->av.grh_gid_fl = tmp; 1717 memcpy(ah->av.rgid, attr->grh.dgid.raw, 16); 1718 } 1719 1720 if (is_eth) { 1721 if (ctx->cmds_supp_uhw & MLX5_USER_CMDS_SUPP_UHW_CREATE_AH) { 1722 struct mlx5_create_ah_resp resp = {}; 1723 1724 if (ibv_cmd_create_ah(pd, &ah->ibv_ah, attr, &resp.ibv_resp, sizeof(resp))) 1725 goto err; 1726 1727 ah->kern_ah = true; 1728 memcpy(ah->av.rmac, resp.dmac, ETHERNET_LL_SIZE); 1729 } else { 1730 uint16_t vid; 1731 1732 if (ibv_resolve_eth_l2_from_gid(pd->context, attr, 1733 ah->av.rmac, &vid)) 1734 goto err; 1735 } 1736 } 1737 1738 return &ah->ibv_ah; 1739 err: 1740 free(ah); 1741 return NULL; 1742 } 1743 1744 int mlx5_destroy_ah(struct ibv_ah *ah) 1745 { 1746 struct mlx5_ah *mah = to_mah(ah); 1747 int err; 1748 1749 if (mah->kern_ah) { 1750 err = ibv_cmd_destroy_ah(ah); 1751 if (err) 1752 return err; 1753 } 1754 1755 free(mah); 1756 return 0; 1757 } 1758 1759 int mlx5_attach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid) 1760 { 1761 return ibv_cmd_attach_mcast(qp, gid, lid); 1762 } 1763 1764 int mlx5_detach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid) 1765 { 1766 return ibv_cmd_detach_mcast(qp, gid, lid); 1767 } 1768 1769 struct ibv_qp *mlx5_create_qp_ex(struct ibv_context *context, 1770 struct ibv_qp_init_attr_ex *attr) 1771 { 1772 return create_qp(context, attr); 1773 } 1774 1775 int mlx5_get_srq_num(struct ibv_srq *srq, uint32_t *srq_num) 1776 { 1777 struct mlx5_srq *msrq = to_msrq(srq); 1778 1779 *srq_num = msrq->srqn; 1780 1781 return 0; 1782 } 1783 1784 struct ibv_xrcd * 1785 mlx5_open_xrcd(struct ibv_context *context, 1786 struct ibv_xrcd_init_attr *xrcd_init_attr) 1787 { 1788 int err; 1789 struct verbs_xrcd *xrcd; 1790 struct ibv_open_xrcd cmd = {}; 1791 struct ibv_open_xrcd_resp resp = {}; 1792 1793 xrcd = calloc(1, sizeof(*xrcd)); 1794 if (!xrcd) 1795 return NULL; 1796 1797 err = ibv_cmd_open_xrcd(context, xrcd, sizeof(*xrcd), xrcd_init_attr, 1798 &cmd, sizeof(cmd), &resp, sizeof(resp)); 1799 if (err) { 1800 free(xrcd); 1801 return NULL; 1802 } 1803 1804 return &xrcd->xrcd; 1805 } 1806 1807 int mlx5_close_xrcd(struct ibv_xrcd *ib_xrcd) 1808 { 1809 struct verbs_xrcd *xrcd = container_of(ib_xrcd, struct verbs_xrcd, xrcd); 1810 int ret; 1811 1812 ret = ibv_cmd_close_xrcd(xrcd); 1813 if (!ret) 1814 free(xrcd); 1815 1816 return ret; 1817 } 1818 1819 static struct ibv_srq * 1820 mlx5_create_xrc_srq(struct ibv_context *context, 1821 struct ibv_srq_init_attr_ex *attr) 1822 { 1823 int err; 1824 struct mlx5_create_srq_ex cmd; 1825 struct mlx5_create_srq_resp resp; 1826 struct mlx5_srq *msrq; 1827 struct mlx5_context *ctx = to_mctx(context); 1828 int max_sge; 1829 struct ibv_srq *ibsrq; 1830 int uidx; 1831 FILE *fp = ctx->dbg_fp; 1832 1833 msrq = calloc(1, sizeof(*msrq)); 1834 if (!msrq) 1835 return NULL; 1836 1837 ibsrq = (struct ibv_srq *)&msrq->vsrq; 1838 1839 memset(&cmd, 0, sizeof(cmd)); 1840 memset(&resp, 0, sizeof(resp)); 1841 1842 if (mlx5_spinlock_init(&msrq->lock)) { 1843 fprintf(stderr, "%s-%d:\n", __func__, __LINE__); 1844 goto err; 1845 } 1846 1847 if (attr->attr.max_wr > ctx->max_srq_recv_wr) { 1848 fprintf(stderr, "%s-%d:max_wr %d, max_srq_recv_wr %d\n", 1849 __func__, __LINE__, attr->attr.max_wr, 1850 ctx->max_srq_recv_wr); 1851 errno = EINVAL; 1852 goto err_spl; 1853 } 1854 1855 /* 1856 * this calculation does not consider required control segments. The 1857 * final calculation is done again later. This is done so to avoid 1858 * overflows of variables 1859 */ 1860 max_sge = ctx->max_recv_wr / sizeof(struct mlx5_wqe_data_seg); 1861 if (attr->attr.max_sge > max_sge) { 1862 fprintf(stderr, "%s-%d:max_wr %d, max_srq_recv_wr %d\n", 1863 __func__, __LINE__, attr->attr.max_wr, 1864 ctx->max_srq_recv_wr); 1865 errno = EINVAL; 1866 goto err_spl; 1867 } 1868 1869 msrq->max = align_queue_size(attr->attr.max_wr + 1); 1870 msrq->max_gs = attr->attr.max_sge; 1871 msrq->counter = 0; 1872 1873 if (mlx5_alloc_srq_buf(context, msrq)) { 1874 fprintf(stderr, "%s-%d:\n", __func__, __LINE__); 1875 goto err_spl; 1876 } 1877 1878 msrq->db = mlx5_alloc_dbrec(ctx); 1879 if (!msrq->db) { 1880 fprintf(stderr, "%s-%d:\n", __func__, __LINE__); 1881 goto err_free; 1882 } 1883 1884 *msrq->db = 0; 1885 1886 cmd.buf_addr = (uintptr_t)msrq->buf.buf; 1887 cmd.db_addr = (uintptr_t)msrq->db; 1888 msrq->wq_sig = srq_sig_enabled(); 1889 if (msrq->wq_sig) 1890 cmd.flags = MLX5_SRQ_FLAG_SIGNATURE; 1891 1892 attr->attr.max_sge = msrq->max_gs; 1893 if (ctx->cqe_version) { 1894 uidx = mlx5_store_uidx(ctx, msrq); 1895 if (uidx < 0) { 1896 mlx5_dbg(fp, MLX5_DBG_QP, "Couldn't find free user index\n"); 1897 goto err_free_db; 1898 } 1899 cmd.uidx = uidx; 1900 } else { 1901 cmd.uidx = 0xffffff; 1902 pthread_mutex_lock(&ctx->srq_table_mutex); 1903 } 1904 1905 err = ibv_cmd_create_srq_ex(context, &msrq->vsrq, sizeof(msrq->vsrq), 1906 attr, &cmd.ibv_cmd, sizeof(cmd), 1907 &resp.ibv_resp, sizeof(resp)); 1908 if (err) 1909 goto err_free_uidx; 1910 1911 if (!ctx->cqe_version) { 1912 err = mlx5_store_srq(to_mctx(context), resp.srqn, msrq); 1913 if (err) 1914 goto err_destroy; 1915 1916 pthread_mutex_unlock(&ctx->srq_table_mutex); 1917 } 1918 1919 msrq->srqn = resp.srqn; 1920 msrq->rsc.type = MLX5_RSC_TYPE_XSRQ; 1921 msrq->rsc.rsn = ctx->cqe_version ? cmd.uidx : resp.srqn; 1922 1923 return ibsrq; 1924 1925 err_destroy: 1926 ibv_cmd_destroy_srq(ibsrq); 1927 1928 err_free_uidx: 1929 if (ctx->cqe_version) 1930 mlx5_clear_uidx(ctx, cmd.uidx); 1931 else 1932 pthread_mutex_unlock(&ctx->srq_table_mutex); 1933 1934 err_free_db: 1935 mlx5_free_db(ctx, msrq->db); 1936 1937 err_free: 1938 free(msrq->wrid); 1939 mlx5_free_buf(&msrq->buf); 1940 1941 err_spl: 1942 mlx5_spinlock_destroy(&msrq->lock); 1943 1944 err: 1945 free(msrq); 1946 1947 return NULL; 1948 } 1949 1950 struct ibv_srq *mlx5_create_srq_ex(struct ibv_context *context, 1951 struct ibv_srq_init_attr_ex *attr) 1952 { 1953 if (!(attr->comp_mask & IBV_SRQ_INIT_ATTR_TYPE) || 1954 (attr->srq_type == IBV_SRQT_BASIC)) 1955 return mlx5_create_srq(attr->pd, 1956 (struct ibv_srq_init_attr *)attr); 1957 else if (attr->srq_type == IBV_SRQT_XRC) 1958 return mlx5_create_xrc_srq(context, attr); 1959 1960 return NULL; 1961 } 1962 1963 int mlx5_query_device_ex(struct ibv_context *context, 1964 const struct ibv_query_device_ex_input *input, 1965 struct ibv_device_attr_ex *attr, 1966 size_t attr_size) 1967 { 1968 struct mlx5_context *mctx = to_mctx(context); 1969 struct mlx5_query_device_ex_resp resp; 1970 struct mlx5_query_device_ex cmd; 1971 struct ibv_device_attr *a; 1972 uint64_t raw_fw_ver; 1973 unsigned sub_minor; 1974 unsigned major; 1975 unsigned minor; 1976 int err; 1977 int cmd_supp_uhw = mctx->cmds_supp_uhw & 1978 MLX5_USER_CMDS_SUPP_UHW_QUERY_DEVICE; 1979 1980 memset(&cmd, 0, sizeof(cmd)); 1981 memset(&resp, 0, sizeof(resp)); 1982 err = ibv_cmd_query_device_ex(context, input, attr, attr_size, 1983 &raw_fw_ver, 1984 &cmd.ibv_cmd, sizeof(cmd.ibv_cmd), sizeof(cmd), 1985 &resp.ibv_resp, sizeof(resp.ibv_resp), 1986 cmd_supp_uhw ? sizeof(resp) : sizeof(resp.ibv_resp)); 1987 if (err) 1988 return err; 1989 1990 attr->tso_caps = resp.tso_caps; 1991 attr->rss_caps.rx_hash_fields_mask = resp.rss_caps.rx_hash_fields_mask; 1992 attr->rss_caps.rx_hash_function = resp.rss_caps.rx_hash_function; 1993 attr->packet_pacing_caps = resp.packet_pacing_caps.caps; 1994 1995 if (resp.support_multi_pkt_send_wqe) 1996 mctx->vendor_cap_flags |= MLX5_VENDOR_CAP_FLAGS_MPW; 1997 1998 mctx->cqe_comp_caps = resp.cqe_comp_caps; 1999 2000 major = (raw_fw_ver >> 32) & 0xffff; 2001 minor = (raw_fw_ver >> 16) & 0xffff; 2002 sub_minor = raw_fw_ver & 0xffff; 2003 a = &attr->orig_attr; 2004 snprintf(a->fw_ver, sizeof(a->fw_ver), "%d.%d.%04d", 2005 major, minor, sub_minor); 2006 2007 return 0; 2008 } 2009 2010 static int rwq_sig_enabled(struct ibv_context *context) 2011 { 2012 char *env; 2013 2014 env = getenv("MLX5_RWQ_SIGNATURE"); 2015 if (env) 2016 return 1; 2017 2018 return 0; 2019 } 2020 2021 static void mlx5_free_rwq_buf(struct mlx5_rwq *rwq, struct ibv_context *context) 2022 { 2023 struct mlx5_context *ctx = to_mctx(context); 2024 2025 mlx5_free_actual_buf(ctx, &rwq->buf); 2026 free(rwq->rq.wrid); 2027 } 2028 2029 static int mlx5_alloc_rwq_buf(struct ibv_context *context, 2030 struct mlx5_rwq *rwq, 2031 int size) 2032 { 2033 int err; 2034 enum mlx5_alloc_type default_alloc_type = MLX5_ALLOC_TYPE_PREFER_CONTIG; 2035 2036 rwq->rq.wrid = malloc(rwq->rq.wqe_cnt * sizeof(uint64_t)); 2037 if (!rwq->rq.wrid) { 2038 errno = ENOMEM; 2039 return -1; 2040 } 2041 2042 err = mlx5_alloc_prefered_buf(to_mctx(context), &rwq->buf, 2043 align(rwq->buf_size, to_mdev 2044 (context->device)->page_size), 2045 to_mdev(context->device)->page_size, 2046 default_alloc_type, 2047 MLX5_RWQ_PREFIX); 2048 2049 if (err) { 2050 free(rwq->rq.wrid); 2051 errno = ENOMEM; 2052 return -1; 2053 } 2054 2055 return 0; 2056 } 2057 2058 struct ibv_wq *mlx5_create_wq(struct ibv_context *context, 2059 struct ibv_wq_init_attr *attr) 2060 { 2061 struct mlx5_create_wq cmd; 2062 struct mlx5_create_wq_resp resp; 2063 int err; 2064 struct mlx5_rwq *rwq; 2065 struct mlx5_context *ctx = to_mctx(context); 2066 int ret; 2067 int32_t usr_idx = 0; 2068 FILE *fp = ctx->dbg_fp; 2069 2070 if (attr->wq_type != IBV_WQT_RQ) 2071 return NULL; 2072 2073 memset(&cmd, 0, sizeof(cmd)); 2074 memset(&resp, 0, sizeof(resp)); 2075 2076 rwq = calloc(1, sizeof(*rwq)); 2077 if (!rwq) 2078 return NULL; 2079 2080 ret = ibv_init_wq(&rwq->wq); 2081 if (ret < 0) 2082 goto err; 2083 2084 rwq->wq_sig = rwq_sig_enabled(context); 2085 if (rwq->wq_sig) 2086 cmd.drv.flags = MLX5_RWQ_FLAG_SIGNATURE; 2087 2088 ret = mlx5_calc_rwq_size(ctx, rwq, attr); 2089 if (ret < 0) { 2090 errno = -ret; 2091 goto err_cleanup_wq; 2092 } 2093 2094 rwq->buf_size = ret; 2095 if (mlx5_alloc_rwq_buf(context, rwq, ret)) 2096 goto err_cleanup_wq; 2097 2098 mlx5_init_rwq_indices(rwq); 2099 2100 if (mlx5_spinlock_init(&rwq->rq.lock)) 2101 goto err_free_rwq_buf; 2102 2103 rwq->db = mlx5_alloc_dbrec(ctx); 2104 if (!rwq->db) 2105 goto err_spl; 2106 2107 rwq->db[MLX5_RCV_DBR] = 0; 2108 rwq->db[MLX5_SND_DBR] = 0; 2109 rwq->pbuff = rwq->buf.buf + rwq->rq.offset; 2110 rwq->recv_db = &rwq->db[MLX5_RCV_DBR]; 2111 cmd.drv.buf_addr = (uintptr_t)rwq->buf.buf; 2112 cmd.drv.db_addr = (uintptr_t)rwq->db; 2113 cmd.drv.rq_wqe_count = rwq->rq.wqe_cnt; 2114 cmd.drv.rq_wqe_shift = rwq->rq.wqe_shift; 2115 usr_idx = mlx5_store_uidx(ctx, rwq); 2116 if (usr_idx < 0) { 2117 mlx5_dbg(fp, MLX5_DBG_QP, "Couldn't find free user index\n"); 2118 goto err_free_db_rec; 2119 } 2120 2121 cmd.drv.user_index = usr_idx; 2122 err = ibv_cmd_create_wq(context, attr, &rwq->wq, &cmd.ibv_cmd, 2123 sizeof(cmd.ibv_cmd), 2124 sizeof(cmd), 2125 &resp.ibv_resp, sizeof(resp.ibv_resp), 2126 sizeof(resp)); 2127 if (err) 2128 goto err_create; 2129 2130 rwq->rsc.type = MLX5_RSC_TYPE_RWQ; 2131 rwq->rsc.rsn = cmd.drv.user_index; 2132 2133 rwq->wq.post_recv = mlx5_post_wq_recv; 2134 return &rwq->wq; 2135 2136 err_create: 2137 mlx5_clear_uidx(ctx, cmd.drv.user_index); 2138 err_free_db_rec: 2139 mlx5_free_db(to_mctx(context), rwq->db); 2140 err_spl: 2141 mlx5_spinlock_destroy(&rwq->rq.lock); 2142 err_free_rwq_buf: 2143 mlx5_free_rwq_buf(rwq, context); 2144 err_cleanup_wq: 2145 ibv_cleanup_wq(&rwq->wq); 2146 err: 2147 free(rwq); 2148 return NULL; 2149 } 2150 2151 int mlx5_modify_wq(struct ibv_wq *wq, struct ibv_wq_attr *attr) 2152 { 2153 struct mlx5_modify_wq cmd = {}; 2154 struct mlx5_rwq *rwq = to_mrwq(wq); 2155 2156 if ((attr->attr_mask & IBV_WQ_ATTR_STATE) && 2157 attr->wq_state == IBV_WQS_RDY) { 2158 if ((attr->attr_mask & IBV_WQ_ATTR_CURR_STATE) && 2159 attr->curr_wq_state != wq->state) 2160 return -EINVAL; 2161 2162 if (wq->state == IBV_WQS_RESET) { 2163 mlx5_spin_lock(&to_mcq(wq->cq)->lock); 2164 __mlx5_cq_clean(to_mcq(wq->cq), 2165 rwq->rsc.rsn, NULL); 2166 mlx5_spin_unlock(&to_mcq(wq->cq)->lock); 2167 mlx5_init_rwq_indices(rwq); 2168 rwq->db[MLX5_RCV_DBR] = 0; 2169 rwq->db[MLX5_SND_DBR] = 0; 2170 } 2171 } 2172 2173 return ibv_cmd_modify_wq(wq, attr, &cmd.ibv_cmd, sizeof(cmd.ibv_cmd), sizeof(cmd)); 2174 } 2175 2176 int mlx5_destroy_wq(struct ibv_wq *wq) 2177 { 2178 struct mlx5_rwq *rwq = to_mrwq(wq); 2179 int ret; 2180 2181 ret = ibv_cmd_destroy_wq(wq); 2182 if (ret) 2183 return ret; 2184 2185 mlx5_spin_lock(&to_mcq(wq->cq)->lock); 2186 __mlx5_cq_clean(to_mcq(wq->cq), rwq->rsc.rsn, NULL); 2187 mlx5_spin_unlock(&to_mcq(wq->cq)->lock); 2188 mlx5_clear_uidx(to_mctx(wq->context), rwq->rsc.rsn); 2189 mlx5_free_db(to_mctx(wq->context), rwq->db); 2190 mlx5_spinlock_destroy(&rwq->rq.lock); 2191 mlx5_free_rwq_buf(rwq, wq->context); 2192 ibv_cleanup_wq(&rwq->wq); 2193 free(rwq); 2194 2195 return 0; 2196 } 2197 2198 struct ibv_rwq_ind_table *mlx5_create_rwq_ind_table(struct ibv_context *context, 2199 struct ibv_rwq_ind_table_init_attr *init_attr) 2200 { 2201 struct ibv_create_rwq_ind_table *cmd; 2202 struct mlx5_create_rwq_ind_table_resp resp; 2203 struct ibv_rwq_ind_table *ind_table; 2204 uint32_t required_tbl_size; 2205 int num_tbl_entries; 2206 int cmd_size; 2207 int err; 2208 2209 num_tbl_entries = 1 << init_attr->log_ind_tbl_size; 2210 /* Data must be u64 aligned */ 2211 required_tbl_size = (num_tbl_entries * sizeof(uint32_t)) < sizeof(uint64_t) ? 2212 sizeof(uint64_t) : (num_tbl_entries * sizeof(uint32_t)); 2213 2214 cmd_size = required_tbl_size + sizeof(*cmd); 2215 cmd = calloc(1, cmd_size); 2216 if (!cmd) 2217 return NULL; 2218 2219 memset(&resp, 0, sizeof(resp)); 2220 ind_table = calloc(1, sizeof(*ind_table)); 2221 if (!ind_table) 2222 goto free_cmd; 2223 2224 err = ibv_cmd_create_rwq_ind_table(context, init_attr, ind_table, cmd, 2225 cmd_size, cmd_size, &resp.ibv_resp, sizeof(resp.ibv_resp), 2226 sizeof(resp)); 2227 if (err) 2228 goto err; 2229 2230 free(cmd); 2231 return ind_table; 2232 2233 err: 2234 free(ind_table); 2235 free_cmd: 2236 free(cmd); 2237 return NULL; 2238 } 2239 2240 int mlx5_destroy_rwq_ind_table(struct ibv_rwq_ind_table *rwq_ind_table) 2241 { 2242 int ret; 2243 2244 ret = ibv_cmd_destroy_rwq_ind_table(rwq_ind_table); 2245 2246 if (ret) 2247 return ret; 2248 2249 free(rwq_ind_table); 2250 return 0; 2251 } 2252