]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
crypto: hisilicon/qm - disable same error report before resetting
authorWeili Qian <qianweili@huawei.com>
Sat, 26 Oct 2024 11:44:29 +0000 (19:44 +0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Sat, 2 Nov 2024 10:23:25 +0000 (18:23 +0800)
If an error indicating that the device needs to be reset is reported,
disable the error reporting before device reset is complete,
enable the error reporting after the reset is complete to prevent
the same error from being reported repeatedly.

Fixes: eaebf4c3b103 ("crypto: hisilicon - Unify hardware error init/uninit into QM")
Signed-off-by: Weili Qian <qianweili@huawei.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/hisilicon/hpre/hpre_main.c
drivers/crypto/hisilicon/qm.c
drivers/crypto/hisilicon/sec2/sec_main.c
drivers/crypto/hisilicon/zip/zip_main.c
include/linux/hisi_acc_qm.h

index c5de1f6b6d3b8d7f3244a701ad576a5072b97693..96fde9437b4b8fd21c4b524a5b266e34b6122af8 100644 (file)
@@ -1353,11 +1353,15 @@ 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_open_axi_master_ooo(struct hisi_qm *qm)
@@ -1371,6 +1375,27 @@ static void hpre_open_axi_master_ooo(struct hisi_qm *qm)
               qm->io_base + HPRE_AM_OOO_SHUTDOWN_ENB);
 }
 
+static enum acc_err_result hpre_get_err_result(struct hisi_qm *qm)
+{
+       u32 err_status;
+
+       err_status = hpre_get_hw_err_status(qm);
+       if (err_status) {
+               if (err_status & qm->err_info.ecc_2bits_mask)
+                       qm->err_status.is_dev_ecc_mbit = true;
+               hpre_log_hw_error(qm, err_status);
+
+               if (err_status & qm->err_info.dev_reset_mask) {
+                       /* Disable the same error reporting until device is recovered. */
+                       hpre_disable_error_report(qm, err_status);
+                       return ACC_ERR_NEED_RESET;
+               }
+               hpre_clear_hw_err_status(qm, err_status);
+       }
+
+       return ACC_ERR_RECOVERED;
+}
+
 static void hpre_err_info_init(struct hisi_qm *qm)
 {
        struct hisi_qm_err_info *err_info = &qm->err_info;
@@ -1397,12 +1422,12 @@ 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,
-       .log_dev_hw_err         = hpre_log_hw_error,
        .open_axi_master_ooo    = hpre_open_axi_master_ooo,
        .open_sva_prefetch      = hpre_open_sva_prefetch,
        .close_sva_prefetch     = hpre_close_sva_prefetch,
        .show_last_dfx_regs     = hpre_show_last_dfx_regs,
        .err_info_init          = hpre_err_info_init,
+       .get_err_result         = hpre_get_err_result,
 };
 
 static int hpre_pf_probe_init(struct hpre *hpre)
index 1cdda09ee817bef71b7de74a35ae1b874674419f..19c1b5d3c954cb114a99587ed0e458dadf8f12cd 100644 (file)
@@ -271,12 +271,6 @@ enum vft_type {
        SHAPER_VFT,
 };
 
-enum acc_err_result {
-       ACC_ERR_NONE,
-       ACC_ERR_NEED_RESET,
-       ACC_ERR_RECOVERED,
-};
-
 enum qm_alg_type {
        ALG_TYPE_0,
        ALG_TYPE_1,
@@ -1488,22 +1482,25 @@ 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)
 {
-       u32 error_status, tmp;
-
-       /* read err sts */
-       tmp = readl(qm->io_base + QM_ABNORMAL_INT_STATUS);
-       error_status = qm->error_mask & tmp;
+       u32 error_status;
 
-       if (error_status) {
+       error_status = qm_get_hw_error_status(qm);
+       if (error_status & qm->error_mask) {
                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 (error_status & qm->err_info.qm_reset_mask) {
+                       /* Disable the same error reporting until device is recovered. */
+                       writel(qm->err_info.nfe & (~error_status),
+                              qm->io_base + QM_RAS_NFE_ENABLE);
                        return ACC_ERR_NEED_RESET;
+               }
 
+               /* Clear error source if not need reset. */
                writel(error_status, qm->io_base + QM_ABNORMAL_INT_SOURCE);
                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;
@@ -3924,30 +3921,12 @@ EXPORT_SYMBOL_GPL(hisi_qm_sriov_configure);
 
 static enum acc_err_result qm_dev_err_handle(struct hisi_qm *qm)
 {
-       u32 err_sts;
-
-       if (!qm->err_ini->get_dev_hw_err_status) {
-               dev_err(&qm->pdev->dev, "Device doesn't support get hw error status!\n");
+       if (!qm->err_ini->get_err_result) {
+               dev_err(&qm->pdev->dev, "Device doesn't support reset!\n");
                return ACC_ERR_NONE;
        }
 
-       /* get device hardware error status */
-       err_sts = qm->err_ini->get_dev_hw_err_status(qm);
-       if (err_sts) {
-               if (err_sts & qm->err_info.ecc_2bits_mask)
-                       qm->err_status.is_dev_ecc_mbit = true;
-
-               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)
-                       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);
-       }
-
-       return ACC_ERR_RECOVERED;
+       return qm->err_ini->get_err_result(qm);
 }
 
 static enum acc_err_result qm_process_dev_error(struct hisi_qm *qm)
index 316ab385e335530aae03f87568b3a4d67ac52629..8ec5333bb5aa32d044fc47ec4b75f6309db79bcc 100644 (file)
@@ -1056,11 +1056,15 @@ 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_open_axi_master_ooo(struct hisi_qm *qm)
@@ -1072,6 +1076,27 @@ static void sec_open_axi_master_ooo(struct hisi_qm *qm)
        writel(val | SEC_AXI_SHUTDOWN_ENABLE, qm->io_base + SEC_CONTROL_REG);
 }
 
+static enum acc_err_result sec_get_err_result(struct hisi_qm *qm)
+{
+       u32 err_status;
+
+       err_status = sec_get_hw_err_status(qm);
+       if (err_status) {
+               if (err_status & qm->err_info.ecc_2bits_mask)
+                       qm->err_status.is_dev_ecc_mbit = true;
+               sec_log_hw_error(qm, err_status);
+
+               if (err_status & qm->err_info.dev_reset_mask) {
+                       /* Disable the same error reporting until device is recovered. */
+                       sec_disable_error_report(qm, err_status);
+                       return ACC_ERR_NEED_RESET;
+               }
+               sec_clear_hw_err_status(qm, err_status);
+       }
+
+       return ACC_ERR_RECOVERED;
+}
+
 static void sec_err_info_init(struct hisi_qm *qm)
 {
        struct hisi_qm_err_info *err_info = &qm->err_info;
@@ -1098,12 +1123,12 @@ 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,
-       .log_dev_hw_err         = sec_log_hw_error,
        .open_axi_master_ooo    = sec_open_axi_master_ooo,
        .open_sva_prefetch      = sec_open_sva_prefetch,
        .close_sva_prefetch     = sec_close_sva_prefetch,
        .show_last_dfx_regs     = sec_show_last_dfx_regs,
        .err_info_init          = sec_err_info_init,
+       .get_err_result         = sec_get_err_result,
 };
 
 static int sec_pf_probe_init(struct sec_dev *sec)
index 638adfc6f6831c1ce0368a97324c69cac4971c64..9239b251c2d7263d8b18df01394856b04ea65dd3 100644 (file)
@@ -1107,11 +1107,15 @@ 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_open_axi_master_ooo(struct hisi_qm *qm)
@@ -1141,6 +1145,27 @@ static void hisi_zip_close_axi_master_ooo(struct hisi_qm *qm)
               qm->io_base + HZIP_CORE_INT_SET);
 }
 
+static enum acc_err_result hisi_zip_get_err_result(struct hisi_qm *qm)
+{
+       u32 err_status;
+
+       err_status = hisi_zip_get_hw_err_status(qm);
+       if (err_status) {
+               if (err_status & qm->err_info.ecc_2bits_mask)
+                       qm->err_status.is_dev_ecc_mbit = true;
+               hisi_zip_log_hw_error(qm, err_status);
+
+               if (err_status & qm->err_info.dev_reset_mask) {
+                       /* Disable the same error reporting until device is recovered. */
+                       hisi_zip_disable_error_report(qm, err_status);
+                       return ACC_ERR_NEED_RESET;
+               }
+               hisi_zip_clear_hw_err_status(qm, err_status);
+       }
+
+       return ACC_ERR_RECOVERED;
+}
+
 static void hisi_zip_err_info_init(struct hisi_qm *qm)
 {
        struct hisi_qm_err_info *err_info = &qm->err_info;
@@ -1168,13 +1193,13 @@ 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,
-       .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,
        .open_sva_prefetch      = hisi_zip_open_sva_prefetch,
        .close_sva_prefetch     = hisi_zip_close_sva_prefetch,
        .show_last_dfx_regs     = hisi_zip_show_last_dfx_regs,
        .err_info_init          = hisi_zip_err_info_init,
+       .get_err_result         = hisi_zip_get_err_result,
 };
 
 static int hisi_zip_pf_probe_init(struct hisi_zip *hisi_zip)
index 7272eac850e8a293737775bbf4663f920cfb636a..6dbd0d49628f23cf07b3683dedb15b461379bd53 100644 (file)
@@ -229,6 +229,12 @@ struct hisi_qm_status {
 
 struct hisi_qm;
 
+enum acc_err_result {
+       ACC_ERR_NONE,
+       ACC_ERR_NEED_RESET,
+       ACC_ERR_RECOVERED,
+};
+
 struct hisi_qm_err_info {
        char *acpi_rst;
        u32 msi_wr_port;
@@ -257,9 +263,9 @@ struct hisi_qm_err_ini {
        void (*close_axi_master_ooo)(struct hisi_qm *qm);
        void (*open_sva_prefetch)(struct hisi_qm *qm);
        void (*close_sva_prefetch)(struct hisi_qm *qm);
-       void (*log_dev_hw_err)(struct hisi_qm *qm, u32 err_sts);
        void (*show_last_dfx_regs)(struct hisi_qm *qm);
        void (*err_info_init)(struct hisi_qm *qm);
+       enum acc_err_result (*get_err_result)(struct hisi_qm *qm);
 };
 
 struct hisi_qm_cap_info {