Skip to content

Commit 85acd1b

Browse files
Weili Qianherbertx
authored andcommitted
crypto: hisilicon/qm - invalidate queues in use
Before the device reset, although the driver has set the queue status to intercept doorbells sent by the task process, the reset thread is isolated from the user-mode task process, so the task process may still send doorbells. Therefore, before the reset, the queue is directly invalidated, and the device directly discards the doorbells sent by the process. Signed-off-by: Weili Qian <qianweili@huawei.com> Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent 5ce9891 commit 85acd1b

1 file changed

Lines changed: 40 additions & 13 deletions

File tree

  • drivers/crypto/hisilicon

drivers/crypto/hisilicon/qm.c

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545

4646
#define QM_SQ_TYPE_MASK GENMASK(3, 0)
4747
#define QM_SQ_TAIL_IDX(sqc) ((le16_to_cpu((sqc).w11) >> 6) & 0x1)
48+
#define QM_SQC_DISABLE_QP (1U << 6)
49+
#define QM_XQC_RANDOM_DATA 0xaaaa
4850

4951
/* cqc shift */
5052
#define QM_CQ_HOP_NUM_SHIFT 0
@@ -3194,6 +3196,9 @@ static int qm_eq_aeq_ctx_cfg(struct hisi_qm *qm)
31943196

31953197
qm_init_eq_aeq_status(qm);
31963198

3199+
/* Before starting the dev, clear the memory and then configure to device using. */
3200+
memset(qm->qdma.va, 0, qm->qdma.size);
3201+
31973202
ret = qm_eq_ctx_cfg(qm);
31983203
if (ret) {
31993204
dev_err(dev, "Set eqc failed!\n");
@@ -3205,9 +3210,13 @@ static int qm_eq_aeq_ctx_cfg(struct hisi_qm *qm)
32053210

32063211
static int __hisi_qm_start(struct hisi_qm *qm)
32073212
{
3213+
struct device *dev = &qm->pdev->dev;
32083214
int ret;
32093215

3210-
WARN_ON(!qm->qdma.va);
3216+
if (!qm->qdma.va) {
3217+
dev_err(dev, "qm qdma is NULL!\n");
3218+
return -EINVAL;
3219+
}
32113220

32123221
if (qm->fun_type == QM_HW_PF) {
32133222
ret = hisi_qm_set_vft(qm, 0, qm->qp_base, qm->qp_num);
@@ -3281,7 +3290,7 @@ static int qm_restart(struct hisi_qm *qm)
32813290
for (i = 0; i < qm->qp_num; i++) {
32823291
qp = &qm->qp_array[i];
32833292
if (atomic_read(&qp->qp_status.flags) == QP_STOP &&
3284-
qp->is_resetting == true) {
3293+
qp->is_resetting == true && qp->is_in_kernel == true) {
32853294
ret = qm_start_qp_nolock(qp, 0);
32863295
if (ret < 0) {
32873296
dev_err(dev, "Failed to start qp%d!\n", i);
@@ -3313,24 +3322,44 @@ static void qm_stop_started_qp(struct hisi_qm *qm)
33133322
}
33143323

33153324
/**
3316-
* qm_clear_queues() - Clear all queues memory in a qm.
3317-
* @qm: The qm in which the queues will be cleared.
3325+
* qm_invalid_queues() - invalid all queues in use.
3326+
* @qm: The qm in which the queues will be invalidated.
33183327
*
3319-
* This function clears all queues memory in a qm. Reset of accelerator can
3320-
* use this to clear queues.
3328+
* This function invalid all queues in use. If the doorbell command is sent
3329+
* to device in user space after the device is reset, the device discards
3330+
* the doorbell command.
33213331
*/
3322-
static void qm_clear_queues(struct hisi_qm *qm)
3332+
static void qm_invalid_queues(struct hisi_qm *qm)
33233333
{
33243334
struct hisi_qp *qp;
3335+
struct qm_sqc *sqc;
3336+
struct qm_cqc *cqc;
33253337
int i;
33263338

3339+
/*
3340+
* Normal stop queues is no longer used and does not need to be
3341+
* invalid queues.
3342+
*/
3343+
if (qm->status.stop_reason == QM_NORMAL)
3344+
return;
3345+
3346+
if (qm->status.stop_reason == QM_DOWN)
3347+
hisi_qm_cache_wb(qm);
3348+
33273349
for (i = 0; i < qm->qp_num; i++) {
33283350
qp = &qm->qp_array[i];
3329-
if (qp->is_in_kernel && qp->is_resetting)
3351+
if (!qp->is_resetting)
3352+
continue;
3353+
3354+
/* Modify random data and set sqc close bit to invalid queue. */
3355+
sqc = qm->sqc + i;
3356+
cqc = qm->cqc + i;
3357+
sqc->w8 = cpu_to_le16(QM_XQC_RANDOM_DATA);
3358+
sqc->w13 = cpu_to_le16(QM_SQC_DISABLE_QP);
3359+
cqc->w8 = cpu_to_le16(QM_XQC_RANDOM_DATA);
3360+
if (qp->is_in_kernel)
33303361
memset(qp->qdma.va, 0, qp->qdma.size);
33313362
}
3332-
3333-
memset(qm->qdma.va, 0, qm->qdma.size);
33343363
}
33353364

33363365
/**
@@ -3387,7 +3416,7 @@ int hisi_qm_stop(struct hisi_qm *qm, enum qm_stop_reason r)
33873416
}
33883417
}
33893418

3390-
qm_clear_queues(qm);
3419+
qm_invalid_queues(qm);
33913420
qm->status.stop_reason = QM_NORMAL;
33923421

33933422
err_unlock:
@@ -4785,8 +4814,6 @@ void hisi_qm_dev_shutdown(struct pci_dev *pdev)
47854814
ret = hisi_qm_stop(qm, QM_DOWN);
47864815
if (ret)
47874816
dev_err(&pdev->dev, "Fail to stop qm in shutdown!\n");
4788-
4789-
hisi_qm_cache_wb(qm);
47904817
}
47914818
EXPORT_SYMBOL_GPL(hisi_qm_dev_shutdown);
47924819

0 commit comments

Comments
 (0)