From: Weili Qian qianweili@huawei.com
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 --- 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, 46 insertions(+), 36 deletions(-)
diff --git a/v1/drv/hisi_hpre_udrv.c b/v1/drv/hisi_hpre_udrv.c index 0b2bdd5..84ec710 100644 --- a/v1/drv/hisi_hpre_udrv.c +++ b/v1/drv/hisi_hpre_udrv.c @@ -1938,10 +1938,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;
@@ -2091,7 +2091,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 ea4b199..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; @@ -727,15 +741,15 @@ int qm_recv(struct wd_queue *q, void **resp, __u32 num) } }
- if (i) - qm_rx_update(info, i); + if (i) { + 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);