Commit a83d2961 authored by Weihang Li's avatar Weihang Li Committed by David S. Miller

net: hns3: implement .process_hw_error for hns3 client

When hardware or IMP get specified error it may need the client
to take some special operations.

This patch implements the hns3 client's process_hw_errorx.
Signed-off-by: default avatarWeihang Li <liweihang@hisilicon.com>
Signed-off-by: default avatarHuazhong Tan <tanhuazhong@huawei.com>
Reviewed-by: default avatarPeng Li <lipeng321@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e8df45c2
...@@ -146,6 +146,12 @@ enum hnae3_reset_notify_type { ...@@ -146,6 +146,12 @@ enum hnae3_reset_notify_type {
HNAE3_RESTORE_CLIENT, HNAE3_RESTORE_CLIENT,
}; };
enum hnae3_hw_error_type {
HNAE3_PPU_POISON_ERROR,
HNAE3_CMDQ_ECC_ERROR,
HNAE3_IMP_RD_POISON_ERROR,
};
enum hnae3_reset_type { enum hnae3_reset_type {
HNAE3_VF_RESET, HNAE3_VF_RESET,
HNAE3_VF_FUNC_RESET, HNAE3_VF_FUNC_RESET,
...@@ -210,7 +216,8 @@ struct hnae3_client_ops { ...@@ -210,7 +216,8 @@ struct hnae3_client_ops {
int (*setup_tc)(struct hnae3_handle *handle, u8 tc); int (*setup_tc)(struct hnae3_handle *handle, u8 tc);
int (*reset_notify)(struct hnae3_handle *handle, int (*reset_notify)(struct hnae3_handle *handle,
enum hnae3_reset_notify_type type); enum hnae3_reset_notify_type type);
enum hnae3_reset_type (*process_hw_error)(struct hnae3_handle *handle); void (*process_hw_error)(struct hnae3_handle *handle,
enum hnae3_hw_error_type);
}; };
#define HNAE3_CLIENT_NAME_LENGTH 16 #define HNAE3_CLIENT_NAME_LENGTH 16
......
...@@ -4470,12 +4470,36 @@ int hns3_set_channels(struct net_device *netdev, ...@@ -4470,12 +4470,36 @@ int hns3_set_channels(struct net_device *netdev,
return hns3_reset_notify(h, HNAE3_UP_CLIENT); return hns3_reset_notify(h, HNAE3_UP_CLIENT);
} }
static const struct hns3_hw_error_info hns3_hw_err[] = {
{ .type = HNAE3_PPU_POISON_ERROR,
.msg = "PPU poison" },
{ .type = HNAE3_CMDQ_ECC_ERROR,
.msg = "IMP CMDQ error" },
{ .type = HNAE3_IMP_RD_POISON_ERROR,
.msg = "IMP RD poison" },
};
static void hns3_process_hw_error(struct hnae3_handle *handle,
enum hnae3_hw_error_type type)
{
int i;
for (i = 0; i < ARRAY_SIZE(hns3_hw_err); i++) {
if (hns3_hw_err[i].type == type) {
dev_err(&handle->pdev->dev, "Detected %s!\n",
hns3_hw_err[i].msg);
break;
}
}
}
static const struct hnae3_client_ops client_ops = { static const struct hnae3_client_ops client_ops = {
.init_instance = hns3_client_init, .init_instance = hns3_client_init,
.uninit_instance = hns3_client_uninit, .uninit_instance = hns3_client_uninit,
.link_status_change = hns3_link_status_change, .link_status_change = hns3_link_status_change,
.setup_tc = hns3_client_setup_tc, .setup_tc = hns3_client_setup_tc,
.reset_notify = hns3_reset_notify, .reset_notify = hns3_reset_notify,
.process_hw_error = hns3_process_hw_error,
}; };
/* hns3_init_module - Driver registration routine /* hns3_init_module - Driver registration routine
......
...@@ -552,6 +552,11 @@ union l4_hdr_info { ...@@ -552,6 +552,11 @@ union l4_hdr_info {
unsigned char *hdr; unsigned char *hdr;
}; };
struct hns3_hw_error_info {
enum hnae3_hw_error_type type;
const char *msg;
};
static inline int ring_space(struct hns3_enet_ring *ring) static inline int ring_space(struct hns3_enet_ring *ring)
{ {
/* This smp_load_acquire() pairs with smp_store_release() in /* This smp_load_acquire() pairs with smp_store_release() in
......
...@@ -1325,10 +1325,12 @@ static int hclge_handle_pf_ras_error(struct hclge_dev *hdev, ...@@ -1325,10 +1325,12 @@ static int hclge_handle_pf_ras_error(struct hclge_dev *hdev,
/* log PPU(RCB) errors */ /* log PPU(RCB) errors */
desc_data = (__le32 *)&desc[3]; desc_data = (__le32 *)&desc[3];
status = le32_to_cpu(*desc_data) & HCLGE_PPU_PF_INT_RAS_MASK; status = le32_to_cpu(*desc_data) & HCLGE_PPU_PF_INT_RAS_MASK;
if (status) if (status) {
hclge_log_error(dev, "PPU_PF_ABNORMAL_INT_ST0", hclge_log_error(dev, "PPU_PF_ABNORMAL_INT_ST0",
&hclge_ppu_pf_abnormal_int[0], status, &hclge_ppu_pf_abnormal_int[0], status,
&ae_dev->hw_err_reset_req); &ae_dev->hw_err_reset_req);
hclge_report_hw_error(hdev, HNAE3_PPU_POISON_ERROR);
}
/* clear all PF RAS errors */ /* clear all PF RAS errors */
hclge_cmd_reuse_desc(&desc[0], false); hclge_cmd_reuse_desc(&desc[0], false);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#define __HCLGE_ERR_H #define __HCLGE_ERR_H
#include "hclge_main.h" #include "hclge_main.h"
#include "hnae3.h"
#define HCLGE_MPF_RAS_INT_MIN_BD_NUM 10 #define HCLGE_MPF_RAS_INT_MIN_BD_NUM 10
#define HCLGE_PF_RAS_INT_MIN_BD_NUM 4 #define HCLGE_PF_RAS_INT_MIN_BD_NUM 4
......
...@@ -3265,6 +3265,38 @@ static int hclge_func_reset_sync_vf(struct hclge_dev *hdev) ...@@ -3265,6 +3265,38 @@ static int hclge_func_reset_sync_vf(struct hclge_dev *hdev)
return -ETIME; return -ETIME;
} }
void hclge_report_hw_error(struct hclge_dev *hdev,
enum hnae3_hw_error_type type)
{
struct hnae3_client *client = hdev->nic_client;
u16 i;
if (!client || !client->ops->process_hw_error ||
!test_bit(HCLGE_STATE_NIC_REGISTERED, &hdev->state))
return;
for (i = 0; i < hdev->num_vmdq_vport + 1; i++)
client->ops->process_hw_error(&hdev->vport[i].nic, type);
}
static void hclge_handle_imp_error(struct hclge_dev *hdev)
{
u32 reg_val;
reg_val = hclge_read_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG);
if (reg_val & BIT(HCLGE_VECTOR0_IMP_RD_POISON_B)) {
hclge_report_hw_error(hdev, HNAE3_IMP_RD_POISON_ERROR);
reg_val &= ~BIT(HCLGE_VECTOR0_IMP_RD_POISON_B);
hclge_write_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG, reg_val);
}
if (reg_val & BIT(HCLGE_VECTOR0_IMP_CMDQ_ERR_B)) {
hclge_report_hw_error(hdev, HNAE3_CMDQ_ECC_ERROR);
reg_val &= ~BIT(HCLGE_VECTOR0_IMP_CMDQ_ERR_B);
hclge_write_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG, reg_val);
}
}
int hclge_func_reset_cmd(struct hclge_dev *hdev, int func_id) int hclge_func_reset_cmd(struct hclge_dev *hdev, int func_id)
{ {
struct hclge_desc desc; struct hclge_desc desc;
...@@ -3471,6 +3503,7 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev) ...@@ -3471,6 +3503,7 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev)
hdev->rst_stats.flr_rst_cnt++; hdev->rst_stats.flr_rst_cnt++;
break; break;
case HNAE3_IMP_RESET: case HNAE3_IMP_RESET:
hclge_handle_imp_error(hdev);
reg_val = hclge_read_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG); reg_val = hclge_read_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG);
hclge_write_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG, hclge_write_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG,
BIT(HCLGE_VECTOR0_IMP_RESET_INT_B) | reg_val); BIT(HCLGE_VECTOR0_IMP_RESET_INT_B) | reg_val);
......
...@@ -178,6 +178,8 @@ enum HLCGE_PORT_TYPE { ...@@ -178,6 +178,8 @@ enum HLCGE_PORT_TYPE {
#define HCLGE_VECTOR0_RX_CMDQ_INT_B 1 #define HCLGE_VECTOR0_RX_CMDQ_INT_B 1
#define HCLGE_VECTOR0_IMP_RESET_INT_B 1 #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_MAC_DEFAULT_FRAME \ #define HCLGE_MAC_DEFAULT_FRAME \
(ETH_HLEN + ETH_FCS_LEN + 2 * VLAN_HLEN + ETH_DATA_LEN) (ETH_HLEN + ETH_FCS_LEN + 2 * VLAN_HLEN + ETH_DATA_LEN)
...@@ -986,4 +988,6 @@ int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid, ...@@ -986,4 +988,6 @@ int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid,
void hclge_task_schedule(struct hclge_dev *hdev, unsigned long delay_time); void hclge_task_schedule(struct hclge_dev *hdev, unsigned long delay_time);
int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev,
struct hclge_desc *desc); struct hclge_desc *desc);
void hclge_report_hw_error(struct hclge_dev *hdev,
enum hnae3_hw_error_type type);
#endif #endif
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