From nobody Tue Dec 16 20:02:08 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 37043C41513 for ; Fri, 13 Oct 2023 03:52:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229556AbjJMDwz (ORCPT ); Thu, 12 Oct 2023 23:52:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55072 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229437AbjJMDwx (ORCPT ); Thu, 12 Oct 2023 23:52:53 -0400 Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4E825B7; Thu, 12 Oct 2023 20:52:50 -0700 (PDT) Received: from kwepemm000005.china.huawei.com (unknown [172.30.72.57]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4S6CCF1dmTzvPxs; Fri, 13 Oct 2023 11:48:09 +0800 (CST) Received: from huawei.com (10.50.163.32) by kwepemm000005.china.huawei.com (7.193.23.27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.31; Fri, 13 Oct 2023 11:52:47 +0800 From: Longfang Liu To: , CC: , , Subject: [PATCH] crypto: hisilicon/qm - fix EQ/AEQ interrupt issue Date: Fri, 13 Oct 2023 11:49:57 +0800 Message-ID: <20231013034957.28311-1-liulongfang@huawei.com> X-Mailer: git-send-email 2.24.0 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.50.163.32] X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) To kwepemm000005.china.huawei.com (7.193.23.27) X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" During hisilicon accelerator live migration operation. In order to prevent the problem of EQ/AEQ interrupt loss. Migration driver will trigger an EQ/AEQ doorbell at the end of the migration. This operation may cause double interruption of EQ/AEQ events. To ensure that the EQ/AEQ interrupt processing function is normal. The interrupt handling functionality of EQ/AEQ needs to be updated. Used to handle repeated interrupts event. Fixes: b0eed085903e ("hisi_acc_vfio_pci: Add support for VFIO live migratio= n") Signed-off-by: Longfang Liu --- drivers/crypto/hisilicon/qm.c | 105 +++++++++++++--------------------- include/linux/hisi_acc_qm.h | 1 + 2 files changed, 41 insertions(+), 65 deletions(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index f3b55c044dd3..c12dedcd6bba 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -854,47 +854,15 @@ static void qm_poll_req_cb(struct hisi_qp *qp) qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_CQ, qp->qp_status.cq_head, 1); } =20 -static int qm_get_complete_eqe_num(struct hisi_qm_poll_data *poll_data) -{ - struct hisi_qm *qm =3D poll_data->qm; - struct qm_eqe *eqe =3D qm->eqe + qm->status.eq_head; - u16 eq_depth =3D qm->eq_depth; - int eqe_num =3D 0; - u16 cqn; - - while (QM_EQE_PHASE(eqe) =3D=3D qm->status.eqc_phase) { - cqn =3D le32_to_cpu(eqe->dw0) & QM_EQE_CQN_MASK; - poll_data->qp_finish_id[eqe_num] =3D cqn; - eqe_num++; - - if (qm->status.eq_head =3D=3D eq_depth - 1) { - qm->status.eqc_phase =3D !qm->status.eqc_phase; - eqe =3D qm->eqe; - qm->status.eq_head =3D 0; - } else { - eqe++; - qm->status.eq_head++; - } - - if (eqe_num =3D=3D (eq_depth >> 1) - 1) - break; - } - - qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0); - - return eqe_num; -} - static void qm_work_process(struct work_struct *work) { struct hisi_qm_poll_data *poll_data =3D container_of(work, struct hisi_qm_poll_data, work); struct hisi_qm *qm =3D poll_data->qm; + u16 eqe_num =3D poll_data->eqe_num; struct hisi_qp *qp; - int eqe_num, i; + int i; =20 - /* Get qp id of completed tasks and re-enable the interrupt. */ - eqe_num =3D qm_get_complete_eqe_num(poll_data); for (i =3D eqe_num - 1; i >=3D 0; i--) { qp =3D &qm->qp_array[poll_data->qp_finish_id[i]]; if (unlikely(atomic_read(&qp->qp_status.flags) =3D=3D QP_STOP)) @@ -910,39 +878,55 @@ static void qm_work_process(struct work_struct *work) } } =20 -static bool do_qm_eq_irq(struct hisi_qm *qm) +static void qm_get_complete_eqe_num(struct hisi_qm *qm) { struct qm_eqe *eqe =3D qm->eqe + qm->status.eq_head; - struct hisi_qm_poll_data *poll_data; - u16 cqn; + struct hisi_qm_poll_data *poll_data =3D NULL; + u16 eq_depth =3D qm->eq_depth; + u16 cqn, eqe_num =3D 0; =20 - if (!readl(qm->io_base + QM_VF_EQ_INT_SOURCE)) - return false; + if (QM_EQE_PHASE(eqe) !=3D qm->status.eqc_phase) { + atomic64_inc(&qm->debug.dfx.err_irq_cnt); + qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0); + return; + } =20 - if (QM_EQE_PHASE(eqe) =3D=3D qm->status.eqc_phase) { + cqn =3D le32_to_cpu(eqe->dw0) & QM_EQE_CQN_MASK; + if (unlikely(cqn >=3D qm->qp_num)) + return; + poll_data =3D &qm->poll_data[cqn]; + + while (QM_EQE_PHASE(eqe) =3D=3D qm->status.eqc_phase) { cqn =3D le32_to_cpu(eqe->dw0) & QM_EQE_CQN_MASK; - poll_data =3D &qm->poll_data[cqn]; - queue_work(qm->wq, &poll_data->work); + poll_data->qp_finish_id[eqe_num] =3D cqn; + eqe_num++; + + if (qm->status.eq_head =3D=3D eq_depth - 1) { + qm->status.eqc_phase =3D !qm->status.eqc_phase; + eqe =3D qm->eqe; + qm->status.eq_head =3D 0; + } else { + eqe++; + qm->status.eq_head++; + } =20 - return true; + if (eqe_num =3D=3D (eq_depth >> 1) - 1) + break; } =20 - return false; + poll_data->eqe_num =3D eqe_num; + queue_work(qm->wq, &poll_data->work); + qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0); } =20 static irqreturn_t qm_eq_irq(int irq, void *data) { struct hisi_qm *qm =3D data; - bool ret; - - ret =3D do_qm_eq_irq(qm); - if (ret) - return IRQ_HANDLED; =20 - atomic64_inc(&qm->debug.dfx.err_irq_cnt); - qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0); + /* Get qp id of completed tasks and re-enable the interrupt */ + qm_get_complete_eqe_num(qm); =20 - return IRQ_NONE; + return IRQ_HANDLED; } =20 static irqreturn_t qm_mb_cmd_irq(int irq, void *data) @@ -1024,6 +1008,8 @@ static irqreturn_t qm_aeq_thread(int irq, void *data) u16 aeq_depth =3D qm->aeq_depth; u32 type, qp_id; =20 + atomic64_inc(&qm->debug.dfx.aeq_irq_cnt); + while (QM_AEQE_PHASE(aeqe) =3D=3D qm->status.aeqc_phase) { type =3D (le32_to_cpu(aeqe->dw0) >> QM_AEQE_TYPE_SHIFT) & QM_AEQE_TYPE_MASK; @@ -1062,17 +1048,6 @@ static irqreturn_t qm_aeq_thread(int irq, void *data) return IRQ_HANDLED; } =20 -static irqreturn_t qm_aeq_irq(int irq, void *data) -{ - struct hisi_qm *qm =3D data; - - atomic64_inc(&qm->debug.dfx.aeq_irq_cnt); - if (!readl(qm->io_base + QM_VF_AEQ_INT_SOURCE)) - return IRQ_NONE; - - return IRQ_WAKE_THREAD; -} - static void qm_init_qp_status(struct hisi_qp *qp) { struct hisi_qp_status *qp_status =3D &qp->qp_status; @@ -4997,8 +4972,8 @@ static int qm_register_aeq_irq(struct hisi_qm *qm) return 0; =20 irq_vector =3D val & QM_IRQ_VECTOR_MASK; - ret =3D request_threaded_irq(pci_irq_vector(pdev, irq_vector), qm_aeq_irq, - qm_aeq_thread, 0, qm->dev_name, qm); + ret =3D request_threaded_irq(pci_irq_vector(pdev, irq_vector), NULL, + qm_aeq_thread, IRQF_ONESHOT, qm->dev_name, qm); if (ret) dev_err(&pdev->dev, "failed to request eq irq, ret =3D %d", ret); =20 diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index 34c64a02712c..369206363569 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -276,6 +276,7 @@ struct hisi_qm_poll_data { struct hisi_qm *qm; struct work_struct work; u16 *qp_finish_id; + u16 eqe_num; }; =20 /** --=20 2.24.0