
driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IC9UQB CVE: NA ---------------------------------------------------------------------- If the number of interrupts is not the power of 2, some interrupts cannot be unmapd when the interrupts are released. As a result, allocating interrupts again will fail. Therefore, when allocating interrupts, change the number of interrupts to the power of 2. For vf, irq vector 3 is reserved, request a reserved interrupt, for pf, request abnormal irq, the redundant check is deleted. Fixes: dbdc1ec31fc0 ("crypto: hisilicon - add device error report through abnormal irq") Signed-off-by: Weili Qian <qianweili@huawei.com> Signed-off-by: JiangShui Yang <yangjiangshui@h-partners.com> --- drivers/crypto/hisilicon/qm.c | 51 +++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 94b369dd6e3a..d7a7826cb016 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -4966,6 +4966,15 @@ void hisi_qm_reset_done(struct pci_dev *pdev) } EXPORT_SYMBOL_GPL(hisi_qm_reset_done); +static irqreturn_t qm_rsvd_irq(int irq, void *data) +{ + struct hisi_qm *qm = data; + + dev_info(&qm->pdev->dev, "Reserved interrupt, ignore!\n"); + + return IRQ_HANDLED; +} + static irqreturn_t qm_abnormal_irq(int irq, void *data) { struct hisi_qm *qm = data; @@ -5258,17 +5267,14 @@ static void qm_unregister_abnormal_irq(struct hisi_qm *qm) struct pci_dev *pdev = qm->pdev; u32 irq_vector, val; - if (qm->fun_type == QM_HW_VF) - return; - - if (!qm->err_ini->err_info_init) - return; - val = qm->cap_tables.qm_cap_table[QM_ABNORMAL_IRQ].cap_val; if (!((val >> QM_IRQ_TYPE_SHIFT) & QM_ABN_IRQ_TYPE_MASK)) return; - irq_vector = val & QM_IRQ_VECTOR_MASK; + + if (qm->fun_type == QM_HW_VF && qm->ver < QM_HW_V3) + return; + free_irq(pci_irq_vector(pdev, irq_vector), qm); } @@ -5278,24 +5284,29 @@ static int qm_register_abnormal_irq(struct hisi_qm *qm) u32 irq_vector, val; int ret; - if (qm->fun_type == QM_HW_VF) + val = qm->cap_tables.qm_cap_table[QM_ABNORMAL_IRQ].cap_val; + if (!((val >> QM_IRQ_TYPE_SHIFT) & QM_ABN_IRQ_TYPE_MASK)) return 0; + irq_vector = val & QM_IRQ_VECTOR_MASK; - if (!qm->err_ini->err_info_init) { - dev_info(&qm->pdev->dev, "device doesnot support error init!\n"); - return 0; - } + /* For VF, this is a reserved interrupt in V3 version. */ + if (qm->fun_type == QM_HW_VF) { + if (qm->ver < QM_HW_V3) + return 0; - val = qm->cap_tables.qm_cap_table[QM_ABNORMAL_IRQ].cap_val; - if (!((val >> QM_IRQ_TYPE_SHIFT) & QM_ABN_IRQ_TYPE_MASK)) + ret = request_irq(pci_irq_vector(pdev, irq_vector), qm_rsvd_irq, + IRQF_NO_AUTOEN, qm->dev_name, qm); + if (ret) { + dev_err(&pdev->dev, "failed to request reserved irq, ret = %d!\n", ret); + return ret; + } return 0; + } INIT_WORK(&qm->rst_work, hisi_qm_controller_reset); - - irq_vector = val & QM_IRQ_VECTOR_MASK; ret = request_irq(pci_irq_vector(pdev, irq_vector), qm_abnormal_irq, 0, qm->dev_name, qm); if (ret) { - dev_err(&qm->pdev->dev, "failed to request abnormal irq, ret = %d!\n", ret); + dev_err(&pdev->dev, "failed to request abnormal irq, ret = %d!\n", ret); return ret; } @@ -5738,6 +5749,12 @@ static int hisi_qm_pci_init(struct hisi_qm *qm) pci_set_master(pdev); num_vec = qm_get_irq_num(qm); + if (!num_vec) { + dev_err(dev, "Device irq num is zero!\n"); + ret = -EINVAL; + goto err_get_pci_res; + } + num_vec = roundup_pow_of_two(num_vec); ret = pci_alloc_irq_vectors(pdev, num_vec, num_vec, PCI_IRQ_MSI); if (ret < 0) { dev_err(dev, "Failed to enable MSI vectors!\n"); -- 2.33.0