提交 27b8c201 编写于 作者: T tanshukun 提交者: Xie XiuQi

crypto/hisilicon/qm: fix flr and 2bit ecc confilct

driver inclusion
category: bugfix
bugzilla: NA
CVE: NA

when 2bit ecc occur, the master OOO register will block immediately
without any notice for driver. if user trigger flr sametime, the ECAM
will broken and can not be recovered except reboot.

If the 2bit ECC happens before FLR, we will give up the FLR. if FLR
early, we will block the irq of hw error.

Feature or Bugfix:Bugfix
Signed-off-by: Ntanshukun (A) <tanshukun1@huawei.com>
Reviewed-by: Nhuangdaode <huangdaode@hisilicon.com>
Reviewed-by: NZhou Wang <wangzhou1@hisilicon.com>
Reviewed-by: NYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 dcd33c6b
...@@ -111,6 +111,7 @@ ...@@ -111,6 +111,7 @@
#define QM_ABNORMAL_INT_SOURCE 0x100000 #define QM_ABNORMAL_INT_SOURCE 0x100000
#define QM_ABNORMAL_INT_MASK 0x100004 #define QM_ABNORMAL_INT_MASK 0x100004
#define QM_HW_ERROR_IRQ_DISABLE GENMASK(12, 0)
#define QM_ABNORMAL_INT_STATUS 0x100008 #define QM_ABNORMAL_INT_STATUS 0x100008
#define QM_ABNORMAL_INF00 0x100010 #define QM_ABNORMAL_INF00 0x100010
#define QM_FIFO_OVERFLOW_TYPE 0xc0 #define QM_FIFO_OVERFLOW_TYPE 0xc0
...@@ -207,6 +208,7 @@ struct hisi_qm_hw_ops { ...@@ -207,6 +208,7 @@ struct hisi_qm_hw_ops {
int (*debug_init)(struct hisi_qm *qm); int (*debug_init)(struct hisi_qm *qm);
void (*hw_error_init)(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe, void (*hw_error_init)(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe,
u32 msi); u32 msi);
void (*hw_error_uninit)(struct hisi_qm *qm);
pci_ers_result_t (*hw_error_handle)(struct hisi_qm *qm); pci_ers_result_t (*hw_error_handle)(struct hisi_qm *qm);
}; };
...@@ -1071,6 +1073,11 @@ static void qm_hw_error_init_v2(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe, ...@@ -1071,6 +1073,11 @@ static void qm_hw_error_init_v2(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe,
writel(irq_unmask, qm->io_base + QM_ABNORMAL_INT_MASK); writel(irq_unmask, qm->io_base + QM_ABNORMAL_INT_MASK);
} }
static void qm_hw_error_uninit_v2(struct hisi_qm *qm)
{
writel(QM_HW_ERROR_IRQ_DISABLE, qm->io_base + QM_ABNORMAL_INT_MASK);
}
static void qm_log_hw_error(struct hisi_qm *qm, u32 error_status) static void qm_log_hw_error(struct hisi_qm *qm, u32 error_status)
{ {
const struct hisi_qm_hw_error *err; const struct hisi_qm_hw_error *err;
...@@ -1142,6 +1149,7 @@ static const struct hisi_qm_hw_ops qm_hw_ops_v2 = { ...@@ -1142,6 +1149,7 @@ static const struct hisi_qm_hw_ops qm_hw_ops_v2 = {
.qm_db = qm_db_v2, .qm_db = qm_db_v2,
.get_irq_num = qm_get_irq_num_v2, .get_irq_num = qm_get_irq_num_v2,
.hw_error_init = qm_hw_error_init_v2, .hw_error_init = qm_hw_error_init_v2,
.hw_error_uninit = qm_hw_error_uninit_v2,
.hw_error_handle = qm_hw_error_handle_v2, .hw_error_handle = qm_hw_error_handle_v2,
}; };
...@@ -2643,6 +2651,19 @@ void hisi_qm_hw_error_init(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe, ...@@ -2643,6 +2651,19 @@ void hisi_qm_hw_error_init(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe,
} }
EXPORT_SYMBOL_GPL(hisi_qm_hw_error_init); EXPORT_SYMBOL_GPL(hisi_qm_hw_error_init);
void hisi_qm_hw_error_uninit(struct hisi_qm *qm)
{
if (!qm->ops->hw_error_uninit) {
dev_err(&qm->pdev->dev,
"QM version %d doesn't support hw error handling!\n",
qm->ver);
return;
}
qm->ops->hw_error_uninit(qm);
}
EXPORT_SYMBOL_GPL(hisi_qm_hw_error_uninit);
/** /**
* hisi_qm_hw_error_handle() - Handle qm non-fatal hardware errors. * hisi_qm_hw_error_handle() - Handle qm non-fatal hardware errors.
* @qm: The qm which has non-fatal hardware errors. * @qm: The qm which has non-fatal hardware errors.
...@@ -2704,6 +2725,19 @@ enum qm_hw_ver hisi_qm_get_hw_version(struct pci_dev *pdev) ...@@ -2704,6 +2725,19 @@ enum qm_hw_ver hisi_qm_get_hw_version(struct pci_dev *pdev)
} }
EXPORT_SYMBOL_GPL(hisi_qm_get_hw_version); EXPORT_SYMBOL_GPL(hisi_qm_get_hw_version);
int hisi_qm_get_hw_error_status(struct hisi_qm *qm)
{
u32 err_sts;
err_sts = readl(qm->io_base + QM_ABNORMAL_INT_STATUS) &
QM_ECC_MBIT;
if (err_sts)
return err_sts;
return 0;
}
EXPORT_SYMBOL_GPL(hisi_qm_get_hw_error_status);
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Zhou Wang <wangzhou1@hisilicon.com>"); MODULE_AUTHOR("Zhou Wang <wangzhou1@hisilicon.com>");
MODULE_DESCRIPTION("HiSilicon Accelerator queue manager driver"); MODULE_DESCRIPTION("HiSilicon Accelerator queue manager driver");
...@@ -346,10 +346,12 @@ void hisi_qm_debug_regs_clear(struct hisi_qm *qm); ...@@ -346,10 +346,12 @@ void hisi_qm_debug_regs_clear(struct hisi_qm *qm);
int hisi_qm_debug_init(struct hisi_qm *qm); int hisi_qm_debug_init(struct hisi_qm *qm);
void hisi_qm_hw_error_init(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe, void hisi_qm_hw_error_init(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe,
u32 msi); u32 msi);
void hisi_qm_hw_error_uninit(struct hisi_qm *qm);
pci_ers_result_t hisi_qm_hw_error_handle(struct hisi_qm *qm); pci_ers_result_t hisi_qm_hw_error_handle(struct hisi_qm *qm);
void hisi_qm_clear_queues(struct hisi_qm *qm); void hisi_qm_clear_queues(struct hisi_qm *qm);
enum qm_hw_ver hisi_qm_get_hw_version(struct pci_dev *pdev); enum qm_hw_ver hisi_qm_get_hw_version(struct pci_dev *pdev);
int hisi_qm_restart(struct hisi_qm *qm); int hisi_qm_restart(struct hisi_qm *qm);
int hisi_qm_get_hw_error_status(struct hisi_qm *qm);
struct hisi_acc_sgl_pool; struct hisi_acc_sgl_pool;
struct hisi_acc_hw_sgl *hisi_acc_sg_buf_map_to_hw_sgl(struct device *dev, struct hisi_acc_hw_sgl *hisi_acc_sg_buf_map_to_hw_sgl(struct device *dev,
......
...@@ -64,6 +64,8 @@ ...@@ -64,6 +64,8 @@
#define HZIP_CORE_INT_SOURCE 0x3010A0 #define HZIP_CORE_INT_SOURCE 0x3010A0
#define HZIP_CORE_INT_MASK 0x3010A4 #define HZIP_CORE_INT_MASK 0x3010A4
#define HZIP_HW_ERROR_IRQ_ENABLE 1
#define HZIP_HW_ERROR_IRQ_DISABLE 0
#define HZIP_CORE_INT_STATUS 0x3010AC #define HZIP_CORE_INT_STATUS 0x3010AC
#define HZIP_CORE_INT_STATUS_M_ECC BIT(1) #define HZIP_CORE_INT_STATUS_M_ECC BIT(1)
#define HZIP_CORE_SRAM_ECC_ERR_INFO 0x301148 #define HZIP_CORE_SRAM_ECC_ERR_INFO 0x301148
...@@ -85,6 +87,9 @@ ...@@ -85,6 +87,9 @@
#define HZIP_SOFT_CTRL_CNT_CLR_CE 0x301000 #define HZIP_SOFT_CTRL_CNT_CLR_CE 0x301000
#define HZIP_SOFT_CTRL_CNT_CLR_CE_BIT BIT(0) #define HZIP_SOFT_CTRL_CNT_CLR_CE_BIT BIT(0)
#define HZIP_SOFT_CTRL_ZIP_CONTROL 0x30100C
#define HZIP_AXI_SHUTDOWN_ENABLE BIT(14)
#define HZIP_AXI_SHUTDOWN_DISABLE 0xFFFFBFFF
#define HZIP_MSE_ENABLE 1 #define HZIP_MSE_ENABLE 1
#define HZIP_MSE_DISABLE 0 #define HZIP_MSE_DISABLE 0
...@@ -431,6 +436,7 @@ static void hisi_zip_debug_regs_clear(struct hisi_zip *hisi_zip) ...@@ -431,6 +436,7 @@ static void hisi_zip_debug_regs_clear(struct hisi_zip *hisi_zip)
static void hisi_zip_hw_error_set_state(struct hisi_zip *hisi_zip, bool state) static void hisi_zip_hw_error_set_state(struct hisi_zip *hisi_zip, bool state)
{ {
struct hisi_qm *qm = &hisi_zip->qm; struct hisi_qm *qm = &hisi_zip->qm;
u32 val;
if (qm->ver == QM_HW_V1) { if (qm->ver == QM_HW_V1) {
writel(HZIP_CORE_INT_DISABLE, qm->io_base + HZIP_CORE_INT_MASK); writel(HZIP_CORE_INT_DISABLE, qm->io_base + HZIP_CORE_INT_MASK);
...@@ -445,17 +451,27 @@ static void hisi_zip_hw_error_set_state(struct hisi_zip *hisi_zip, bool state) ...@@ -445,17 +451,27 @@ static void hisi_zip_hw_error_set_state(struct hisi_zip *hisi_zip, bool state)
writel(HZIP_CORE_INT_RAS_NFE_ENABLE, writel(HZIP_CORE_INT_RAS_NFE_ENABLE,
hisi_zip->qm.io_base + HZIP_CORE_INT_RAS_NFE_ENB); hisi_zip->qm.io_base + HZIP_CORE_INT_RAS_NFE_ENB);
val = readl(hisi_zip->qm.io_base + HZIP_SOFT_CTRL_ZIP_CONTROL);
if (state) { if (state) {
/* clear ZIP hw error source if having */ /* clear ZIP hw error source if having */
writel(HZIP_CORE_INT_DISABLE, hisi_zip->qm.io_base + writel(HZIP_CORE_INT_DISABLE, hisi_zip->qm.io_base +
HZIP_CORE_INT_SOURCE); HZIP_CORE_INT_SOURCE);
/* enable ZIP hw error interrupts */ /* enable ZIP hw error interrupts */
writel(0, hisi_zip->qm.io_base + HZIP_CORE_INT_MASK); writel(0, hisi_zip->qm.io_base + HZIP_CORE_INT_MASK);
/* enable ZIP block master OOO when m-bit error occur */
val = val | HZIP_AXI_SHUTDOWN_ENABLE;
} else { } else {
/* disable ZIP hw error interrupts */ /* disable ZIP hw error interrupts */
writel(HZIP_CORE_INT_DISABLE, writel(HZIP_CORE_INT_DISABLE,
hisi_zip->qm.io_base + HZIP_CORE_INT_MASK); hisi_zip->qm.io_base + HZIP_CORE_INT_MASK);
/* disable ZIP block master OOO when m-bit error occur */
val = val & HZIP_AXI_SHUTDOWN_DISABLE;
} }
writel(val, hisi_zip->qm.io_base + HZIP_SOFT_CTRL_ZIP_CONTROL);
} }
static inline struct hisi_qm *file_to_qm(struct ctrl_debug_file *file) static inline struct hisi_qm *file_to_qm(struct ctrl_debug_file *file)
...@@ -1323,13 +1339,64 @@ static pci_ers_result_t hisi_zip_slot_reset(struct pci_dev *pdev) ...@@ -1323,13 +1339,64 @@ static pci_ers_result_t hisi_zip_slot_reset(struct pci_dev *pdev)
return PCI_ERS_RESULT_RECOVERED; return PCI_ERS_RESULT_RECOVERED;
} }
static void hisi_zip_set_hw_error(struct hisi_zip *hisi_zip, bool state)
{
struct pci_dev *pdev = hisi_zip->qm.pdev;
struct hisi_zip *zip = pci_get_drvdata(pci_physfn(pdev));
struct hisi_qm *qm = &zip->qm;
if (state)
hisi_qm_hw_error_init(&hisi_zip->qm, QM_BASE_CE,
QM_BASE_NFE | QM_ACC_WB_NOT_READY_TIMEOUT,
0, QM_DB_RANDOM_INVALID);
else
hisi_qm_hw_error_uninit(qm);
hisi_zip_hw_error_set_state(zip, state);
}
static int hisi_zip_get_hw_error_status(struct hisi_zip *hisi_zip)
{
u32 err_sts;
err_sts = readl(hisi_zip->qm.io_base + HZIP_CORE_INT_STATUS) &
HZIP_CORE_INT_STATUS_M_ECC;
if (err_sts)
return err_sts;
return 0;
}
static int hisi_zip_check_hw_error(struct hisi_zip *hisi_zip)
{
struct pci_dev *pdev = hisi_zip->qm.pdev;
struct hisi_zip *zip = pci_get_drvdata(pci_physfn(pdev));
struct hisi_qm *qm = &zip->qm;
int ret;
ret = hisi_qm_get_hw_error_status(qm);
if (ret)
return ret;
return hisi_zip_get_hw_error_status(zip);
}
static void hisi_zip_reset_prepare(struct pci_dev *pdev) static void hisi_zip_reset_prepare(struct pci_dev *pdev)
{ {
struct hisi_zip *hisi_zip = pci_get_drvdata(pdev); struct hisi_zip *hisi_zip = pci_get_drvdata(pdev);
struct hisi_qm *qm = &hisi_zip->qm; struct hisi_qm *qm = &hisi_zip->qm;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
u32 delay = 0;
int ret; int ret;
hisi_zip_set_hw_error(hisi_zip, HZIP_HW_ERROR_IRQ_DISABLE);
while (hisi_zip_check_hw_error(hisi_zip)) {
msleep(++delay);
if (delay > HZIP_RESET_WAIT_TIMEOUT)
return;
}
ret = hisi_zip_reset_prepare_ready(hisi_zip); ret = hisi_zip_reset_prepare_ready(hisi_zip);
if (ret) { if (ret) {
dev_err(dev, "FLR not ready!\n"); dev_err(dev, "FLR not ready!\n");
...@@ -1355,6 +1422,14 @@ static void hisi_zip_flr_reset_complete(struct hisi_zip *hisi_zip) ...@@ -1355,6 +1422,14 @@ static void hisi_zip_flr_reset_complete(struct hisi_zip *hisi_zip)
{ {
struct pci_dev *pdev = hisi_zip->qm.pdev; struct pci_dev *pdev = hisi_zip->qm.pdev;
struct hisi_zip *zip = pci_get_drvdata(pci_physfn(pdev)); struct hisi_zip *zip = pci_get_drvdata(pci_physfn(pdev));
struct device *dev = &zip->qm.pdev->dev;
u32 id;
pci_read_config_dword(zip->qm.pdev, PCI_COMMAND, &id);
if (id == ~0) {
hisi_zip_remove(zip->qm.pdev);
dev_err(dev, "Device can not be used!\n");
}
clear_bit(HISI_ZIP_RESET, &zip->status); clear_bit(HISI_ZIP_RESET, &zip->status);
} }
...@@ -1366,21 +1441,23 @@ static void hisi_zip_reset_done(struct pci_dev *pdev) ...@@ -1366,21 +1441,23 @@ static void hisi_zip_reset_done(struct pci_dev *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
int ret; int ret;
hisi_zip_set_hw_error(hisi_zip, HZIP_HW_ERROR_IRQ_ENABLE);
ret = hisi_qm_restart(qm); ret = hisi_qm_restart(qm);
if (ret) { if (ret) {
dev_err(dev, "Failed to start QM!\n"); dev_err(dev, "Failed to start QM!\n");
return; goto flr_done;
} }
if (pdev->is_physfn) { if (pdev->is_physfn) {
hisi_zip_set_user_domain_and_cache(hisi_zip); hisi_zip_set_user_domain_and_cache(hisi_zip);
hisi_zip_hw_error_init(hisi_zip);
if (hisi_zip->ctrl->num_vfs) if (hisi_zip->ctrl->num_vfs)
hisi_zip_vf_q_assign(hisi_zip, hisi_zip_vf_q_assign(hisi_zip,
hisi_zip->ctrl->num_vfs); hisi_zip->ctrl->num_vfs);
hisi_zip_vf_reset_done(hisi_zip); hisi_zip_vf_reset_done(hisi_zip);
} }
flr_done:
hisi_zip_flr_reset_complete(hisi_zip); hisi_zip_flr_reset_complete(hisi_zip);
dev_info(dev, "FLR reset complete\n"); dev_info(dev, "FLR reset complete\n");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册