driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8WNSG CVE: NA
--------------------------------------------------------
1.qm_hw_error parse in qm_abnormal_irq and qm_log_hw_error is different, ARRAY_SIZE(qm_hw_error) exceeds actual treatment area. 2.add method judgement in qm_clear_device.
Signed-off-by: wangyuan wangyuan46@huawei.com --- drivers/crypto/hisilicon/qm.c | 37 +++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 13 deletions(-)
diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 25bb24b4c131..7ca30b7d0446 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -277,8 +277,7 @@ static const struct hisi_qm_hw_error qm_hw_error[] = { { .int_msk = BIT(9), .msg = "qm_sq_vf_invalid" }, { .int_msk = BIT(10), .msg = "qm_db_timeout" }, { .int_msk = BIT(11), .msg = "qm_of_fifo_of" }, - { .int_msk = BIT(12), .msg = "qm_db_random_invalid" }, - { /* sentinel */ } + { .int_msk = BIT(12), .msg = "qm_db_random_invalid" } };
static const char * const qm_db_timeout[] = { @@ -774,10 +773,11 @@ static irqreturn_t qm_aeq_irq(int irq, void *data)
static irqreturn_t qm_abnormal_irq(int irq, void *data) { - const struct hisi_qm_hw_error *err = qm_hw_error; + const struct hisi_qm_hw_error *err; struct hisi_qm *qm = data; struct device *dev = &qm->pdev->dev; u32 error_status, tmp; + int i;
atomic64_inc(&qm->debug.dfx.abnormal_irq_cnt); if (qm->abnormal_fix) { @@ -789,12 +789,12 @@ static irqreturn_t qm_abnormal_irq(int irq, void *data) tmp = readl(qm->io_base + QM_ABNORMAL_INT_STATUS); error_status = qm->msi_mask & tmp;
- while (err->msg) { - if (err->int_msk & error_status) - dev_err(dev, "%s [error status=0x%x] found\n", - err->msg, err->int_msk); + for (i = 0; i < ARRAY_SIZE(qm_hw_error); i++) { + err = &qm_hw_error[i]; + if (!(err->int_msk & error_status)) + continue;
- err++; + dev_err(dev, "%s [error status=0x%x] found\n", err->msg, err->int_msk); }
/* clear err sts */ @@ -1218,8 +1218,10 @@ static int dump_show(struct hisi_qm *qm, void *info, #define BYTE_PER_DW 4
info_buf = kzalloc(info_size, GFP_KERNEL); - if (!info_buf) + if (!info_buf) { + dev_err(dev, "Fail to alloc dump info buf\n"); return -ENOMEM; + }
for (i = 0; i < info_size; i++, info_curr++) { if (i % BYTE_PER_DW == 0) @@ -2639,12 +2641,23 @@ static int hisi_qm_memory_init(struct hisi_qm *qm)
static int qm_clear_device(struct hisi_qm *qm) { + acpi_handle handle = ACPI_HANDLE(&qm->pdev->dev); u32 val; int ret;
if (qm->fun_type == QM_HW_VF) return 0;
+ if (!handle) { + pci_warn(qm->pdev, "Device does not support reset, return.\n"); + return 0; + } + + if (!acpi_has_method(handle, qm->err_ini.err_info.acpi_rst)) { + pci_warn(qm->pdev, "BIOS has no reset method, return.\n"); + return 0; + } + /* OOO register set and check */ writel(MASTER_GLOBAL_CTRL_SHUTDOWN, qm->io_base + MASTER_GLOBAL_CTRL);
@@ -3771,10 +3784,8 @@ static int qm_vf_reset_prepare(struct pci_dev *pdev,
ret = hisi_qm_stop(qm, stop_reason); if (ret) { - hisi_qm_set_hw_reset(qm, - QM_RESET_STOP_TX_OFFSET); - hisi_qm_set_hw_reset(qm, - QM_RESET_STOP_RX_OFFSET); + hisi_qm_set_hw_reset(qm, QM_RESET_STOP_TX_OFFSET); + hisi_qm_set_hw_reset(qm, QM_RESET_STOP_RX_OFFSET); atomic_set(&qm->status.flags, QM_STOP); } }