216 lines
6.2 KiB
Diff
216 lines
6.2 KiB
Diff
From 62f8f743652212ed6e56c9d81b6cb9ae23b2be92 Mon Sep 17 00:00:00 2001
|
|
From: Weili Qian <qianweili@huawei.com>
|
|
Date: Sat, 12 Oct 2024 11:12:43 +0800
|
|
Subject: [PATCH 35/39] uadk/v1: check queue status before sending doorbells
|
|
|
|
When the device needs to be reset, the queue status is
|
|
set to disable before resetting. The user process checks
|
|
the queue status before sending the doorbell. If the queue
|
|
is disable, the user process returns failure.
|
|
|
|
Currently, the task execution order in user mode is as follows:
|
|
1. check the queue status.
|
|
2. fill in or parse the BD.
|
|
3. send the doorbell to the hardware.
|
|
|
|
To reduce the possibility of sending doorbells during reset,
|
|
the task execution order is modified as follows:
|
|
1. fill in or parse the BD.
|
|
2. check the queue status.
|
|
3. send the doorbell to the hardware.
|
|
|
|
In addition, a rmb() is added before the doorbell is
|
|
sent to ensure that the queue status check is complete.
|
|
|
|
rmb() and wmb() can be replaced by mb() in hisi_qm_send().
|
|
Therefore, the barrier on the wd_reg_read() and wd_reg_write()
|
|
can be deleted.
|
|
|
|
Signed-off-by: Weili Qian <qianweili@huawei.com>
|
|
Signed-off-by: Qi Tao <taoqi10@huawei.com>
|
|
---
|
|
v1/drv/hisi_hpre_udrv.c | 10 ++++---
|
|
v1/drv/hisi_qm_udrv.c | 60 ++++++++++++++++++++++++-----------------
|
|
v1/drv/hisi_qm_udrv.h | 4 +--
|
|
v1/wd_util.h | 8 +-----
|
|
4 files changed, 44 insertions(+), 38 deletions(-)
|
|
|
|
diff --git a/v1/drv/hisi_hpre_udrv.c b/v1/drv/hisi_hpre_udrv.c
|
|
index 5832e9a..05518ab 100644
|
|
--- a/v1/drv/hisi_hpre_udrv.c
|
|
+++ b/v1/drv/hisi_hpre_udrv.c
|
|
@@ -1930,10 +1930,10 @@ static int fill_sm2_enc_sqe(void *msg, struct qm_queue_info *info, __u16 idx)
|
|
goto fail_fill_sqe;
|
|
}
|
|
|
|
- /* make sure the request is all in memory before doorbell */
|
|
- mb();
|
|
info->sq_tail_index = i;
|
|
- qm_tx_update(info, 1);
|
|
+ ret = qm_tx_update(info, 1);
|
|
+ if (unlikely(ret))
|
|
+ goto fail_fill_sqe;
|
|
|
|
return ret;
|
|
|
|
@@ -2083,7 +2083,9 @@ static int parse_first_sqe(void *hw_msg, struct qm_queue_info *info, __u16 idx,
|
|
WD_ERR("first BD error = %u\n", msg->result);
|
|
|
|
info->cq_head_index = i;
|
|
- qm_rx_update(info, 1);
|
|
+ ret = qm_rx_update(info, 1);
|
|
+ if (unlikely(ret))
|
|
+ return ret;
|
|
|
|
return 1;
|
|
}
|
|
diff --git a/v1/drv/hisi_qm_udrv.c b/v1/drv/hisi_qm_udrv.c
|
|
index 731492b..175a5c4 100644
|
|
--- a/v1/drv/hisi_qm_udrv.c
|
|
+++ b/v1/drv/hisi_qm_udrv.c
|
|
@@ -582,10 +582,20 @@ void qm_uninit_queue(struct wd_queue *q)
|
|
qinfo->priv = NULL;
|
|
}
|
|
|
|
-void qm_tx_update(struct qm_queue_info *info, __u32 num)
|
|
+int qm_tx_update(struct qm_queue_info *info, __u32 num)
|
|
{
|
|
+ if (unlikely(wd_reg_read(info->ds_tx_base) == 1)) {
|
|
+ WD_ERR("wd queue hw error happened before qm send!\n");
|
|
+ return -WD_HW_EACCESS;
|
|
+ }
|
|
+
|
|
+ /* make sure the request is all in memory before doorbell */
|
|
+ mb();
|
|
+
|
|
info->db(info, DOORBELL_CMD_SQ, info->sq_tail_index, 0);
|
|
__atomic_add_fetch(&info->used, num, __ATOMIC_RELAXED);
|
|
+
|
|
+ return WD_SUCCESS;
|
|
}
|
|
|
|
int qm_send(struct wd_queue *q, void **req, __u32 num)
|
|
@@ -595,11 +605,6 @@ int qm_send(struct wd_queue *q, void **req, __u32 num)
|
|
int ret;
|
|
__u32 i;
|
|
|
|
- if (unlikely(wd_reg_read(info->ds_tx_base) == 1)) {
|
|
- WD_ERR("wd queue hw error happened before qm send!\n");
|
|
- return -WD_HW_EACCESS;
|
|
- }
|
|
-
|
|
wd_spinlock(&info->sd_lock);
|
|
if (unlikely((__u32)__atomic_load_n(&info->used, __ATOMIC_RELAXED) >
|
|
info->sq_depth - num - 1)) {
|
|
@@ -623,19 +628,10 @@ int qm_send(struct wd_queue *q, void **req, __u32 num)
|
|
info->sq_tail_index++;
|
|
}
|
|
|
|
- /* make sure the request is all in memory before doorbell */
|
|
- mb();
|
|
- qm_tx_update(info, num);
|
|
+ ret = qm_tx_update(info, num);
|
|
wd_unspinlock(&info->sd_lock);
|
|
|
|
- return WD_SUCCESS;
|
|
-}
|
|
-
|
|
-void qm_rx_update(struct qm_queue_info *info, __u32 num)
|
|
-{
|
|
- /* set c_flag to enable interrupt when use poll */
|
|
- info->db(info, DOORBELL_CMD_CQ, info->cq_head_index, info->is_poll);
|
|
- __atomic_sub_fetch(&info->used, num, __ATOMIC_RELAXED);
|
|
+ return ret;
|
|
}
|
|
|
|
void qm_rx_from_cache(struct qm_queue_info *info, void **resp, __u32 num)
|
|
@@ -677,6 +673,24 @@ static int check_ds_rx_base(struct qm_queue_info *info,
|
|
return -WD_HW_EACCESS;
|
|
}
|
|
|
|
+int qm_rx_update(struct qm_queue_info *info, __u32 num)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = check_ds_rx_base(info, NULL, 0, 0);
|
|
+ if (unlikely(ret))
|
|
+ return ret;
|
|
+
|
|
+ /* make sure queue status check is complete. */
|
|
+ rmb();
|
|
+
|
|
+ /* set c_flag to enable interrupt when use poll */
|
|
+ info->db(info, DOORBELL_CMD_CQ, info->cq_head_index, info->is_poll);
|
|
+ __atomic_sub_fetch(&info->used, num, __ATOMIC_RELAXED);
|
|
+
|
|
+ return WD_SUCCESS;
|
|
+}
|
|
+
|
|
int qm_recv(struct wd_queue *q, void **resp, __u32 num)
|
|
{
|
|
struct q_info *qinfo = q->qinfo;
|
|
@@ -728,18 +742,14 @@ int qm_recv(struct wd_queue *q, void **resp, __u32 num)
|
|
}
|
|
|
|
if (i) {
|
|
- qm_rx_update(info, i);
|
|
- } else {
|
|
- wd_unspinlock(&info->rc_lock);
|
|
- return 0;
|
|
+ ret = qm_rx_update(info, i);
|
|
+ if (!ret)
|
|
+ ret = i;
|
|
}
|
|
|
|
wd_unspinlock(&info->rc_lock);
|
|
- ret = check_ds_rx_base(info, resp, num, 0);
|
|
- if (unlikely(ret))
|
|
- return ret;
|
|
|
|
- return i;
|
|
+ return ret;
|
|
}
|
|
|
|
static int hw_type_check(struct wd_queue *q, const char *hw_type)
|
|
diff --git a/v1/drv/hisi_qm_udrv.h b/v1/drv/hisi_qm_udrv.h
|
|
index 542d20d..4d54cf6 100644
|
|
--- a/v1/drv/hisi_qm_udrv.h
|
|
+++ b/v1/drv/hisi_qm_udrv.h
|
|
@@ -191,8 +191,8 @@ int qm_init_hwsgl_mem(struct wd_queue *q, void *pool, struct wd_sgl *sgl);
|
|
int qm_uninit_hwsgl_mem(struct wd_queue *q, void *pool, struct wd_sgl *sgl);
|
|
int qm_merge_hwsgl(struct wd_queue *q, void *pool,
|
|
struct wd_sgl *dst_sgl, struct wd_sgl *src_sgl);
|
|
-void qm_tx_update(struct qm_queue_info *info, __u32 num);
|
|
-void qm_rx_update(struct qm_queue_info *info, __u32 num);
|
|
+int qm_tx_update(struct qm_queue_info *info, __u32 num);
|
|
+int qm_rx_update(struct qm_queue_info *info, __u32 num);
|
|
void qm_rx_from_cache(struct qm_queue_info *info, void **resp, __u32 num);
|
|
|
|
#define HISI_QM_API_VER_BASE "hisi_qm_v1"
|
|
diff --git a/v1/wd_util.h b/v1/wd_util.h
|
|
index 9180fc1..21137d2 100644
|
|
--- a/v1/wd_util.h
|
|
+++ b/v1/wd_util.h
|
|
@@ -383,17 +383,11 @@ struct wcrypto_ecc_out {
|
|
static inline void wd_reg_write(void *reg_addr, uint32_t value)
|
|
{
|
|
*((uint32_t *)reg_addr) = value;
|
|
- wmb(); /* load fence */
|
|
}
|
|
|
|
static inline uint32_t wd_reg_read(void *reg_addr)
|
|
{
|
|
- uint32_t temp;
|
|
-
|
|
- temp = *((uint32_t *)reg_addr);
|
|
- rmb(); /* load fence */
|
|
-
|
|
- return temp;
|
|
+ return *((uint32_t *)reg_addr);
|
|
}
|
|
|
|
void wd_spinlock(struct wd_lock *lock);
|
|
--
|
|
2.25.1
|
|
|