summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYixian Liu <liuyixian@huawei.com>2018-03-21 14:11:18 +0800
committerJason Gunthorpe <jgg@mellanox.com>2018-03-22 12:42:48 -0600
commite95955773d4357a0b09a43128352047afce8f35b (patch)
treef7eb9964dd9c2e0cdf6e416a831215c98a73e745
parent761fc376c999df9febaa491bffae2f6722f423ff (diff)
downloadlinux-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.c38
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)