[PATCH for-next 2/4] RDMA/erdma: Support non-contiguous kernel CQ buffers
Cheng Xu <[email protected]>
| Newsgroups | org.kernel.vger.linux-rdma |
|---|---|
| Message-ID | <[email protected]> |
A single coherent allocation for a kernel CQ can fail when memory is fragmented. Use page-sized coherent buffers and describe them with the existing MTT. Keep the userspace CQ path and doorbell allocation unchanged. Signed-off-by: Cheng Xu <[email protected]> --- drivers/infiniband/hw/erdma/erdma_cq.c | 15 ++--- drivers/infiniband/hw/erdma/erdma_verbs.c | 77 +++++++++-------------- drivers/infiniband/hw/erdma/erdma_verbs.h | 3 +- 3 files changed, 38 insertions(+), 57 deletions(-) diff --git a/drivers/infiniband/hw/erdma/erdma_cq.c b/drivers/infiniband/hw/erdma/erdma_cq.c index 4cc0254b0ab5..7cfb067c0b40 100644 --- a/drivers/infiniband/hw/erdma/erdma_cq.c +++ b/drivers/infiniband/hw/erdma/erdma_cq.c @@ -8,8 +8,8 @@ static void *get_next_valid_cqe(struct erdma_cq *cq) { - __be32 *cqe = get_queue_entry(cq->kern_cq.qbuf, cq->kern_cq.ci, - cq->depth, CQE_SHIFT); + __be32 *cqe = erdma_kmem_get_entry(&cq->kern_cq.qbuf_mem, + cq->kern_cq.ci, cq->depth, CQE_SHIFT); u32 owner = FIELD_GET(ERDMA_CQE_HDR_OWNER_MASK, be32_to_cpu(READ_ONCE(*cqe))); @@ -242,15 +242,16 @@ void erdma_remove_cqes_of_qp(struct ib_cq *ibcq, u32 qpn) while (ncqe > 0) { cur_cq_ci = prev_cq_ci + ncqe - 1; - cqe = get_queue_entry(cq->kern_cq.qbuf, cur_cq_ci, cq->depth, - CQE_SHIFT); + cqe = erdma_kmem_get_entry(&cq->kern_cq.qbuf_mem, cur_cq_ci, + cq->depth, CQE_SHIFT); if (be32_to_cpu(cqe->qpn) == qpn) { ++nqp_cqe; } else if (nqp_cqe) { - dst_cqe = get_queue_entry(cq->kern_cq.qbuf, - cur_cq_ci + nqp_cqe, - cq->depth, CQE_SHIFT); + dst_cqe = + erdma_kmem_get_entry(&cq->kern_cq.qbuf_mem, + cur_cq_ci + nqp_cqe, + cq->depth, CQE_SHIFT); owner = FIELD_GET(ERDMA_CQE_HDR_OWNER_MASK, be32_to_cpu(dst_cqe->hdr)); cqe->hdr = cpu_to_be32( diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c index 918abc9377ab..49bf3b2a60b9 100644 --- a/drivers/infiniband/hw/erdma/erdma_verbs.c +++ b/drivers/infiniband/hw/erdma/erdma_verbs.c @@ -177,7 +177,6 @@ static int create_cq_cmd(struct erdma_ucontext *uctx, struct erdma_cq *cq) struct erdma_dev *dev = to_edev(cq->ibcq.device); struct erdma_cmdq_create_cq_req req; struct erdma_mem *mem; - u32 page_size; erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA, CMDQ_OPCODE_CREATE_CQ); @@ -187,48 +186,35 @@ static int create_cq_cmd(struct erdma_ucontext *uctx, struct erdma_cq *cq) req.cfg1 = FIELD_PREP(ERDMA_CMD_CREATE_CQ_EQN_MASK, cq->assoc_eqn); if (rdma_is_kernel_res(&cq->ibcq.res)) { - page_size = SZ_32M; - req.cfg0 |= FIELD_PREP(ERDMA_CMD_CREATE_CQ_PAGESIZE_MASK, - ilog2(page_size) - ERDMA_HW_PAGE_SHIFT); - req.qbuf_addr_l = lower_32_bits(cq->kern_cq.qbuf_dma_addr); - req.qbuf_addr_h = upper_32_bits(cq->kern_cq.qbuf_dma_addr); - - req.cfg1 |= FIELD_PREP(ERDMA_CMD_CREATE_CQ_MTT_CNT_MASK, 1) | - FIELD_PREP(ERDMA_CMD_CREATE_CQ_MTT_LEVEL_MASK, - ERDMA_MR_MTT_0LEVEL); - - req.first_page_offset = 0; + mem = &cq->kern_cq.qbuf_mem; req.cq_dbrec_dma = cq->kern_cq.dbrec_dma; } else { mem = &cq->user_cq.qbuf_mem; - req.cfg0 |= - FIELD_PREP(ERDMA_CMD_CREATE_CQ_PAGESIZE_MASK, - ilog2(mem->page_size) - ERDMA_HW_PAGE_SHIFT); - if (mem->mtt_nents == 1) { - req.qbuf_addr_l = lower_32_bits(mem->mtt->buf[0]); - req.qbuf_addr_h = upper_32_bits(mem->mtt->buf[0]); - req.cfg1 |= - FIELD_PREP(ERDMA_CMD_CREATE_CQ_MTT_LEVEL_MASK, - ERDMA_MR_MTT_0LEVEL); - } else { - req.qbuf_addr_l = lower_32_bits(mem->mtt->buf_dma); - req.qbuf_addr_h = upper_32_bits(mem->mtt->buf_dma); - req.cfg1 |= - FIELD_PREP(ERDMA_CMD_CREATE_CQ_MTT_LEVEL_MASK, - ERDMA_MR_MTT_1LEVEL); - } - req.cfg1 |= FIELD_PREP(ERDMA_CMD_CREATE_CQ_MTT_CNT_MASK, - mem->mtt_nents); - - req.first_page_offset = mem->page_offset; req.cq_dbrec_dma = cq->user_cq.dbrec_dma; + } - if (uctx->ext_db.enable) { - req.cfg1 |= FIELD_PREP( - ERDMA_CMD_CREATE_CQ_MTT_DB_CFG_MASK, 1); - req.cfg2 = FIELD_PREP(ERDMA_CMD_CREATE_CQ_DB_CFG_MASK, - uctx->ext_db.cdb_off); - } + req.cfg0 |= FIELD_PREP(ERDMA_CMD_CREATE_CQ_PAGESIZE_MASK, + ilog2(mem->page_size) - ERDMA_HW_PAGE_SHIFT); + if (mem->mtt_nents == 1) { + req.qbuf_addr_l = lower_32_bits(mem->mtt->buf[0]); + req.qbuf_addr_h = upper_32_bits(mem->mtt->buf[0]); + req.cfg1 |= FIELD_PREP(ERDMA_CMD_CREATE_CQ_MTT_LEVEL_MASK, + ERDMA_MR_MTT_0LEVEL); + } else { + req.qbuf_addr_l = lower_32_bits(mem->mtt->buf_dma); + req.qbuf_addr_h = upper_32_bits(mem->mtt->buf_dma); + req.cfg1 |= FIELD_PREP(ERDMA_CMD_CREATE_CQ_MTT_LEVEL_MASK, + ERDMA_MR_MTT_1LEVEL); + } + req.cfg1 |= FIELD_PREP(ERDMA_CMD_CREATE_CQ_MTT_CNT_MASK, + mem->mtt_nents); + req.first_page_offset = mem->page_offset; + + if (uctx && uctx->ext_db.enable) { + req.cfg1 |= + FIELD_PREP(ERDMA_CMD_CREATE_CQ_MTT_DB_CFG_MASK, 1); + req.cfg2 = FIELD_PREP(ERDMA_CMD_CREATE_CQ_DB_CFG_MASK, + uctx->ext_db.cdb_off); } return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL, @@ -1392,8 +1378,7 @@ int erdma_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata) wait_for_completion(&cq->free); if (rdma_is_kernel_res(&cq->ibcq.res)) { - dma_free_coherent(&dev->pdev->dev, cq->depth << CQE_SHIFT, - cq->kern_cq.qbuf, cq->kern_cq.qbuf_dma_addr); + put_mtt_entries(dev, &cq->kern_cq.qbuf_mem); dma_pool_free(dev->db_pool, cq->kern_cq.dbrec, cq->kern_cq.dbrec_dma); } else { @@ -1991,10 +1976,8 @@ static int erdma_init_kernel_cq(struct erdma_cq *cq) { struct erdma_dev *dev = to_edev(cq->ibcq.device); - cq->kern_cq.qbuf = - dma_alloc_coherent(&dev->pdev->dev, cq->depth << CQE_SHIFT, - &cq->kern_cq.qbuf_dma_addr, GFP_KERNEL); - if (!cq->kern_cq.qbuf) + if (erdma_alloc_kmem(dev, &cq->kern_cq.qbuf_mem, + cq->depth << CQE_SHIFT)) return -ENOMEM; cq->kern_cq.dbrec = dma_pool_zalloc(dev->db_pool, GFP_KERNEL, @@ -2009,8 +1992,7 @@ static int erdma_init_kernel_cq(struct erdma_cq *cq) return 0; err_out: - dma_free_coherent(&dev->pdev->dev, cq->depth << CQE_SHIFT, - cq->kern_cq.qbuf, cq->kern_cq.qbuf_dma_addr); + put_mtt_entries(dev, &cq->kern_cq.qbuf_mem); return -ENOMEM; } @@ -2077,8 +2059,7 @@ int erdma_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, erdma_unmap_user_dbrecords(ctx, &cq->user_cq.user_dbr_page); put_mtt_entries(dev, &cq->user_cq.qbuf_mem); } else { - dma_free_coherent(&dev->pdev->dev, depth << CQE_SHIFT, - cq->kern_cq.qbuf, cq->kern_cq.qbuf_dma_addr); + put_mtt_entries(dev, &cq->kern_cq.qbuf_mem); dma_pool_free(dev->db_pool, cq->kern_cq.dbrec, cq->kern_cq.dbrec_dma); } diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/infiniband/hw/erdma/erdma_verbs.h index eb7318cf7a52..5056d60357db 100644 --- a/drivers/infiniband/hw/erdma/erdma_verbs.h +++ b/drivers/infiniband/hw/erdma/erdma_verbs.h @@ -352,8 +352,7 @@ struct erdma_qp { }; struct erdma_kcq_info { - void *qbuf; - dma_addr_t qbuf_dma_addr; + struct erdma_mem qbuf_mem; u32 ci; u32 cmdsn; u32 notify_cnt; -- 2.31.1