driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8LFYK CVE: NA
----------------------------------------------------------------------
Interrupt resources like wokrqueue are applied for in function hisi_qm_memory_init(). During resource application, whether the device supports this type of interrupt is not checked. As a result, the applied resources may not be used. Therefore, the interrupt resource application is moved to function qm_irqs_register(). When the interrupt type is not supported, the interrupt resource is not applied, avoiding resource waste.
Signed-off-by: Weili Qian qianweili@huawei.com Signed-off-by: JiangShui Yang yangjiangshui@h-partners.com --- drivers/crypto/hisilicon/hpre/hpre_main.c | 9 +- drivers/crypto/hisilicon/qm.c | 181 ++++++++++++---------- drivers/crypto/hisilicon/sec2/sec_main.c | 13 +- drivers/crypto/hisilicon/zip/zip_main.c | 6 +- include/linux/hisi_acc_qm.h | 2 - 5 files changed, 108 insertions(+), 103 deletions(-)
diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c index 44d3eedfb755..7f6689482e33 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_main.c +++ b/drivers/crypto/hisilicon/hpre/hpre_main.c @@ -358,6 +358,8 @@ static struct dfx_diff_registers hpre_diff_regs[] = { }, };
+static const struct hisi_qm_err_ini hpre_err_ini; + bool hpre_check_alg_support(struct hisi_qm *qm, u32 alg) { u32 cap_val; @@ -1162,6 +1164,7 @@ static int hpre_qm_init(struct hisi_qm *qm, struct pci_dev *pdev) qm->qp_num = pf_q_num; qm->debug.curr_qm_qp_num = pf_q_num; qm->qm_list = &hpre_devices; + qm->err_ini = &hpre_err_ini; if (pf_q_num_flag) set_bit(QM_MODULE_PARAM, &qm->misc_ctl); } @@ -1367,10 +1370,6 @@ static int hpre_pf_probe_init(struct hpre *hpre) return ret;
hpre_open_sva_prefetch(qm); - - qm->err_ini = &hpre_err_ini; - qm->err_ini->err_info_init(qm); - hisi_qm_dev_err_init(qm); ret = hpre_show_last_regs_init(qm); if (ret) pci_err(qm->pdev, "Failed to init last word regs!\n"); @@ -1462,7 +1461,6 @@ static int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id)
err_with_err_init: hpre_show_last_regs_uninit(qm); - hisi_qm_dev_err_uninit(qm);
err_with_qm_init: hisi_qm_uninit(qm); @@ -1488,7 +1486,6 @@ static void hpre_remove(struct pci_dev *pdev) hpre_cnt_regs_clear(qm); qm->debug.curr_qm_qp_num = 0; hpre_show_last_regs_uninit(qm); - hisi_qm_dev_err_uninit(qm); }
hisi_qm_uninit(qm); diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 470675093ad1..81cc0fd3944b 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -2838,10 +2838,8 @@ static void hisi_qp_memory_uninit(struct hisi_qm *qm, int num) for (i = num - 1; i >= 0; i--) { qdma = &qm->qp_array[i].qdma; dma_free_coherent(dev, qdma->size, qdma->va, qdma->dma); - kfree(qm->poll_data[i].qp_finish_id); }
- kfree(qm->poll_data); kfree(qm->qp_array); }
@@ -2851,18 +2849,12 @@ static int hisi_qp_memory_init(struct hisi_qm *qm, size_t dma_size, int id, struct device *dev = &qm->pdev->dev; size_t off = qm->sqe_size * sq_depth; struct hisi_qp *qp; - int ret = -ENOMEM; - - qm->poll_data[id].qp_finish_id = kcalloc(qm->qp_num, sizeof(u16), - GFP_KERNEL); - if (!qm->poll_data[id].qp_finish_id) - return -ENOMEM;
qp = &qm->qp_array[id]; qp->qdma.va = dma_alloc_coherent(dev, dma_size, &qp->qdma.dma, GFP_KERNEL); if (!qp->qdma.va) - goto err_free_qp_finish_id; + return -ENOMEM;
qp->sqe = qp->qdma.va; qp->sqe_dma = qp->qdma.dma; @@ -2875,10 +2867,6 @@ static int hisi_qp_memory_init(struct hisi_qm *qm, size_t dma_size, int id, qp->qp_id = id;
return 0; - -err_free_qp_finish_id: - kfree(qm->poll_data[id].qp_finish_id); - return ret; }
static inline bool is_iommu_used(struct device *dev) @@ -2984,11 +2972,6 @@ static void hisi_qm_set_state(struct hisi_qm *qm, u8 state) writel(state, qm->io_base + QM_VF_STATE); }
-static void hisi_qm_unint_work(struct hisi_qm *qm) -{ - destroy_workqueue(qm->wq); -} - static void hisi_qm_free_rsv_buf(struct hisi_qm *qm) { struct qm_dma *xqc_dma = &qm->xqc_buf.qcdma; @@ -3023,9 +3006,6 @@ static void hisi_qm_memory_uninit(struct hisi_qm *qm) */ void hisi_qm_uninit(struct hisi_qm *qm) { - qm_cmd_uninit(qm); - hisi_qm_unint_work(qm); - down_write(&qm->qps_lock); hisi_qm_memory_uninit(qm); hisi_qm_set_state(qm, QM_NOT_READY); @@ -3374,12 +3354,12 @@ static enum acc_err_result qm_hw_error_handle(struct hisi_qm *qm, bool need_rese }
/** - * hisi_qm_dev_err_init() - Initialize device error configuration. + * qm_dev_err_init() - Initialize device error configuration. * @qm: The qm for which we want to do error initialization. * * Initialize QM and device error related configuration. */ -void hisi_qm_dev_err_init(struct hisi_qm *qm) +static void qm_dev_err_init(struct hisi_qm *qm) { if (qm->fun_type == QM_HW_VF) return; @@ -3392,15 +3372,14 @@ void hisi_qm_dev_err_init(struct hisi_qm *qm) } qm->err_ini->hw_err_enable(qm); } -EXPORT_SYMBOL_GPL(hisi_qm_dev_err_init);
/** - * hisi_qm_dev_err_uninit() - Uninitialize device error configuration. + * qm_dev_err_uninit() - Uninitialize device error configuration. * @qm: The qm for which we want to do error uninitialization. * * Uninitialize QM and device error related configuration. */ -void hisi_qm_dev_err_uninit(struct hisi_qm *qm) +static void qm_dev_err_uninit(struct hisi_qm *qm) { if (qm->fun_type == QM_HW_VF) return; @@ -3413,7 +3392,6 @@ void hisi_qm_dev_err_uninit(struct hisi_qm *qm) } qm->err_ini->hw_err_disable(qm); } -EXPORT_SYMBOL_GPL(hisi_qm_dev_err_uninit);
/** * hisi_qm_free_qps() - free multiple queue pairs. @@ -4507,7 +4485,7 @@ static int qm_controller_reset_done(struct hisi_qm *qm) }
qm_restart_prepare(qm); - hisi_qm_dev_err_init(qm); + qm_dev_err_init(qm); if (qm->err_ini->open_axi_master_ooo) qm->err_ini->open_axi_master_ooo(qm);
@@ -4621,7 +4599,7 @@ void hisi_qm_reset_prepare(struct pci_dev *pdev) return; }
- hisi_qm_dev_err_uninit(pf_qm); + qm_dev_err_uninit(pf_qm); /* * Check whether there is an ECC mbit error, * If it occurs, need to wait for soft reset @@ -4693,7 +4671,7 @@ void hisi_qm_reset_done(struct pci_dev *pdev) } }
- hisi_qm_dev_err_init(pf_qm); + qm_dev_err_init(pf_qm);
ret = qm_restart(qm); if (ret) { @@ -5018,10 +4996,15 @@ static void qm_unregister_abnormal_irq(struct hisi_qm *qm) if (qm->fun_type == QM_HW_VF) return;
+ if (!qm->err_ini->err_info_init) + return; + val = qm->cap_tables.qm_cap_table[QM_ABN_IRQ_TYPE_CAP_IDX].cap_val; if (!((val >> QM_IRQ_TYPE_SHIFT) & QM_ABN_IRQ_TYPE_MASK)) return;
+ qm_dev_err_uninit(qm); + irq_vector = val & QM_IRQ_VECTOR_MASK; free_irq(pci_irq_vector(pdev, irq_vector), qm); } @@ -5035,16 +5018,27 @@ static int qm_register_abnormal_irq(struct hisi_qm *qm) if (qm->fun_type == QM_HW_VF) return 0;
+ if (!qm->err_ini->err_info_init) { + dev_info(&qm->pdev->dev, "Device doesnot support error init!\n"); + return 0; + } + val = qm->cap_tables.qm_cap_table[QM_ABN_IRQ_TYPE_CAP_IDX].cap_val; if (!((val >> QM_IRQ_TYPE_SHIFT) & QM_ABN_IRQ_TYPE_MASK)) return 0;
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) + if (ret) { dev_err(&qm->pdev->dev, "failed to request abnormal irq, ret = %d", ret); + return ret; + }
- return ret; + INIT_WORK(&qm->rst_work, hisi_qm_controller_reset); + qm->err_ini->err_info_init(qm); + qm_dev_err_init(qm); + + return 0; }
static void qm_unregister_mb_cmd_irq(struct hisi_qm *qm) @@ -5056,6 +5050,8 @@ static void qm_unregister_mb_cmd_irq(struct hisi_qm *qm) if (!((val >> QM_IRQ_TYPE_SHIFT) & QM_IRQ_TYPE_MASK)) return;
+ qm_cmd_uninit(qm); + irq_vector = val & QM_IRQ_VECTOR_MASK; free_irq(pci_irq_vector(pdev, irq_vector), qm); } @@ -5072,12 +5068,18 @@ static int qm_register_mb_cmd_irq(struct hisi_qm *qm)
irq_vector = val & QM_IRQ_VECTOR_MASK; ret = request_irq(pci_irq_vector(pdev, irq_vector), qm_mb_cmd_irq, 0, qm->dev_name, qm); - if (ret) + if (ret) { dev_err(&pdev->dev, "failed to request function communication irq, ret = %d", ret); + return ret; + }
- return ret; + INIT_WORK(&qm->cmd_process, qm_cmd_process); + qm_cmd_init(qm); + + return 0; }
+/* Disable aeq interrupt by hisi_qm_stop(). */ static void qm_unregister_aeq_irq(struct hisi_qm *qm) { struct pci_dev *pdev = qm->pdev; @@ -5091,6 +5093,7 @@ static void qm_unregister_aeq_irq(struct hisi_qm *qm) free_irq(pci_irq_vector(pdev, irq_vector), qm); }
+/* Enable aeq interrupt by hisi_qm_start(). */ static int qm_register_aeq_irq(struct hisi_qm *qm) { struct pci_dev *pdev = qm->pdev; @@ -5105,11 +5108,62 @@ static int qm_register_aeq_irq(struct hisi_qm *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); + dev_err(&pdev->dev, "failed to request aeq irq, ret = %d", ret); + + return ret; +} + +static void qm_uninit_eq_work(struct hisi_qm *qm) +{ + int i; + + for (i = qm->qp_num - 1; i >= 0; i--) + kfree(qm->poll_data[i].qp_finish_id); + + kfree(qm->poll_data); + destroy_workqueue(qm->wq); +} + +static int qm_init_eq_work(struct hisi_qm *qm) +{ + int ret = -ENOMEM; + u16 eq_depth; + int i; + + qm->poll_data = kcalloc(qm->qp_num, sizeof(struct hisi_qm_poll_data), GFP_KERNEL); + if (!qm->poll_data) + return ret; + + qm_get_xqc_depth(qm, &qm->eq_depth, &qm->aeq_depth, QM_XEQ_DEPTH_CAP); + eq_depth = qm->eq_depth >> 1; + for (i = 0; i < qm->qp_num; i++) { + qm->poll_data[i].qp_finish_id = kcalloc(eq_depth, sizeof(u16), GFP_KERNEL); + if (!qm->poll_data[i].qp_finish_id) + goto free_qp_finish_id; + + INIT_WORK(&qm->poll_data[i].work, qm_work_process); + qm->poll_data[i].qm = qm; + }
+ qm->wq = alloc_workqueue("%s", WQ_HIGHPRI | WQ_MEM_RECLAIM | + WQ_UNBOUND, num_online_cpus(), + pci_name(qm->pdev)); + if (!qm->wq) { + dev_err(&qm->pdev->dev, "failed to alloc workqueue!\n"); + goto free_qp_finish_id; + } + + return 0; + +free_qp_finish_id: + for (i = i - 1; i >= 0; i--) + kfree(qm->poll_data[i].qp_finish_id); + + kfree(qm->poll_data); return ret; }
+/* Disable eq interrupt by hisi_qm_stop(). */ static void qm_unregister_eq_irq(struct hisi_qm *qm) { struct pci_dev *pdev = qm->pdev; @@ -5119,10 +5173,13 @@ static void qm_unregister_eq_irq(struct hisi_qm *qm) if (!((val >> QM_IRQ_TYPE_SHIFT) & QM_IRQ_TYPE_MASK)) return;
+ qm_uninit_eq_work(qm); + irq_vector = val & QM_IRQ_VECTOR_MASK; free_irq(pci_irq_vector(pdev, irq_vector), qm); }
+/* Enable eq interrupt by hisi_qm_start(). */ static int qm_register_eq_irq(struct hisi_qm *qm) { struct pci_dev *pdev = qm->pdev; @@ -5135,10 +5192,18 @@ static int qm_register_eq_irq(struct hisi_qm *qm)
irq_vector = val & QM_IRQ_VECTOR_MASK; ret = request_irq(pci_irq_vector(pdev, irq_vector), qm_eq_irq, 0, qm->dev_name, qm); - if (ret) + if (ret) { dev_err(&pdev->dev, "failed to request eq irq, ret = %d", ret); + return ret; + }
- return ret; + ret = qm_init_eq_work(qm); + if (ret) { + free_irq(pci_irq_vector(pdev, irq_vector), qm); + return ret; + } + + return 0; }
static void qm_irqs_unregister(struct hisi_qm *qm) @@ -5366,30 +5431,6 @@ static int hisi_qm_pci_init(struct hisi_qm *qm) return ret; }
-static int hisi_qm_init_work(struct hisi_qm *qm) -{ - int i; - - for (i = 0; i < qm->qp_num; i++) - INIT_WORK(&qm->poll_data[i].work, qm_work_process); - - if (qm->fun_type == QM_HW_PF) - INIT_WORK(&qm->rst_work, hisi_qm_controller_reset); - - if (qm->ver > QM_HW_V2) - INIT_WORK(&qm->cmd_process, qm_cmd_process); - - qm->wq = alloc_workqueue("%s", WQ_HIGHPRI | WQ_MEM_RECLAIM | - WQ_UNBOUND, num_online_cpus(), - pci_name(qm->pdev)); - if (!qm->wq) { - pci_err(qm->pdev, "failed to alloc workqueue!\n"); - return -ENOMEM; - } - - return 0; -} - static int hisi_qp_alloc_memory(struct hisi_qm *qm) { struct device *dev = &qm->pdev->dev; @@ -5401,19 +5442,12 @@ static int hisi_qp_alloc_memory(struct hisi_qm *qm) if (!qm->qp_array) return -ENOMEM;
- qm->poll_data = kcalloc(qm->qp_num, sizeof(struct hisi_qm_poll_data), GFP_KERNEL); - if (!qm->poll_data) { - kfree(qm->qp_array); - return -ENOMEM; - } - qm_get_xqc_depth(qm, &sq_depth, &cq_depth, QM_QP_DEPTH_CAP);
/* one more page for device or qp statuses */ qp_dma_size = qm->sqe_size * sq_depth + sizeof(struct qm_cqe) * cq_depth; qp_dma_size = PAGE_ALIGN(qp_dma_size) + PAGE_SIZE; for (i = 0; i < qm->qp_num; i++) { - qm->poll_data[i].qm = qm; ret = hisi_qp_memory_init(qm, qp_dma_size, i, sq_depth, cq_depth); if (ret) goto err_init_qp_mem; @@ -5482,7 +5516,6 @@ static int hisi_qm_memory_init(struct hisi_qm *qm) } while (0)
idr_init(&qm->qp_idr); - qm_get_xqc_depth(qm, &qm->eq_depth, &qm->aeq_depth, QM_XEQ_DEPTH_CAP); qm->qdma.size = QMC_ALIGN(sizeof(struct qm_eqe) * qm->eq_depth) + QMC_ALIGN(sizeof(struct qm_aeqe) * qm->aeq_depth) + QMC_ALIGN(sizeof(struct qm_sqc) * qm->qp_num) + @@ -5567,16 +5600,8 @@ int hisi_qm_init(struct hisi_qm *qm) if (ret) goto err_alloc_uacce;
- ret = hisi_qm_init_work(qm); - if (ret) - goto err_free_qm_memory; - - qm_cmd_init(qm); - return 0;
-err_free_qm_memory: - hisi_qm_memory_uninit(qm); err_alloc_uacce: qm_remove_uacce(qm); err_irq_register: @@ -5714,7 +5739,7 @@ static int qm_rebuild_for_resume(struct hisi_qm *qm) }
qm_cmd_init(qm); - hisi_qm_dev_err_init(qm); + qm_dev_err_init(qm); /* Set the doorbell timeout to QM_DB_TIMEOUT_CFG ns. */ writel(QM_DB_TIMEOUT_SET, qm->io_base + QM_DB_TIMEOUT_CFG); qm_disable_clock_gate(qm); diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c index 6b5e6f6d42ed..f20e71dfbce4 100644 --- a/drivers/crypto/hisilicon/sec2/sec_main.c +++ b/drivers/crypto/hisilicon/sec2/sec_main.c @@ -1083,15 +1083,11 @@ static int sec_pf_probe_init(struct sec_dev *sec) struct hisi_qm *qm = &sec->qm; int ret;
- qm->err_ini = &sec_err_ini; - qm->err_ini->err_info_init(qm); - ret = sec_set_user_domain_and_cache(qm); if (ret) return ret;
sec_open_sva_prefetch(qm); - hisi_qm_dev_err_init(qm); sec_debug_regs_clear(qm); ret = sec_show_last_regs_init(qm); if (ret) @@ -1140,6 +1136,7 @@ static int sec_qm_init(struct hisi_qm *qm, struct pci_dev *pdev) qm->qp_num = pf_q_num; qm->debug.curr_qm_qp_num = pf_q_num; qm->qm_list = &sec_devices; + qm->err_ini = &sec_err_ini; if (pf_q_num_flag) set_bit(QM_MODULE_PARAM, &qm->misc_ctl); } else if (qm->fun_type == QM_HW_VF && qm->ver == QM_HW_V1) { @@ -1202,11 +1199,6 @@ static int sec_probe_init(struct sec_dev *sec) return 0; }
-static void sec_probe_uninit(struct hisi_qm *qm) -{ - hisi_qm_dev_err_uninit(qm); -} - static int sec_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct sec_dev *sec; @@ -1275,7 +1267,6 @@ static int sec_probe(struct pci_dev *pdev, const struct pci_device_id *id) hisi_qm_stop(qm, QM_NORMAL); err_probe_uninit: sec_show_last_regs_uninit(qm); - sec_probe_uninit(qm); err_qm_uninit: sec_qm_uninit(qm); return ret; @@ -1301,8 +1292,6 @@ static void sec_remove(struct pci_dev *pdev) sec_debug_regs_clear(qm); sec_show_last_regs_uninit(qm);
- sec_probe_uninit(qm); - sec_qm_uninit(qm); }
diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c index 6bf607668aa4..aeab08fbbb04 100644 --- a/drivers/crypto/hisilicon/zip/zip_main.c +++ b/drivers/crypto/hisilicon/zip/zip_main.c @@ -1168,8 +1168,6 @@ static int hisi_zip_pf_probe_init(struct hisi_zip *hisi_zip)
hisi_zip->ctrl = ctrl; ctrl->hisi_zip = hisi_zip; - qm->err_ini = &hisi_zip_err_ini; - qm->err_ini->err_info_init(qm);
ret = hisi_zip_set_user_domain_and_cache(qm); if (ret) @@ -1180,7 +1178,6 @@ static int hisi_zip_pf_probe_init(struct hisi_zip *hisi_zip) return ret;
hisi_zip_open_sva_prefetch(qm); - hisi_qm_dev_err_init(qm); hisi_zip_debug_regs_clear(qm);
ret = hisi_zip_show_last_regs_init(qm); @@ -1230,6 +1227,7 @@ static int hisi_zip_qm_init(struct hisi_qm *qm, struct pci_dev *pdev) qm->qp_num = pf_q_num; qm->debug.curr_qm_qp_num = pf_q_num; qm->qm_list = &zip_devices; + qm->err_ini = &hisi_zip_err_ini; if (pf_q_num_flag) set_bit(QM_MODULE_PARAM, &qm->misc_ctl); } else if (qm->fun_type == QM_HW_VF && qm->ver == QM_HW_V1) { @@ -1363,7 +1361,6 @@ static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id)
err_dev_err_uninit: hisi_zip_show_last_regs_uninit(qm); - hisi_qm_dev_err_uninit(qm);
err_qm_uninit: hisi_zip_qm_uninit(qm); @@ -1386,7 +1383,6 @@ static void hisi_zip_remove(struct pci_dev *pdev) hisi_zip_debugfs_exit(qm); hisi_qm_stop(qm, QM_NORMAL); hisi_zip_show_last_regs_uninit(qm); - hisi_qm_dev_err_uninit(qm); hisi_zip_qm_uninit(qm); }
diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index 113e0720441f..4b1aa012cc82 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -553,8 +553,6 @@ void hisi_qm_debug_regs_clear(struct hisi_qm *qm); int hisi_qm_sriov_enable(struct pci_dev *pdev, int max_vfs); int hisi_qm_sriov_disable(struct pci_dev *pdev, bool is_frozen); int hisi_qm_sriov_configure(struct pci_dev *pdev, int num_vfs); -void hisi_qm_dev_err_init(struct hisi_qm *qm); -void hisi_qm_dev_err_uninit(struct hisi_qm *qm); int hisi_qm_regs_debugfs_init(struct hisi_qm *qm, struct dfx_diff_registers *dregs, u32 reg_len); void hisi_qm_regs_debugfs_uninit(struct hisi_qm *qm, u32 reg_len);