From 07a7830061e657ce352e690dbe0a794ffb10d22e Mon Sep 17 00:00:00 2001
From: Lijun Ou <oulijun@huawei.com>
Date: Sat, 12 Jan 2019 18:36:29 +0800
Subject: [PATCH 31/31] RDMA/hns: RDMA/hns: Assign rq head pointer when enable
 rq record db
Origin: https://git.kernel.org/linus/de77503a59403e7045c18c6bb0a10c245a99b648

When flush cqe, it needs to get the pointer of rq and sq from db address
space of user and update it into qp context by modified qp. if rq does not
exist, it will not get the value from db address space of user.

Signed-off-by: Lijun Ou <oulijun@huawei.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
---
 drivers/infiniband/hw/hns/hns_roce_qp.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

Index: linux/drivers/infiniband/hw/hns/hns_roce_qp.c
===================================================================
--- linux.orig/drivers/infiniband/hw/hns/hns_roce_qp.c
+++ linux/drivers/infiniband/hw/hns/hns_roce_qp.c
@@ -652,6 +652,10 @@ static int hns_roce_create_qp_common(str
 				dev_err(dev, "rq record doorbell map failed!\n");
 				goto err_sq_dbmap;
 			}
+
+			/* indicate kernel supports rq record db */
+			resp.cap_flags |= HNS_ROCE_SUPPORT_RQ_RECORD_DB;
+			hr_qp->rdb_en = 1;
 		}
 	} else {
 		if (init_attr->create_flags &
@@ -760,16 +764,11 @@ static int hns_roce_create_qp_common(str
 	else
 		hr_qp->doorbell_qpn = cpu_to_le64(hr_qp->qpn);
 
-	if (ib_pd->uobject && (udata->outlen >= sizeof(resp)) &&
-		(hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB)) {
-
-		/* indicate kernel supports rq record db */
-		resp.cap_flags |= HNS_ROCE_SUPPORT_RQ_RECORD_DB;
-		ret = ib_copy_to_udata(udata, &resp, sizeof(resp));
+	if (udata) {
+		ret = ib_copy_to_udata(udata, &resp,
+				       min(udata->outlen, sizeof(resp)));
 		if (ret)
 			goto err_qp;
-
-		hr_qp->rdb_en = 1;
 	}
 	hr_qp->event = hns_roce_ib_qp_event;
 
@@ -946,7 +945,9 @@ int hns_roce_modify_qp(struct ib_qp *ibq
 	    (attr_mask & IB_QP_STATE) && new_state == IB_QPS_ERR) {
 		if (hr_qp->sdb_en == 1) {
 			hr_qp->sq.head = *(int *)(hr_qp->sdb.virt_addr);
-			hr_qp->rq.head = *(int *)(hr_qp->rdb.virt_addr);
+
+			if (hr_qp->rdb_en == 1)
+				hr_qp->rq.head = *(int *)(hr_qp->rdb.virt_addr);
 		} else {
 			dev_warn(dev, "flush cqe is not supported in userspace!\n");
 			goto out;
