diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c index 82627fe2488d37692f250e07d7eb45149f880fa5..a517d079351ca130b2b64588c4c82c764287324d 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_main.c +++ b/drivers/crypto/hisilicon/hpre/hpre_main.c @@ -1265,11 +1265,26 @@ static u32 hpre_get_hw_err_status(struct hisi_qm *qm) static void hpre_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts) { - u32 nfe; - writel(err_sts, qm->io_base + HPRE_HAC_SOURCE_INT); - nfe = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_NFE_MASK_CAP, qm->cap_ver); - writel(nfe, qm->io_base + HPRE_RAS_NFE_ENB); +} + +static void hpre_disable_error_report(struct hisi_qm *qm, u32 err_type) +{ + u32 nfe_mask; + + nfe_mask = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_NFE_MASK_CAP, qm->cap_ver); + writel(nfe_mask & (~err_type), qm->io_base + HPRE_RAS_NFE_ENB); +} + +static void hpre_enable_error_report(struct hisi_qm *qm) +{ + u32 nfe_mask, ce_mask; + + nfe_mask = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_NFE_MASK_CAP, qm->cap_ver); + ce_mask = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_CE_MASK_CAP, qm->cap_ver); + + writel(nfe_mask, qm->io_base + HPRE_RAS_NFE_ENB); + writel(ce_mask, qm->io_base + HPRE_RAS_CE_ENB); } static void hpre_open_axi_master_ooo(struct hisi_qm *qm) @@ -1309,6 +1324,8 @@ static const struct hisi_qm_err_ini hpre_err_ini = { .hw_err_disable = hpre_hw_error_disable, .get_dev_hw_err_status = hpre_get_hw_err_status, .clear_dev_hw_err_status = hpre_clear_hw_err_status, + .disable_error_report = hpre_disable_error_report, + .enable_error_report = hpre_enable_error_report, .log_dev_hw_err = hpre_log_hw_error, .open_axi_master_ooo = hpre_open_axi_master_ooo, .open_sva_prefetch = hpre_open_sva_prefetch, diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index a1e30adbe0096824c1dc44a983c79992e9080d71..cb43cff04d81ea2fb77f5d7bc2df78475d73ee28 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -375,7 +375,7 @@ struct hisi_qm_hw_ops { int (*debug_init)(struct hisi_qm *qm); void (*hw_error_init)(struct hisi_qm *qm); void (*hw_error_uninit)(struct hisi_qm *qm); - enum acc_err_result (*hw_error_handle)(struct hisi_qm *qm); + enum acc_err_result (*hw_error_handle)(struct hisi_qm *qm, bool need_reset); int (*set_msi)(struct hisi_qm *qm, bool set); }; @@ -1569,24 +1569,35 @@ static void qm_log_hw_error(struct hisi_qm *qm, u32 error_status) } } -static enum acc_err_result qm_hw_error_handle_v2(struct hisi_qm *qm) +static enum acc_err_result qm_hw_error_handle_v2(struct hisi_qm *qm, bool need_reset) { u32 error_status, tmp; /* read err sts */ tmp = readl(qm->io_base + QM_ABNORMAL_INT_STATUS); - error_status = qm->error_mask & tmp; - + error_status = tmp & (~qm->err_info.qm_err_type); + qm->err_info.qm_err_type |= tmp; if (error_status) { if (error_status & QM_ECC_MBIT) qm->err_status.is_qm_ecc_mbit = true; qm_log_hw_error(qm, error_status); - if (error_status & qm->err_info.qm_reset_mask) + /* If the device is ready to reset, only print new error type. */ + if (!need_reset) + return ACC_ERR_RECOVERED; + + if (error_status & qm->err_info.qm_reset_mask) { + /* Disable the same error reporting until the error is recovered. */ + writel(qm->err_info.nfe & (~qm->err_info.qm_err_type), + qm->io_base + QM_RAS_NFE_ENABLE); return ACC_ERR_NEED_RESET; + } - writel(error_status, qm->io_base + QM_ABNORMAL_INT_SOURCE); + /* Clear error source if not need reset. */ + writel(qm->err_info.qm_err_type, qm->io_base + QM_ABNORMAL_INT_SOURCE); + /* Avoid bios disable error type in v2 version, re-enable. */ writel(qm->err_info.nfe, qm->io_base + QM_RAS_NFE_ENABLE); + writel(qm->err_info.ce, qm->io_base + QM_RAS_CE_ENABLE); } return ACC_ERR_RECOVERED; @@ -3446,14 +3457,14 @@ static void qm_hw_error_uninit(struct hisi_qm *qm) qm->ops->hw_error_uninit(qm); } -static enum acc_err_result qm_hw_error_handle(struct hisi_qm *qm) +static enum acc_err_result qm_hw_error_handle(struct hisi_qm *qm, bool need_reset) { if (!qm->ops->hw_error_handle) { dev_err(&qm->pdev->dev, "QM doesn't support hw error report!\n"); return ACC_ERR_NONE; } - return qm->ops->hw_error_handle(qm); + return qm->ops->hw_error_handle(qm, need_reset); } /** @@ -4077,17 +4088,19 @@ int hisi_qm_sriov_configure(struct pci_dev *pdev, int num_vfs) } EXPORT_SYMBOL_GPL(hisi_qm_sriov_configure); -static enum acc_err_result qm_dev_err_handle(struct hisi_qm *qm) +static enum acc_err_result qm_dev_err_handle(struct hisi_qm *qm, bool need_reset) { - u32 err_sts; + u32 err_sts, tmp; if (!qm->err_ini->get_dev_hw_err_status) { dev_err(&qm->pdev->dev, "Device doesn't support get hw error status!\n"); return ACC_ERR_NONE; } - /* get device hardware error status */ - err_sts = qm->err_ini->get_dev_hw_err_status(qm); + /* Get device hardware new error status */ + tmp = qm->err_ini->get_dev_hw_err_status(qm); + err_sts = tmp & (~qm->err_info.dev_err_type); + qm->err_info.dev_err_type |= tmp; if (err_sts) { if (err_sts & qm->err_info.ecc_2bits_mask) qm->err_status.is_dev_ecc_mbit = true; @@ -4095,11 +4108,21 @@ static enum acc_err_result qm_dev_err_handle(struct hisi_qm *qm) if (qm->err_ini->log_dev_hw_err) qm->err_ini->log_dev_hw_err(qm, err_sts); - if (err_sts & qm->err_info.dev_reset_mask) + /* If the device is ready to reset, only print new error type. */ + if (!need_reset) + return ACC_ERR_RECOVERED; + + if (err_sts & qm->err_info.dev_reset_mask) { + /* Disable the same error reporting until the error is recovered. */ + qm->err_ini->disable_error_report(qm, qm->err_info.dev_err_type); return ACC_ERR_NEED_RESET; + } - if (qm->err_ini->clear_dev_hw_err_status) - qm->err_ini->clear_dev_hw_err_status(qm, err_sts); + /* Clear error source if not need reset. */ + if (qm->err_ini->clear_dev_hw_err_status) { + qm->err_ini->clear_dev_hw_err_status(qm, qm->err_info.dev_err_type); + qm->err_ini->enable_error_report(qm); + } } return ACC_ERR_RECOVERED; @@ -4108,16 +4131,25 @@ static enum acc_err_result qm_dev_err_handle(struct hisi_qm *qm) static enum acc_err_result qm_process_dev_error(struct hisi_qm *qm) { enum acc_err_result qm_ret, dev_ret; + bool need_reset = true; + + if (!test_bit(QM_RST_SCHED, &qm->misc_ctl)) { + qm->err_info.qm_err_type = 0; + qm->err_info.dev_err_type = 0; + } else { + need_reset = false; + } /* log qm error */ - qm_ret = qm_hw_error_handle(qm); + qm_ret = qm_hw_error_handle(qm, need_reset); /* log device error */ - dev_ret = qm_dev_err_handle(qm); + dev_ret = qm_dev_err_handle(qm, need_reset); + if (need_reset && (qm_ret == ACC_ERR_NEED_RESET || + dev_ret == ACC_ERR_NEED_RESET)) + return ACC_ERR_NEED_RESET; - return (qm_ret == ACC_ERR_NEED_RESET || - dev_ret == ACC_ERR_NEED_RESET) ? - ACC_ERR_NEED_RESET : ACC_ERR_RECOVERED; + return ACC_ERR_RECOVERED; } /** @@ -4317,8 +4349,6 @@ static int qm_controller_reset_prepare(struct hisi_qm *qm) if (ret) pci_err(pdev, "failed to stop by vfs in soft reset!\n"); - clear_bit(QM_RST_SCHED, &qm->misc_ctl); - return 0; } @@ -4557,6 +4587,7 @@ static int qm_controller_reset_done(struct hisi_qm *qm) return ret; } } + clear_bit(QM_RST_SCHED, &qm->misc_ctl); ret = qm_dev_hw_init(qm); if (ret) { @@ -4630,6 +4661,7 @@ static int qm_controller_reset(struct hisi_qm *qm) err_reset: pci_err(pdev, "Controller reset failed (%d)\n", ret); + clear_bit(QM_RST_SCHED, &qm->misc_ctl); qm_reset_bit_clear(qm); /* if resetting fails, isolate the device */ diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c index 784416c0c559ba826f4e3dc13597f8be7a35deef..b2eab04f989c1d9aeb5f174aca796fc94fed3774 100644 --- a/drivers/crypto/hisilicon/sec2/sec_main.c +++ b/drivers/crypto/hisilicon/sec2/sec_main.c @@ -1012,11 +1012,25 @@ static u32 sec_get_hw_err_status(struct hisi_qm *qm) static void sec_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts) { - u32 nfe; - writel(err_sts, qm->io_base + SEC_CORE_INT_SOURCE); - nfe = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_NFE_MASK_CAP, qm->cap_ver); - writel(nfe, qm->io_base + SEC_RAS_NFE_REG); +} + +static void sec_disable_error_report(struct hisi_qm *qm, u32 err_type) +{ + u32 nfe_mask; + + nfe_mask = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_NFE_MASK_CAP, qm->cap_ver); + writel(nfe_mask & (~err_type), qm->io_base + SEC_RAS_NFE_REG); +} + +static void sec_enable_error_report(struct hisi_qm *qm) +{ + u32 nfe_mask, ce_mask; + + nfe_mask = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_NFE_MASK_CAP, qm->cap_ver); + ce_mask = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_CE_MASK_CAP, qm->cap_ver); + writel(nfe_mask, qm->io_base + SEC_RAS_NFE_REG); + writel(ce_mask, qm->io_base + SEC_RAS_CE_REG); } static void sec_open_axi_master_ooo(struct hisi_qm *qm) @@ -1054,6 +1068,8 @@ static const struct hisi_qm_err_ini sec_err_ini = { .hw_err_disable = sec_hw_error_disable, .get_dev_hw_err_status = sec_get_hw_err_status, .clear_dev_hw_err_status = sec_clear_hw_err_status, + .disable_error_report = sec_disable_error_report, + .enable_error_report = sec_enable_error_report, .log_dev_hw_err = sec_log_hw_error, .open_axi_master_ooo = sec_open_axi_master_ooo, .open_sva_prefetch = sec_open_sva_prefetch, diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c index 1099c16f55550b7bfe5af861b6d61d7cc7ec4417..6675c8198481e95701b4eb1aa33c8e29057eac15 100644 --- a/drivers/crypto/hisilicon/zip/zip_main.c +++ b/drivers/crypto/hisilicon/zip/zip_main.c @@ -1008,11 +1008,25 @@ static u32 hisi_zip_get_hw_err_status(struct hisi_qm *qm) static void hisi_zip_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts) { - u32 nfe; - writel(err_sts, qm->io_base + HZIP_CORE_INT_SOURCE); - nfe = hisi_qm_get_hw_info(qm, zip_basic_cap_info, ZIP_NFE_MASK_CAP, qm->cap_ver); - writel(nfe, qm->io_base + HZIP_CORE_INT_RAS_NFE_ENB); +} + +static void hisi_zip_disable_error_report(struct hisi_qm *qm, u32 err_type) +{ + u32 nfe_mask; + + nfe_mask = hisi_qm_get_hw_info(qm, zip_basic_cap_info, ZIP_NFE_MASK_CAP, qm->cap_ver); + writel(nfe_mask & (~err_type), qm->io_base + HZIP_CORE_INT_RAS_NFE_ENB); +} + +static void hisi_zip_enable_error_report(struct hisi_qm *qm) +{ + u32 nfe_mask, ce_mask; + + nfe_mask = hisi_qm_get_hw_info(qm, zip_basic_cap_info, ZIP_NFE_MASK_CAP, qm->cap_ver); + ce_mask = hisi_qm_get_hw_info(qm, zip_basic_cap_info, ZIP_CE_MASK_CAP, qm->cap_ver); + writel(nfe_mask, qm->io_base + HZIP_CORE_INT_RAS_NFE_ENB); + writel(ce_mask, qm->io_base + HZIP_CORE_INT_RAS_CE_ENB); } static void hisi_zip_open_axi_master_ooo(struct hisi_qm *qm) @@ -1069,6 +1083,8 @@ static const struct hisi_qm_err_ini hisi_zip_err_ini = { .hw_err_disable = hisi_zip_hw_error_disable, .get_dev_hw_err_status = hisi_zip_get_hw_err_status, .clear_dev_hw_err_status = hisi_zip_clear_hw_err_status, + .disable_error_report = hisi_zip_disable_error_report, + .enable_error_report = hisi_zip_enable_error_report, .log_dev_hw_err = hisi_zip_log_hw_error, .open_axi_master_ooo = hisi_zip_open_axi_master_ooo, .close_axi_master_ooo = hisi_zip_close_axi_master_ooo, diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index f349144f2bd4c686713037e5e7ca33891fce7fec..83d013f1bf3937497c25a8af6b0a45d4ac188286 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -252,6 +252,8 @@ struct hisi_qm_err_info { u32 ce; u32 nfe; u32 fe; + u32 qm_err_type; + u32 dev_err_type; }; struct hisi_qm_err_status { @@ -265,6 +267,8 @@ struct hisi_qm_err_ini { void (*hw_err_disable)(struct hisi_qm *qm); u32 (*get_dev_hw_err_status)(struct hisi_qm *qm); void (*clear_dev_hw_err_status)(struct hisi_qm *qm, u32 err_sts); + void (*disable_error_report)(struct hisi_qm *qm, u32 err_type); + void (*enable_error_report)(struct hisi_qm *qm); void (*open_axi_master_ooo)(struct hisi_qm *qm); void (*close_axi_master_ooo)(struct hisi_qm *qm); void (*open_sva_prefetch)(struct hisi_qm *qm);