diff options
author | Shiju Jose <shiju.jose@huawei.com> | 2018-10-19 20:15:26 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-10-22 19:31:13 -0700 |
commit | 5a9f0eac935b3edbcb3155301cc8aa1e22c04ccd (patch) | |
tree | 9ed292629ab0e9bd99ce1050f6c257aaa5224a19 | |
parent | aeb5e02aca91522733eb1db595ac607d30c87767 (diff) | |
download | linux-5a9f0eac935b3edbcb3155301cc8aa1e22c04ccd.tar.bz2 |
net: hns3: Add PCIe AER callback error_detected
Set of hw errors occurred in the HNS3 are reported to the
hns3 driver through PCIe AER and RAS.The error info will be
processed and appropriately recovered.
This patch adds error_detected callback and error processing.
Signed-off-by: Shiju Jose <shiju.jose@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
6 files changed, 101 insertions, 1 deletions
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index c3bd2a10bc7d..2af3a2dc72b2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -429,6 +429,7 @@ struct hnae3_ae_ops { struct ethtool_rxnfc *cmd, u32 *rule_locs); int (*restore_fd_rules)(struct hnae3_handle *handle); void (*enable_fd)(struct hnae3_handle *handle, bool enable); + pci_ers_result_t (*process_hw_error)(struct hnae3_ae_dev *ae_dev); }; struct hnae3_dcb_ops { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 76ce2f21178b..3c6fa39831e3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1771,6 +1771,35 @@ static void hns3_shutdown(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D3hot); } +static pci_ers_result_t hns3_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev); + pci_ers_result_t ret; + + dev_info(&pdev->dev, "PCI error detected, state(=%d)!!\n", state); + + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + + if (!ae_dev) { + dev_err(&pdev->dev, + "Can't recover - error happened during device init\n"); + return PCI_ERS_RESULT_NONE; + } + + if (ae_dev->ops->process_hw_error) + ret = ae_dev->ops->process_hw_error(ae_dev); + else + return PCI_ERS_RESULT_NONE; + + return ret; +} + +static const struct pci_error_handlers hns3_err_handler = { + .error_detected = hns3_error_detected, +}; + static struct pci_driver hns3_driver = { .name = hns3_driver_name, .id_table = hns3_pci_tbl, @@ -1778,6 +1807,7 @@ static struct pci_driver hns3_driver = { .remove = hns3_remove, .shutdown = hns3_shutdown, .sriov_configure = hns3_pci_sriov_configure, + .err_handler = &hns3_err_handler, }; /* set default feature to hns3 */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile b/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile index cb8ddd043476..580e81743681 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile @@ -6,6 +6,6 @@ ccflags-y := -Idrivers/net/ethernet/hisilicon/hns3 obj-$(CONFIG_HNS3_HCLGE) += hclge.o -hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o hclge_mbx.o +hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o hclge_mbx.o hclge_err.o hclge-$(CONFIG_HNS3_DCB) += hclge_dcb.o diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c new file mode 100644 index 000000000000..83aca6f89355 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (c) 2016-2017 Hisilicon Limited. */ + +#include "hclge_err.h" + +static const struct hclge_hw_blk hw_blk[] = { + { /* sentinel */ } +}; + +pci_ers_result_t hclge_process_ras_hw_error(struct hnae3_ae_dev *ae_dev) +{ + struct hclge_dev *hdev = ae_dev->priv; + struct device *dev = &hdev->pdev->dev; + u32 sts, val; + int i = 0; + + sts = hclge_read_dev(&hdev->hw, HCLGE_RAS_PF_OTHER_INT_STS_REG); + + /* Processing Non-fatal errors */ + if (sts & HCLGE_RAS_REG_NFE_MASK) { + val = (sts >> HCLGE_RAS_REG_NFE_SHIFT) & 0xFF; + i = 0; + while (hw_blk[i].name) { + if (!(hw_blk[i].msk & val)) { + i++; + continue; + } + dev_warn(dev, "%s ras non-fatal error identified\n", + hw_blk[i].name); + if (hw_blk[i].process_error) + hw_blk[i].process_error(hdev, + HCLGE_ERR_INT_RAS_NFE); + i++; + } + } + + return PCI_ERS_RESULT_NEED_RESET; +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h new file mode 100644 index 000000000000..ea1637cf63e1 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2016-2017 Hisilicon Limited. */ + +#ifndef __HCLGE_ERR_H +#define __HCLGE_ERR_H + +#include "hclge_main.h" + +#define HCLGE_RAS_PF_OTHER_INT_STS_REG 0x20B00 +#define HCLGE_RAS_REG_FE_MASK 0xFF +#define HCLGE_RAS_REG_NFE_MASK 0xFF00 +#define HCLGE_RAS_REG_NFE_SHIFT 8 + +enum hclge_err_int_type { + HCLGE_ERR_INT_MSIX = 0, + HCLGE_ERR_INT_RAS_CE = 1, + HCLGE_ERR_INT_RAS_NFE = 2, + HCLGE_ERR_INT_RAS_FE = 3, +}; + +struct hclge_hw_blk { + u32 msk; + const char *name; + void (*process_error)(struct hclge_dev *hdev, + enum hclge_err_int_type type); +}; + +pci_ers_result_t hclge_process_ras_hw_error(struct hnae3_ae_dev *ae_dev); +#endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 1bd83e8268fc..94d36787b4c9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -19,6 +19,7 @@ #include "hclge_mbx.h" #include "hclge_mdio.h" #include "hclge_tm.h" +#include "hclge_err.h" #include "hnae3.h" #define HCLGE_NAME "hclge" @@ -7312,6 +7313,7 @@ static const struct hnae3_ae_ops hclge_ops = { .get_fd_all_rules = hclge_get_all_rules, .restore_fd_rules = hclge_restore_fd_entries, .enable_fd = hclge_enable_fd, + .process_hw_error = hclge_process_ras_hw_error, }; static struct hnae3_ae_algo ae_algo = { |