diff options
author | Yixian Liu <liuyixian@huawei.com> | 2018-03-21 14:11:18 +0800 |
---|---|---|
committer | Jason Gunthorpe <jgg@mellanox.com> | 2018-03-22 12:42:48 -0600 |
commit | e95955773d4357a0b09a43128352047afce8f35b (patch) | |
tree | f7eb9964dd9c2e0cdf6e416a831215c98a73e745 | |
parent | 761fc376c999df9febaa491bffae2f6722f423ff (diff) | |
download | linux-e95955773d4357a0b09a43128352047afce8f35b.tar.bz2 |
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 <zhangxiping3@huawei.com>
Fixes: 9b44703d0a21 ("RDMA/hns: Support cq record doorbell for the user space")
Signed-off-by: Yixian Liu <liuyixian@huawei.com>
Signed-off-by: Lijun Ou <oulijun@huawei.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
-rw-r--r-- | drivers/infiniband/hw/hns/hns_roce_cq.c | 38 |
1 files 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) |