From 6e4ee881aa5eb420fc101cf7d8970d3ba202d926 Mon Sep 17 00:00:00 2001
From: Liulongfang <liulongfang@huawei.com>
Date: Wed, 11 May 2022 11:44:26 +0800
Subject: [PATCH 116/183] uadk: add BD id check for sync mode

In synchronous mode, when multiple threads in a single queue send and
receive messages, if one thread exits the message overtime, other threads
may receive the overtime message, resulting in message misalignment.

Therefore, we need to add the message sequence number check. if it is
not our own sequence number, it means that the message is received
incorrectly and needs to exit.

Signed-off-by: Liulongfang <liulongfang@huawei.com>
---
 drv/hisi_comp.c          | 34 ++++++++++++++++++++++------------
 drv/hisi_hpre.c          | 17 +++++++++++++++++
 drv/hisi_qm_udrv.c       | 36 ++++++++++++++++++++++++++++++++++++
 drv/hisi_sec.c           | 35 +++++++++++++++++++++++++++++++----
 include/drv/wd_dh_drv.h  |  2 +-
 include/drv/wd_ecc_drv.h |  2 +-
 include/drv/wd_rsa_drv.h |  2 +-
 include/hisi_qm_udrv.h   | 15 +++++++++++++++
 8 files changed, 124 insertions(+), 19 deletions(-)

diff --git a/drv/hisi_comp.c b/drv/hisi_comp.c
index 9fdf3f1..e1d2f6e 100644
--- a/drv/hisi_comp.c
+++ b/drv/hisi_comp.c
@@ -873,6 +873,7 @@ static int hisi_zip_comp_send(handle_t ctx, struct wd_comp_msg *msg, void *priv)
 	__u16 count = 0;
 	int ret;
 
+	hisi_set_msg_id(h_qp, &msg->tag);
 	ret = fill_zip_comp_sqe(qp, msg, &sqe);
 	if (unlikely(ret < 0)) {
 		WD_ERR("failed to fill zip sqe, ret = %d!\n", ret);
@@ -939,6 +940,22 @@ static void free_hw_sgl(handle_t h_qp, struct hisi_zip_sqe *sqe,
 	}
 }
 
+static void get_ctx_buf(struct hisi_zip_sqe *sqe,
+			 struct wd_comp_msg *recv_msg)
+{
+	recv_msg->avail_out = sqe->dest_avail_out;
+	if (VA_ADDR(sqe->stream_ctx_addr_h, sqe->stream_ctx_addr_l)) {
+		/*
+		 * In ASYNC mode, recv_msg->ctx_buf is NULL.
+		 * recv_msg->ctx_buf is only valid in SYNC mode.
+		 * ctx_dwx uses 4 BYTES
+		 */
+		*(__u32 *)recv_msg->ctx_buf = sqe->ctx_dw0;
+		*(__u32 *)(recv_msg->ctx_buf + CTX_DW1_OFFSET) = sqe->ctx_dw1;
+		*(__u32 *)(recv_msg->ctx_buf + CTX_DW2_OFFSET) = sqe->ctx_dw2;
+	}
+}
+
 static int parse_zip_sqe(struct hisi_qp *qp, struct hisi_zip_sqe *sqe,
 			 struct wd_comp_msg *recv_msg)
 {
@@ -947,7 +964,7 @@ static int parse_zip_sqe(struct hisi_qp *qp, struct hisi_zip_sqe *sqe,
 	__u16 lstblk = sqe->dw3 & HZ_LSTBLK_MASK;
 	__u32 status = sqe->dw3 & HZ_STATUS_MASK;
 	__u32 type = sqe->dw9 & HZ_REQ_TYPE_MASK;
-	int alg_type;
+	int alg_type, ret;
 	__u32 tag;
 
 	alg_type = get_alg_type(type);
@@ -957,6 +974,9 @@ static int parse_zip_sqe(struct hisi_qp *qp, struct hisi_zip_sqe *sqe,
 	}
 
 	tag = ops[alg_type].get_tag(sqe);
+	ret = hisi_check_bd_id((handle_t)qp, recv_msg->tag, tag);
+	if (ret)
+		return ret;
 
 	recv_msg->tag = tag;
 
@@ -980,17 +1000,7 @@ static int parse_zip_sqe(struct hisi_qp *qp, struct hisi_zip_sqe *sqe,
 
 	ops[alg_type].get_data_size(sqe, qp->q_info.qc_type, recv_msg);
 
-	recv_msg->avail_out = sqe->dest_avail_out;
-	if (VA_ADDR(sqe->stream_ctx_addr_h, sqe->stream_ctx_addr_l)) {
-		/*
-		 * In ASYNC mode, recv_msg->ctx_buf is NULL.
-		 * recv_msg->ctx_buf is only valid in SYNC mode.
-		 * ctx_dwx uses 4 BYTES
-		 */
-		*(__u32 *)recv_msg->ctx_buf = sqe->ctx_dw0;
-		*(__u32 *)(recv_msg->ctx_buf + CTX_DW1_OFFSET) = sqe->ctx_dw1;
-		*(__u32 *)(recv_msg->ctx_buf + CTX_DW2_OFFSET) = sqe->ctx_dw2;
-	}
+	get_ctx_buf(sqe, recv_msg);
 
 	/* last block no space, need resend null size req */
 	if (ctx_st == HZ_DECOMP_NO_SPACE)
diff --git a/drv/hisi_hpre.c b/drv/hisi_hpre.c
index 7e14027..33127e0 100644
--- a/drv/hisi_hpre.c
+++ b/drv/hisi_hpre.c
@@ -528,6 +528,7 @@ static int rsa_send(handle_t ctx, struct wd_rsa_msg *msg)
 	if (ret < 0)
 		return ret;
 
+	hisi_set_msg_id(h_qp, &msg->tag);
 	hw_msg.done = 0x1;
 	hw_msg.etype = 0x0;
 	hw_msg.low_tag = msg->tag;
@@ -546,6 +547,10 @@ static int rsa_recv(handle_t ctx, struct wd_rsa_msg *msg)
 	if (ret < 0)
 		return ret;
 
+	ret = hisi_check_bd_id(h_qp, msg->tag, hw_msg.low_tag);
+	if (ret)
+		return ret;
+
 	if (hw_msg.done != HPRE_HW_TASK_DONE ||
 			hw_msg.etype || hw_msg.etype1) {
 		WD_ERR("failed to do rsa task! done=0x%x, etype=0x%x, etype1=0x%x!\n",
@@ -668,6 +673,7 @@ static int dh_send(handle_t ctx, struct wd_dh_msg *msg)
 	if (ret)
 		return ret;
 
+	hisi_set_msg_id(h_qp, &msg->tag);
 	hw_msg.low_out = LW_U32((uintptr_t)req->pri);
 	hw_msg.hi_out = HI_U32((uintptr_t)req->pri);
 	hw_msg.done = 0x1;
@@ -688,6 +694,10 @@ static int dh_recv(handle_t ctx, struct wd_dh_msg *msg)
 	if (ret < 0)
 		return ret;
 
+	ret = hisi_check_bd_id(h_qp, msg->tag, hw_msg.low_tag);
+	if (ret)
+		return ret;
+
 	if (hw_msg.done != HPRE_HW_TASK_DONE ||
 			hw_msg.etype || hw_msg.etype1) {
 		WD_ERR("failed to do dh task! done=0x%x, etype=0x%x, etype1=0x%x!\n",
@@ -1766,6 +1776,9 @@ free_dst:
 
 static int ecc_send(handle_t ctx, struct wd_ecc_msg *msg)
 {
+	handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx);
+
+	hisi_set_msg_id(h_qp, &msg->tag);
 	if (msg->req.op_type == WD_SM2_ENCRYPT)
 		return sm2_enc_send(ctx, msg);
 	else if (msg->req.op_type == WD_SM2_DECRYPT)
@@ -2333,6 +2346,10 @@ static int ecc_recv(handle_t ctx, struct wd_ecc_msg *msg)
 	if (ret)
 		return ret;
 
+	ret = hisi_check_bd_id(h_qp, msg->tag, hw_msg.low_tag);
+	if (ret)
+		return ret;
+
 	if (hw_msg.alg == HPRE_ALG_ECDH_MULTIPLY &&
 		hw_msg.sm2_mlen == HPRE_SM2_ENC)
 		return sm2_enc_parse(h_qp, msg, &hw_msg);
diff --git a/drv/hisi_qm_udrv.c b/drv/hisi_qm_udrv.c
index 2c0d87c..53d5a55 100644
--- a/drv/hisi_qm_udrv.c
+++ b/drv/hisi_qm_udrv.c
@@ -528,6 +528,42 @@ int hisi_qm_recv(handle_t h_qp, void *resp, __u16 expect, __u16 *count)
 	return ret;
 }
 
+int hisi_check_bd_id(handle_t h_qp, __u32 mid, __u32 bid)
+{
+	struct hisi_qp *qp = (struct hisi_qp *)h_qp;
+	__u8 mode = qp->q_info.qp_mode;
+
+	if (mode == CTX_MODE_SYNC && mid != bid) {
+		WD_ERR("failed to recv self bd, send id: %u, recv id: %u\n",
+			    mid, bid);
+		return -WD_EINVAL;
+	}
+
+	return 0;
+}
+
+void hisi_set_msg_id(handle_t h_qp, __u32 *tag)
+{
+	static __thread __u64 rand_seed = 0x330eabcd;
+	struct hisi_qp *qp = (struct hisi_qp *)h_qp;
+	__u8 mode = qp->q_info.qp_mode;
+	__u16 seeds[3] = {0};
+	__u64 id;
+
+	/*
+	 * The random message id on a single queue is obtained through the
+	 * system's pseudo-random number generation algorithm to ensure
+	 * that 1024 packets on a queue will not have duplicate id
+	 */
+	if (mode == CTX_MODE_SYNC) {
+		seeds[0] = LW_U16(rand_seed);
+		seeds[1] = LW_U16(rand_seed >> 16);
+		id = nrand48(seeds);
+		*tag = LW_U32(id);
+		rand_seed = id;
+	}
+}
+
 static void *hisi_qm_create_sgl(__u32 sge_num)
 {
 	void *sgl;
diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c
index 396e11e..88eacc3 100644
--- a/drv/hisi_sec.c
+++ b/drv/hisi_sec.c
@@ -929,6 +929,7 @@ int hisi_sec_cipher_send(handle_t ctx, struct wd_cipher_msg *msg)
 			return ret;
 	}
 
+	hisi_set_msg_id(h_qp, &msg->tag);
 	sqe.type2.clen_ivhlen |= (__u32)msg->in_bytes;
 	sqe.type2.tag = (__u16)msg->tag;
 	fill_cipher_bd2_addr(msg, &sqe);
@@ -959,6 +960,10 @@ int hisi_sec_cipher_recv(handle_t ctx, struct wd_cipher_msg *recv_msg)
 	if (ret < 0)
 		return ret;
 
+	ret = hisi_check_bd_id(h_qp, (__u16)recv_msg->tag, sqe.type2.tag);
+	if (ret)
+		return ret;
+
 	parse_cipher_bd2(&sqe, recv_msg);
 	recv_msg->tag = sqe.type2.tag;
 
@@ -1130,6 +1135,7 @@ int hisi_sec_cipher_send_v3(handle_t ctx, struct wd_cipher_msg *msg)
 			return ret;
 	}
 
+	hisi_set_msg_id(h_qp, &msg->tag);
 	sqe.c_len_ivin = (__u32)msg->in_bytes;
 	sqe.tag = (__u64)(uintptr_t)msg->tag;
 	fill_cipher_bd3_addr(msg, &sqe);
@@ -1187,6 +1193,10 @@ int hisi_sec_cipher_recv_v3(handle_t ctx, struct wd_cipher_msg *recv_msg)
 	if (ret < 0)
 		return ret;
 
+	ret = hisi_check_bd_id(h_qp, recv_msg->tag, sqe.tag);
+	if (ret)
+		return ret;
+
 	parse_cipher_bd3(&sqe, recv_msg);
 	recv_msg->tag = sqe.tag;
 
@@ -1366,7 +1376,8 @@ int hisi_sec_digest_send(handle_t ctx, struct wd_digest_msg *msg)
 
 	qm_fill_digest_long_bd(msg, &sqe);
 
-	sqe.type2.tag = msg->tag;
+	hisi_set_msg_id(h_qp, &msg->tag);
+	sqe.type2.tag = (__u16)msg->tag;
 	ret = hisi_qm_send(h_qp, &sqe, 1, &count);
 	if (ret < 0) {
 		if (ret != -WD_EBUSY)
@@ -1395,6 +1406,10 @@ int hisi_sec_digest_recv(handle_t ctx, struct wd_digest_msg *recv_msg)
 	if (ret < 0)
 		return ret;
 
+	ret = hisi_check_bd_id(h_qp, (__u16)recv_msg->tag, sqe.type2.tag);
+	if (ret)
+		return ret;
+
 	parse_digest_bd2(&sqe, recv_msg);
 
 	if (recv_msg->data_fmt == WD_SGL_BUF)
@@ -1515,6 +1530,7 @@ int hisi_sec_digest_send_v3(handle_t ctx, struct wd_digest_msg *msg)
 
 	qm_fill_digest_long_bd3(msg, &sqe);
 
+	hisi_set_msg_id(h_qp, &msg->tag);
 	sqe.tag = (__u64)(uintptr_t)msg->tag;
 
 	ret = hisi_qm_send(h_qp, &sqe, 1, &count);
@@ -1566,6 +1582,10 @@ int hisi_sec_digest_recv_v3(handle_t ctx, struct wd_digest_msg *recv_msg)
 	if (ret < 0)
 		return ret;
 
+	ret = hisi_check_bd_id(h_qp, recv_msg->tag, sqe.tag);
+	if (ret)
+		return ret;
+
 	parse_digest_bd3(&sqe, recv_msg);
 
 	if (recv_msg->data_fmt == WD_SGL_BUF)
@@ -1851,7 +1871,7 @@ int hisi_sec_aead_send(handle_t ctx, struct wd_aead_msg *msg)
 	}
 
 	fill_aead_bd2_addr(msg, &sqe);
-
+	hisi_set_msg_id(h_qp, &msg->tag);
 	sqe.type2.tag = (__u16)msg->tag;
 
 	ret = hisi_qm_send(h_qp, &sqe, 1, &count);
@@ -1912,6 +1932,10 @@ int hisi_sec_aead_recv(handle_t ctx, struct wd_aead_msg *recv_msg)
 	if (ret < 0)
 		return ret;
 
+	ret = hisi_check_bd_id(h_qp, (__u16)recv_msg->tag, sqe.type2.tag);
+	if (ret)
+		return ret;
+
 	parse_aead_bd2(&sqe, recv_msg);
 
 	if (recv_msg->data_fmt == WD_SGL_BUF)
@@ -2078,7 +2102,6 @@ static int fill_aead_bd3(struct wd_aead_msg *msg, struct hisi_sec_sqe3 *sqe)
 	return 0;
 }
 
-
 int hisi_sec_aead_send_v3(handle_t ctx, struct wd_aead_msg *msg)
 {
 	handle_t h_qp = (handle_t)wd_ctx_get_priv(ctx);
@@ -2108,7 +2131,7 @@ int hisi_sec_aead_send_v3(handle_t ctx, struct wd_aead_msg *msg)
 	}
 
 	fill_aead_bd3_addr(msg, &sqe);
-
+	hisi_set_msg_id(h_qp, &msg->tag);
 	sqe.tag = msg->tag;
 	ret = hisi_qm_send(h_qp, &sqe, 1, &count);
 	if (ret < 0) {
@@ -2168,6 +2191,10 @@ int hisi_sec_aead_recv_v3(handle_t ctx, struct wd_aead_msg *recv_msg)
 	if (ret < 0)
 		return ret;
 
+	ret = hisi_check_bd_id(h_qp, recv_msg->tag, sqe.tag);
+	if (ret)
+		return ret;
+
 	parse_aead_bd3(&sqe, recv_msg);
 
 	if (recv_msg->data_fmt == WD_SGL_BUF)
diff --git a/include/drv/wd_dh_drv.h b/include/drv/wd_dh_drv.h
index 5d436d1..0d3fb2b 100644
--- a/include/drv/wd_dh_drv.h
+++ b/include/drv/wd_dh_drv.h
@@ -13,7 +13,7 @@ extern "C" {
 /* DH message format */
 struct wd_dh_msg {
 	struct wd_dh_req req;
-	__u64 tag; /* User-defined request identifier */
+	__u32 tag; /* User-defined request identifier */
 	void *g;
 	__u16 gbytes;
 	__u16 key_bytes; /* Input key bytes */
diff --git a/include/drv/wd_ecc_drv.h b/include/drv/wd_ecc_drv.h
index 7e0d27e..66ed641 100644
--- a/include/drv/wd_ecc_drv.h
+++ b/include/drv/wd_ecc_drv.h
@@ -48,7 +48,7 @@ extern "C" {
 struct wd_ecc_msg {
 	struct wd_ecc_req req;
 	struct wd_hash_mt hash;
-	__u64 tag; /* User-defined request identifier */
+	__u32 tag; /* User-defined request identifier */
 	__u8 *key; /* Input key VA, should be DMA buffer */
 	__u16 key_bytes; /* key bytes */
 	__u8 curve_id; /* Ec curve denoted by enum wd_ecc_curve_type */
diff --git a/include/drv/wd_rsa_drv.h b/include/drv/wd_rsa_drv.h
index 948625f..837420e 100644
--- a/include/drv/wd_rsa_drv.h
+++ b/include/drv/wd_rsa_drv.h
@@ -39,7 +39,7 @@ struct wd_rsa_kg_out {
 /* RSA message format */
 struct wd_rsa_msg {
 	struct wd_rsa_req req;
-	__u64 tag; /* User-defined request identifier */
+	__u32 tag; /* User-defined request identifier */
 	__u16 key_bytes; /* Input key bytes */
 	__u8 key_type; /* Denoted by enum wd_rsa_key_type */
 	__u8 result; /* Data format, denoted by WD error code */
diff --git a/include/hisi_qm_udrv.h b/include/hisi_qm_udrv.h
index 68de837..773f57b 100644
--- a/include/hisi_qm_udrv.h
+++ b/include/hisi_qm_udrv.h
@@ -116,6 +116,21 @@ int hisi_qm_recv(handle_t h_qp, void *resp, __u16 expect, __u16 *count);
 handle_t hisi_qm_alloc_qp(struct hisi_qm_priv *config, handle_t ctx);
 void hisi_qm_free_qp(handle_t h_qp);
 
+/**
+ * hisi_check_bd_id - Check the SQE BD's id and send msg id.
+ * @h_qp: Handle of the qp.
+ * @mid: send message id.
+ * @bid: recv BD id.
+ */
+int hisi_check_bd_id(handle_t h_qp, __u32 mid, __u32 bid);
+
+/**
+ * hisi_set_msg_id - set the message tag id.
+ * @h_qp: Handle of the qp.
+ * @tag: the message tag id.
+ */
+void hisi_set_msg_id(handle_t h_qp, __u32 *tag);
+
 /**
  * hisi_qm_create_sglpool - Create sgl pool in qm.
  * @sgl_num: the sgl number.
-- 
2.27.0

