From 12eec1ba0070d641eb9d506add9bc79f66211289 Mon Sep 17 00:00:00 2001 From: JiangShui Yang Date: Thu, 9 Nov 2023 20:16:47 +0800 Subject: [PATCH 01/12] Revert "crypto: hisilicon/qm - remove redundant cache writeback" driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I773SD CVE: NA ---------------------------------------------------------------------- replace it with the mainline solusion. This reverts commit ed3b55dab298bb1261cc155a386a17760105cdd9. Signed-off-by: JiangShui Yang --- drivers/crypto/hisilicon/qm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 58df0aff80ba..d36182e27f8d 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -2428,6 +2428,7 @@ static void hisi_qm_uacce_put_queue(struct uacce_queue *q) { struct hisi_qp *qp = q->priv; + hisi_qm_cache_wb(qp->qm); hisi_qm_release_qp(qp); } -- Gitee From 93a5a99e4f689517176ea0077484d29c88f79fb9 Mon Sep 17 00:00:00 2001 From: Weili Qian Date: Sat, 13 Aug 2022 18:35:45 +0800 Subject: [PATCH 02/12] crypto: hisilicon/qm - remove unneeded hardware cache write back mainline inclusion from mainline-v6.1-rc1 commit 6a088a2cbcaf40747cf2881df47f4f5d65acd7ab category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8FI6W CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6a088a2cbcaf40747cf2881df47f4f5d65acd7ab ---------------------------------------------------------------------- Data in the hardware cache needs to be written back to the memory before the queue memory is released. Currently, the queue memory is applied for when the driver is loaded and released when the driver is removed. Therefore, the hardware cache does not need to be written back when process puts queue. Signed-off-by: Weili Qian Signed-off-by: Yang Shen Signed-off-by: Herbert Xu Signed-off-by: JiangShui Yang --- drivers/crypto/hisilicon/qm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index d36182e27f8d..58df0aff80ba 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -2428,7 +2428,6 @@ static void hisi_qm_uacce_put_queue(struct uacce_queue *q) { struct hisi_qp *qp = q->priv; - hisi_qm_cache_wb(qp->qm); hisi_qm_release_qp(qp); } -- Gitee From a9ab22e0e5789b3dc5a72a6b632ef71dbb54d100 Mon Sep 17 00:00:00 2001 From: JiangShui Yang Date: Fri, 10 Nov 2023 09:02:24 +0800 Subject: [PATCH 03/12] Revert "crypto: hisilicon/qm: Set the VF QM state register" driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8FI6W CVE: NA ---------------------------------------------------------------------- replace it with the mainline solusion. This reverts commit b5592e08022f801ee8ff6db035a69924d7a21d1a. Signed-off-by: JiangShui Yang --- drivers/crypto/hisilicon/qm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 58df0aff80ba..8b90fc393965 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -3107,10 +3107,10 @@ void hisi_qm_uninit(struct hisi_qm *qm) up_write(&qm->qps_lock); return; } + up_write(&qm->qps_lock); hisi_qm_memory_uninit(qm); hisi_qm_set_state(qm, VF_NOT_READY); - up_write(&qm->qps_lock); qm_remove_uacce(qm); qm_irqs_unregister(qm); @@ -3125,6 +3125,7 @@ EXPORT_SYMBOL_GPL(hisi_qm_uninit); * @number: The number of queues in vft. * * We can allocate multiple queues to a qm by configuring virtual function + * table. We get related configures by this function. Normally, we call this * function in VF driver to get the queue information. * * qm hw v1 does not support this interface. -- Gitee From 2ca2eccbb995def4247a92b796e8cbf933ae692d Mon Sep 17 00:00:00 2001 From: JiangShui Yang Date: Fri, 10 Nov 2023 09:24:45 +0800 Subject: [PATCH 04/12] Revert "vfio/hisilicon: modify QM for live migration driver" driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8FI6W CVE: NA ---------------------------------------------------------------------- replace it with the mainline solusion. This reverts commit cf8167eca399a31f5304ddaf32d15a0d967732c2. Signed-off-by: JiangShui Yang --- drivers/crypto/hisilicon/qm.c | 14 -------------- include/linux/hisi_acc_qm.h | 7 ------- 2 files changed, 21 deletions(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 8b90fc393965..8d6210218073 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -3053,13 +3053,6 @@ static void hisi_qm_pci_uninit(struct hisi_qm *qm) pci_disable_device(pdev); } -static void hisi_qm_set_state(struct hisi_qm *qm, enum vf_state state) -{ - /* set vf driver state */ - if (qm->ver > QM_HW_V2) - writel(state, qm->io_base + QM_VF_STATE); -} - static void hisi_qm_unint_work(struct hisi_qm *qm) { destroy_workqueue(qm->wq); @@ -3110,7 +3103,6 @@ void hisi_qm_uninit(struct hisi_qm *qm) up_write(&qm->qps_lock); hisi_qm_memory_uninit(qm); - hisi_qm_set_state(qm, VF_NOT_READY); qm_remove_uacce(qm); qm_irqs_unregister(qm); @@ -3295,8 +3287,6 @@ int hisi_qm_start(struct hisi_qm *qm) if (!ret) atomic_set(&qm->status.flags, QM_START); - hisi_qm_set_state(qm, VF_READY); - err_unlock: up_write(&qm->qps_lock); return ret; @@ -3390,8 +3380,6 @@ int hisi_qm_stop(struct hisi_qm *qm, enum qm_stop_reason r) struct device *dev = &qm->pdev->dev; int ret = 0; - hisi_qm_set_state(qm, VF_PREPARE); - down_write(&qm->qps_lock); qm->status.stop_reason = r; @@ -5432,8 +5420,6 @@ static int hisi_qm_pci_init(struct hisi_qm *qm) goto err_get_pci_res; pci_set_master(pdev); - hisi_qm_set_state(qm, VF_PREPARE); - num_vec = qm_get_irq_num(qm); ret = pci_alloc_irq_vectors(pdev, num_vec, num_vec, PCI_IRQ_MSI); if (ret < 0) { diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index 83d013f1bf39..7f594b2aa9e9 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -91,7 +91,6 @@ #define QM_SHAPER_CFG 0x100164 #define QM_SHAPER_ENABLE BIT(30) #define QM_SHAPER_TYPE1_OFFSET 10 -#define QM_VF_STATE 0x0060 /* page number for queue file region */ #define QM_DOORBELL_PAGE_NR 1 @@ -139,12 +138,6 @@ enum qm_debug_file { DEBUG_FILE_NUM, }; -enum vf_state { - VF_READY = 0x0, - VF_NOT_READY, - VF_PREPARE, -}; - enum qm_mist_ctl_bits { QM_DRIVER_DOWN = 0x0, QM_RST_SCHED, -- Gitee From 8cc5491a1ab11416920ffa1d05c9ae8018023d44 Mon Sep 17 00:00:00 2001 From: Longfang Liu Date: Tue, 8 Mar 2022 18:49:00 +0000 Subject: [PATCH 05/12] crypto: hisilicon/qm: Set the VF QM state register mainline inclusion from mainline-v5.18-rc1 commit 1e459b25081d4f939b8a1fb4c71dab0cec8f974a category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8FI6W CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1e459b25081d4f939b8a1fb4c71dab0cec8f974a ---------------------------------------------------------------------- We use VF QM state register to record the status of the QM configuration state. This will be used in the ACC migration driver to determine whether we can safely save and restore the QM data. Signed-off-by: Longfang Liu Acked-by: Zhou Wang Signed-off-by: Shameer Kolothum Link: https://lore.kernel.org/r/20220308184902.2242-8-shameerali.kolothum.thodi@huawei.com Signed-off-by: Alex Williamson Signed-off-by: JiangShui <1175135535@qq.com> --- drivers/crypto/hisilicon/qm.c | 10 +++++++++- include/linux/hisi_acc_qm.h | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 8d6210218073..b9e04c2d30cf 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -3053,6 +3053,12 @@ static void hisi_qm_pci_uninit(struct hisi_qm *qm) pci_disable_device(pdev); } +static void hisi_qm_set_state(struct hisi_qm *qm, u8 state) +{ + if (qm->ver > QM_HW_V2 && qm->fun_type == QM_HW_VF) + writel(state, qm->io_base + QM_VF_STATE); +} + static void hisi_qm_unint_work(struct hisi_qm *qm) { destroy_workqueue(qm->wq); @@ -3100,9 +3106,10 @@ void hisi_qm_uninit(struct hisi_qm *qm) up_write(&qm->qps_lock); return; } - up_write(&qm->qps_lock); hisi_qm_memory_uninit(qm); + hisi_qm_set_state(qm, QM_NOT_READY); + up_write(&qm->qps_lock); qm_remove_uacce(qm); qm_irqs_unregister(qm); @@ -3287,6 +3294,7 @@ int hisi_qm_start(struct hisi_qm *qm) if (!ret) atomic_set(&qm->status.flags, QM_START); + hisi_qm_set_state(qm, QM_READY); err_unlock: up_write(&qm->qps_lock); return ret; diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index 7f594b2aa9e9..9af4659490f5 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -67,6 +67,7 @@ #define QM_DB_RAND_SHIFT_V2 16 #define QM_DB_INDEX_SHIFT_V2 32 #define QM_DB_PRIORITY_SHIFT_V2 48 +#define QM_VF_STATE 0x60 /* qm cache */ #define QM_CACHE_CTL 0x100050 @@ -138,6 +139,11 @@ enum qm_debug_file { DEBUG_FILE_NUM, }; +enum qm_vf_state { + QM_READY = 0, + QM_NOT_READY, +}; + enum qm_mist_ctl_bits { QM_DRIVER_DOWN = 0x0, QM_RST_SCHED, -- Gitee From 25bd1403267692edb57536222a97c0af824ac9d7 Mon Sep 17 00:00:00 2001 From: JiangShui Yang Date: Fri, 10 Nov 2023 15:36:59 +0800 Subject: [PATCH 06/12] vfio/migration: adapts to element naming changes in the vf_state structure driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I773SD CVE: NA ---------------------------------------------------------------------- the definition of the vf_state structure is changed in the header file. Signed-off-by: JiangShui Yang --- drivers/crypto/hisilicon/migration/acc_vf_migration.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/hisilicon/migration/acc_vf_migration.c b/drivers/crypto/hisilicon/migration/acc_vf_migration.c index cdaa55aa8716..c486dab90dd4 100644 --- a/drivers/crypto/hisilicon/migration/acc_vf_migration.c +++ b/drivers/crypto/hisilicon/migration/acc_vf_migration.c @@ -543,7 +543,7 @@ static void vf_qm_fun_restart(struct hisi_qm *qm, * normally at this time. so if Guest acc driver have removed, * don't need to restart QP. */ - if (vf_data->vf_state != VF_READY) { + if (vf_data->vf_state != QM_READY) { dev_err(dev, "failed to restart VF!\n"); return; } @@ -1251,7 +1251,7 @@ static void acc_vf_reset(void *device_data) vfio_pci_vendor_data(device_data); struct hisi_qm *qm = acc_vf_dev->vf_qm; struct device *dev = &qm->pdev->dev; - u32 vf_state = VF_NOT_READY; + u32 vf_state = QM_NOT_READY; int ret; dev_info(dev, "QEMU prepare to Reset Guest!\n"); -- Gitee From ff2d125e0f5f9ee42e9d416808680dacd6a72cfc Mon Sep 17 00:00:00 2001 From: JiangShui Yang Date: Fri, 10 Nov 2023 15:42:48 +0800 Subject: [PATCH 07/12] Revert "crypto: hisilicon/sec - fix for resource leak" driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8FI6W CVE: NA ---------------------------------------------------------------------- replace it with the mainline solusion. This reverts commit aac0f39e1d7e0daffa10c89b8587533d3766fd1f. Signed-off-by: JiangShui Yang --- drivers/crypto/hisilicon/sec2/sec_crypto.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c index 43a3c7245505..ff096ef504fd 100644 --- a/drivers/crypto/hisilicon/sec2/sec_crypto.c +++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c @@ -984,7 +984,6 @@ static int sec_cipher_map(struct sec_ctx *ctx, struct sec_req *req, ret = sec_aead_mac_init(a_req); if (unlikely(ret)) { dev_err(dev, "fail to init mac data for ICV!\n"); - hisi_acc_sg_buf_unmap(dev, src, req->in); return ret; } } -- Gitee From f6d09034a422476db153fb09c606d0d06b523ea5 Mon Sep 17 00:00:00 2001 From: Wenkai Lin Date: Fri, 15 Sep 2023 17:13:29 +0800 Subject: [PATCH 08/12] crypto: hisilicon/sec - fix for sgl unmmap problem mainline inclusion from mainline-v6.7-rc1 commit ce2cb2e1b8a27d929a0eaa042049912b0756efe0 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8FI6W CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ce2cb2e1b8a27d929a0eaa042049912b0756efe0 ---------------------------------------------------------------------- When sec_aead_mac_init returns an error code, sec_cipher_map will exit abnormally, the hardware sgl should be unmmaped. Signed-off-by: Wenkai Lin Signed-off-by: Herbert Xu Signed-off-by: JiangShui Yang --- drivers/crypto/hisilicon/sec2/sec_crypto.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c index ff096ef504fd..43a3c7245505 100644 --- a/drivers/crypto/hisilicon/sec2/sec_crypto.c +++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c @@ -984,6 +984,7 @@ static int sec_cipher_map(struct sec_ctx *ctx, struct sec_req *req, ret = sec_aead_mac_init(a_req); if (unlikely(ret)) { dev_err(dev, "fail to init mac data for ICV!\n"); + hisi_acc_sg_buf_unmap(dev, src, req->in); return ret; } } -- Gitee From 56d3645e79ba5c5a2e99d44b16ab94301fb75c85 Mon Sep 17 00:00:00 2001 From: JiangShui Yang Date: Fri, 10 Nov 2023 15:48:18 +0800 Subject: [PATCH 09/12] Revert "crypto: hisilicon/qm - fix EQ/AEQ interrupt issue" driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8FI6W CVE: NA ---------------------------------------------------------------------- replace it with the mainline solusion. This reverts commit 24a30ee769c7d2d793e75af94ea06ffa9d1e393e. Signed-off-by: JiangShui Yang --- drivers/crypto/hisilicon/qm.c | 107 +++++++++++++++++++++------------- include/linux/hisi_acc_qm.h | 1 - 2 files changed, 65 insertions(+), 43 deletions(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index b9e04c2d30cf..69fb18d8262f 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -1030,15 +1030,47 @@ 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); } +static int qm_get_complete_eqe_num(struct hisi_qm_poll_data *poll_data) +{ + struct hisi_qm *qm = poll_data->qm; + struct qm_eqe *eqe = qm->eqe + qm->status.eq_head; + u16 eq_depth = qm->eq_depth; + int eqe_num = 0; + u16 cqn; + + while (QM_EQE_PHASE(eqe) == qm->status.eqc_phase) { + cqn = le32_to_cpu(eqe->dw0) & QM_EQE_CQN_MASK; + poll_data->qp_finish_id[eqe_num] = cqn; + eqe_num++; + + if (qm->status.eq_head == eq_depth - 1) { + qm->status.eqc_phase = !qm->status.eqc_phase; + eqe = qm->eqe; + qm->status.eq_head = 0; + } else { + eqe++; + qm->status.eq_head++; + } + + if (eqe_num == (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 = container_of(work, struct hisi_qm_poll_data, work); struct hisi_qm *qm = poll_data->qm; - u16 eqe_num = poll_data->eqe_num; struct hisi_qp *qp; - int i; + int eqe_num, i; + /* Get qp id of completed tasks and re-enable the interrupt. */ + eqe_num = qm_get_complete_eqe_num(poll_data); for (i = eqe_num - 1; i >= 0; i--) { qp = &qm->qp_array[poll_data->qp_finish_id[i]]; if (unlikely(atomic_read(&qp->qp_status.flags) == QP_STOP)) @@ -1054,57 +1086,39 @@ static void qm_work_process(struct work_struct *work) } } -static void qm_get_complete_eqe_num(struct hisi_qm *qm) +static bool do_qm_eq_irq(struct hisi_qm *qm) { struct qm_eqe *eqe = qm->eqe + qm->status.eq_head; - struct hisi_qm_poll_data *poll_data = NULL; - u16 eq_depth = qm->eq_depth; - u16 cqn, eqe_num = 0; - - if (QM_EQE_PHASE(eqe) != qm->status.eqc_phase) { - qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0); - return; - } + struct hisi_qm_poll_data *poll_data; + u16 cqn; - cqn = le32_to_cpu(eqe->dw0) & QM_EQE_CQN_MASK; - if (cqn >= qm->qp_num) - return; - poll_data = &qm->poll_data[cqn]; + if (!readl(qm->io_base + QM_VF_EQ_INT_SOURCE)) + return false; - while (QM_EQE_PHASE(eqe) == qm->status.eqc_phase) { + if (QM_EQE_PHASE(eqe) == qm->status.eqc_phase) { cqn = le32_to_cpu(eqe->dw0) & QM_EQE_CQN_MASK; - poll_data->qp_finish_id[eqe_num] = cqn; - eqe_num++; - - if (qm->status.eq_head == eq_depth - 1) { - qm->status.eqc_phase = !qm->status.eqc_phase; - eqe = qm->eqe; - qm->status.eq_head = 0; - } else { - eqe++; - qm->status.eq_head++; - } + poll_data = &qm->poll_data[cqn]; + queue_work(qm->wq, &poll_data->work); - if (eqe_num == (eq_depth >> 1) - 1) - break; + return true; } - qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0); - - if (poll_data) { - poll_data->eqe_num = eqe_num; - queue_work(qm->wq, &poll_data->work); - } + return false; } static irqreturn_t qm_eq_irq(int irq, void *data) { struct hisi_qm *qm = data; + bool ret; - /* Get qp id of completed tasks and re-enable the interrupt */ - qm_get_complete_eqe_num(qm); + ret = do_qm_eq_irq(qm); + if (ret) + return IRQ_HANDLED; - return IRQ_HANDLED; + atomic64_inc(&qm->debug.dfx.err_irq_cnt); + qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0); + + return IRQ_NONE; } static irqreturn_t qm_mb_cmd_irq(int irq, void *data) @@ -1186,8 +1200,6 @@ static irqreturn_t qm_aeq_thread(int irq, void *data) u16 aeq_depth = qm->aeq_depth; u32 type, qp_id; - atomic64_inc(&qm->debug.dfx.aeq_irq_cnt); - while (QM_AEQE_PHASE(aeqe) == qm->status.aeqc_phase) { type = (le32_to_cpu(aeqe->dw0) >> QM_AEQE_TYPE_SHIFT) & QM_AEQE_TYPE_MASK; @@ -1226,6 +1238,17 @@ static irqreturn_t qm_aeq_thread(int irq, void *data) return IRQ_HANDLED; } +static irqreturn_t qm_aeq_irq(int irq, void *data) +{ + struct hisi_qm *qm = 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 = &qp->qp_status; @@ -5195,8 +5218,8 @@ static int qm_register_aeq_irq(struct hisi_qm *qm) return 0; irq_vector = val & QM_IRQ_VECTOR_MASK; - ret = request_threaded_irq(pci_irq_vector(pdev, irq_vector), NULL, - qm_aeq_thread, IRQF_ONESHOT, qm->dev_name, qm); + ret = request_threaded_irq(pci_irq_vector(pdev, irq_vector), qm_aeq_irq, + qm_aeq_thread, 0, qm->dev_name, qm); if (ret) dev_err(&pdev->dev, "failed to request eq irq, ret = %d", ret); diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index 9af4659490f5..3fb45fd25b61 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -305,7 +305,6 @@ struct hisi_qm_poll_data { struct hisi_qm *qm; struct work_struct work; u16 *qp_finish_id; - u16 eqe_num; }; /** -- Gitee From c103778333ec97fd6b3ba099d5ebc984a1b6fac3 Mon Sep 17 00:00:00 2001 From: Longfang Liu Date: Fri, 13 Oct 2023 11:49:57 +0800 Subject: [PATCH 10/12] crypto: hisilicon/qm - fix EQ/AEQ interrupt issue mainline inclusion from mainline-v6.7-rc1 commit 5acab6eb592387191c1bb745ba9b815e1e076db5 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8FI6W CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5acab6eb592387191c1bb745ba9b815e1e076db5 ---------------------------------------------------------------------- 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 migration") Signed-off-by: Longfang Liu Signed-off-by: Herbert Xu Signed-off-by: JiangShui Yang --- 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 69fb18d8262f..b8c878856eec 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -1030,47 +1030,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); } -static int qm_get_complete_eqe_num(struct hisi_qm_poll_data *poll_data) -{ - struct hisi_qm *qm = poll_data->qm; - struct qm_eqe *eqe = qm->eqe + qm->status.eq_head; - u16 eq_depth = qm->eq_depth; - int eqe_num = 0; - u16 cqn; - - while (QM_EQE_PHASE(eqe) == qm->status.eqc_phase) { - cqn = le32_to_cpu(eqe->dw0) & QM_EQE_CQN_MASK; - poll_data->qp_finish_id[eqe_num] = cqn; - eqe_num++; - - if (qm->status.eq_head == eq_depth - 1) { - qm->status.eqc_phase = !qm->status.eqc_phase; - eqe = qm->eqe; - qm->status.eq_head = 0; - } else { - eqe++; - qm->status.eq_head++; - } - - if (eqe_num == (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 = container_of(work, struct hisi_qm_poll_data, work); struct hisi_qm *qm = poll_data->qm; + u16 eqe_num = poll_data->eqe_num; struct hisi_qp *qp; - int eqe_num, i; + int i; - /* Get qp id of completed tasks and re-enable the interrupt. */ - eqe_num = qm_get_complete_eqe_num(poll_data); for (i = eqe_num - 1; i >= 0; i--) { qp = &qm->qp_array[poll_data->qp_finish_id[i]]; if (unlikely(atomic_read(&qp->qp_status.flags) == QP_STOP)) @@ -1086,39 +1054,55 @@ static void qm_work_process(struct work_struct *work) } } -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 = qm->eqe + qm->status.eq_head; - struct hisi_qm_poll_data *poll_data; - u16 cqn; + struct hisi_qm_poll_data *poll_data = NULL; + u16 eq_depth = qm->eq_depth; + u16 cqn, eqe_num = 0; - if (!readl(qm->io_base + QM_VF_EQ_INT_SOURCE)) - return false; + if (QM_EQE_PHASE(eqe) != 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; + } + + cqn = le32_to_cpu(eqe->dw0) & QM_EQE_CQN_MASK; + if (unlikely(cqn >= qm->qp_num)) + return; + poll_data = &qm->poll_data[cqn]; - if (QM_EQE_PHASE(eqe) == qm->status.eqc_phase) { + while (QM_EQE_PHASE(eqe) == qm->status.eqc_phase) { cqn = le32_to_cpu(eqe->dw0) & QM_EQE_CQN_MASK; - poll_data = &qm->poll_data[cqn]; - queue_work(qm->wq, &poll_data->work); + poll_data->qp_finish_id[eqe_num] = cqn; + eqe_num++; - return true; + if (qm->status.eq_head == eq_depth - 1) { + qm->status.eqc_phase = !qm->status.eqc_phase; + eqe = qm->eqe; + qm->status.eq_head = 0; + } else { + eqe++; + qm->status.eq_head++; + } + + if (eqe_num == (eq_depth >> 1) - 1) + break; } - return false; + poll_data->eqe_num = eqe_num; + queue_work(qm->wq, &poll_data->work); + qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0); } static irqreturn_t qm_eq_irq(int irq, void *data) { struct hisi_qm *qm = data; - bool ret; - - ret = do_qm_eq_irq(qm); - if (ret) - return IRQ_HANDLED; - 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); - return IRQ_NONE; + return IRQ_HANDLED; } static irqreturn_t qm_mb_cmd_irq(int irq, void *data) @@ -1200,6 +1184,8 @@ static irqreturn_t qm_aeq_thread(int irq, void *data) u16 aeq_depth = qm->aeq_depth; u32 type, qp_id; + atomic64_inc(&qm->debug.dfx.aeq_irq_cnt); + while (QM_AEQE_PHASE(aeqe) == qm->status.aeqc_phase) { type = (le32_to_cpu(aeqe->dw0) >> QM_AEQE_TYPE_SHIFT) & QM_AEQE_TYPE_MASK; @@ -1238,17 +1224,6 @@ static irqreturn_t qm_aeq_thread(int irq, void *data) return IRQ_HANDLED; } -static irqreturn_t qm_aeq_irq(int irq, void *data) -{ - struct hisi_qm *qm = 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 = &qp->qp_status; @@ -5218,8 +5193,8 @@ static int qm_register_aeq_irq(struct hisi_qm *qm) return 0; irq_vector = val & QM_IRQ_VECTOR_MASK; - ret = request_threaded_irq(pci_irq_vector(pdev, irq_vector), qm_aeq_irq, - qm_aeq_thread, 0, qm->dev_name, qm); + ret = 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 = %d", ret); diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index 3fb45fd25b61..9af4659490f5 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -305,6 +305,7 @@ struct hisi_qm_poll_data { struct hisi_qm *qm; struct work_struct work; u16 *qp_finish_id; + u16 eqe_num; }; /** -- Gitee From e8c97b6e4290b8d32f0d018b1f82c8a8f3ded151 Mon Sep 17 00:00:00 2001 From: JiangShui Yang Date: Fri, 10 Nov 2023 15:45:14 +0800 Subject: [PATCH 11/12] Revert "crypto: hisilicon/qm - prevent soft lockup in qm_poll_req_cb()'s loop" driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8FI6W CVE: NA ---------------------------------------------------------------------- replace it with the mainline solusion. This reverts commit d07dbb660520043737e001bf0b8e3fa7bddb2a93. Signed-off-by: JiangShui Yang --- drivers/crypto/hisilicon/qm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index b8c878856eec..a77250968cc8 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -1022,8 +1022,6 @@ 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, 0); atomic_dec(&qp->qp_status.used); - - cond_resched(); } /* set c_flag */ -- Gitee From 6395c097dfbd1a6aed81afaacdbae9c2c292961a Mon Sep 17 00:00:00 2001 From: Longfang Liu Date: Fri, 20 Oct 2023 17:35:58 +0800 Subject: [PATCH 12/12] crypto: hisilicon/qm - prevent soft lockup in receive loop mainline inclusion from mainline-v6.7-rc1 commit 33fc506d2ac514be1072499a263c3bff8c7c95a0 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8FI6W CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=33fc506d2ac514be107249a263c3bff8c7c95a0 ---------------------------------------------------------------------- In the scenario where the accelerator business is fully loaded. When the workqueue receiving messages and performing callback processing, there are a large number of messages that need to be received, and there are continuously messages that have been processed and need to be received. This will cause the receive loop here to be locked for a long time. This scenario will cause watchdog timeout problems on OS with kernel preemption turned off. The error logs: watchdog: BUG: soft lockup - CPU#23 stuck for 23s! [kworker/u262:1:1407] [ 1461.978428][ C23] Call trace: [ 1461.981890][ C23] complete+0x8c/0xf0 [ 1461.986031][ C23] kcryptd_async_done+0x154/0x1f4 [dm_crypt] [ 1461.992154][ C23] sec_skcipher_callback+0x7c/0xf4 [hisi_sec2] [ 1461.998446][ C23] sec_req_cb+0x104/0x1f4 [hisi_sec2] [ 1462.003950][ C23] qm_poll_req_cb+0xcc/0x150 [hisi_qm] [ 1462.009531][ C23] qm_work_process+0x60/0xc0 [hisi_qm] [ 1462.015101][ C23] process_one_work+0x1c4/0x470 [ 1462.020052][ C23] worker_thread+0x150/0x3c4 [ 1462.024735][ C23] kthread+0x108/0x13c [ 1462.028889][ C23] ret_from_fork+0x10/0x18 Therefore, it is necessary to add an actively scheduled operation in the while loop to prevent this problem. After adding it, no matter whether the OS turns on or off the kernel preemption function. Neither will cause watchdog timeout issues. Signed-off-by: Longfang Liu Signed-off-by: Herbert Xu Signed-off-by: JiangShui Yang --- drivers/crypto/hisilicon/qm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index a77250968cc8..b8c878856eec 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -1022,6 +1022,8 @@ 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, 0); atomic_dec(&qp->qp_status.used); + + cond_resched(); } /* set c_flag */ -- Gitee