RDMA/hns: Fix cq record doorbell enable in kernel
authorYixian Liu <liuyixian@huawei.com>
Wed, 21 Mar 2018 06:11:18 +0000 (14:11 +0800)
committerJason Gunthorpe <jgg@mellanox.com>
Thu, 22 Mar 2018 18:42:48 +0000 (12:42 -0600)
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>
drivers/infiniband/hw/hns/hns_roce_cq.c

index 095a9100717d1bbb4193010963463963ba2bc8d5..14734d0d0b76086dfc5ea76e84ae3dc27a2a58b9 100644 (file)
@@ -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)