Commit 9b47243c authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'add-vf-fault-detect-support-for-hns3-ethernet-driver'

Jijie Shao says:

====================
add vf fault detect support for HNS3 ethernet driver
====================

Link: https://lore.kernel.org/r/20231007031215.1067758-1-shaojijie@huawei.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents bbb63db3 8a45c4f9
...@@ -103,6 +103,7 @@ enum HNAE3_DEV_CAP_BITS { ...@@ -103,6 +103,7 @@ enum HNAE3_DEV_CAP_BITS {
HNAE3_DEV_SUPPORT_LANE_NUM_B, HNAE3_DEV_SUPPORT_LANE_NUM_B,
HNAE3_DEV_SUPPORT_WOL_B, HNAE3_DEV_SUPPORT_WOL_B,
HNAE3_DEV_SUPPORT_TM_FLUSH_B, HNAE3_DEV_SUPPORT_TM_FLUSH_B,
HNAE3_DEV_SUPPORT_VF_FAULT_B,
}; };
#define hnae3_ae_dev_fd_supported(ae_dev) \ #define hnae3_ae_dev_fd_supported(ae_dev) \
...@@ -177,6 +178,9 @@ enum HNAE3_DEV_CAP_BITS { ...@@ -177,6 +178,9 @@ enum HNAE3_DEV_CAP_BITS {
#define hnae3_ae_dev_tm_flush_supported(hdev) \ #define hnae3_ae_dev_tm_flush_supported(hdev) \
test_bit(HNAE3_DEV_SUPPORT_TM_FLUSH_B, (hdev)->ae_dev->caps) test_bit(HNAE3_DEV_SUPPORT_TM_FLUSH_B, (hdev)->ae_dev->caps)
#define hnae3_ae_dev_vf_fault_supported(ae_dev) \
test_bit(HNAE3_DEV_SUPPORT_VF_FAULT_B, (ae_dev)->caps)
enum HNAE3_PF_CAP_BITS { enum HNAE3_PF_CAP_BITS {
HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B = 0, HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B = 0,
}; };
...@@ -271,6 +275,7 @@ enum hnae3_reset_type { ...@@ -271,6 +275,7 @@ enum hnae3_reset_type {
HNAE3_GLOBAL_RESET, HNAE3_GLOBAL_RESET,
HNAE3_IMP_RESET, HNAE3_IMP_RESET,
HNAE3_NONE_RESET, HNAE3_NONE_RESET,
HNAE3_VF_EXP_RESET,
HNAE3_MAX_RESET, HNAE3_MAX_RESET,
}; };
......
...@@ -157,6 +157,7 @@ static const struct hclge_comm_caps_bit_map hclge_pf_cmd_caps[] = { ...@@ -157,6 +157,7 @@ static const struct hclge_comm_caps_bit_map hclge_pf_cmd_caps[] = {
{HCLGE_COMM_CAP_LANE_NUM_B, HNAE3_DEV_SUPPORT_LANE_NUM_B}, {HCLGE_COMM_CAP_LANE_NUM_B, HNAE3_DEV_SUPPORT_LANE_NUM_B},
{HCLGE_COMM_CAP_WOL_B, HNAE3_DEV_SUPPORT_WOL_B}, {HCLGE_COMM_CAP_WOL_B, HNAE3_DEV_SUPPORT_WOL_B},
{HCLGE_COMM_CAP_TM_FLUSH_B, HNAE3_DEV_SUPPORT_TM_FLUSH_B}, {HCLGE_COMM_CAP_TM_FLUSH_B, HNAE3_DEV_SUPPORT_TM_FLUSH_B},
{HCLGE_COMM_CAP_VF_FAULT_B, HNAE3_DEV_SUPPORT_VF_FAULT_B},
}; };
static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = { static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = {
......
...@@ -93,6 +93,7 @@ enum hclge_opcode_type { ...@@ -93,6 +93,7 @@ enum hclge_opcode_type {
HCLGE_OPC_DFX_SSU_REG_2 = 0x004F, HCLGE_OPC_DFX_SSU_REG_2 = 0x004F,
HCLGE_OPC_QUERY_DEV_SPECS = 0x0050, HCLGE_OPC_QUERY_DEV_SPECS = 0x0050,
HCLGE_OPC_GET_QUEUE_ERR_VF = 0x0067,
/* MAC command */ /* MAC command */
HCLGE_OPC_CONFIG_MAC_MODE = 0x0301, HCLGE_OPC_CONFIG_MAC_MODE = 0x0301,
...@@ -348,6 +349,7 @@ enum HCLGE_COMM_CAP_BITS { ...@@ -348,6 +349,7 @@ enum HCLGE_COMM_CAP_BITS {
HCLGE_COMM_CAP_GRO_B = 20, HCLGE_COMM_CAP_GRO_B = 20,
HCLGE_COMM_CAP_FD_B = 21, HCLGE_COMM_CAP_FD_B = 21,
HCLGE_COMM_CAP_FEC_STATS_B = 25, HCLGE_COMM_CAP_FEC_STATS_B = 25,
HCLGE_COMM_CAP_VF_FAULT_B = 26,
HCLGE_COMM_CAP_LANE_NUM_B = 27, HCLGE_COMM_CAP_LANE_NUM_B = 27,
HCLGE_COMM_CAP_WOL_B = 28, HCLGE_COMM_CAP_WOL_B = 28,
HCLGE_COMM_CAP_TM_FLUSH_B = 31, HCLGE_COMM_CAP_TM_FLUSH_B = 31,
......
...@@ -414,6 +414,9 @@ static struct hns3_dbg_cap_info hns3_dbg_cap[] = { ...@@ -414,6 +414,9 @@ static struct hns3_dbg_cap_info hns3_dbg_cap[] = {
}, { }, {
.name = "support tm flush", .name = "support tm flush",
.cap_bit = HNAE3_DEV_SUPPORT_TM_FLUSH_B, .cap_bit = HNAE3_DEV_SUPPORT_TM_FLUSH_B,
}, {
.name = "support vf fault detect",
.cap_bit = HNAE3_DEV_SUPPORT_VF_FAULT_B,
} }
}; };
......
...@@ -1301,10 +1301,12 @@ static const struct hclge_hw_type_id hclge_hw_type_id_st[] = { ...@@ -1301,10 +1301,12 @@ static const struct hclge_hw_type_id hclge_hw_type_id_st[] = {
.msg = "tqp_int_ecc_error" .msg = "tqp_int_ecc_error"
}, { }, {
.type_id = PF_ABNORMAL_INT_ERROR, .type_id = PF_ABNORMAL_INT_ERROR,
.msg = "pf_abnormal_int_error" .msg = "pf_abnormal_int_error",
.cause_by_vf = true
}, { }, {
.type_id = MPF_ABNORMAL_INT_ERROR, .type_id = MPF_ABNORMAL_INT_ERROR,
.msg = "mpf_abnormal_int_error" .msg = "mpf_abnormal_int_error",
.cause_by_vf = true
}, { }, {
.type_id = COMMON_ERROR, .type_id = COMMON_ERROR,
.msg = "common_error" .msg = "common_error"
...@@ -2759,7 +2761,7 @@ void hclge_handle_occurred_error(struct hclge_dev *hdev) ...@@ -2759,7 +2761,7 @@ void hclge_handle_occurred_error(struct hclge_dev *hdev)
hclge_handle_error_info_log(ae_dev); hclge_handle_error_info_log(ae_dev);
} }
static void static bool
hclge_handle_error_type_reg_log(struct device *dev, hclge_handle_error_type_reg_log(struct device *dev,
struct hclge_mod_err_info *mod_info, struct hclge_mod_err_info *mod_info,
struct hclge_type_reg_err_info *type_reg_info) struct hclge_type_reg_err_info *type_reg_info)
...@@ -2770,6 +2772,7 @@ hclge_handle_error_type_reg_log(struct device *dev, ...@@ -2770,6 +2772,7 @@ hclge_handle_error_type_reg_log(struct device *dev,
u8 mod_id, total_module, type_id, total_type, i, is_ras; u8 mod_id, total_module, type_id, total_type, i, is_ras;
u8 index_module = MODULE_NONE; u8 index_module = MODULE_NONE;
u8 index_type = NONE_ERROR; u8 index_type = NONE_ERROR;
bool cause_by_vf = false;
mod_id = mod_info->mod_id; mod_id = mod_info->mod_id;
type_id = type_reg_info->type_id & HCLGE_ERR_TYPE_MASK; type_id = type_reg_info->type_id & HCLGE_ERR_TYPE_MASK;
...@@ -2788,6 +2791,7 @@ hclge_handle_error_type_reg_log(struct device *dev, ...@@ -2788,6 +2791,7 @@ hclge_handle_error_type_reg_log(struct device *dev,
for (i = 0; i < total_type; i++) { for (i = 0; i < total_type; i++) {
if (type_id == hclge_hw_type_id_st[i].type_id) { if (type_id == hclge_hw_type_id_st[i].type_id) {
index_type = i; index_type = i;
cause_by_vf = hclge_hw_type_id_st[i].cause_by_vf;
break; break;
} }
} }
...@@ -2805,6 +2809,8 @@ hclge_handle_error_type_reg_log(struct device *dev, ...@@ -2805,6 +2809,8 @@ hclge_handle_error_type_reg_log(struct device *dev,
dev_err(dev, "reg_value:\n"); dev_err(dev, "reg_value:\n");
for (i = 0; i < type_reg_info->reg_num; i++) for (i = 0; i < type_reg_info->reg_num; i++)
dev_err(dev, "0x%08x\n", type_reg_info->hclge_reg[i]); dev_err(dev, "0x%08x\n", type_reg_info->hclge_reg[i]);
return cause_by_vf;
} }
static void hclge_handle_error_module_log(struct hnae3_ae_dev *ae_dev, static void hclge_handle_error_module_log(struct hnae3_ae_dev *ae_dev,
...@@ -2815,6 +2821,7 @@ static void hclge_handle_error_module_log(struct hnae3_ae_dev *ae_dev, ...@@ -2815,6 +2821,7 @@ static void hclge_handle_error_module_log(struct hnae3_ae_dev *ae_dev,
struct device *dev = &hdev->pdev->dev; struct device *dev = &hdev->pdev->dev;
struct hclge_mod_err_info *mod_info; struct hclge_mod_err_info *mod_info;
struct hclge_sum_err_info *sum_info; struct hclge_sum_err_info *sum_info;
bool cause_by_vf = false;
u8 mod_num, err_num, i; u8 mod_num, err_num, i;
u32 offset = 0; u32 offset = 0;
...@@ -2843,12 +2850,16 @@ static void hclge_handle_error_module_log(struct hnae3_ae_dev *ae_dev, ...@@ -2843,12 +2850,16 @@ static void hclge_handle_error_module_log(struct hnae3_ae_dev *ae_dev,
type_reg_info = (struct hclge_type_reg_err_info *) type_reg_info = (struct hclge_type_reg_err_info *)
&buf[offset++]; &buf[offset++];
hclge_handle_error_type_reg_log(dev, mod_info, if (hclge_handle_error_type_reg_log(dev, mod_info,
type_reg_info); type_reg_info))
cause_by_vf = true;
offset += type_reg_info->reg_num; offset += type_reg_info->reg_num;
} }
} }
if (hnae3_ae_dev_vf_fault_supported(hdev->ae_dev) && cause_by_vf)
set_bit(HNAE3_VF_EXP_RESET, &ae_dev->hw_err_reset_req);
} }
static int hclge_query_all_err_bd_num(struct hclge_dev *hdev, u32 *bd_num) static int hclge_query_all_err_bd_num(struct hclge_dev *hdev, u32 *bd_num)
...@@ -2940,3 +2951,98 @@ int hclge_handle_error_info_log(struct hnae3_ae_dev *ae_dev) ...@@ -2940,3 +2951,98 @@ int hclge_handle_error_info_log(struct hnae3_ae_dev *ae_dev)
out: out:
return ret; return ret;
} }
static bool hclge_reset_vf_in_bitmap(struct hclge_dev *hdev,
unsigned long *bitmap)
{
struct hclge_vport *vport;
bool exist_set = false;
int func_id;
int ret;
func_id = find_first_bit(bitmap, HCLGE_VPORT_NUM);
if (func_id == PF_VPORT_ID)
return false;
while (func_id != HCLGE_VPORT_NUM) {
vport = hclge_get_vf_vport(hdev,
func_id - HCLGE_VF_VPORT_START_NUM);
if (!vport) {
dev_err(&hdev->pdev->dev, "invalid func id(%d)\n",
func_id);
return false;
}
dev_info(&hdev->pdev->dev, "do function %d recovery.", func_id);
ret = hclge_reset_tqp(&vport->nic);
if (ret) {
dev_err(&hdev->pdev->dev,
"failed to reset tqp, ret = %d.", ret);
return false;
}
ret = hclge_inform_vf_reset(vport, HNAE3_VF_FUNC_RESET);
if (ret) {
dev_err(&hdev->pdev->dev,
"failed to reset func %d, ret = %d.",
func_id, ret);
return false;
}
exist_set = true;
clear_bit(func_id, bitmap);
func_id = find_first_bit(bitmap, HCLGE_VPORT_NUM);
}
return exist_set;
}
static void hclge_get_vf_fault_bitmap(struct hclge_desc *desc,
unsigned long *bitmap)
{
#define HCLGE_FIR_FAULT_BYTES 24
#define HCLGE_SEC_FAULT_BYTES 8
u8 *buff;
BUILD_BUG_ON(HCLGE_FIR_FAULT_BYTES + HCLGE_SEC_FAULT_BYTES !=
BITS_TO_BYTES(HCLGE_VPORT_NUM));
memcpy(bitmap, desc[0].data, HCLGE_FIR_FAULT_BYTES);
buff = (u8 *)bitmap + HCLGE_FIR_FAULT_BYTES;
memcpy(buff, desc[1].data, HCLGE_SEC_FAULT_BYTES);
}
int hclge_handle_vf_queue_err_ras(struct hclge_dev *hdev)
{
unsigned long vf_fault_bitmap[BITS_TO_LONGS(HCLGE_VPORT_NUM)];
struct hclge_desc desc[2];
bool cause_by_vf = false;
int ret;
if (!test_and_clear_bit(HNAE3_VF_EXP_RESET,
&hdev->ae_dev->hw_err_reset_req) ||
!hnae3_ae_dev_vf_fault_supported(hdev->ae_dev))
return 0;
hclge_comm_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_GET_QUEUE_ERR_VF,
true);
desc[0].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT);
hclge_comm_cmd_setup_basic_desc(&desc[1], HCLGE_OPC_GET_QUEUE_ERR_VF,
true);
ret = hclge_comm_cmd_send(&hdev->hw.hw, desc, 2);
if (ret) {
dev_err(&hdev->pdev->dev,
"failed to get vf bitmap, ret = %d.\n", ret);
return ret;
}
hclge_get_vf_fault_bitmap(desc, vf_fault_bitmap);
cause_by_vf = hclge_reset_vf_in_bitmap(hdev, vf_fault_bitmap);
if (cause_by_vf)
hdev->ae_dev->hw_err_reset_req = 0;
return 0;
}
...@@ -196,6 +196,7 @@ struct hclge_hw_module_id { ...@@ -196,6 +196,7 @@ struct hclge_hw_module_id {
struct hclge_hw_type_id { struct hclge_hw_type_id {
enum hclge_err_type_list type_id; enum hclge_err_type_list type_id;
const char *msg; const char *msg;
bool cause_by_vf; /* indicate the error may from vf exception */
}; };
struct hclge_sum_err_info { struct hclge_sum_err_info {
...@@ -228,4 +229,5 @@ int hclge_handle_hw_msix_error(struct hclge_dev *hdev, ...@@ -228,4 +229,5 @@ int hclge_handle_hw_msix_error(struct hclge_dev *hdev,
unsigned long *reset_requests); unsigned long *reset_requests);
int hclge_handle_error_info_log(struct hnae3_ae_dev *ae_dev); int hclge_handle_error_info_log(struct hnae3_ae_dev *ae_dev);
int hclge_handle_mac_tnl(struct hclge_dev *hdev); int hclge_handle_mac_tnl(struct hclge_dev *hdev);
int hclge_handle_vf_queue_err_ras(struct hclge_dev *hdev);
#endif #endif
...@@ -3424,7 +3424,7 @@ static int hclge_get_status(struct hnae3_handle *handle) ...@@ -3424,7 +3424,7 @@ static int hclge_get_status(struct hnae3_handle *handle)
return hdev->hw.mac.link; return hdev->hw.mac.link;
} }
static struct hclge_vport *hclge_get_vf_vport(struct hclge_dev *hdev, int vf) struct hclge_vport *hclge_get_vf_vport(struct hclge_dev *hdev, int vf)
{ {
if (!pci_num_vf(hdev->pdev)) { if (!pci_num_vf(hdev->pdev)) {
dev_err(&hdev->pdev->dev, dev_err(&hdev->pdev->dev,
...@@ -4468,6 +4468,7 @@ static void hclge_handle_err_recovery(struct hclge_dev *hdev) ...@@ -4468,6 +4468,7 @@ static void hclge_handle_err_recovery(struct hclge_dev *hdev)
if (hclge_find_error_source(hdev)) { if (hclge_find_error_source(hdev)) {
hclge_handle_error_info_log(ae_dev); hclge_handle_error_info_log(ae_dev);
hclge_handle_mac_tnl(hdev); hclge_handle_mac_tnl(hdev);
hclge_handle_vf_queue_err_ras(hdev);
} }
hclge_handle_err_reset_request(hdev); hclge_handle_err_reset_request(hdev);
......
...@@ -1146,4 +1146,6 @@ int hclge_dbg_dump_rst_info(struct hclge_dev *hdev, char *buf, int len); ...@@ -1146,4 +1146,6 @@ int hclge_dbg_dump_rst_info(struct hclge_dev *hdev, char *buf, int len);
int hclge_push_vf_link_status(struct hclge_vport *vport); int hclge_push_vf_link_status(struct hclge_vport *vport);
int hclge_enable_vport_vlan_filter(struct hclge_vport *vport, bool request_en); int hclge_enable_vport_vlan_filter(struct hclge_vport *vport, bool request_en);
int hclge_mac_update_stats(struct hclge_dev *hdev); int hclge_mac_update_stats(struct hclge_dev *hdev);
struct hclge_vport *hclge_get_vf_vport(struct hclge_dev *hdev, int vf);
int hclge_inform_vf_reset(struct hclge_vport *vport, u16 reset_type);
#endif #endif
...@@ -124,7 +124,7 @@ static int hclge_send_mbx_msg(struct hclge_vport *vport, u8 *msg, u16 msg_len, ...@@ -124,7 +124,7 @@ static int hclge_send_mbx_msg(struct hclge_vport *vport, u8 *msg, u16 msg_len,
return status; return status;
} }
static int hclge_inform_vf_reset(struct hclge_vport *vport, u16 reset_type) int hclge_inform_vf_reset(struct hclge_vport *vport, u16 reset_type)
{ {
__le16 msg_data; __le16 msg_data;
u8 dest_vfid; u8 dest_vfid;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment