Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

qedr: Add support for PD,PKEY and CQ verbs

Add support for protection domain and completion queue verbs.

Signed-off-by: Rajesh Borundia <rajesh.borundia@cavium.com>
Signed-off-by: Ram Amrani <Ram.Amrani@cavium.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>

authored by

Ram Amrani and committed by
Doug Ledford
a7efd777 ac1b36e5

+777 -1
+48 -1
drivers/infiniband/hw/qedr/main.c
··· 87 87 88 88 dev->ibdev.uverbs_cmd_mask = QEDR_UVERBS(GET_CONTEXT) | 89 89 QEDR_UVERBS(QUERY_DEVICE) | 90 - QEDR_UVERBS(QUERY_PORT); 90 + QEDR_UVERBS(QUERY_PORT) | 91 + QEDR_UVERBS(ALLOC_PD) | 92 + QEDR_UVERBS(DEALLOC_PD) | 93 + QEDR_UVERBS(CREATE_COMP_CHANNEL) | 94 + QEDR_UVERBS(CREATE_CQ) | 95 + QEDR_UVERBS(RESIZE_CQ) | 96 + QEDR_UVERBS(DESTROY_CQ) | 97 + QEDR_UVERBS(REQ_NOTIFY_CQ); 91 98 92 99 dev->ibdev.phys_port_cnt = 1; 93 100 dev->ibdev.num_comp_vectors = dev->num_cnq; ··· 111 104 dev->ibdev.alloc_ucontext = qedr_alloc_ucontext; 112 105 dev->ibdev.dealloc_ucontext = qedr_dealloc_ucontext; 113 106 dev->ibdev.mmap = qedr_mmap; 107 + 108 + dev->ibdev.alloc_pd = qedr_alloc_pd; 109 + dev->ibdev.dealloc_pd = qedr_dealloc_pd; 110 + 111 + dev->ibdev.create_cq = qedr_create_cq; 112 + dev->ibdev.destroy_cq = qedr_destroy_cq; 113 + dev->ibdev.resize_cq = qedr_resize_cq; 114 + dev->ibdev.req_notify_cq = qedr_arm_cq; 115 + 116 + dev->ibdev.query_pkey = qedr_query_pkey; 114 117 115 118 dev->ibdev.dma_device = &dev->pdev->dev; 116 119 ··· 339 322 { 340 323 u16 hw_comp_cons, sw_comp_cons; 341 324 struct qedr_cnq *cnq = handle; 325 + struct regpair *cq_handle; 326 + struct qedr_cq *cq; 342 327 343 328 qed_sb_ack(cnq->sb, IGU_INT_DISABLE, 0); 344 329 ··· 353 334 rmb(); 354 335 355 336 while (sw_comp_cons != hw_comp_cons) { 337 + cq_handle = (struct regpair *)qed_chain_consume(&cnq->pbl); 338 + cq = (struct qedr_cq *)(uintptr_t)HILO_U64(cq_handle->hi, 339 + cq_handle->lo); 340 + 341 + if (cq == NULL) { 342 + DP_ERR(cnq->dev, 343 + "Received NULL CQ cq_handle->hi=%d cq_handle->lo=%d sw_comp_cons=%d hw_comp_cons=%d\n", 344 + cq_handle->hi, cq_handle->lo, sw_comp_cons, 345 + hw_comp_cons); 346 + 347 + break; 348 + } 349 + 350 + if (cq->sig != QEDR_CQ_MAGIC_NUMBER) { 351 + DP_ERR(cnq->dev, 352 + "Problem with cq signature, cq_handle->hi=%d ch_handle->lo=%d cq=%p\n", 353 + cq_handle->hi, cq_handle->lo, cq); 354 + break; 355 + } 356 + 357 + cq->arm_flags = 0; 358 + 359 + if (cq->ibcq.comp_handler) 360 + (*cq->ibcq.comp_handler) 361 + (&cq->ibcq, cq->ibcq.cq_context); 362 + 356 363 sw_comp_cons = qed_chain_get_cons_idx(&cnq->pbl); 364 + 357 365 cnq->n_comp++; 366 + 358 367 } 359 368 360 369 qed_ops->rdma_cnq_prod_update(cnq->dev->rdma_ctx, cnq->index,
+78
drivers/infiniband/hw/qedr/qedr.h
··· 50 50 51 51 #define QEDR_MSG_INIT "INIT" 52 52 #define QEDR_MSG_MISC "MISC" 53 + #define QEDR_MSG_CQ " CQ" 54 + #define QEDR_MSG_MR " MR" 55 + 56 + #define QEDR_CQ_MAGIC_NUMBER (0x11223344) 53 57 54 58 struct qedr_dev; 55 59 ··· 185 181 #define QEDR_ROCE_PKEY_TABLE_LEN 1 186 182 #define QEDR_ROCE_PKEY_DEFAULT 0xffff 187 183 184 + struct qedr_pbl { 185 + struct list_head list_entry; 186 + void *va; 187 + dma_addr_t pa; 188 + }; 189 + 188 190 struct qedr_ucontext { 189 191 struct ib_ucontext ibucontext; 190 192 struct qedr_dev *dev; ··· 204 194 205 195 /* Lock to protect mm list */ 206 196 struct mutex mm_list_lock; 197 + }; 198 + 199 + union db_prod64 { 200 + struct rdma_pwm_val32_data data; 201 + u64 raw; 202 + }; 203 + 204 + enum qedr_cq_type { 205 + QEDR_CQ_TYPE_GSI, 206 + QEDR_CQ_TYPE_KERNEL, 207 + QEDR_CQ_TYPE_USER, 208 + }; 209 + 210 + struct qedr_pbl_info { 211 + u32 num_pbls; 212 + u32 num_pbes; 213 + u32 pbl_size; 214 + u32 pbe_size; 215 + bool two_layered; 216 + }; 217 + 218 + struct qedr_userq { 219 + struct ib_umem *umem; 220 + struct qedr_pbl_info pbl_info; 221 + struct qedr_pbl *pbl_tbl; 222 + u64 buf_addr; 223 + size_t buf_len; 224 + }; 225 + 226 + struct qedr_cq { 227 + struct ib_cq ibcq; 228 + 229 + enum qedr_cq_type cq_type; 230 + u32 sig; 231 + 232 + u16 icid; 233 + 234 + /* Lock to protect multiplem CQ's */ 235 + spinlock_t cq_lock; 236 + u8 arm_flags; 237 + struct qed_chain pbl; 238 + 239 + void __iomem *db_addr; 240 + union db_prod64 db; 241 + 242 + u8 pbl_toggle; 243 + union rdma_cqe *latest_cqe; 244 + union rdma_cqe *toggle_cqe; 245 + 246 + u32 cq_cons; 247 + 248 + struct qedr_userq q; 249 + }; 250 + 251 + struct qedr_pd { 252 + struct ib_pd ibpd; 253 + u32 pd_id; 254 + struct qedr_ucontext *uctx; 207 255 }; 208 256 209 257 struct qedr_mm { ··· 281 213 static inline struct qedr_dev *get_qedr_dev(struct ib_device *ibdev) 282 214 { 283 215 return container_of(ibdev, struct qedr_dev, ibdev); 216 + } 217 + 218 + static inline struct qedr_pd *get_qedr_pd(struct ib_pd *ibpd) 219 + { 220 + return container_of(ibpd, struct qedr_pd, ibpd); 221 + } 222 + 223 + static inline struct qedr_cq *get_qedr_cq(struct ib_cq *ibcq) 224 + { 225 + return container_of(ibcq, struct qedr_cq, ibcq); 284 226 } 285 227 286 228 #endif
+79
drivers/infiniband/hw/qedr/qedr_hsi_rdma.h
··· 47 47 __le32 imm_data_hi; 48 48 __le16 rq_cons; 49 49 u8 flags; 50 + #define RDMA_CQE_RESPONDER_TOGGLE_BIT_MASK 0x1 51 + #define RDMA_CQE_RESPONDER_TOGGLE_BIT_SHIFT 0 52 + #define RDMA_CQE_RESPONDER_TYPE_MASK 0x3 53 + #define RDMA_CQE_RESPONDER_TYPE_SHIFT 1 54 + #define RDMA_CQE_RESPONDER_INV_FLG_MASK 0x1 55 + #define RDMA_CQE_RESPONDER_INV_FLG_SHIFT 3 56 + #define RDMA_CQE_RESPONDER_IMM_FLG_MASK 0x1 57 + #define RDMA_CQE_RESPONDER_IMM_FLG_SHIFT 4 58 + #define RDMA_CQE_RESPONDER_RDMA_FLG_MASK 0x1 59 + #define RDMA_CQE_RESPONDER_RDMA_FLG_SHIFT 5 60 + #define RDMA_CQE_RESPONDER_RESERVED2_MASK 0x3 61 + #define RDMA_CQE_RESPONDER_RESERVED2_SHIFT 6 62 + u8 status; 50 63 }; 51 64 52 65 struct rdma_cqe_requester { ··· 71 58 __le32 reserved3; 72 59 __le16 reserved4; 73 60 u8 flags; 61 + #define RDMA_CQE_REQUESTER_TOGGLE_BIT_MASK 0x1 62 + #define RDMA_CQE_REQUESTER_TOGGLE_BIT_SHIFT 0 63 + #define RDMA_CQE_REQUESTER_TYPE_MASK 0x3 64 + #define RDMA_CQE_REQUESTER_TYPE_SHIFT 1 65 + #define RDMA_CQE_REQUESTER_RESERVED5_MASK 0x1F 66 + #define RDMA_CQE_REQUESTER_RESERVED5_SHIFT 3 74 67 u8 status; 75 68 }; 76 69 ··· 85 66 struct regpair qp_handle; 86 67 __le16 reserved1[7]; 87 68 u8 flags; 69 + #define RDMA_CQE_COMMON_TOGGLE_BIT_MASK 0x1 70 + #define RDMA_CQE_COMMON_TOGGLE_BIT_SHIFT 0 71 + #define RDMA_CQE_COMMON_TYPE_MASK 0x3 72 + #define RDMA_CQE_COMMON_TYPE_SHIFT 1 73 + #define RDMA_CQE_COMMON_RESERVED2_MASK 0x1F 74 + #define RDMA_CQE_COMMON_RESERVED2_SHIFT 3 88 75 u8 status; 89 76 }; 90 77 ··· 99 74 struct rdma_cqe_responder resp; 100 75 struct rdma_cqe_requester req; 101 76 struct rdma_cqe_common cmn; 77 + }; 78 + 79 + /* * CQE requester status enumeration */ 80 + enum rdma_cqe_requester_status_enum { 81 + RDMA_CQE_REQ_STS_OK, 82 + RDMA_CQE_REQ_STS_BAD_RESPONSE_ERR, 83 + RDMA_CQE_REQ_STS_LOCAL_LENGTH_ERR, 84 + RDMA_CQE_REQ_STS_LOCAL_QP_OPERATION_ERR, 85 + RDMA_CQE_REQ_STS_LOCAL_PROTECTION_ERR, 86 + RDMA_CQE_REQ_STS_MEMORY_MGT_OPERATION_ERR, 87 + RDMA_CQE_REQ_STS_REMOTE_INVALID_REQUEST_ERR, 88 + RDMA_CQE_REQ_STS_REMOTE_ACCESS_ERR, 89 + RDMA_CQE_REQ_STS_REMOTE_OPERATION_ERR, 90 + RDMA_CQE_REQ_STS_RNR_NAK_RETRY_CNT_ERR, 91 + RDMA_CQE_REQ_STS_TRANSPORT_RETRY_CNT_ERR, 92 + RDMA_CQE_REQ_STS_WORK_REQUEST_FLUSHED_ERR, 93 + MAX_RDMA_CQE_REQUESTER_STATUS_ENUM 94 + }; 95 + 96 + /* CQE responder status enumeration */ 97 + enum rdma_cqe_responder_status_enum { 98 + RDMA_CQE_RESP_STS_OK, 99 + RDMA_CQE_RESP_STS_LOCAL_ACCESS_ERR, 100 + RDMA_CQE_RESP_STS_LOCAL_LENGTH_ERR, 101 + RDMA_CQE_RESP_STS_LOCAL_QP_OPERATION_ERR, 102 + RDMA_CQE_RESP_STS_LOCAL_PROTECTION_ERR, 103 + RDMA_CQE_RESP_STS_MEMORY_MGT_OPERATION_ERR, 104 + RDMA_CQE_RESP_STS_REMOTE_INVALID_REQUEST_ERR, 105 + RDMA_CQE_RESP_STS_WORK_REQUEST_FLUSHED_ERR, 106 + MAX_RDMA_CQE_RESPONDER_STATUS_ENUM 107 + }; 108 + 109 + /* CQE type enumeration */ 110 + enum rdma_cqe_type { 111 + RDMA_CQE_TYPE_REQUESTER, 112 + RDMA_CQE_TYPE_RESPONDER_RQ, 113 + RDMA_CQE_TYPE_RESPONDER_SRQ, 114 + RDMA_CQE_TYPE_INVALID, 115 + MAX_RDMA_CQE_TYPE 102 116 }; 103 117 104 118 struct rdma_sq_sge { ··· 157 93 __le32 length; 158 94 __le32 l_key; 159 95 }; 96 + 97 + /* Rdma doorbell data for CQ */ 98 + struct rdma_pwm_val32_data { 99 + __le16 icid; 100 + u8 agg_flags; 101 + u8 params; 102 + #define RDMA_PWM_VAL32_DATA_AGG_CMD_MASK 0x3 103 + #define RDMA_PWM_VAL32_DATA_AGG_CMD_SHIFT 0 104 + #define RDMA_PWM_VAL32_DATA_BYPASS_EN_MASK 0x1 105 + #define RDMA_PWM_VAL32_DATA_BYPASS_EN_SHIFT 2 106 + #define RDMA_PWM_VAL32_DATA_RESERVED_MASK 0x1F 107 + #define RDMA_PWM_VAL32_DATA_RESERVED_SHIFT 3 108 + __le32 value; 109 + }; 110 + 160 111 #endif /* __QED_HSI_RDMA__ */
+539
drivers/infiniband/hw/qedr/verbs.c
··· 49 49 #include "verbs.h" 50 50 #include <rdma/qedr-abi.h> 51 51 52 + #define DB_ADDR_SHIFT(addr) ((addr) << DB_PWM_ADDR_OFFSET_SHIFT) 53 + 54 + int qedr_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey) 55 + { 56 + if (index > QEDR_ROCE_PKEY_TABLE_LEN) 57 + return -EINVAL; 58 + 59 + *pkey = QEDR_ROCE_PKEY_DEFAULT; 60 + return 0; 61 + } 62 + 52 63 int qedr_query_gid(struct ib_device *ibdev, u8 port, int index, 53 64 union ib_gid *sgid) 54 65 { ··· 464 453 } 465 454 DP_DEBUG(dev, QEDR_MSG_INIT, "qedr_mmap return code: %d\n", rc); 466 455 return rc; 456 + } 457 + 458 + struct ib_pd *qedr_alloc_pd(struct ib_device *ibdev, 459 + struct ib_ucontext *context, struct ib_udata *udata) 460 + { 461 + struct qedr_dev *dev = get_qedr_dev(ibdev); 462 + struct qedr_ucontext *uctx = NULL; 463 + struct qedr_alloc_pd_uresp uresp; 464 + struct qedr_pd *pd; 465 + u16 pd_id; 466 + int rc; 467 + 468 + DP_DEBUG(dev, QEDR_MSG_INIT, "Function called from: %s\n", 469 + (udata && context) ? "User Lib" : "Kernel"); 470 + 471 + if (!dev->rdma_ctx) { 472 + DP_ERR(dev, "invlaid RDMA context\n"); 473 + return ERR_PTR(-EINVAL); 474 + } 475 + 476 + pd = kzalloc(sizeof(*pd), GFP_KERNEL); 477 + if (!pd) 478 + return ERR_PTR(-ENOMEM); 479 + 480 + dev->ops->rdma_alloc_pd(dev->rdma_ctx, &pd_id); 481 + 482 + uresp.pd_id = pd_id; 483 + pd->pd_id = pd_id; 484 + 485 + if (udata && context) { 486 + rc = ib_copy_to_udata(udata, &uresp, sizeof(uresp)); 487 + if (rc) 488 + DP_ERR(dev, "copy error pd_id=0x%x.\n", pd_id); 489 + uctx = get_qedr_ucontext(context); 490 + uctx->pd = pd; 491 + pd->uctx = uctx; 492 + } 493 + 494 + return &pd->ibpd; 495 + } 496 + 497 + int qedr_dealloc_pd(struct ib_pd *ibpd) 498 + { 499 + struct qedr_dev *dev = get_qedr_dev(ibpd->device); 500 + struct qedr_pd *pd = get_qedr_pd(ibpd); 501 + 502 + if (!pd) 503 + pr_err("Invalid PD received in dealloc_pd\n"); 504 + 505 + DP_DEBUG(dev, QEDR_MSG_INIT, "Deallocating PD %d\n", pd->pd_id); 506 + dev->ops->rdma_dealloc_pd(dev->rdma_ctx, pd->pd_id); 507 + 508 + kfree(pd); 509 + 510 + return 0; 511 + } 512 + 513 + static void qedr_free_pbl(struct qedr_dev *dev, 514 + struct qedr_pbl_info *pbl_info, struct qedr_pbl *pbl) 515 + { 516 + struct pci_dev *pdev = dev->pdev; 517 + int i; 518 + 519 + for (i = 0; i < pbl_info->num_pbls; i++) { 520 + if (!pbl[i].va) 521 + continue; 522 + dma_free_coherent(&pdev->dev, pbl_info->pbl_size, 523 + pbl[i].va, pbl[i].pa); 524 + } 525 + 526 + kfree(pbl); 527 + } 528 + 529 + #define MIN_FW_PBL_PAGE_SIZE (4 * 1024) 530 + #define MAX_FW_PBL_PAGE_SIZE (64 * 1024) 531 + 532 + #define NUM_PBES_ON_PAGE(_page_size) (_page_size / sizeof(u64)) 533 + #define MAX_PBES_ON_PAGE NUM_PBES_ON_PAGE(MAX_FW_PBL_PAGE_SIZE) 534 + #define MAX_PBES_TWO_LAYER (MAX_PBES_ON_PAGE * MAX_PBES_ON_PAGE) 535 + 536 + static struct qedr_pbl *qedr_alloc_pbl_tbl(struct qedr_dev *dev, 537 + struct qedr_pbl_info *pbl_info, 538 + gfp_t flags) 539 + { 540 + struct pci_dev *pdev = dev->pdev; 541 + struct qedr_pbl *pbl_table; 542 + dma_addr_t *pbl_main_tbl; 543 + dma_addr_t pa; 544 + void *va; 545 + int i; 546 + 547 + pbl_table = kcalloc(pbl_info->num_pbls, sizeof(*pbl_table), flags); 548 + if (!pbl_table) 549 + return ERR_PTR(-ENOMEM); 550 + 551 + for (i = 0; i < pbl_info->num_pbls; i++) { 552 + va = dma_alloc_coherent(&pdev->dev, pbl_info->pbl_size, 553 + &pa, flags); 554 + if (!va) 555 + goto err; 556 + 557 + memset(va, 0, pbl_info->pbl_size); 558 + pbl_table[i].va = va; 559 + pbl_table[i].pa = pa; 560 + } 561 + 562 + /* Two-Layer PBLs, if we have more than one pbl we need to initialize 563 + * the first one with physical pointers to all of the rest 564 + */ 565 + pbl_main_tbl = (dma_addr_t *)pbl_table[0].va; 566 + for (i = 0; i < pbl_info->num_pbls - 1; i++) 567 + pbl_main_tbl[i] = pbl_table[i + 1].pa; 568 + 569 + return pbl_table; 570 + 571 + err: 572 + for (i--; i >= 0; i--) 573 + dma_free_coherent(&pdev->dev, pbl_info->pbl_size, 574 + pbl_table[i].va, pbl_table[i].pa); 575 + 576 + qedr_free_pbl(dev, pbl_info, pbl_table); 577 + 578 + return ERR_PTR(-ENOMEM); 579 + } 580 + 581 + static int qedr_prepare_pbl_tbl(struct qedr_dev *dev, 582 + struct qedr_pbl_info *pbl_info, 583 + u32 num_pbes, int two_layer_capable) 584 + { 585 + u32 pbl_capacity; 586 + u32 pbl_size; 587 + u32 num_pbls; 588 + 589 + if ((num_pbes > MAX_PBES_ON_PAGE) && two_layer_capable) { 590 + if (num_pbes > MAX_PBES_TWO_LAYER) { 591 + DP_ERR(dev, "prepare pbl table: too many pages %d\n", 592 + num_pbes); 593 + return -EINVAL; 594 + } 595 + 596 + /* calculate required pbl page size */ 597 + pbl_size = MIN_FW_PBL_PAGE_SIZE; 598 + pbl_capacity = NUM_PBES_ON_PAGE(pbl_size) * 599 + NUM_PBES_ON_PAGE(pbl_size); 600 + 601 + while (pbl_capacity < num_pbes) { 602 + pbl_size *= 2; 603 + pbl_capacity = pbl_size / sizeof(u64); 604 + pbl_capacity = pbl_capacity * pbl_capacity; 605 + } 606 + 607 + num_pbls = DIV_ROUND_UP(num_pbes, NUM_PBES_ON_PAGE(pbl_size)); 608 + num_pbls++; /* One for the layer0 ( points to the pbls) */ 609 + pbl_info->two_layered = true; 610 + } else { 611 + /* One layered PBL */ 612 + num_pbls = 1; 613 + pbl_size = max_t(u32, MIN_FW_PBL_PAGE_SIZE, 614 + roundup_pow_of_two((num_pbes * sizeof(u64)))); 615 + pbl_info->two_layered = false; 616 + } 617 + 618 + pbl_info->num_pbls = num_pbls; 619 + pbl_info->pbl_size = pbl_size; 620 + pbl_info->num_pbes = num_pbes; 621 + 622 + DP_DEBUG(dev, QEDR_MSG_MR, 623 + "prepare pbl table: num_pbes=%d, num_pbls=%d, pbl_size=%d\n", 624 + pbl_info->num_pbes, pbl_info->num_pbls, pbl_info->pbl_size); 625 + 626 + return 0; 627 + } 628 + 629 + static void qedr_populate_pbls(struct qedr_dev *dev, struct ib_umem *umem, 630 + struct qedr_pbl *pbl, 631 + struct qedr_pbl_info *pbl_info) 632 + { 633 + int shift, pg_cnt, pages, pbe_cnt, total_num_pbes = 0; 634 + struct qedr_pbl *pbl_tbl; 635 + struct scatterlist *sg; 636 + struct regpair *pbe; 637 + int entry; 638 + u32 addr; 639 + 640 + if (!pbl_info->num_pbes) 641 + return; 642 + 643 + /* If we have a two layered pbl, the first pbl points to the rest 644 + * of the pbls and the first entry lays on the second pbl in the table 645 + */ 646 + if (pbl_info->two_layered) 647 + pbl_tbl = &pbl[1]; 648 + else 649 + pbl_tbl = pbl; 650 + 651 + pbe = (struct regpair *)pbl_tbl->va; 652 + if (!pbe) { 653 + DP_ERR(dev, "cannot populate PBL due to a NULL PBE\n"); 654 + return; 655 + } 656 + 657 + pbe_cnt = 0; 658 + 659 + shift = ilog2(umem->page_size); 660 + 661 + for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) { 662 + pages = sg_dma_len(sg) >> shift; 663 + for (pg_cnt = 0; pg_cnt < pages; pg_cnt++) { 664 + /* store the page address in pbe */ 665 + pbe->lo = cpu_to_le32(sg_dma_address(sg) + 666 + umem->page_size * pg_cnt); 667 + addr = upper_32_bits(sg_dma_address(sg) + 668 + umem->page_size * pg_cnt); 669 + pbe->hi = cpu_to_le32(addr); 670 + pbe_cnt++; 671 + total_num_pbes++; 672 + pbe++; 673 + 674 + if (total_num_pbes == pbl_info->num_pbes) 675 + return; 676 + 677 + /* If the given pbl is full storing the pbes, 678 + * move to next pbl. 679 + */ 680 + if (pbe_cnt == (pbl_info->pbl_size / sizeof(u64))) { 681 + pbl_tbl++; 682 + pbe = (struct regpair *)pbl_tbl->va; 683 + pbe_cnt = 0; 684 + } 685 + } 686 + } 687 + } 688 + 689 + static int qedr_copy_cq_uresp(struct qedr_dev *dev, 690 + struct qedr_cq *cq, struct ib_udata *udata) 691 + { 692 + struct qedr_create_cq_uresp uresp; 693 + int rc; 694 + 695 + memset(&uresp, 0, sizeof(uresp)); 696 + 697 + uresp.db_offset = DB_ADDR_SHIFT(DQ_PWM_OFFSET_UCM_RDMA_CQ_CONS_32BIT); 698 + uresp.icid = cq->icid; 699 + 700 + rc = ib_copy_to_udata(udata, &uresp, sizeof(uresp)); 701 + if (rc) 702 + DP_ERR(dev, "copy error cqid=0x%x.\n", cq->icid); 703 + 704 + return rc; 705 + } 706 + 707 + static void consume_cqe(struct qedr_cq *cq) 708 + { 709 + if (cq->latest_cqe == cq->toggle_cqe) 710 + cq->pbl_toggle ^= RDMA_CQE_REQUESTER_TOGGLE_BIT_MASK; 711 + 712 + cq->latest_cqe = qed_chain_consume(&cq->pbl); 713 + } 714 + 715 + static inline int qedr_align_cq_entries(int entries) 716 + { 717 + u64 size, aligned_size; 718 + 719 + /* We allocate an extra entry that we don't report to the FW. */ 720 + size = (entries + 1) * QEDR_CQE_SIZE; 721 + aligned_size = ALIGN(size, PAGE_SIZE); 722 + 723 + return aligned_size / QEDR_CQE_SIZE; 724 + } 725 + 726 + static inline int qedr_init_user_queue(struct ib_ucontext *ib_ctx, 727 + struct qedr_dev *dev, 728 + struct qedr_userq *q, 729 + u64 buf_addr, size_t buf_len, 730 + int access, int dmasync) 731 + { 732 + int page_cnt; 733 + int rc; 734 + 735 + q->buf_addr = buf_addr; 736 + q->buf_len = buf_len; 737 + q->umem = ib_umem_get(ib_ctx, q->buf_addr, q->buf_len, access, dmasync); 738 + if (IS_ERR(q->umem)) { 739 + DP_ERR(dev, "create user queue: failed ib_umem_get, got %ld\n", 740 + PTR_ERR(q->umem)); 741 + return PTR_ERR(q->umem); 742 + } 743 + 744 + page_cnt = ib_umem_page_count(q->umem); 745 + rc = qedr_prepare_pbl_tbl(dev, &q->pbl_info, page_cnt, 0); 746 + if (rc) 747 + goto err0; 748 + 749 + q->pbl_tbl = qedr_alloc_pbl_tbl(dev, &q->pbl_info, GFP_KERNEL); 750 + if (IS_ERR_OR_NULL(q->pbl_tbl)) 751 + goto err0; 752 + 753 + qedr_populate_pbls(dev, q->umem, q->pbl_tbl, &q->pbl_info); 754 + 755 + return 0; 756 + 757 + err0: 758 + ib_umem_release(q->umem); 759 + 760 + return rc; 761 + } 762 + 763 + static inline void qedr_init_cq_params(struct qedr_cq *cq, 764 + struct qedr_ucontext *ctx, 765 + struct qedr_dev *dev, int vector, 766 + int chain_entries, int page_cnt, 767 + u64 pbl_ptr, 768 + struct qed_rdma_create_cq_in_params 769 + *params) 770 + { 771 + memset(params, 0, sizeof(*params)); 772 + params->cq_handle_hi = upper_32_bits((uintptr_t)cq); 773 + params->cq_handle_lo = lower_32_bits((uintptr_t)cq); 774 + params->cnq_id = vector; 775 + params->cq_size = chain_entries - 1; 776 + params->dpi = (ctx) ? ctx->dpi : dev->dpi; 777 + params->pbl_num_pages = page_cnt; 778 + params->pbl_ptr = pbl_ptr; 779 + params->pbl_two_level = 0; 780 + } 781 + 782 + static void doorbell_cq(struct qedr_cq *cq, u32 cons, u8 flags) 783 + { 784 + /* Flush data before signalling doorbell */ 785 + wmb(); 786 + cq->db.data.agg_flags = flags; 787 + cq->db.data.value = cpu_to_le32(cons); 788 + writeq(cq->db.raw, cq->db_addr); 789 + 790 + /* Make sure write would stick */ 791 + mmiowb(); 792 + } 793 + 794 + int qedr_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags) 795 + { 796 + struct qedr_cq *cq = get_qedr_cq(ibcq); 797 + unsigned long sflags; 798 + 799 + if (cq->cq_type == QEDR_CQ_TYPE_GSI) 800 + return 0; 801 + 802 + spin_lock_irqsave(&cq->cq_lock, sflags); 803 + 804 + cq->arm_flags = 0; 805 + 806 + if (flags & IB_CQ_SOLICITED) 807 + cq->arm_flags |= DQ_UCM_ROCE_CQ_ARM_SE_CF_CMD; 808 + 809 + if (flags & IB_CQ_NEXT_COMP) 810 + cq->arm_flags |= DQ_UCM_ROCE_CQ_ARM_CF_CMD; 811 + 812 + doorbell_cq(cq, cq->cq_cons - 1, cq->arm_flags); 813 + 814 + spin_unlock_irqrestore(&cq->cq_lock, sflags); 815 + 816 + return 0; 817 + } 818 + 819 + struct ib_cq *qedr_create_cq(struct ib_device *ibdev, 820 + const struct ib_cq_init_attr *attr, 821 + struct ib_ucontext *ib_ctx, struct ib_udata *udata) 822 + { 823 + struct qedr_ucontext *ctx = get_qedr_ucontext(ib_ctx); 824 + struct qed_rdma_destroy_cq_out_params destroy_oparams; 825 + struct qed_rdma_destroy_cq_in_params destroy_iparams; 826 + struct qedr_dev *dev = get_qedr_dev(ibdev); 827 + struct qed_rdma_create_cq_in_params params; 828 + struct qedr_create_cq_ureq ureq; 829 + int vector = attr->comp_vector; 830 + int entries = attr->cqe; 831 + struct qedr_cq *cq; 832 + int chain_entries; 833 + int page_cnt; 834 + u64 pbl_ptr; 835 + u16 icid; 836 + int rc; 837 + 838 + DP_DEBUG(dev, QEDR_MSG_INIT, 839 + "create_cq: called from %s. entries=%d, vector=%d\n", 840 + udata ? "User Lib" : "Kernel", entries, vector); 841 + 842 + if (entries > QEDR_MAX_CQES) { 843 + DP_ERR(dev, 844 + "create cq: the number of entries %d is too high. Must be equal or below %d.\n", 845 + entries, QEDR_MAX_CQES); 846 + return ERR_PTR(-EINVAL); 847 + } 848 + 849 + chain_entries = qedr_align_cq_entries(entries); 850 + chain_entries = min_t(int, chain_entries, QEDR_MAX_CQES); 851 + 852 + cq = kzalloc(sizeof(*cq), GFP_KERNEL); 853 + if (!cq) 854 + return ERR_PTR(-ENOMEM); 855 + 856 + if (udata) { 857 + memset(&ureq, 0, sizeof(ureq)); 858 + if (ib_copy_from_udata(&ureq, udata, sizeof(ureq))) { 859 + DP_ERR(dev, 860 + "create cq: problem copying data from user space\n"); 861 + goto err0; 862 + } 863 + 864 + if (!ureq.len) { 865 + DP_ERR(dev, 866 + "create cq: cannot create a cq with 0 entries\n"); 867 + goto err0; 868 + } 869 + 870 + cq->cq_type = QEDR_CQ_TYPE_USER; 871 + 872 + rc = qedr_init_user_queue(ib_ctx, dev, &cq->q, ureq.addr, 873 + ureq.len, IB_ACCESS_LOCAL_WRITE, 1); 874 + if (rc) 875 + goto err0; 876 + 877 + pbl_ptr = cq->q.pbl_tbl->pa; 878 + page_cnt = cq->q.pbl_info.num_pbes; 879 + } else { 880 + cq->cq_type = QEDR_CQ_TYPE_KERNEL; 881 + 882 + rc = dev->ops->common->chain_alloc(dev->cdev, 883 + QED_CHAIN_USE_TO_CONSUME, 884 + QED_CHAIN_MODE_PBL, 885 + QED_CHAIN_CNT_TYPE_U32, 886 + chain_entries, 887 + sizeof(union rdma_cqe), 888 + &cq->pbl); 889 + if (rc) 890 + goto err1; 891 + 892 + page_cnt = qed_chain_get_page_cnt(&cq->pbl); 893 + pbl_ptr = qed_chain_get_pbl_phys(&cq->pbl); 894 + } 895 + 896 + qedr_init_cq_params(cq, ctx, dev, vector, chain_entries, page_cnt, 897 + pbl_ptr, &params); 898 + 899 + rc = dev->ops->rdma_create_cq(dev->rdma_ctx, &params, &icid); 900 + if (rc) 901 + goto err2; 902 + 903 + cq->icid = icid; 904 + cq->sig = QEDR_CQ_MAGIC_NUMBER; 905 + spin_lock_init(&cq->cq_lock); 906 + 907 + if (ib_ctx) { 908 + rc = qedr_copy_cq_uresp(dev, cq, udata); 909 + if (rc) 910 + goto err3; 911 + } else { 912 + /* Generate doorbell address. */ 913 + cq->db_addr = dev->db_addr + 914 + DB_ADDR_SHIFT(DQ_PWM_OFFSET_UCM_RDMA_CQ_CONS_32BIT); 915 + cq->db.data.icid = cq->icid; 916 + cq->db.data.params = DB_AGG_CMD_SET << 917 + RDMA_PWM_VAL32_DATA_AGG_CMD_SHIFT; 918 + 919 + /* point to the very last element, passing it we will toggle */ 920 + cq->toggle_cqe = qed_chain_get_last_elem(&cq->pbl); 921 + cq->pbl_toggle = RDMA_CQE_REQUESTER_TOGGLE_BIT_MASK; 922 + cq->latest_cqe = NULL; 923 + consume_cqe(cq); 924 + cq->cq_cons = qed_chain_get_cons_idx_u32(&cq->pbl); 925 + } 926 + 927 + DP_DEBUG(dev, QEDR_MSG_CQ, 928 + "create cq: icid=0x%0x, addr=%p, size(entries)=0x%0x\n", 929 + cq->icid, cq, params.cq_size); 930 + 931 + return &cq->ibcq; 932 + 933 + err3: 934 + destroy_iparams.icid = cq->icid; 935 + dev->ops->rdma_destroy_cq(dev->rdma_ctx, &destroy_iparams, 936 + &destroy_oparams); 937 + err2: 938 + if (udata) 939 + qedr_free_pbl(dev, &cq->q.pbl_info, cq->q.pbl_tbl); 940 + else 941 + dev->ops->common->chain_free(dev->cdev, &cq->pbl); 942 + err1: 943 + if (udata) 944 + ib_umem_release(cq->q.umem); 945 + err0: 946 + kfree(cq); 947 + return ERR_PTR(-EINVAL); 948 + } 949 + 950 + int qedr_resize_cq(struct ib_cq *ibcq, int new_cnt, struct ib_udata *udata) 951 + { 952 + struct qedr_dev *dev = get_qedr_dev(ibcq->device); 953 + struct qedr_cq *cq = get_qedr_cq(ibcq); 954 + 955 + DP_ERR(dev, "cq %p RESIZE NOT SUPPORTED\n", cq); 956 + 957 + return 0; 958 + } 959 + 960 + int qedr_destroy_cq(struct ib_cq *ibcq) 961 + { 962 + struct qedr_dev *dev = get_qedr_dev(ibcq->device); 963 + struct qed_rdma_destroy_cq_out_params oparams; 964 + struct qed_rdma_destroy_cq_in_params iparams; 965 + struct qedr_cq *cq = get_qedr_cq(ibcq); 966 + 967 + DP_DEBUG(dev, QEDR_MSG_CQ, "destroy cq: cq_id %d", cq->icid); 968 + 969 + /* GSIs CQs are handled by driver, so they don't exist in the FW */ 970 + if (cq->cq_type != QEDR_CQ_TYPE_GSI) { 971 + iparams.icid = cq->icid; 972 + dev->ops->rdma_destroy_cq(dev->rdma_ctx, &iparams, &oparams); 973 + dev->ops->common->chain_free(dev->cdev, &cq->pbl); 974 + } 975 + 976 + if (ibcq->uobject && ibcq->uobject->context) { 977 + qedr_free_pbl(dev, &cq->q.pbl_info, cq->q.pbl_tbl); 978 + ib_umem_release(cq->q.umem); 979 + } 980 + 981 + kfree(cq); 982 + 983 + return 0; 467 984 }
+14
drivers/infiniband/hw/qedr/verbs.h
··· 40 40 41 41 int qedr_query_gid(struct ib_device *, u8 port, int index, union ib_gid *gid); 42 42 43 + int qedr_query_pkey(struct ib_device *, u8 port, u16 index, u16 *pkey); 44 + 43 45 struct ib_ucontext *qedr_alloc_ucontext(struct ib_device *, struct ib_udata *); 44 46 int qedr_dealloc_ucontext(struct ib_ucontext *); 45 47 ··· 51 49 int qedr_add_gid(struct ib_device *device, u8 port_num, 52 50 unsigned int index, const union ib_gid *gid, 53 51 const struct ib_gid_attr *attr, void **context); 52 + struct ib_pd *qedr_alloc_pd(struct ib_device *, 53 + struct ib_ucontext *, struct ib_udata *); 54 + int qedr_dealloc_pd(struct ib_pd *pd); 55 + 56 + struct ib_cq *qedr_create_cq(struct ib_device *ibdev, 57 + const struct ib_cq_init_attr *attr, 58 + struct ib_ucontext *ib_ctx, 59 + struct ib_udata *udata); 60 + int qedr_resize_cq(struct ib_cq *, int cqe, struct ib_udata *); 61 + int qedr_destroy_cq(struct ib_cq *); 62 + int qedr_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags); 63 + 54 64 #endif
+19
include/uapi/rdma/qedr-abi.h
··· 50 50 __u32 sges_per_srq_wr; 51 51 __u32 max_cqes; 52 52 }; 53 + 54 + struct qedr_alloc_pd_ureq { 55 + __u64 rsvd1; 56 + }; 57 + 58 + struct qedr_alloc_pd_uresp { 59 + __u32 pd_id; 60 + }; 61 + 62 + struct qedr_create_cq_ureq { 63 + __u64 addr; 64 + __u64 len; 65 + }; 66 + 67 + struct qedr_create_cq_uresp { 68 + __u32 db_offset; 69 + __u16 icid; 70 + }; 71 + 53 72 #endif /* __QEDR_USER_H__ */