From e95955773d4357a0b09a43128352047afce8f35b Mon Sep 17 00:00:00 2001 From: Yixian Liu Date: Wed, 21 Mar 2018 14:11:18 +0800 Subject: [PATCH] RDMA/hns: Fix cq record doorbell enable in kernel Upon detecting both kernel and user space support record doorbell, the kernel needs to enable this capability in hardware by db_en, and it should take place before cq context configuration in hns_roce_cq_alloc. Currently, db_en is configured after cq alloc and db_map_user has similar problem. Reported-by: Xiping Zhang Fixes: 9b44703d0a21 ("RDMA/hns: Support cq record doorbell for the user space") Signed-off-by: Yixian Liu Signed-off-by: Lijun Ou Signed-off-by: Jason Gunthorpe --- drivers/infiniband/hw/hns/hns_roce_cq.c | 38 +++++++++++-------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/drivers/infiniband/hw/hns/hns_roce_cq.c b/drivers/infiniband/hw/hns/hns_roce_cq.c index 095a9100717d..14734d0d0b76 100644 --- a/drivers/infiniband/hw/hns/hns_roce_cq.c +++ b/drivers/infiniband/hw/hns/hns_roce_cq.c @@ -355,6 +355,18 @@ struct ib_cq *hns_roce_ib_create_cq(struct ib_device *ib_dev, goto err_cq; } + if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB) && + (udata->outlen >= sizeof(resp))) { + ret = hns_roce_db_map_user(to_hr_ucontext(context), + ucmd.db_addr, &hr_cq->db); + if (ret) { + dev_err(dev, "cq record doorbell map failed!\n"); + goto err_mtt; + } + hr_cq->db_en = 1; + resp.cap_flags |= HNS_ROCE_SUPPORT_CQ_RECORD_DB; + } + /* Get user space parameters */ uar = &to_hr_ucontext(context)->uar; } else { @@ -385,17 +397,7 @@ struct ib_cq *hns_roce_ib_create_cq(struct ib_device *ib_dev, hr_cq, vector); if (ret) { dev_err(dev, "Creat CQ .Failed to cq_alloc.\n"); - goto err_mtt; - } - - if (context && (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB) && - (udata->outlen >= sizeof(resp))) { - ret = hns_roce_db_map_user(to_hr_ucontext(context), - ucmd.db_addr, &hr_cq->db); - if (ret) { - dev_err(dev, "cq record doorbell map failed!\n"); - goto err_cqc; - } + goto err_dbmap; } /* @@ -414,28 +416,22 @@ struct ib_cq *hns_roce_ib_create_cq(struct ib_device *ib_dev, if (context) { resp.cqn = hr_cq->cqn; - if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB) && - (udata->outlen >= sizeof(resp))) { - hr_cq->db_en = 1; - resp.cap_flags |= HNS_ROCE_SUPPORT_CQ_RECORD_DB; - } - ret = ib_copy_to_udata(udata, &resp, sizeof(resp)); if (ret) - goto err_dbmap; + goto err_cqc; } return &hr_cq->ib_cq; +err_cqc: + hns_roce_free_cq(hr_dev, hr_cq); + err_dbmap: if (context && (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB) && (udata->outlen >= sizeof(resp))) hns_roce_db_unmap_user(to_hr_ucontext(context), &hr_cq->db); -err_cqc: - hns_roce_free_cq(hr_dev, hr_cq); - err_mtt: hns_roce_mtt_cleanup(hr_dev, &hr_cq->hr_buf.hr_mtt); if (context)