From b8e8ddd4a20005c98b22a89bcdcb38ac15e547ea Mon Sep 17 00:00:00 2001
From: Yu'an Wang <wangyuan46@huawei.com>
Date: Tue, 8 Jun 2021 21:22:47 +0800
Subject: [PATCH] crypto: hisilicon- count send_ref when sending bd

hulk inclusion
category: Bugfix
bugzilla: NA
CVE: NA

When a BD is delivered, the RAS resets occasionally clear the BD that is
being delivered. The count send_ref ensures that the RAS process does
not perform operations on this QP when the BD is delivered.

Signed-off-by: Yu'an Wang <wangyuan46@huawei.com>
Signed-off-by: Weili Qian <qianweili@huawei.com>
Reviewed-by: Zibo Xu <xuzaibo@huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
---
 drivers/crypto/hisilicon/qm.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c
index 91cd64e09c74..a6bf95cb7baf 100644
--- a/drivers/crypto/hisilicon/qm.c
+++ b/drivers/crypto/hisilicon/qm.c
@@ -2049,7 +2049,9 @@ static int hisi_qm_stop_qp_nolock(struct hisi_qp *qp)
 		flush_work(&qp->qm->work);
 
 	/* waiting for increase used count in qp send and last poll qp finish */
-	udelay(WAIT_PERIOD);
+	while (atomic_read(&qp->qp_status.send_ref))
+		udelay(WAIT_PERIOD);
+
 	if (unlikely(qp->is_resetting && atomic_read(&qp->qp_status.used)))
 		qp_stop_fail_cb(qp);
 
@@ -2094,25 +2096,27 @@ EXPORT_SYMBOL_GPL(hisi_qm_stop_qp);
 int hisi_qp_send(struct hisi_qp *qp, const void *msg)
 {
 	struct hisi_qp_status *qp_status = &qp->qp_status;
-	u16 sq_tail = qp_status->sq_tail;
-	u16 sq_tail_next = (sq_tail + 1) % QM_Q_DEPTH;
-	void *sqe = qm_get_avail_sqe(qp);
+	void *sqe;
 
 	if (unlikely(atomic_read(&qp->qp_status.flags) == QP_STOP ||
 		     atomic_read(&qp->qm->status.flags) == QM_STOP) ||
 		     qp->is_resetting) {
-		dev_info_ratelimited(&qp->qm->pdev->dev, "QM resetting...\n");
+		dev_info_ratelimited(&qp->qm->pdev->dev, "QP is stopped or resetting\n");
 		return -EAGAIN;
 	}
 
-	if (!sqe)
+	atomic_inc(&qp->qp_status.send_ref);
+	sqe = qm_get_avail_sqe(qp);
+	if (!sqe) {
+		atomic_dec(&qp->qp_status.send_ref);
 		return -EBUSY;
+	}
 
 	memcpy(sqe, msg, qp->qm->sqe_size);
-
-	qm_db(qp->qm, qp->qp_id, QM_DOORBELL_CMD_SQ, sq_tail_next, 0);
+	qp_status->sq_tail = (qp_status->sq_tail + 1) % QM_Q_DEPTH;
+	qm_db(qp->qm, qp->qp_id, QM_DOORBELL_CMD_SQ, qp_status->sq_tail, 0);
 	atomic_inc(&qp->qp_status.used);
-	qp_status->sq_tail = sq_tail_next;
+	atomic_dec(&qp->qp_status.send_ref);
 
 	return 0;
 }
-- 
GitLab