From 2880d64c8d73375978d2767c5dd7803b444f9016 Mon Sep 17 00:00:00 2001
From: Yangyang Li <liyangyang20@huawei.com>
Date: Mon, 16 Oct 2023 16:10:06 +0800
Subject: [PATCH] libhns: Support SRQ record doorbell

Compared with normal doorbell, using record doorbell can shorten the
process of ringing the doorbell and reduce the latency.

During SRQ creation, the kernel driver will allocate doorbell buffer
and notify userspace whether the SRQ record doorbell is enabled with
the flag HNS_ROCE_RSP_SRQ_CAP_RECORD_DB. The userspace driver will decide
whether to use record doorbell or normal doorbell based on this flag
in post SRQ recv process.

This patch relies on the corresponding kernel patch:
RDMA/hns: Support SRQ record doorbell

Signed-off-by: Yangyang Li <liyangyang20@huawei.com>
Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com>
---
 providers/hns/hns_roce_u.h       |  4 +++-
 providers/hns/hns_roce_u_db.c    |  1 +
 providers/hns/hns_roce_u_hw_v2.c | 14 +++++++++-----
 providers/hns/hns_roce_u_verbs.c | 12 +++++++-----
 4 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/providers/hns/hns_roce_u.h b/providers/hns/hns_roce_u.h
index ae9ae51..197bde9 100644
--- a/providers/hns/hns_roce_u.h
+++ b/providers/hns/hns_roce_u.h
@@ -187,6 +187,7 @@ struct hns_roce_buf {
 enum hns_roce_db_type {
 	HNS_ROCE_QP_TYPE_DB,
 	HNS_ROCE_CQ_TYPE_DB,
+	HNS_ROCE_SRQ_TYPE_DB,
 	HNS_ROCE_DB_TYPE_NUM
 };
 
@@ -351,7 +352,8 @@ struct hns_roce_srq {
 	unsigned int			max_gs;
 	unsigned int			rsv_sge;
 	unsigned int			wqe_shift;
-	unsigned int			*db;
+	unsigned int			*rdb;
+	unsigned int                    cap_flags;
 	unsigned short			counter;
 	struct list_node xrc_srcq_node;
 };
diff --git a/providers/hns/hns_roce_u_db.c b/providers/hns/hns_roce_u_db.c
index 73a71de..bbef988 100644
--- a/providers/hns/hns_roce_u_db.c
+++ b/providers/hns/hns_roce_u_db.c
@@ -41,6 +41,7 @@
 static const unsigned int db_size[] = {
 	[HNS_ROCE_QP_TYPE_DB] = 4,
 	[HNS_ROCE_CQ_TYPE_DB] = 4,
+	[HNS_ROCE_SRQ_TYPE_DB] = 4,
 };
 
 static struct hns_roce_db_page *hns_roce_add_db_page(
diff --git a/providers/hns/hns_roce_u_hw_v2.c b/providers/hns/hns_roce_u_hw_v2.c
index ac40d5d..714a34e 100644
--- a/providers/hns/hns_roce_u_hw_v2.c
+++ b/providers/hns/hns_roce_u_hw_v2.c
@@ -2109,11 +2109,15 @@ static void fill_wqe_idx(struct hns_roce_srq *srq, unsigned int wqe_idx)
 	idx_que->head++;
 }
 
-static void update_srq_db(struct hns_roce_db *db, struct hns_roce_srq *srq)
+static void update_srq_db(struct hns_roce_context *ctx, struct hns_roce_db *db,
+                         struct hns_roce_srq *srq)
 {
 	hr_reg_write(db, DB_TAG, srq->srqn);
 	hr_reg_write(db, DB_CMD, HNS_ROCE_V2_SRQ_DB);
 	hr_reg_write(db, DB_PI, srq->idx_que.head);
+
+	hns_roce_write64(ctx, ctx->uar + ROCEE_VF_DB_CFG0_OFFSET,
+                        (__le32 *)db);
 }
 
 static int check_srq_recv(struct hns_roce_context *ctx)
@@ -2176,10 +2180,10 @@ static int hns_roce_u_v2_post_srq_recv(struct ibv_srq *ib_srq,
 		 */
 		udma_to_device_barrier();
 
-		update_srq_db(&srq_db, srq);
-
-		hns_roce_write64(ctx, ctx->uar + ROCEE_VF_DB_CFG0_OFFSET,
-				 (__le32 *)&srq_db);
+               if (srq->cap_flags & HNS_ROCE_RSP_SRQ_CAP_RECORD_DB)
+                       *srq->rdb = srq->idx_que.head & 0xffff;
+               else
+                       update_srq_db(ctx, &srq_db, srq);
 	}
 
 	hns_roce_spin_unlock(&srq->hr_lock);
diff --git a/providers/hns/hns_roce_u_verbs.c b/providers/hns/hns_roce_u_verbs.c
index f76341c..1c2d94d 100644
--- a/providers/hns/hns_roce_u_verbs.c
+++ b/providers/hns/hns_roce_u_verbs.c
@@ -866,7 +866,8 @@ static int exec_srq_create_cmd(struct ibv_context *context,
 
 	cmd_ex.buf_addr = (uintptr_t)srq->wqe_buf.buf;
 	cmd_ex.que_addr = (uintptr_t)srq->idx_que.buf.buf;
-	cmd_ex.db_addr = (uintptr_t)srq->db;
+	cmd_ex.db_addr = (uintptr_t)srq->rdb;
+	cmd_ex.req_cap_flags |= HNS_ROCE_SRQ_CAP_RECORD_DB;
 
 	ret = ibv_cmd_create_srq_ex(context, &srq->verbs_srq, init_attr,
 				    &cmd_ex.ibv_cmd, sizeof(cmd_ex),
@@ -875,6 +876,7 @@ static int exec_srq_create_cmd(struct ibv_context *context,
 		return ret;
 
 	srq->srqn = resp_ex.srqn;
+	srq->cap_flags = resp_ex.cap_flags;
 
 	return 0;
 }
@@ -932,8 +934,8 @@ static struct ibv_srq *create_srq(struct ibv_context *context,
 	if (alloc_srq_buf(srq))
 		goto err_free_srq;
 
-	srq->db = hns_roce_alloc_db(hr_ctx, HNS_ROCE_QP_TYPE_DB);
-	if (!srq->db)
+	srq->rdb = hns_roce_alloc_db(hr_ctx, HNS_ROCE_SRQ_TYPE_DB);
+	if (!srq->rdb)
 		goto err_srq_buf;
 
 	ret = exec_srq_create_cmd(context, srq, init_attr);
@@ -956,7 +958,7 @@ err_destroy_srq:
 	ibv_cmd_destroy_srq(&srq->verbs_srq.srq);
 
 err_srq_db:
-	hns_roce_free_db(hr_ctx, srq->db, HNS_ROCE_QP_TYPE_DB);
+	hns_roce_free_db(hr_ctx, srq->rdb, HNS_ROCE_SRQ_TYPE_DB);
 
 err_srq_buf:
 	free_srq_buf(srq);
@@ -1048,7 +1050,7 @@ int hns_roce_u_destroy_srq(struct ibv_srq *ibv_srq)
 
 	hns_roce_clear_srq(ctx, srq->srqn);
 
-	hns_roce_free_db(ctx, srq->db, HNS_ROCE_QP_TYPE_DB);
+	hns_roce_free_db(ctx, srq->rdb, HNS_ROCE_SRQ_TYPE_DB);
 	free_srq_buf(srq);
 	free(srq);
 
-- 
2.25.1

