188 lines
7.2 KiB
Diff
188 lines
7.2 KiB
Diff
From 1405375054d9e15c95982cd1eb6608a7dad08de7 Mon Sep 17 00:00:00 2001
|
|
From: Yufeng Mo <moyufeng@huawei.com>
|
|
Date: Sat, 24 Jul 2021 15:45:11 +0800
|
|
Subject: [PATCH 076/283] net: hns3: add support for handling all errors
|
|
through MSI-X
|
|
|
|
mainline inclusion
|
|
from mainline-v5.14-rc1
|
|
commit 17f59244029bf9c0673725efdd0386ed95e127a7
|
|
category: feature
|
|
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EMUR
|
|
CVE: NA
|
|
|
|
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=17f59244029bf9c0673725efdd0386ed95e127a7
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
Currently, hardware errors can be reported through AER or MSI-X mode.
|
|
However, the AER mode is intended to handle only bus errors, but not
|
|
hardware errors. On the other hand, virtual machines cannot handle
|
|
AER errors. When an AER error is reported, virtual machines will be
|
|
suspended. So add support for handling all these hardware errors
|
|
through MSI-X mode which depends on a newer version of firmware,
|
|
and reserve the handler of the AER mode for compatibility.
|
|
|
|
Signed-off-by: Yufeng Mo <moyufeng@huawei.com>
|
|
Signed-off-by: Jiaran Zhang <zhangjiaran@huawei.com>
|
|
Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
Reviewed-by: Yongxin Li <liyongxin1@huawei.com>
|
|
Signed-off-by: Junxin Chen <chenjunxin1@huawei.com>
|
|
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
|
|
Signed-off-by: Xiaodong Li <lixiaodong67@huawei.com>
|
|
---
|
|
.../hisilicon/hns3/hns3pf/hclge_err.c | 16 +++++++
|
|
.../hisilicon/hns3/hns3pf/hclge_main.c | 47 ++++++++++---------
|
|
.../hisilicon/hns3/hns3pf/hclge_main.h | 1 +
|
|
3 files changed, 41 insertions(+), 23 deletions(-)
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
|
|
index 18c60ea70fc4..3855c029829a 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
|
|
@@ -1614,11 +1614,27 @@ static const struct hclge_hw_blk hw_blk[] = {
|
|
{ /* sentinel */ }
|
|
};
|
|
|
|
+static void hclge_config_all_msix_error(struct hclge_dev *hdev, bool enable)
|
|
+{
|
|
+ u32 reg_val;
|
|
+
|
|
+ reg_val = hclge_read_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG);
|
|
+
|
|
+ if (enable)
|
|
+ reg_val |= BIT(HCLGE_VECTOR0_ALL_MSIX_ERR_B);
|
|
+ else
|
|
+ reg_val &= ~BIT(HCLGE_VECTOR0_ALL_MSIX_ERR_B);
|
|
+
|
|
+ hclge_write_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG, reg_val);
|
|
+}
|
|
+
|
|
int hclge_config_nic_hw_error(struct hclge_dev *hdev, bool state)
|
|
{
|
|
const struct hclge_hw_blk *module = hw_blk;
|
|
int ret = 0;
|
|
|
|
+ hclge_config_all_msix_error(hdev, state);
|
|
+
|
|
while (module->name) {
|
|
if (module->config_err_int) {
|
|
ret = module->config_err_int(hdev, state);
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
index 062572b2f779..f56cc318e2ad 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
@@ -3220,11 +3220,13 @@ static int hclge_set_vf_link_state(struct hnae3_handle *handle, int vf,
|
|
|
|
static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
|
|
{
|
|
- u32 cmdq_src_reg, msix_src_reg;
|
|
+ u32 cmdq_src_reg, msix_src_reg, hw_err_src_reg;
|
|
|
|
/* fetch the events from their corresponding regs */
|
|
cmdq_src_reg = hclge_read_dev(&hdev->hw, HCLGE_VECTOR0_CMDQ_SRC_REG);
|
|
msix_src_reg = hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_INT_STS);
|
|
+ hw_err_src_reg = hclge_read_dev(&hdev->hw,
|
|
+ HCLGE_RAS_PF_OTHER_INT_STS_REG);
|
|
|
|
/* Assumption: If by any chance reset and mailbox events are reported
|
|
* together then we will only process reset event in this go and will
|
|
@@ -3252,11 +3254,11 @@ static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
|
|
return HCLGE_VECTOR0_EVENT_RST;
|
|
}
|
|
|
|
- /* check for vector0 msix event source */
|
|
- if (msix_src_reg & HCLGE_VECTOR0_REG_MSIX_MASK) {
|
|
- *clearval = msix_src_reg;
|
|
+ /* check for vector0 msix event and hardware error event source */
|
|
+ if (msix_src_reg & HCLGE_VECTOR0_REG_MSIX_MASK ||
|
|
+ hw_err_src_reg & HCLGE_RAS_REG_NFE_MASK ||
|
|
+ hw_err_src_reg & HCLGE_RAS_REG_ROCEE_ERR_MASK)
|
|
return HCLGE_VECTOR0_EVENT_ERR;
|
|
- }
|
|
|
|
/* check for vector0 mailbox(=CMDQ RX) event source */
|
|
if (BIT(HCLGE_VECTOR0_RX_CMDQ_INT_B) & cmdq_src_reg) {
|
|
@@ -3267,9 +3269,8 @@ static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
|
|
|
|
/* print other vector0 event source */
|
|
dev_info(&hdev->pdev->dev,
|
|
- "CMDQ INT status:0x%x, other INT status:0x%x\n",
|
|
- cmdq_src_reg, msix_src_reg);
|
|
- *clearval = msix_src_reg;
|
|
+ "INT status: CMDQ(%#x) HW errors(%#x) other(%#x)\n",
|
|
+ cmdq_src_reg, hw_err_src_reg, msix_src_reg);
|
|
|
|
return HCLGE_VECTOR0_EVENT_OTHER;
|
|
}
|
|
@@ -3340,15 +3341,10 @@ static irqreturn_t hclge_misc_irq_handle(int irq, void *data)
|
|
|
|
hclge_clear_event_cause(hdev, event_cause, clearval);
|
|
|
|
- /* Enable interrupt if it is not cause by reset. And when
|
|
- * clearval equal to 0, it means interrupt status may be
|
|
- * cleared by hardware before driver reads status register.
|
|
- * For this case, vector0 interrupt also should be enabled.
|
|
- */
|
|
- if (!clearval ||
|
|
- event_cause == HCLGE_VECTOR0_EVENT_MBX) {
|
|
+ /* Enable interrupt if it is not caused by reset event or error event */
|
|
+ if (event_cause == HCLGE_VECTOR0_EVENT_MBX ||
|
|
+ event_cause == HCLGE_VECTOR0_EVENT_OTHER)
|
|
hclge_enable_vector(&hdev->misc_vector, true);
|
|
- }
|
|
|
|
return IRQ_HANDLED;
|
|
}
|
|
@@ -4165,22 +4161,27 @@ static void hclge_misc_err_recovery(struct hclge_dev *hdev)
|
|
{
|
|
struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
|
|
struct device *dev = &hdev->pdev->dev;
|
|
+ enum hnae3_reset_type reset_type;
|
|
u32 msix_sts_reg;
|
|
|
|
msix_sts_reg = hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_INT_STS);
|
|
-
|
|
if (msix_sts_reg & HCLGE_VECTOR0_REG_MSIX_MASK) {
|
|
- if (hclge_handle_hw_msix_error(hdev,
|
|
- &hdev->default_reset_request))
|
|
+ if (hclge_handle_hw_msix_error
|
|
+ (hdev, &hdev->default_reset_request))
|
|
dev_info(dev, "received msix interrupt 0x%x\n",
|
|
msix_sts_reg);
|
|
+ }
|
|
+ hclge_enable_vector(&hdev->misc_vector, true);
|
|
|
|
- if (hdev->default_reset_request)
|
|
- if (ae_dev->ops->reset_event)
|
|
- ae_dev->ops->reset_event(hdev->pdev, NULL);
|
|
+ hclge_handle_hw_ras_error(ae_dev);
|
|
+ if (ae_dev->hw_err_reset_req) {
|
|
+ reset_type = hclge_get_reset_level(ae_dev,
|
|
+ &ae_dev->hw_err_reset_req);
|
|
+ hclge_set_def_reset_request(ae_dev, reset_type);
|
|
}
|
|
|
|
- hclge_enable_vector(&hdev->misc_vector, true);
|
|
+ if (hdev->default_reset_request && ae_dev->ops->reset_event)
|
|
+ ae_dev->ops->reset_event(hdev->pdev, NULL);
|
|
}
|
|
|
|
static void hclge_errhand_service_task(struct hclge_dev *hdev)
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
|
|
index c8eb73b58326..1a262a247701 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
|
|
@@ -187,6 +187,7 @@ enum HLCGE_PORT_TYPE {
|
|
#define HCLGE_VECTOR0_IMP_RESET_INT_B 1
|
|
#define HCLGE_VECTOR0_IMP_CMDQ_ERR_B 4U
|
|
#define HCLGE_VECTOR0_IMP_RD_POISON_B 5U
|
|
+#define HCLGE_VECTOR0_ALL_MSIX_ERR_B 6U
|
|
|
|
#define HCLGE_MAC_DEFAULT_FRAME \
|
|
(ETH_HLEN + ETH_FCS_LEN + 2 * VLAN_HLEN + ETH_DATA_LEN)
|
|
--
|
|
2.34.1
|
|
|