numam-dpdk/drivers/net/hns3/hns3_intr.c
Hongbo Zheng f9f24ecd79 net/hns3: fix concurrent interrupt handling
Currently, if RAS interrupt and FLR occurred at the same time, FLR will
be detected and corresponding schedule state will be set during RAS
interrupt processing. However, the schedule state value will be
overridden in subsequent RAS processing, resulting in FLR processing
failure. This patch solves this problem.

Fixes: 2790c64647 ("net/hns3: support device reset")
Cc: stable@dpdk.org

Signed-off-by: Hongbo Zheng <zhenghongbo3@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
2021-04-13 11:13:41 +02:00

2648 lines
65 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2018-2021 HiSilicon Limited.
*/
#include <rte_alarm.h>
#include <rte_cycles.h>
#include <rte_ethdev.h>
#include <rte_io.h>
#include <rte_malloc.h>
#include "hns3_ethdev.h"
#include "hns3_logs.h"
#include "hns3_intr.h"
#include "hns3_regs.h"
#include "hns3_rxtx.h"
#define SWITCH_CONTEXT_US 10
#define HNS3_CHECK_MERGE_CNT(val) \
do { \
if (val) \
hw->reset.stats.merge_cnt++; \
} while (0)
static const char *reset_string[HNS3_MAX_RESET] = {
"none", "vf_func", "vf_pf_func", "vf_full", "flr",
"vf_global", "pf_func", "global", "IMP",
};
static const struct hns3_hw_error mac_afifo_tnl_int[] = {
{
.int_msk = BIT(0),
.msg = "egu_cge_afifo_ecc_1bit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(1),
.msg = "egu_cge_afifo_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(2),
.msg = "egu_lge_afifo_ecc_1bit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(3),
.msg = "egu_lge_afifo_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(4),
.msg = "cge_igu_afifo_ecc_1bit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(5),
.msg = "cge_igu_afifo_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(6),
.msg = "lge_igu_afifo_ecc_1bit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(7),
.msg = "lge_igu_afifo_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(8),
.msg = "cge_igu_afifo_overflow_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(9),
.msg = "lge_igu_afifo_overflow_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(10),
.msg = "egu_cge_afifo_underrun_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(11),
.msg = "egu_lge_afifo_underrun_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(12),
.msg = "egu_ge_afifo_underrun_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(13),
.msg = "ge_igu_afifo_overflow_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error ppu_mpf_abnormal_int_st1[] = {
{
.int_msk = 0xFFFFFFFF,
.msg = "rpu_rx_pkt_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error ppu_mpf_abnormal_int_st2_ras[] = {
{
.int_msk = BIT(13),
.msg = "rpu_rx_pkt_bit32_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(14),
.msg = "rpu_rx_pkt_bit33_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(15),
.msg = "rpu_rx_pkt_bit34_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(16),
.msg = "rpu_rx_pkt_bit35_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(17),
.msg = "rcb_tx_ring_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(18),
.msg = "rcb_rx_ring_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(19),
.msg = "rcb_tx_fbd_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(20),
.msg = "rcb_rx_ebd_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(21),
.msg = "rcb_tso_info_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(22),
.msg = "rcb_tx_int_info_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(23),
.msg = "rcb_rx_int_info_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(24),
.msg = "tpu_tx_pkt_0_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(25),
.msg = "tpu_tx_pkt_1_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(26),
.msg = "rd_bus_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(27),
.msg = "wr_bus_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(30),
.msg = "ooo_ecc_err_detect",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(31),
.msg = "ooo_ecc_err_multpl",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error ppu_mpf_abnormal_int_st2_msix[] = {
{
.int_msk = BIT(29),
.msg = "rx_q_search_miss",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error ssu_port_based_pf_int[] = {
{
.int_msk = BIT(0),
.msg = "roc_pkt_without_key_port",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(9),
.msg = "low_water_line_err_port",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error ppp_pf_abnormal_int[] = {
{
.int_msk = BIT(0),
.msg = "tx_vlan_tag_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(1),
.msg = "rss_list_tc_unassigned_queue_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error ppu_pf_abnormal_int_ras[] = {
{
.int_msk = BIT(3),
.msg = "tx_rd_fbd_poison",
.reset_level = HNS3_FUNC_RESET
}, {
.int_msk = BIT(4),
.msg = "rx_rd_ebd_poison",
.reset_level = HNS3_FUNC_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error ppu_pf_abnormal_int_msix[] = {
{
.int_msk = BIT(0),
.msg = "over_8bd_no_fe",
.reset_level = HNS3_FUNC_RESET
}, {
.int_msk = BIT(1),
.msg = "tso_mss_cmp_min_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(2),
.msg = "tso_mss_cmp_max_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(5),
.msg = "buf_wait_timeout",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error imp_tcm_ecc_int[] = {
{
.int_msk = BIT(1),
.msg = "imp_itcm0_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(3),
.msg = "imp_itcm1_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(5),
.msg = "imp_itcm2_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(7),
.msg = "imp_itcm3_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(9),
.msg = "imp_dtcm0_mem0_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(11),
.msg = "imp_dtcm0_mem1_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(13),
.msg = "imp_dtcm1_mem0_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(15),
.msg = "imp_dtcm1_mem1_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(17),
.msg = "imp_itcm4_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error cmdq_mem_ecc_int[] = {
{
.int_msk = BIT(1),
.msg = "cmdq_nic_rx_depth_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(3),
.msg = "cmdq_nic_tx_depth_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(5),
.msg = "cmdq_nic_rx_tail_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(7),
.msg = "cmdq_nic_tx_tail_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(9),
.msg = "cmdq_nic_rx_head_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(11),
.msg = "cmdq_nic_tx_head_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(13),
.msg = "cmdq_nic_rx_addr_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(15),
.msg = "cmdq_nic_tx_addr_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error tqp_int_ecc_int[] = {
{
.int_msk = BIT(6),
.msg = "tqp_int_cfg_even_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(7),
.msg = "tqp_int_cfg_odd_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(8),
.msg = "tqp_int_ctrl_even_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(9),
.msg = "tqp_int_ctrl_odd_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(10),
.msg = "tx_queue_scan_int_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(11),
.msg = "rx_queue_scan_int_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error imp_rd_poison_int[] = {
{
.int_msk = BIT(0),
.msg = "imp_rd_poison_int",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
#define HNS3_SSU_MEM_ECC_ERR(x) \
{ \
.int_msk = BIT(x), \
.msg = "ssu_mem" #x "_ecc_mbit_err", \
.reset_level = HNS3_GLOBAL_RESET \
}
static const struct hns3_hw_error ssu_ecc_multi_bit_int_0[] = {
HNS3_SSU_MEM_ECC_ERR(0),
HNS3_SSU_MEM_ECC_ERR(1),
HNS3_SSU_MEM_ECC_ERR(2),
HNS3_SSU_MEM_ECC_ERR(3),
HNS3_SSU_MEM_ECC_ERR(4),
HNS3_SSU_MEM_ECC_ERR(5),
HNS3_SSU_MEM_ECC_ERR(6),
HNS3_SSU_MEM_ECC_ERR(7),
HNS3_SSU_MEM_ECC_ERR(8),
HNS3_SSU_MEM_ECC_ERR(9),
HNS3_SSU_MEM_ECC_ERR(10),
HNS3_SSU_MEM_ECC_ERR(11),
HNS3_SSU_MEM_ECC_ERR(12),
HNS3_SSU_MEM_ECC_ERR(13),
HNS3_SSU_MEM_ECC_ERR(14),
HNS3_SSU_MEM_ECC_ERR(15),
HNS3_SSU_MEM_ECC_ERR(16),
HNS3_SSU_MEM_ECC_ERR(17),
HNS3_SSU_MEM_ECC_ERR(18),
HNS3_SSU_MEM_ECC_ERR(19),
HNS3_SSU_MEM_ECC_ERR(20),
HNS3_SSU_MEM_ECC_ERR(21),
HNS3_SSU_MEM_ECC_ERR(22),
HNS3_SSU_MEM_ECC_ERR(23),
HNS3_SSU_MEM_ECC_ERR(24),
HNS3_SSU_MEM_ECC_ERR(25),
HNS3_SSU_MEM_ECC_ERR(26),
HNS3_SSU_MEM_ECC_ERR(27),
HNS3_SSU_MEM_ECC_ERR(28),
HNS3_SSU_MEM_ECC_ERR(29),
HNS3_SSU_MEM_ECC_ERR(30),
HNS3_SSU_MEM_ECC_ERR(31),
{ .int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET}
};
static const struct hns3_hw_error ssu_ecc_multi_bit_int_1[] = {
{
.int_msk = BIT(0),
.msg = "ssu_mem32_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error ssu_common_ecc_int[] = {
{
.int_msk = BIT(0),
.msg = "buf_sum_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(1),
.msg = "ppp_mb_num_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = BIT(2),
.msg = "ppp_mbid_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(3),
.msg = "ppp_rlt_mac_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(4),
.msg = "ppp_rlt_host_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(5),
.msg = "cks_edit_position_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(6),
.msg = "cks_edit_condition_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(7),
.msg = "vlan_edit_condition_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(8),
.msg = "vlan_num_ot_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(9),
.msg = "vlan_num_in_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error igu_int[] = {
{
.int_msk = BIT(0),
.msg = "igu_rx_buf0_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(2),
.msg = "igu_rx_buf1_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error msix_ecc_int[] = {
{
.int_msk = BIT(1),
.msg = "msix_nic_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error ppp_mpf_abnormal_int_st1[] = {
{
.int_msk = BIT(0),
.msg = "vf_vlan_ad_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(1),
.msg = "umv_mcast_group_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(2),
.msg = "umv_key_mem0_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(3),
.msg = "umv_key_mem1_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(4),
.msg = "umv_key_mem2_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(5),
.msg = "umv_key_mem3_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(6),
.msg = "umv_ad_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(7),
.msg = "rss_tc_mode_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(8),
.msg = "rss_idt_mem0_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(9),
.msg = "rss_idt_mem1_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(10),
.msg = "rss_idt_mem2_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(11),
.msg = "rss_idt_mem3_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(12),
.msg = "rss_idt_mem4_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(13),
.msg = "rss_idt_mem5_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(14),
.msg = "rss_idt_mem6_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(15),
.msg = "rss_idt_mem7_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(16),
.msg = "rss_idt_mem8_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(17),
.msg = "rss_idt_mem9_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(18),
.msg = "rss_idt_mem10_ecc_m1bit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(19),
.msg = "rss_idt_mem11_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(20),
.msg = "rss_idt_mem12_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(21),
.msg = "rss_idt_mem13_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(22),
.msg = "rss_idt_mem14_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(23),
.msg = "rss_idt_mem15_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(24),
.msg = "port_vlan_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(25),
.msg = "mcast_linear_table_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(26),
.msg = "mcast_result_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(27),
.msg = "flow_director_ad_mem0_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(28),
.msg = "flow_director_ad_mem1_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(29),
.msg = "rx_vlan_tag_memory_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(30),
.msg = "Tx_UP_mapping_config_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error ppp_mpf_abnormal_int_st3[] = {
{
.int_msk = BIT(0),
.msg = "hfs_fifo_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(1),
.msg = "rslt_descr_fifo_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(2),
.msg = "tx_vlan_tag_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(3),
.msg = "FD_CN0_memory_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(4),
.msg = "FD_CN1_memory_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(5),
.msg = "GRO_AD_memory_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error ppu_mpf_abnormal_int_st3[] = {
{
.int_msk = BIT(4),
.msg = "gro_bd_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(5),
.msg = "gro_context_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(6),
.msg = "rx_stash_cfg_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(7),
.msg = "axi_rd_fbd_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error tm_sch_int[] = {
{
.int_msk = BIT(1),
.msg = "tm_sch_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(2),
.msg = "tm_sch_port_shap_sub_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(3),
.msg = "tm_sch_port_shap_sub_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(4),
.msg = "tm_sch_pg_pshap_sub_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(5),
.msg = "tm_sch_pg_pshap_sub_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(6),
.msg = "tm_sch_pg_cshap_sub_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(7),
.msg = "tm_sch_pg_cshap_sub_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(8),
.msg = "tm_sch_pri_pshap_sub_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(9),
.msg = "tm_sch_pri_pshap_sub_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(10),
.msg = "tm_sch_pri_cshap_sub_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(11),
.msg = "tm_sch_pri_cshap_sub_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(12),
.msg = "tm_sch_port_shap_offset_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(13),
.msg = "tm_sch_port_shap_offset_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(14),
.msg = "tm_sch_pg_pshap_offset_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(15),
.msg = "tm_sch_pg_pshap_offset_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(16),
.msg = "tm_sch_pg_cshap_offset_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(17),
.msg = "tm_sch_pg_cshap_offset_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(18),
.msg = "tm_sch_pri_pshap_offset_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(19),
.msg = "tm_sch_pri_pshap_offset_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(20),
.msg = "tm_sch_pri_cshap_offset_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(21),
.msg = "tm_sch_pri_cshap_offset_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(22),
.msg = "tm_sch_rq_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(23),
.msg = "tm_sch_rq_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(24),
.msg = "tm_sch_nq_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(25),
.msg = "tm_sch_nq_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(26),
.msg = "tm_sch_roce_up_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(27),
.msg = "tm_sch_roce_up_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(28),
.msg = "tm_sch_rcb_byte_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(29),
.msg = "tm_sch_rcb_byte_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(30),
.msg = "tm_sch_ssu_byte_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(31),
.msg = "tm_sch_ssu_byte_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error qcn_fifo_int[] = {
{
.int_msk = BIT(0),
.msg = "qcn_shap_gp0_sch_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(1),
.msg = "qcn_shap_gp0_sch_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(2),
.msg = "qcn_shap_gp1_sch_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(3),
.msg = "qcn_shap_gp1_sch_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(4),
.msg = "qcn_shap_gp2_sch_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(5),
.msg = "qcn_shap_gp2_sch_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(6),
.msg = "qcn_shap_gp3_sch_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(7),
.msg = "qcn_shap_gp3_sch_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(8),
.msg = "qcn_shap_gp0_offset_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(9),
.msg = "qcn_shap_gp0_offset_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(10),
.msg = "qcn_shap_gp1_offset_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(11),
.msg = "qcn_shap_gp1_offset_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(12),
.msg = "qcn_shap_gp2_offset_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(13),
.msg = "qcn_shap_gp2_offset_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(14),
.msg = "qcn_shap_gp3_offset_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(15),
.msg = "qcn_shap_gp3_offset_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(16),
.msg = "qcn_byte_info_fifo_rd_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(17),
.msg = "qcn_byte_info_fifo_wr_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error qcn_ecc_int[] = {
{
.int_msk = BIT(1),
.msg = "qcn_byte_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(3),
.msg = "qcn_time_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(5),
.msg = "qcn_fb_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(7),
.msg = "qcn_link_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(9),
.msg = "qcn_rate_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(11),
.msg = "qcn_tmplt_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(13),
.msg = "qcn_shap_cfg_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(15),
.msg = "qcn_gp0_barrel_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(17),
.msg = "qcn_gp1_barrel_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(19),
.msg = "qcn_gp2_barrel_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(21),
.msg = "qcn_gp3_barral_mem_ecc_mbit_err",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error ncsi_ecc_int[] = {
{
.int_msk = BIT(1),
.msg = "ncsi_tx_ecc_mbit_err",
.reset_level = HNS3_NONE_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error ssu_fifo_overflow_int[] = {
{
.int_msk = BIT(0),
.msg = "ig_mac_inf_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(1),
.msg = "ig_host_inf_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(2),
.msg = "ig_roc_buf_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(3),
.msg = "ig_host_data_fifo_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(4),
.msg = "ig_host_key_fifo_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(5),
.msg = "tx_qcn_fifo_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(6),
.msg = "rx_qcn_fifo_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(7),
.msg = "tx_pf_rd_fifo_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(8),
.msg = "rx_pf_rd_fifo_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(9),
.msg = "qm_eof_fifo_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(10),
.msg = "mb_rlt_fifo_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(11),
.msg = "dup_uncopy_fifo_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(12),
.msg = "dup_cnt_rd_fifo_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(13),
.msg = "dup_cnt_drop_fifo_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(14),
.msg = "dup_cnt_wrb_fifo_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(15),
.msg = "host_cmd_fifo_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(16),
.msg = "mac_cmd_fifo_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(17),
.msg = "host_cmd_bitmap_empty_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(18),
.msg = "mac_cmd_bitmap_empty_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(19),
.msg = "dup_bitmap_empty_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(20),
.msg = "out_queue_bitmap_empty_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(21),
.msg = "bank2_bitmap_empty_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(22),
.msg = "bank1_bitmap_empty_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(23),
.msg = "bank0_bitmap_empty_int",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error ssu_ets_tcg_int[] = {
{
.int_msk = BIT(0),
.msg = "ets_rd_int_rx_tcg",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(1),
.msg = "ets_wr_int_rx_tcg",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(2),
.msg = "ets_rd_int_tx_tcg",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(3),
.msg = "ets_wr_int_tx_tcg",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error igu_egu_tnl_int[] = {
{
.int_msk = BIT(0),
.msg = "rx_buf_overflow",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(1),
.msg = "rx_stp_fifo_overflow",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(2),
.msg = "rx_stp_fifo_underflow",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(3),
.msg = "tx_buf_overflow",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(4),
.msg = "tx_buf_underrun",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(5),
.msg = "rx_stp_buf_overflow",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error ssu_port_based_err_int[] = {
{
.int_msk = BIT(0),
.msg = "roc_pkt_without_key_port",
.reset_level = HNS3_FUNC_RESET
}, {
.int_msk = BIT(1),
.msg = "tpu_pkt_without_key_port",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(2),
.msg = "igu_pkt_without_key_port",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(3),
.msg = "roc_eof_mis_match_port",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(4),
.msg = "tpu_eof_mis_match_port",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(5),
.msg = "igu_eof_mis_match_port",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(6),
.msg = "roc_sof_mis_match_port",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(7),
.msg = "tpu_sof_mis_match_port",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(8),
.msg = "igu_sof_mis_match_port",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(11),
.msg = "ets_rd_int_rx_port",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(12),
.msg = "ets_wr_int_rx_port",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(13),
.msg = "ets_rd_int_tx_port",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = BIT(14),
.msg = "ets_wr_int_tx_port",
.reset_level = HNS3_GLOBAL_RESET
}, {
.int_msk = 0,
.msg = NULL,
.reset_level = HNS3_NONE_RESET
}
};
static const struct hns3_hw_error_desc mpf_ras_err_tbl[] = {
{
.desc_offset = 0,
.data_offset = 0,
.msg = "IMP_TCM_ECC_INT_STS",
.hw_err = imp_tcm_ecc_int
}, {
.desc_offset = 0,
.data_offset = 1,
.msg = "CMDQ_MEM_ECC_INT_STS",
.hw_err = cmdq_mem_ecc_int
}, {
.desc_offset = 0,
.data_offset = 2,
.msg = "IMP_RD_POISON_INT_STS",
.hw_err = imp_rd_poison_int
}, {
.desc_offset = 0,
.data_offset = 3,
.msg = "TQP_INT_ECC_INT_STS",
.hw_err = tqp_int_ecc_int
}, {
.desc_offset = 0,
.data_offset = 4,
.msg = "MSIX_ECC_INT_STS",
.hw_err = msix_ecc_int
}, {
.desc_offset = 2,
.data_offset = 2,
.msg = "SSU_ECC_MULTI_BIT_INT_0",
.hw_err = ssu_ecc_multi_bit_int_0
}, {
.desc_offset = 2,
.data_offset = 3,
.msg = "SSU_ECC_MULTI_BIT_INT_1",
.hw_err = ssu_ecc_multi_bit_int_1
}, {
.desc_offset = 2,
.data_offset = 4,
.msg = "SSU_COMMON_ERR_INT",
.hw_err = ssu_common_ecc_int
}, {
.desc_offset = 3,
.data_offset = 0,
.msg = "IGU_INT_STS",
.hw_err = igu_int
}, {
.desc_offset = 4,
.data_offset = 1,
.msg = "PPP_MPF_ABNORMAL_INT_ST1",
.hw_err = ppp_mpf_abnormal_int_st1
}, {
.desc_offset = 4,
.data_offset = 3,
.msg = "PPP_MPF_ABNORMAL_INT_ST3",
.hw_err = ppp_mpf_abnormal_int_st3
}, {
.desc_offset = 5,
.data_offset = 1,
.msg = "PPU_MPF_ABNORMAL_INT_ST1",
.hw_err = ppu_mpf_abnormal_int_st1
}, {
.desc_offset = 5,
.data_offset = 2,
.msg = "PPU_MPF_ABNORMAL_INT_ST2_RAS",
.hw_err = ppu_mpf_abnormal_int_st2_ras
}, {
.desc_offset = 5,
.data_offset = 3,
.msg = "PPU_MPF_ABNORMAL_INT_ST3",
.hw_err = ppu_mpf_abnormal_int_st3
}, {
.desc_offset = 6,
.data_offset = 0,
.msg = "TM_SCH_RINT",
.hw_err = tm_sch_int
}, {
.desc_offset = 7,
.data_offset = 0,
.msg = "QCN_FIFO_RINT",
.hw_err = qcn_fifo_int
}, {
.desc_offset = 7,
.data_offset = 1,
.msg = "QCN_ECC_RINT",
.hw_err = qcn_ecc_int
}, {
.desc_offset = 9,
.data_offset = 0,
.msg = "NCSI_ECC_INT_RPT",
.hw_err = ncsi_ecc_int
}, {
.desc_offset = 0,
.data_offset = 0,
.msg = NULL,
.hw_err = NULL
}
};
static const struct hns3_hw_error_desc pf_ras_err_tbl[] = {
{
.desc_offset = 0,
.data_offset = 0,
.msg = "SSU_PORT_BASED_ERR_INT_RAS",
.hw_err = ssu_port_based_err_int
}, {
.desc_offset = 0,
.data_offset = 1,
.msg = "SSU_FIFO_OVERFLOW_INT",
.hw_err = ssu_fifo_overflow_int
}, {
.desc_offset = 0,
.data_offset = 2,
.msg = "SSU_ETS_TCG_INT",
.hw_err = ssu_ets_tcg_int
}, {
.desc_offset = 1,
.data_offset = 0,
.msg = "IGU_EGU_TNL_INT_STS",
.hw_err = igu_egu_tnl_int
}, {
.desc_offset = 3,
.data_offset = 0,
.msg = "PPU_PF_ABNORMAL_INT_ST_RAS",
.hw_err = ppu_pf_abnormal_int_ras
}, {
.desc_offset = 0,
.data_offset = 0,
.msg = NULL,
.hw_err = NULL
}
};
static const struct hns3_hw_error_desc mpf_msix_err_tbl[] = {
{
.desc_offset = 1,
.data_offset = 0,
.msg = "MAC_AFIFO_TNL_INT_R",
.hw_err = mac_afifo_tnl_int
}, {
.desc_offset = 5,
.data_offset = 2,
.msg = "PPU_MPF_ABNORMAL_INT_ST2_MSIX",
.hw_err = ppu_mpf_abnormal_int_st2_msix
}, {
.desc_offset = 0,
.data_offset = 0,
.msg = NULL,
.hw_err = NULL
}
};
static const struct hns3_hw_error_desc pf_msix_err_tbl[] = {
{
.desc_offset = 0,
.data_offset = 0,
.msg = "SSU_PORT_BASED_ERR_INT_MSIX",
.hw_err = ssu_port_based_pf_int
}, {
.desc_offset = 2,
.data_offset = 0,
.msg = "PPP_PF_ABNORMAL_INT_ST0",
.hw_err = ppp_pf_abnormal_int
}, {
.desc_offset = 3,
.data_offset = 0,
.msg = "PPU_PF_ABNORMAL_INT_ST_MSIX",
.hw_err = ppu_pf_abnormal_int_msix
}, {
.desc_offset = 0,
.data_offset = 0,
.msg = NULL,
.hw_err = NULL
}
};
enum hns3_hw_err_type {
MPF_MSIX_ERR,
PF_MSIX_ERR,
MPF_RAS_ERR,
PF_RAS_ERR,
};
static int
hns3_config_ncsi_hw_err_int(struct hns3_adapter *hns, bool en)
{
struct hns3_hw *hw = &hns->hw;
struct hns3_cmd_desc desc;
int ret;
/* configure NCSI error interrupts */
hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_NCSI_INT_EN, false);
if (en)
desc.data[0] = rte_cpu_to_le_32(HNS3_NCSI_ERR_INT_EN);
ret = hns3_cmd_send(hw, &desc, 1);
if (ret)
hns3_err(hw, "fail to %s NCSI error interrupts, ret = %d",
en ? "enable" : "disable", ret);
return ret;
}
static int
enable_igu_egu_err_intr(struct hns3_adapter *hns, bool en)
{
struct hns3_hw *hw = &hns->hw;
struct hns3_cmd_desc desc;
int ret;
/* configure IGU,EGU error interrupts */
hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_IGU_COMMON_INT_EN, false);
if (en)
desc.data[0] = rte_cpu_to_le_32(HNS3_IGU_ERR_INT_ENABLE);
else
desc.data[0] = rte_cpu_to_le_32(HNS3_IGU_ERR_INT_DISABLE);
desc.data[1] = rte_cpu_to_le_32(HNS3_IGU_ERR_INT_EN_MASK);
ret = hns3_cmd_send(hw, &desc, 1);
if (ret) {
hns3_err(hw, "fail to %s IGU common interrupts, ret = %d",
en ? "enable" : "disable", ret);
return ret;
}
hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_IGU_EGU_TNL_INT_EN, false);
if (en)
desc.data[0] = rte_cpu_to_le_32(HNS3_IGU_TNL_ERR_INT_EN);
desc.data[1] = rte_cpu_to_le_32(HNS3_IGU_TNL_ERR_INT_EN_MASK);
ret = hns3_cmd_send(hw, &desc, 1);
if (ret) {
hns3_err(hw, "fail to %s IGU-EGU TNL interrupts, ret = %d",
en ? "enable" : "disable", ret);
return ret;
}
return hns3_config_ncsi_hw_err_int(hns, en);
}
static int
config_ppp_err_intr(struct hns3_adapter *hns, uint32_t cmd, bool en)
{
struct hns3_hw *hw = &hns->hw;
struct hns3_cmd_desc desc[2];
int ret;
/* configure PPP error interrupts */
hns3_cmd_setup_basic_desc(&desc[0], cmd, false);
desc[0].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT);
hns3_cmd_setup_basic_desc(&desc[1], cmd, false);
if (cmd == HNS3_OPC_PPP_CMD0_INT_CMD) {
if (en) {
desc[0].data[0] =
rte_cpu_to_le_32(HNS3_PPP_MPF_ECC_ERR_INT0_EN);
desc[0].data[1] =
rte_cpu_to_le_32(HNS3_PPP_MPF_ECC_ERR_INT1_EN);
desc[0].data[4] =
rte_cpu_to_le_32(HNS3_PPP_PF_ERR_INT_EN);
}
desc[1].data[0] =
rte_cpu_to_le_32(HNS3_PPP_MPF_ECC_ERR_INT0_EN_MASK);
desc[1].data[1] =
rte_cpu_to_le_32(HNS3_PPP_MPF_ECC_ERR_INT1_EN_MASK);
desc[1].data[2] =
rte_cpu_to_le_32(HNS3_PPP_PF_ERR_INT_EN_MASK);
} else if (cmd == HNS3_OPC_PPP_CMD1_INT_CMD) {
if (en) {
desc[0].data[0] =
rte_cpu_to_le_32(HNS3_PPP_MPF_ECC_ERR_INT2_EN);
desc[0].data[1] =
rte_cpu_to_le_32(HNS3_PPP_MPF_ECC_ERR_INT3_EN);
}
desc[1].data[0] =
rte_cpu_to_le_32(HNS3_PPP_MPF_ECC_ERR_INT2_EN_MASK);
desc[1].data[1] =
rte_cpu_to_le_32(HNS3_PPP_MPF_ECC_ERR_INT3_EN_MASK);
}
ret = hns3_cmd_send(hw, &desc[0], 2);
if (ret)
hns3_err(hw, "fail to %s PPP error int, ret = %d",
en ? "enable" : "disable", ret);
return ret;
}
static int
enable_ppp_err_intr(struct hns3_adapter *hns, bool en)
{
int ret;
ret = config_ppp_err_intr(hns, HNS3_OPC_PPP_CMD0_INT_CMD, en);
if (ret)
return ret;
return config_ppp_err_intr(hns, HNS3_OPC_PPP_CMD1_INT_CMD, en);
}
static int
enable_ssu_err_intr(struct hns3_adapter *hns, bool en)
{
struct hns3_hw *hw = &hns->hw;
struct hns3_cmd_desc desc[2];
int ret;
/* configure SSU ecc error interrupts */
hns3_cmd_setup_basic_desc(&desc[0], HNS3_OPC_SSU_ECC_INT_CMD, false);
desc[0].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT);
hns3_cmd_setup_basic_desc(&desc[1], HNS3_OPC_SSU_ECC_INT_CMD, false);
if (en) {
desc[0].data[0] =
rte_cpu_to_le_32(HNS3_SSU_1BIT_ECC_ERR_INT_EN);
desc[0].data[1] =
rte_cpu_to_le_32(HNS3_SSU_MULTI_BIT_ECC_ERR_INT_EN);
desc[0].data[4] =
rte_cpu_to_le_32(HNS3_SSU_BIT32_ECC_ERR_INT_EN);
}
desc[1].data[0] = rte_cpu_to_le_32(HNS3_SSU_1BIT_ECC_ERR_INT_EN_MASK);
desc[1].data[1] =
rte_cpu_to_le_32(HNS3_SSU_MULTI_BIT_ECC_ERR_INT_EN_MASK);
desc[1].data[2] = rte_cpu_to_le_32(HNS3_SSU_BIT32_ECC_ERR_INT_EN_MASK);
ret = hns3_cmd_send(hw, &desc[0], 2);
if (ret) {
hns3_err(hw, "fail to %s SSU ECC error interrupt, ret = %d",
en ? "enable" : "disable", ret);
return ret;
}
/* configure SSU common error interrupts */
hns3_cmd_setup_basic_desc(&desc[0], HNS3_OPC_SSU_COMMON_INT_CMD, false);
desc[0].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT);
hns3_cmd_setup_basic_desc(&desc[1], HNS3_OPC_SSU_COMMON_INT_CMD, false);
if (en) {
desc[0].data[0] = rte_cpu_to_le_32(HNS3_SSU_COMMON_INT_EN);
desc[0].data[1] =
rte_cpu_to_le_32(HNS3_SSU_PORT_BASED_ERR_INT_EN);
desc[0].data[2] =
rte_cpu_to_le_32(HNS3_SSU_FIFO_OVERFLOW_ERR_INT_EN);
}
desc[1].data[0] = rte_cpu_to_le_32(HNS3_SSU_COMMON_INT_EN_MASK |
HNS3_SSU_PORT_BASED_ERR_INT_EN_MASK);
desc[1].data[1] =
rte_cpu_to_le_32(HNS3_SSU_FIFO_OVERFLOW_ERR_INT_EN_MASK);
ret = hns3_cmd_send(hw, &desc[0], 2);
if (ret)
hns3_err(hw, "fail to %s SSU COMMON error intr, ret = %d",
en ? "enable" : "disable", ret);
return ret;
}
void
hns3_config_mac_tnl_int(struct hns3_hw *hw, bool en)
{
struct hns3_cmd_desc desc;
int ret;
hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_MAC_TNL_INT_EN, false);
if (en)
desc.data[0] = rte_cpu_to_le_32(HNS3_MAC_TNL_INT_EN);
else
desc.data[0] = 0;
desc.data[1] = rte_cpu_to_le_32(HNS3_MAC_TNL_INT_EN_MASK);
ret = hns3_cmd_send(hw, &desc, 1);
if (ret)
hns3_err(hw, "fail to %s mac tnl intr, ret = %d",
en ? "enable" : "disable", ret);
}
static int
config_ppu_err_intrs(struct hns3_adapter *hns, uint32_t cmd, bool en)
{
struct hns3_hw *hw = &hns->hw;
struct hns3_cmd_desc desc[2];
int num = 1;
/* configure PPU error interrupts */
switch (cmd) {
case HNS3_OPC_PPU_MPF_ECC_INT_CMD:
hns3_cmd_setup_basic_desc(&desc[0], cmd, false);
desc[0].flag |= HNS3_CMD_FLAG_NEXT;
hns3_cmd_setup_basic_desc(&desc[1], cmd, false);
if (en) {
desc[0].data[0] = HNS3_PPU_MPF_ABNORMAL_INT0_EN;
desc[0].data[1] = HNS3_PPU_MPF_ABNORMAL_INT1_EN;
desc[1].data[3] = HNS3_PPU_MPF_ABNORMAL_INT3_EN;
desc[1].data[4] = HNS3_PPU_MPF_ABNORMAL_INT2_EN;
}
desc[1].data[0] = HNS3_PPU_MPF_ABNORMAL_INT0_EN_MASK;
desc[1].data[1] = HNS3_PPU_MPF_ABNORMAL_INT1_EN_MASK;
desc[1].data[2] = HNS3_PPU_MPF_ABNORMAL_INT2_EN_MASK;
desc[1].data[3] |= HNS3_PPU_MPF_ABNORMAL_INT3_EN_MASK;
num = 2;
break;
case HNS3_OPC_PPU_MPF_OTHER_INT_CMD:
hns3_cmd_setup_basic_desc(&desc[0], cmd, false);
if (en)
desc[0].data[0] = HNS3_PPU_MPF_ABNORMAL_INT2_EN2;
desc[0].data[2] = HNS3_PPU_MPF_ABNORMAL_INT2_EN2_MASK;
break;
case HNS3_OPC_PPU_PF_OTHER_INT_CMD:
hns3_cmd_setup_basic_desc(&desc[0], cmd, false);
if (en)
desc[0].data[0] = HNS3_PPU_PF_ABNORMAL_INT_EN;
desc[0].data[2] = HNS3_PPU_PF_ABNORMAL_INT_EN_MASK;
break;
default:
hns3_err(hw,
"Invalid cmd(%u) to configure PPU error interrupts.",
cmd);
return -EINVAL;
}
return hns3_cmd_send(hw, &desc[0], num);
}
static int
enable_ppu_err_intr(struct hns3_adapter *hns, bool en)
{
struct hns3_hw *hw = &hns->hw;
int ret;
ret = config_ppu_err_intrs(hns, HNS3_OPC_PPU_MPF_ECC_INT_CMD, en);
if (ret) {
hns3_err(hw, "fail to %s PPU MPF ECC error intr, ret = %d",
en ? "enable" : "disable", ret);
return ret;
}
ret = config_ppu_err_intrs(hns, HNS3_OPC_PPU_MPF_OTHER_INT_CMD, en);
if (ret) {
hns3_err(hw, "fail to %s PPU MPF other intr, ret = %d",
en ? "enable" : "disable", ret);
return ret;
}
ret = config_ppu_err_intrs(hns, HNS3_OPC_PPU_PF_OTHER_INT_CMD, en);
if (ret)
hns3_err(hw, "fail to %s PPU PF error interrupts, ret = %d",
en ? "enable" : "disable", ret);
return ret;
}
static int
enable_tm_err_intr(struct hns3_adapter *hns, bool en)
{
struct hns3_hw *hw = &hns->hw;
struct hns3_cmd_desc desc;
int ret;
/* configure TM SCH error interrupts */
hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_TM_SCH_ECC_INT_EN, false);
if (en)
desc.data[0] = rte_cpu_to_le_32(HNS3_TM_SCH_ECC_ERR_INT_EN);
ret = hns3_cmd_send(hw, &desc, 1);
if (ret) {
hns3_err(hw, "fail to %s TM SCH interrupts, ret = %d",
en ? "enable" : "disable", ret);
return ret;
}
/* configure TM QCN hw errors */
hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_TM_QCN_MEM_INT_CFG, true);
ret = hns3_cmd_send(hw, &desc, 1);
if (ret) {
hns3_err(hw, "fail to read TM QCN CFG status, ret = %d\n", ret);
return ret;
}
hns3_cmd_reuse_desc(&desc, false);
if (en)
desc.data[1] = rte_cpu_to_le_32(HNS3_TM_QCN_MEM_ERR_INT_EN);
ret = hns3_cmd_send(hw, &desc, 1);
if (ret)
hns3_err(hw, "fail to %s TM QCN mem errors, ret = %d\n",
en ? "enable" : "disable", ret);
return ret;
}
static int
enable_common_err_intr(struct hns3_adapter *hns, bool en)
{
struct hns3_hw *hw = &hns->hw;
struct hns3_cmd_desc desc[2];
int ret;
/* configure common error interrupts */
hns3_cmd_setup_basic_desc(&desc[0], HNS3_OPC_COMMON_ECC_INT_CFG, false);
desc[0].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT);
hns3_cmd_setup_basic_desc(&desc[1], HNS3_OPC_COMMON_ECC_INT_CFG, false);
if (en) {
desc[0].data[0] =
rte_cpu_to_le_32(HNS3_IMP_TCM_ECC_ERR_INT_EN);
desc[0].data[2] =
rte_cpu_to_le_32(HNS3_CMDQ_NIC_ECC_ERR_INT_EN);
desc[0].data[3] =
rte_cpu_to_le_32(HNS3_IMP_RD_POISON_ERR_INT_EN);
desc[0].data[4] =
rte_cpu_to_le_32(HNS3_TQP_ECC_ERR_INT_EN |
HNS3_MSIX_SRAM_ECC_ERR_INT_EN);
desc[0].data[5] =
rte_cpu_to_le_32(HNS3_IMP_ITCM4_ECC_ERR_INT_EN);
}
desc[1].data[0] = rte_cpu_to_le_32(HNS3_IMP_TCM_ECC_ERR_INT_EN_MASK);
desc[1].data[2] = rte_cpu_to_le_32(HNS3_CMDQ_NIC_ECC_ERR_INT_EN_MASK);
desc[1].data[3] = rte_cpu_to_le_32(HNS3_IMP_RD_POISON_ERR_INT_EN_MASK);
desc[1].data[4] = rte_cpu_to_le_32(HNS3_TQP_ECC_ERR_INT_EN_MASK |
HNS3_MSIX_SRAM_ECC_ERR_INT_EN_MASK);
desc[1].data[5] = rte_cpu_to_le_32(HNS3_IMP_ITCM4_ECC_ERR_INT_EN_MASK);
ret = hns3_cmd_send(hw, &desc[0], RTE_DIM(desc));
if (ret)
hns3_err(hw, "fail to %s common err interrupts, ret = %d\n",
en ? "enable" : "disable", ret);
return ret;
}
static int
enable_mac_err_intr(struct hns3_adapter *hns, bool en)
{
struct hns3_hw *hw = &hns->hw;
struct hns3_cmd_desc desc;
int ret;
/* configure MAC common error interrupts */
hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_MAC_COMMON_INT_EN, false);
if (en)
desc.data[0] = rte_cpu_to_le_32(HNS3_MAC_COMMON_ERR_INT_EN);
desc.data[1] = rte_cpu_to_le_32(HNS3_MAC_COMMON_ERR_INT_EN_MASK);
ret = hns3_cmd_send(hw, &desc, 1);
if (ret)
hns3_err(hw, "fail to %s MAC COMMON error intr: %d",
en ? "enable" : "disable", ret);
return ret;
}
static const struct hns3_hw_blk hw_blk[] = {
{
.name = "IGU_EGU",
.enable_err_intr = enable_igu_egu_err_intr,
},
{
.name = "PPP",
.enable_err_intr = enable_ppp_err_intr,
},
{
.name = "SSU",
.enable_err_intr = enable_ssu_err_intr,
},
{
.name = "PPU",
.enable_err_intr = enable_ppu_err_intr,
},
{
.name = "TM",
.enable_err_intr = enable_tm_err_intr,
},
{
.name = "COMMON",
.enable_err_intr = enable_common_err_intr,
},
{
.name = "MAC",
.enable_err_intr = enable_mac_err_intr,
},
{
.name = NULL,
.enable_err_intr = NULL,
}
};
int
hns3_enable_hw_error_intr(struct hns3_adapter *hns, bool en)
{
const struct hns3_hw_blk *module = hw_blk;
int ret = 0;
while (module->enable_err_intr) {
ret = module->enable_err_intr(hns, en);
if (ret)
return ret;
module++;
}
return ret;
}
static enum hns3_reset_level
hns3_find_highest_level(struct hns3_adapter *hns, const char *reg,
const struct hns3_hw_error *err, uint32_t err_sts)
{
enum hns3_reset_level reset_level = HNS3_FUNC_RESET;
struct hns3_hw *hw = &hns->hw;
bool need_reset = false;
while (err->msg) {
if (err->int_msk & err_sts) {
hns3_warn(hw, "%s %s found [error status=0x%x]",
reg, err->msg, err_sts);
if (err->reset_level != HNS3_NONE_RESET &&
err->reset_level >= reset_level) {
reset_level = err->reset_level;
need_reset = true;
}
}
err++;
}
if (need_reset)
return reset_level;
else
return HNS3_NONE_RESET;
}
static int
query_num_bds(struct hns3_hw *hw, bool is_ras, uint32_t *mpf_bd_num,
uint32_t *pf_bd_num)
{
uint32_t mpf_min_bd_num, pf_min_bd_num;
uint32_t mpf_bd_num_val, pf_bd_num_val;
enum hns3_opcode_type opcode;
struct hns3_cmd_desc desc;
int ret;
if (is_ras) {
opcode = HNS3_OPC_QUERY_RAS_INT_STS_BD_NUM;
mpf_min_bd_num = HNS3_MPF_RAS_INT_MIN_BD_NUM;
pf_min_bd_num = HNS3_PF_RAS_INT_MIN_BD_NUM;
} else {
opcode = HNS3_OPC_QUERY_MSIX_INT_STS_BD_NUM;
mpf_min_bd_num = HNS3_MPF_MSIX_INT_MIN_BD_NUM;
pf_min_bd_num = HNS3_PF_MSIX_INT_MIN_BD_NUM;
}
hns3_cmd_setup_basic_desc(&desc, opcode, true);
ret = hns3_cmd_send(hw, &desc, 1);
if (ret) {
hns3_err(hw, "query num bds in msix failed, ret = %d", ret);
return ret;
}
mpf_bd_num_val = rte_le_to_cpu_32(desc.data[0]);
pf_bd_num_val = rte_le_to_cpu_32(desc.data[1]);
if (mpf_bd_num_val < mpf_min_bd_num || pf_bd_num_val < pf_min_bd_num) {
hns3_err(hw, "error bd num: mpf(%u), min_mpf(%u), "
"pf(%u), min_pf(%u)\n", mpf_bd_num_val, mpf_min_bd_num,
pf_bd_num_val, pf_min_bd_num);
return -EINVAL;
}
*mpf_bd_num = mpf_bd_num_val;
*pf_bd_num = pf_bd_num_val;
return 0;
}
void
hns3_intr_unregister(const struct rte_intr_handle *hdl,
rte_intr_callback_fn cb_fn, void *cb_arg)
{
int retry_cnt = 0;
int ret;
do {
ret = rte_intr_callback_unregister(hdl, cb_fn, cb_arg);
if (ret >= 0) {
break;
} else if (ret != -EAGAIN) {
PMD_INIT_LOG(ERR, "Failed to unregister intr: %d", ret);
break;
}
rte_delay_ms(HNS3_INTR_UNREG_FAIL_DELAY_MS);
} while (retry_cnt++ < HNS3_INTR_UNREG_FAIL_RETRY_CNT);
}
static uint32_t
hns3_get_hw_error_status(struct hns3_cmd_desc *desc, uint8_t desc_offset,
uint8_t data_offset)
{
uint32_t status;
uint32_t *desc_data;
if (desc_offset == 0)
status = rte_le_to_cpu_32(desc[desc_offset].data[data_offset]);
else {
desc_data = (uint32_t *)&desc[desc_offset];
status = rte_le_to_cpu_32(*(desc_data + data_offset));
}
return status;
}
static int
hns3_handle_hw_error(struct hns3_adapter *hns, struct hns3_cmd_desc *desc,
int num, uint64_t *levels, enum hns3_hw_err_type err_type)
{
const struct hns3_hw_error_desc *err = pf_ras_err_tbl;
enum hns3_opcode_type opcode;
enum hns3_reset_level req_level;
struct hns3_hw *hw = &hns->hw;
uint32_t status;
int ret;
switch (err_type) {
case MPF_MSIX_ERR:
err = mpf_msix_err_tbl;
opcode = HNS3_OPC_QUERY_CLEAR_ALL_MPF_MSIX_INT;
break;
case PF_MSIX_ERR:
err = pf_msix_err_tbl;
opcode = HNS3_OPC_QUERY_CLEAR_ALL_PF_MSIX_INT;
break;
case MPF_RAS_ERR:
err = mpf_ras_err_tbl;
opcode = HNS3_OPC_QUERY_CLEAR_MPF_RAS_INT;
break;
case PF_RAS_ERR:
err = pf_ras_err_tbl;
opcode = HNS3_OPC_QUERY_CLEAR_PF_RAS_INT;
break;
default:
hns3_err(hw, "error hardware err_type = %d\n", err_type);
return -EINVAL;
}
/* query all hardware errors */
hns3_cmd_setup_basic_desc(&desc[0], opcode, true);
ret = hns3_cmd_send(hw, &desc[0], num);
if (ret) {
hns3_err(hw, "query hw err int 0x%x cmd failed, ret = %d\n",
opcode, ret);
return ret;
}
/* traverses the error table and process based on the error type */
while (err->msg) {
status = hns3_get_hw_error_status(desc, err->desc_offset,
err->data_offset);
if (status) {
/*
* set the reset_level or non_reset flag based on
* the error type and add error statistics. here just
* set the flag, the actual reset action is in
* hns3_msix_process.
*/
req_level = hns3_find_highest_level(hns, err->msg,
err->hw_err,
status);
hns3_atomic_set_bit(req_level, levels);
}
err++;
}
/* clear all hardware errors */
hns3_cmd_reuse_desc(&desc[0], false);
ret = hns3_cmd_send(hw, &desc[0], num);
if (ret)
hns3_err(hw, "clear all hw err int cmd failed, ret = %d\n",
ret);
return ret;
}
void
hns3_handle_msix_error(struct hns3_adapter *hns, uint64_t *levels)
{
uint32_t mpf_bd_num, pf_bd_num, bd_num;
struct hns3_hw *hw = &hns->hw;
struct hns3_cmd_desc *desc;
int ret;
/* query the number of bds for the MSIx int status */
ret = query_num_bds(hw, false, &mpf_bd_num, &pf_bd_num);
if (ret) {
hns3_err(hw, "fail to query msix int status bd num: ret = %d",
ret);
return;
}
bd_num = RTE_MAX(mpf_bd_num, pf_bd_num);
desc = rte_zmalloc(NULL, bd_num * sizeof(struct hns3_cmd_desc), 0);
if (desc == NULL) {
hns3_err(hw,
"fail to zmalloc desc for handling msix error, size = %zu",
bd_num * sizeof(struct hns3_cmd_desc));
return;
}
/* handle all main PF MSIx errors */
ret = hns3_handle_hw_error(hns, desc, mpf_bd_num, levels, MPF_MSIX_ERR);
if (ret) {
hns3_err(hw, "fail to handle all main pf msix errors, ret = %d",
ret);
goto out;
}
memset(desc, 0, bd_num * sizeof(struct hns3_cmd_desc));
/* handle all PF MSIx errors */
ret = hns3_handle_hw_error(hns, desc, pf_bd_num, levels, PF_MSIX_ERR);
if (ret) {
hns3_err(hw, "fail to handle all pf msix errors, ret = %d",
ret);
goto out;
}
out:
rte_free(desc);
}
void
hns3_handle_ras_error(struct hns3_adapter *hns, uint64_t *levels)
{
uint32_t mpf_bd_num, pf_bd_num, bd_num;
struct hns3_hw *hw = &hns->hw;
struct hns3_cmd_desc *desc;
uint32_t status;
int ret;
status = hns3_read_dev(hw, HNS3_RAS_PF_OTHER_INT_STS_REG);
if ((status & HNS3_RAS_REG_NFE_MASK) == 0)
return;
/* query the number of bds for the RAS int status */
ret = query_num_bds(hw, true, &mpf_bd_num, &pf_bd_num);
if (ret) {
hns3_err(hw, "fail to query ras int status bd num: ret = %d",
ret);
return;
}
bd_num = RTE_MAX(mpf_bd_num, pf_bd_num);
desc = rte_zmalloc(NULL, bd_num * sizeof(struct hns3_cmd_desc), 0);
if (desc == NULL) {
hns3_err(hw,
"fail to zmalloc desc for handing ras error, size = %zu",
bd_num * sizeof(struct hns3_cmd_desc));
return;
}
/* handle all main PF RAS errors */
ret = hns3_handle_hw_error(hns, desc, mpf_bd_num, levels, MPF_RAS_ERR);
if (ret) {
hns3_err(hw, "fail to handle all main pf ras errors, ret = %d",
ret);
goto out;
}
memset(desc, 0, bd_num * sizeof(struct hns3_cmd_desc));
/* handle all PF RAS errors */
ret = hns3_handle_hw_error(hns, desc, pf_bd_num, levels, PF_RAS_ERR);
if (ret) {
hns3_err(hw, "fail to handle all pf ras errors, ret = %d", ret);
goto out;
}
out:
rte_free(desc);
}
int
hns3_reset_init(struct hns3_hw *hw)
{
rte_spinlock_init(&hw->lock);
hw->reset.level = HNS3_NONE_RESET;
hw->reset.stage = RESET_STAGE_NONE;
hw->reset.request = 0;
hw->reset.pending = 0;
hw->reset.resetting = 0;
__atomic_store_n(&hw->reset.disable_cmd, 0, __ATOMIC_RELAXED);
hw->reset.wait_data = rte_zmalloc("wait_data",
sizeof(struct hns3_wait_data), 0);
if (!hw->reset.wait_data) {
PMD_INIT_LOG(ERR, "Failed to allocate memory for wait_data");
return -ENOMEM;
}
return 0;
}
void
hns3_schedule_reset(struct hns3_adapter *hns)
{
struct hns3_hw *hw = &hns->hw;
/* Reschedule the reset process after successful initialization */
if (hw->adapter_state == HNS3_NIC_UNINITIALIZED) {
__atomic_store_n(&hw->reset.schedule, SCHEDULE_PENDING,
__ATOMIC_RELAXED);
return;
}
if (hw->adapter_state >= HNS3_NIC_CLOSED)
return;
/* Schedule restart alarm if it is not scheduled yet */
if (__atomic_load_n(&hw->reset.schedule, __ATOMIC_RELAXED) ==
SCHEDULE_REQUESTED)
return;
if (__atomic_load_n(&hw->reset.schedule, __ATOMIC_RELAXED) ==
SCHEDULE_DEFERRED)
rte_eal_alarm_cancel(hw->reset.ops->reset_service, hns);
else
__atomic_store_n(&hw->reset.schedule, SCHEDULE_REQUESTED,
__ATOMIC_RELAXED);
rte_eal_alarm_set(SWITCH_CONTEXT_US, hw->reset.ops->reset_service, hns);
}
void
hns3_schedule_delayed_reset(struct hns3_adapter *hns)
{
#define DEFERRED_SCHED_US (3 * MSEC_PER_SEC * USEC_PER_MSEC)
struct hns3_hw *hw = &hns->hw;
/* Do nothing if it is uninited or closed */
if (hw->adapter_state == HNS3_NIC_UNINITIALIZED ||
hw->adapter_state >= HNS3_NIC_CLOSED) {
return;
}
if (__atomic_load_n(&hw->reset.schedule, __ATOMIC_RELAXED) !=
SCHEDULE_NONE)
return;
__atomic_store_n(&hw->reset.schedule, SCHEDULE_DEFERRED,
__ATOMIC_RELAXED);
rte_eal_alarm_set(DEFERRED_SCHED_US, hw->reset.ops->reset_service, hns);
}
void
hns3_wait_callback(void *param)
{
struct hns3_wait_data *data = (struct hns3_wait_data *)param;
struct hns3_adapter *hns = data->hns;
struct hns3_hw *hw = &hns->hw;
uint64_t msec;
bool done;
data->count--;
if (data->check_completion) {
/*
* Check if the current time exceeds the deadline
* or a pending reset coming, or reset during close.
*/
msec = get_timeofday_ms();
if (msec > data->end_ms || is_reset_pending(hns) ||
hw->adapter_state == HNS3_NIC_CLOSING) {
done = false;
data->count = 0;
} else
done = data->check_completion(hw);
} else
done = true;
if (!done && data->count > 0) {
rte_eal_alarm_set(data->interval, hns3_wait_callback, data);
return;
}
if (done)
data->result = HNS3_WAIT_SUCCESS;
else {
hns3_err(hw, "%s wait timeout at stage %d",
reset_string[hw->reset.level], hw->reset.stage);
data->result = HNS3_WAIT_TIMEOUT;
}
hns3_schedule_reset(hns);
}
void
hns3_notify_reset_ready(struct hns3_hw *hw, bool enable)
{
uint32_t reg_val;
reg_val = hns3_read_dev(hw, HNS3_CMDQ_TX_DEPTH_REG);
if (enable)
reg_val |= HNS3_NIC_SW_RST_RDY;
else
reg_val &= ~HNS3_NIC_SW_RST_RDY;
hns3_write_dev(hw, HNS3_CMDQ_TX_DEPTH_REG, reg_val);
}
int
hns3_reset_req_hw_reset(struct hns3_adapter *hns)
{
struct hns3_hw *hw = &hns->hw;
if (hw->reset.wait_data->result == HNS3_WAIT_UNKNOWN) {
hw->reset.wait_data->hns = hns;
hw->reset.wait_data->check_completion = NULL;
hw->reset.wait_data->interval = HNS3_RESET_SYNC_US;
hw->reset.wait_data->count = 1;
hw->reset.wait_data->result = HNS3_WAIT_REQUEST;
rte_eal_alarm_set(hw->reset.wait_data->interval,
hns3_wait_callback, hw->reset.wait_data);
return -EAGAIN;
} else if (hw->reset.wait_data->result == HNS3_WAIT_REQUEST)
return -EAGAIN;
/* inform hardware that preparatory work is done */
hns3_notify_reset_ready(hw, true);
return 0;
}
static void
hns3_clear_reset_level(struct hns3_hw *hw, uint64_t *levels)
{
uint64_t merge_cnt = hw->reset.stats.merge_cnt;
int64_t tmp;
switch (hw->reset.level) {
case HNS3_IMP_RESET:
hns3_atomic_clear_bit(HNS3_IMP_RESET, levels);
tmp = hns3_test_and_clear_bit(HNS3_GLOBAL_RESET, levels);
HNS3_CHECK_MERGE_CNT(tmp);
tmp = hns3_test_and_clear_bit(HNS3_FUNC_RESET, levels);
HNS3_CHECK_MERGE_CNT(tmp);
break;
case HNS3_GLOBAL_RESET:
hns3_atomic_clear_bit(HNS3_GLOBAL_RESET, levels);
tmp = hns3_test_and_clear_bit(HNS3_FUNC_RESET, levels);
HNS3_CHECK_MERGE_CNT(tmp);
break;
case HNS3_FUNC_RESET:
hns3_atomic_clear_bit(HNS3_FUNC_RESET, levels);
break;
case HNS3_VF_RESET:
hns3_atomic_clear_bit(HNS3_VF_RESET, levels);
tmp = hns3_test_and_clear_bit(HNS3_VF_PF_FUNC_RESET, levels);
HNS3_CHECK_MERGE_CNT(tmp);
tmp = hns3_test_and_clear_bit(HNS3_VF_FUNC_RESET, levels);
HNS3_CHECK_MERGE_CNT(tmp);
break;
case HNS3_VF_FULL_RESET:
hns3_atomic_clear_bit(HNS3_VF_FULL_RESET, levels);
tmp = hns3_test_and_clear_bit(HNS3_VF_FUNC_RESET, levels);
HNS3_CHECK_MERGE_CNT(tmp);
break;
case HNS3_VF_PF_FUNC_RESET:
hns3_atomic_clear_bit(HNS3_VF_PF_FUNC_RESET, levels);
tmp = hns3_test_and_clear_bit(HNS3_VF_FUNC_RESET, levels);
HNS3_CHECK_MERGE_CNT(tmp);
break;
case HNS3_VF_FUNC_RESET:
hns3_atomic_clear_bit(HNS3_VF_FUNC_RESET, levels);
break;
case HNS3_FLR_RESET:
hns3_atomic_clear_bit(HNS3_FLR_RESET, levels);
break;
case HNS3_NONE_RESET:
default:
return;
};
if (merge_cnt != hw->reset.stats.merge_cnt)
hns3_warn(hw,
"No need to do low-level reset after %s reset. "
"merge cnt: %" PRIx64 " total merge cnt: %" PRIx64,
reset_string[hw->reset.level],
hw->reset.stats.merge_cnt - merge_cnt,
hw->reset.stats.merge_cnt);
}
static bool
hns3_reset_err_handle(struct hns3_adapter *hns)
{
#define MAX_RESET_FAIL_CNT 5
struct hns3_hw *hw = &hns->hw;
if (hw->adapter_state == HNS3_NIC_CLOSING)
goto reset_fail;
if (is_reset_pending(hns)) {
hw->reset.attempts = 0;
hw->reset.stats.fail_cnt++;
hns3_warn(hw, "%s reset fail because new Reset is pending "
"attempts:%" PRIx64,
reset_string[hw->reset.level],
hw->reset.stats.fail_cnt);
hw->reset.level = HNS3_NONE_RESET;
return true;
}
hw->reset.attempts++;
if (hw->reset.attempts < MAX_RESET_FAIL_CNT) {
hns3_atomic_set_bit(hw->reset.level, &hw->reset.pending);
hns3_warn(hw, "%s retry to reset attempts: %d",
reset_string[hw->reset.level],
hw->reset.attempts);
return true;
}
/*
* Failure to reset does not mean that the network port is
* completely unavailable, so cmd still needs to be initialized.
* Regardless of whether the execution is successful or not, the
* flow after execution must be continued.
*/
if (__atomic_load_n(&hw->reset.disable_cmd, __ATOMIC_RELAXED))
(void)hns3_cmd_init(hw);
reset_fail:
hw->reset.attempts = 0;
hw->reset.stats.fail_cnt++;
hns3_warn(hw, "%s reset fail fail_cnt:%" PRIx64 " success_cnt:%" PRIx64
" global_cnt:%" PRIx64 " imp_cnt:%" PRIx64
" request_cnt:%" PRIx64 " exec_cnt:%" PRIx64
" merge_cnt:%" PRIx64 "adapter_state:%d",
reset_string[hw->reset.level], hw->reset.stats.fail_cnt,
hw->reset.stats.success_cnt, hw->reset.stats.global_cnt,
hw->reset.stats.imp_cnt, hw->reset.stats.request_cnt,
hw->reset.stats.exec_cnt, hw->reset.stats.merge_cnt,
hw->adapter_state);
/* IMP no longer waiting the ready flag */
hns3_notify_reset_ready(hw, true);
return false;
}
static int
hns3_reset_pre(struct hns3_adapter *hns)
{
struct hns3_hw *hw = &hns->hw;
struct timeval tv;
int ret;
if (hw->reset.stage == RESET_STAGE_NONE) {
__atomic_store_n(&hns->hw.reset.resetting, 1, __ATOMIC_RELAXED);
hw->reset.stage = RESET_STAGE_DOWN;
ret = hw->reset.ops->stop_service(hns);
gettimeofday(&tv, NULL);
if (ret) {
hns3_warn(hw, "Reset step1 down fail=%d time=%ld.%.6ld",
ret, tv.tv_sec, tv.tv_usec);
return ret;
}
hns3_warn(hw, "Reset step1 down success time=%ld.%.6ld",
tv.tv_sec, tv.tv_usec);
hw->reset.stage = RESET_STAGE_PREWAIT;
}
if (hw->reset.stage == RESET_STAGE_PREWAIT) {
ret = hw->reset.ops->prepare_reset(hns);
gettimeofday(&tv, NULL);
if (ret) {
hns3_warn(hw,
"Reset step2 prepare wait fail=%d time=%ld.%.6ld",
ret, tv.tv_sec, tv.tv_usec);
return ret;
}
hns3_warn(hw, "Reset step2 prepare wait success time=%ld.%.6ld",
tv.tv_sec, tv.tv_usec);
hw->reset.stage = RESET_STAGE_REQ_HW_RESET;
hw->reset.wait_data->result = HNS3_WAIT_UNKNOWN;
}
return 0;
}
static int
hns3_reset_post(struct hns3_adapter *hns)
{
#define TIMEOUT_RETRIES_CNT 5
struct hns3_hw *hw = &hns->hw;
struct timeval tv_delta;
struct timeval tv;
int ret = 0;
if (hw->adapter_state == HNS3_NIC_CLOSING) {
hns3_warn(hw, "Don't do reset_post during closing, just uninit cmd");
hns3_cmd_uninit(hw);
return -EPERM;
}
if (hw->reset.stage == RESET_STAGE_DEV_INIT) {
rte_spinlock_lock(&hw->lock);
if (hw->reset.mbuf_deferred_free) {
hns3_dev_release_mbufs(hns);
hw->reset.mbuf_deferred_free = false;
}
ret = hw->reset.ops->reinit_dev(hns);
rte_spinlock_unlock(&hw->lock);
gettimeofday(&tv, NULL);
if (ret) {
hns3_warn(hw, "Reset step5 devinit fail=%d retries=%d",
ret, hw->reset.retries);
goto err;
}
hns3_warn(hw, "Reset step5 devinit success time=%ld.%.6ld",
tv.tv_sec, tv.tv_usec);
hw->reset.retries = 0;
hw->reset.stage = RESET_STAGE_RESTORE;
rte_eal_alarm_set(SWITCH_CONTEXT_US,
hw->reset.ops->reset_service, hns);
return -EAGAIN;
}
if (hw->reset.stage == RESET_STAGE_RESTORE) {
rte_spinlock_lock(&hw->lock);
ret = hw->reset.ops->restore_conf(hns);
rte_spinlock_unlock(&hw->lock);
gettimeofday(&tv, NULL);
if (ret) {
hns3_warn(hw,
"Reset step6 restore fail=%d retries=%d",
ret, hw->reset.retries);
goto err;
}
hns3_warn(hw, "Reset step6 restore success time=%ld.%.6ld",
tv.tv_sec, tv.tv_usec);
hw->reset.retries = 0;
hw->reset.stage = RESET_STAGE_DONE;
}
if (hw->reset.stage == RESET_STAGE_DONE) {
/* IMP will wait ready flag before reset */
hns3_notify_reset_ready(hw, false);
hns3_clear_reset_level(hw, &hw->reset.pending);
__atomic_store_n(&hns->hw.reset.resetting, 0, __ATOMIC_RELAXED);
hw->reset.attempts = 0;
hw->reset.stats.success_cnt++;
hw->reset.stage = RESET_STAGE_NONE;
rte_spinlock_lock(&hw->lock);
hw->reset.ops->start_service(hns);
rte_spinlock_unlock(&hw->lock);
gettimeofday(&tv, NULL);
timersub(&tv, &hw->reset.start_time, &tv_delta);
hns3_warn(hw, "%s reset done fail_cnt:%" PRIx64
" success_cnt:%" PRIx64 " global_cnt:%" PRIx64
" imp_cnt:%" PRIx64 " request_cnt:%" PRIx64
" exec_cnt:%" PRIx64 " merge_cnt:%" PRIx64,
reset_string[hw->reset.level],
hw->reset.stats.fail_cnt, hw->reset.stats.success_cnt,
hw->reset.stats.global_cnt, hw->reset.stats.imp_cnt,
hw->reset.stats.request_cnt, hw->reset.stats.exec_cnt,
hw->reset.stats.merge_cnt);
hns3_warn(hw,
"%s reset done delta %ld ms time=%ld.%.6ld",
reset_string[hw->reset.level],
tv_delta.tv_sec * MSEC_PER_SEC +
tv_delta.tv_usec / USEC_PER_MSEC,
tv.tv_sec, tv.tv_usec);
hw->reset.level = HNS3_NONE_RESET;
}
return 0;
err:
if (ret == -ETIME) {
hw->reset.retries++;
if (hw->reset.retries < TIMEOUT_RETRIES_CNT) {
rte_eal_alarm_set(HNS3_RESET_SYNC_US,
hw->reset.ops->reset_service, hns);
return -EAGAIN;
}
}
hw->reset.retries = 0;
return -EIO;
}
/*
* There are three scenarios as follows:
* When the reset is not in progress, the reset process starts.
* During the reset process, if the reset level has not changed,
* the reset process continues; otherwise, the reset process is aborted.
* hw->reset.level new_level action
* HNS3_NONE_RESET HNS3_XXXX_RESET start reset
* HNS3_XXXX_RESET HNS3_XXXX_RESET continue reset
* HNS3_LOW_RESET HNS3_HIGH_RESET abort
*/
int
hns3_reset_process(struct hns3_adapter *hns, enum hns3_reset_level new_level)
{
struct hns3_hw *hw = &hns->hw;
struct timeval tv_delta;
struct timeval tv;
int ret;
if (hw->reset.level == HNS3_NONE_RESET) {
hw->reset.level = new_level;
hw->reset.stats.exec_cnt++;
gettimeofday(&hw->reset.start_time, NULL);
hns3_warn(hw, "Start %s reset time=%ld.%.6ld",
reset_string[hw->reset.level],
hw->reset.start_time.tv_sec,
hw->reset.start_time.tv_usec);
}
if (is_reset_pending(hns)) {
gettimeofday(&tv, NULL);
hns3_warn(hw,
"%s reset is aborted by high level time=%ld.%.6ld",
reset_string[hw->reset.level], tv.tv_sec, tv.tv_usec);
if (hw->reset.wait_data->result == HNS3_WAIT_REQUEST)
rte_eal_alarm_cancel(hns3_wait_callback,
hw->reset.wait_data);
goto err;
}
ret = hns3_reset_pre(hns);
if (ret)
goto err;
if (hw->reset.stage == RESET_STAGE_REQ_HW_RESET) {
ret = hns3_reset_req_hw_reset(hns);
if (ret == -EAGAIN)
return ret;
gettimeofday(&tv, NULL);
hns3_warn(hw,
"Reset step3 request IMP reset success time=%ld.%.6ld",
tv.tv_sec, tv.tv_usec);
hw->reset.stage = RESET_STAGE_WAIT;
hw->reset.wait_data->result = HNS3_WAIT_UNKNOWN;
}
if (hw->reset.stage == RESET_STAGE_WAIT) {
ret = hw->reset.ops->wait_hardware_ready(hns);
if (ret)
goto retry;
gettimeofday(&tv, NULL);
hns3_warn(hw, "Reset step4 reset wait success time=%ld.%.6ld",
tv.tv_sec, tv.tv_usec);
hw->reset.stage = RESET_STAGE_DEV_INIT;
}
ret = hns3_reset_post(hns);
if (ret)
goto retry;
return 0;
retry:
if (ret == -EAGAIN)
return ret;
err:
hns3_clear_reset_level(hw, &hw->reset.pending);
if (hns3_reset_err_handle(hns)) {
hw->reset.stage = RESET_STAGE_PREWAIT;
hns3_schedule_reset(hns);
} else {
rte_spinlock_lock(&hw->lock);
if (hw->reset.mbuf_deferred_free) {
hns3_dev_release_mbufs(hns);
hw->reset.mbuf_deferred_free = false;
}
rte_spinlock_unlock(&hw->lock);
__atomic_store_n(&hns->hw.reset.resetting, 0, __ATOMIC_RELAXED);
hw->reset.stage = RESET_STAGE_NONE;
gettimeofday(&tv, NULL);
timersub(&tv, &hw->reset.start_time, &tv_delta);
hns3_warn(hw, "%s reset fail delta %ld ms time=%ld.%.6ld",
reset_string[hw->reset.level],
tv_delta.tv_sec * MSEC_PER_SEC +
tv_delta.tv_usec / USEC_PER_MSEC,
tv.tv_sec, tv.tv_usec);
hw->reset.level = HNS3_NONE_RESET;
}
return -EIO;
}
/*
* The reset process can only be terminated after handshake with IMP(step3),
* so that IMP can complete the reset process normally.
*/
void
hns3_reset_abort(struct hns3_adapter *hns)
{
struct hns3_hw *hw = &hns->hw;
struct timeval tv;
int i;
for (i = 0; i < HNS3_QUIT_RESET_CNT; i++) {
if (hw->reset.level == HNS3_NONE_RESET)
break;
rte_delay_ms(HNS3_QUIT_RESET_DELAY_MS);
}
/* IMP no longer waiting the ready flag */
hns3_notify_reset_ready(hw, true);
rte_eal_alarm_cancel(hw->reset.ops->reset_service, hns);
rte_eal_alarm_cancel(hns3_wait_callback, hw->reset.wait_data);
if (hw->reset.level != HNS3_NONE_RESET) {
gettimeofday(&tv, NULL);
hns3_err(hw, "Failed to terminate reset: %s time=%ld.%.6ld",
reset_string[hw->reset.level], tv.tv_sec, tv.tv_usec);
}
}
static void
hns3_report_lse(void *arg)
{
struct rte_eth_dev *dev = (struct rte_eth_dev *)arg;
struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
if (hw->adapter_state == HNS3_NIC_STARTED)
rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
}
void
hns3_start_report_lse(struct rte_eth_dev *dev)
{
#define DELAY_REPORT_LSE_US 1
/*
* When this function called, the context may hold hns3_hw.lock, if
* report lse right now, in some application such as bonding, it will
* trigger call driver's ops which may acquire hns3_hw.lock again, so
* lead to deadlock.
* Here we use delay report to avoid the deadlock.
*/
rte_eal_alarm_set(DELAY_REPORT_LSE_US, hns3_report_lse, dev);
}
void
hns3_stop_report_lse(struct rte_eth_dev *dev)
{
rte_eal_alarm_cancel(hns3_report_lse, dev);
}