diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 3e21533a2bf5..c4b7bf851a28 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -146,6 +146,12 @@ enum hnae3_reset_notify_type { 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 { HNAE3_VF_RESET, HNAE3_VF_FUNC_RESET, @@ -210,7 +216,8 @@ struct hnae3_client_ops { int (*setup_tc)(struct hnae3_handle *handle, u8 tc); int (*reset_notify)(struct hnae3_handle *handle, 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 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 7070d25ddb5b..5cf4c1ecc5b8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -39,7 +39,7 @@ static int hns3_dbg_queue_info(struct hnae3_handle *h, if (queue_num >= h->kinfo.num_tqps) { dev_err(&h->pdev->dev, - "Queue number(%u) is out of range(%u)\n", queue_num, + "Queue number(%u) is out of range(0-%u)\n", queue_num, h->kinfo.num_tqps - 1); return -EINVAL; } @@ -177,7 +177,7 @@ static int hns3_dbg_bd_info(struct hnae3_handle *h, const char *cmd_buf) } if (q_num >= h->kinfo.num_tqps) { - dev_err(dev, "Queue number(%u) is out of range(%u)\n", q_num, + dev_err(dev, "Queue number(%u) is out of range(0-%u)\n", q_num, h->kinfo.num_tqps - 1); return -EINVAL; } @@ -188,14 +188,14 @@ static int hns3_dbg_bd_info(struct hnae3_handle *h, const char *cmd_buf) tx_index = (cnt == 1) ? value : tx_index; if (tx_index >= ring->desc_num) { - dev_err(dev, "bd index (%u) is out of range(%u)\n", tx_index, + dev_err(dev, "bd index(%u) is out of range(0-%u)\n", tx_index, ring->desc_num - 1); return -EINVAL; } tx_desc = &ring->desc[tx_index]; dev_info(dev, "TX Queue Num: %u, BD Index: %u\n", q_num, tx_index); - dev_info(dev, "(TX) addr: 0x%llx\n", tx_desc->addr); + dev_info(dev, "(TX)addr: 0x%llx\n", tx_desc->addr); dev_info(dev, "(TX)vlan_tag: %u\n", tx_desc->tx.vlan_tag); dev_info(dev, "(TX)send_size: %u\n", tx_desc->tx.send_size); dev_info(dev, "(TX)vlan_tso: %u\n", tx_desc->tx.type_cs_vlan_tso); @@ -219,6 +219,7 @@ static int hns3_dbg_bd_info(struct hnae3_handle *h, const char *cmd_buf) dev_info(dev, "RX Queue Num: %u, BD Index: %u\n", q_num, rx_index); dev_info(dev, "(RX)addr: 0x%llx\n", rx_desc->addr); + dev_info(dev, "(RX)l234_info: %u\n", rx_desc->rx.l234_info); dev_info(dev, "(RX)pkt_len: %u\n", rx_desc->rx.pkt_len); dev_info(dev, "(RX)size: %u\n", rx_desc->rx.size); dev_info(dev, "(RX)rss_hash: %u\n", rx_desc->rx.rss_hash); @@ -238,16 +239,16 @@ static void hns3_dbg_help(struct hnae3_handle *h) char printf_buf[HNS3_DBG_BUF_LEN]; dev_info(&h->pdev->dev, "available commands\n"); - dev_info(&h->pdev->dev, "queue info [number]\n"); + dev_info(&h->pdev->dev, "queue info \n"); dev_info(&h->pdev->dev, "queue map\n"); - dev_info(&h->pdev->dev, "bd info [q_num] \n"); + dev_info(&h->pdev->dev, "bd info \n"); if (!hns3_is_phys_func(h->pdev)) return; dev_info(&h->pdev->dev, "dump fd tcam\n"); dev_info(&h->pdev->dev, "dump tc\n"); - dev_info(&h->pdev->dev, "dump tm map [q_num]\n"); + dev_info(&h->pdev->dev, "dump tm map \n"); dev_info(&h->pdev->dev, "dump tm\n"); dev_info(&h->pdev->dev, "dump qos pause cfg\n"); dev_info(&h->pdev->dev, "dump qos pri map\n"); @@ -259,20 +260,20 @@ static void hns3_dbg_help(struct hnae3_handle *h) dev_info(&h->pdev->dev, "dump mac tnl status\n"); memset(printf_buf, 0, HNS3_DBG_BUF_LEN); - strncat(printf_buf, "dump reg [[bios common] [ssu ]", + strncat(printf_buf, "dump reg [[bios common] [ssu ]", HNS3_DBG_BUF_LEN - 1); strncat(printf_buf + strlen(printf_buf), - " [igu egu ] [rpu ]", + " [igu egu ] [rpu ]", HNS3_DBG_BUF_LEN - strlen(printf_buf) - 1); strncat(printf_buf + strlen(printf_buf), - " [rtc] [ppp] [rcb] [tqp ]]\n", + " [rtc] [ppp] [rcb] [tqp ]]\n", HNS3_DBG_BUF_LEN - strlen(printf_buf) - 1); dev_info(&h->pdev->dev, "%s", printf_buf); memset(printf_buf, 0, HNS3_DBG_BUF_LEN); - strncat(printf_buf, "dump reg dcb [port_id] [pri_id] [pg_id]", + strncat(printf_buf, "dump reg dcb ", HNS3_DBG_BUF_LEN - 1); - strncat(printf_buf + strlen(printf_buf), " [rq_id] [nq_id] [qset_id]\n", + strncat(printf_buf + strlen(printf_buf), " \n", HNS3_DBG_BUF_LEN - strlen(printf_buf) - 1); dev_info(&h->pdev->dev, "%s", printf_buf); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index a11d514f7a25..9f3f8e3cb2c2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4470,12 +4470,36 @@ int hns3_set_channels(struct net_device *netdev, 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 = { .init_instance = hns3_client_init, .uninit_instance = hns3_client_uninit, .link_status_change = hns3_link_status_change, .setup_tc = hns3_client_setup_tc, .reset_notify = hns3_reset_notify, + .process_hw_error = hns3_process_hw_error, }; /* hns3_init_module - Driver registration routine diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index e37e64e70d8d..2110fa3b4479 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -552,6 +552,11 @@ union l4_hdr_info { 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) { /* This smp_load_acquire() pairs with smp_store_release() in diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 0332d6fb4c0d..c52eccc1621d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -59,7 +59,7 @@ static const struct hns3_stats hns3_rxq_stats[] = { #define HNS3_TQP_STATS_COUNT (HNS3_TXQ_STATS_COUNT + HNS3_RXQ_STATS_COUNT) -#define HNS3_SELF_TEST_TYPE_NUM 3 +#define HNS3_SELF_TEST_TYPE_NUM 4 #define HNS3_NIC_LB_TEST_PKT_NUM 1 #define HNS3_NIC_LB_TEST_RING_ID 0 #define HNS3_NIC_LB_TEST_PACKET_SIZE 128 @@ -89,6 +89,7 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en) case HNAE3_LOOP_SERIAL_SERDES: case HNAE3_LOOP_PARALLEL_SERDES: case HNAE3_LOOP_APP: + case HNAE3_LOOP_PHY: ret = h->ae_algo->ops->set_loopback(h, loop, en); break; default: @@ -96,7 +97,7 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en) break; } - if (ret) + if (ret || h->pdev->revision >= 0x21) return ret; if (en) { @@ -143,7 +144,10 @@ static int hns3_lp_down(struct net_device *ndev, enum hnae3_loop loop_mode) static void hns3_lp_setup_skb(struct sk_buff *skb) { +#define HNS3_NIC_LB_DST_MAC_ADDR 0x1f + struct net_device *ndev = skb->dev; + struct hnae3_handle *handle; unsigned char *packet; struct ethhdr *ethh; unsigned int i; @@ -159,7 +163,9 @@ static void hns3_lp_setup_skb(struct sk_buff *skb) * before the packet reaches mac or serdes, which will defect * the purpose of mac or serdes selftest. */ - ethh->h_dest[5] += 0x1f; + handle = hns3_get_handle(ndev); + if (handle->pdev->revision == 0x20) + ethh->h_dest[5] += HNS3_NIC_LB_DST_MAC_ADDR; eth_zero_addr(ethh->h_source); ethh->h_proto = htons(ETH_P_ARP); skb_reset_mac_header(skb); @@ -330,6 +336,10 @@ static void hns3_self_test(struct net_device *ndev, st_param[HNAE3_LOOP_PARALLEL_SERDES][1] = h->flags & HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK; + st_param[HNAE3_LOOP_PHY][0] = HNAE3_LOOP_PHY; + st_param[HNAE3_LOOP_PHY][1] = + h->flags & HNAE3_SUPPORT_PHY_LOOPBACK; + if (if_running) ndev->netdev_ops->ndo_stop(ndev); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 29979be9e33a..4821fe08b5e4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -223,6 +223,9 @@ enum hclge_opcode_type { HCLGE_OPC_MAC_ETHTYPE_ADD = 0x1010, HCLGE_OPC_MAC_ETHTYPE_REMOVE = 0x1011, + /* MAC VLAN commands */ + HCLGE_OPC_MAC_VLAN_SWITCH_PARAM = 0x1033, + /* VLAN commands */ HCLGE_OPC_VLAN_FILTER_CTRL = 0x1100, HCLGE_OPC_VLAN_FILTER_PF_CFG = 0x1101, @@ -771,6 +774,31 @@ struct hclge_vlan_filter_vf_cfg_cmd { u8 vf_bitmap[16]; }; +#define HCLGE_SWITCH_ANTI_SPOOF_B 0U +#define HCLGE_SWITCH_ALW_LPBK_B 1U +#define HCLGE_SWITCH_ALW_LCL_LPBK_B 2U +#define HCLGE_SWITCH_ALW_DST_OVRD_B 3U +#define HCLGE_SWITCH_NO_MASK 0x0 +#define HCLGE_SWITCH_ANTI_SPOOF_MASK 0xFE +#define HCLGE_SWITCH_ALW_LPBK_MASK 0xFD +#define HCLGE_SWITCH_ALW_LCL_LPBK_MASK 0xFB +#define HCLGE_SWITCH_LW_DST_OVRD_MASK 0xF7 + +struct hclge_mac_vlan_switch_cmd { + u8 roce_sel; + u8 rsv1[3]; + __le32 func_id; + u8 switch_param; + u8 rsv2[3]; + u8 param_mask; + u8 rsv3[11]; +}; + +enum hclge_mac_vlan_cfg_sel { + HCLGE_MAC_VLAN_NIC_SEL = 0, + HCLGE_MAC_VLAN_ROCE_SEL, +}; + #define HCLGE_ACCEPT_TAG1_B 0 #define HCLGE_ACCEPT_UNTAG1_B 1 #define HCLGE_PORT_INS_TAG1_EN_B 2 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index 814e0f076e32..816f92084138 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -198,6 +198,28 @@ static int hclge_client_setup_tc(struct hclge_dev *hdev) return 0; } +static int hclge_notify_down_uinit(struct hclge_dev *hdev) +{ + int ret; + + ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT); + if (ret) + return ret; + + return hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT); +} + +static int hclge_notify_init_up(struct hclge_dev *hdev) +{ + int ret; + + ret = hclge_notify_client(hdev, HNAE3_INIT_CLIENT); + if (ret) + return ret; + + return hclge_notify_client(hdev, HNAE3_UP_CLIENT); +} + static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) { struct hclge_vport *vport = hclge_get_vport(h); @@ -218,11 +240,7 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) if (map_changed) { netif_dbg(h, drv, netdev, "set ets\n"); - ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT); - if (ret) - return ret; - - ret = hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT); + ret = hclge_notify_down_uinit(hdev); if (ret) return ret; } @@ -242,11 +260,7 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) if (ret) goto err_out; - ret = hclge_notify_client(hdev, HNAE3_INIT_CLIENT); - if (ret) - return ret; - - ret = hclge_notify_client(hdev, HNAE3_UP_CLIENT); + ret = hclge_notify_init_up(hdev); if (ret) return ret; } @@ -257,10 +271,8 @@ err_out: if (!map_changed) return ret; - if (hclge_notify_client(hdev, HNAE3_INIT_CLIENT)) - return ret; + hclge_notify_init_up(hdev); - hclge_notify_client(hdev, HNAE3_UP_CLIENT); return ret; } @@ -383,11 +395,7 @@ static int hclge_setup_tc(struct hnae3_handle *h, u8 tc, u8 *prio_tc) if (ret) return -EINVAL; - ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT); - if (ret) - return ret; - - ret = hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT); + ret = hclge_notify_down_uinit(hdev); if (ret) return ret; @@ -409,17 +417,11 @@ static int hclge_setup_tc(struct hnae3_handle *h, u8 tc, u8 *prio_tc) else hdev->flag &= ~HCLGE_FLAG_MQPRIO_ENABLE; - ret = hclge_notify_client(hdev, HNAE3_INIT_CLIENT); - if (ret) - return ret; - - return hclge_notify_client(hdev, HNAE3_UP_CLIENT); + return hclge_notify_init_up(hdev); err_out: - if (hclge_notify_client(hdev, HNAE3_INIT_CLIENT)) - return ret; + hclge_notify_init_up(hdev); - hclge_notify_client(hdev, HNAE3_UP_CLIENT); return ret; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 025184a0c839..1debe37fe735 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -4,24 +4,92 @@ #include #include "hclge_debugfs.h" -#include "hclge_cmd.h" #include "hclge_main.h" #include "hclge_tm.h" #include "hnae3.h" +static struct hclge_dbg_reg_type_info hclge_dbg_reg_info[] = { + { .reg_type = "bios common", + .dfx_msg = &hclge_dbg_bios_common_reg[0], + .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_bios_common_reg), + .offset = HCLGE_DBG_DFX_BIOS_OFFSET, + .cmd = HCLGE_OPC_DFX_BIOS_COMMON_REG } }, + { .reg_type = "ssu", + .dfx_msg = &hclge_dbg_ssu_reg_0[0], + .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_ssu_reg_0), + .offset = HCLGE_DBG_DFX_SSU_0_OFFSET, + .cmd = HCLGE_OPC_DFX_SSU_REG_0 } }, + { .reg_type = "ssu", + .dfx_msg = &hclge_dbg_ssu_reg_1[0], + .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_ssu_reg_1), + .offset = HCLGE_DBG_DFX_SSU_1_OFFSET, + .cmd = HCLGE_OPC_DFX_SSU_REG_1 } }, + { .reg_type = "ssu", + .dfx_msg = &hclge_dbg_ssu_reg_2[0], + .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_ssu_reg_2), + .offset = HCLGE_DBG_DFX_SSU_2_OFFSET, + .cmd = HCLGE_OPC_DFX_SSU_REG_2 } }, + { .reg_type = "igu egu", + .dfx_msg = &hclge_dbg_igu_egu_reg[0], + .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_igu_egu_reg), + .offset = HCLGE_DBG_DFX_IGU_OFFSET, + .cmd = HCLGE_OPC_DFX_IGU_EGU_REG } }, + { .reg_type = "rpu", + .dfx_msg = &hclge_dbg_rpu_reg_0[0], + .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_rpu_reg_0), + .offset = HCLGE_DBG_DFX_RPU_0_OFFSET, + .cmd = HCLGE_OPC_DFX_RPU_REG_0 } }, + { .reg_type = "rpu", + .dfx_msg = &hclge_dbg_rpu_reg_1[0], + .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_rpu_reg_1), + .offset = HCLGE_DBG_DFX_RPU_1_OFFSET, + .cmd = HCLGE_OPC_DFX_RPU_REG_1 } }, + { .reg_type = "ncsi", + .dfx_msg = &hclge_dbg_ncsi_reg[0], + .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_ncsi_reg), + .offset = HCLGE_DBG_DFX_NCSI_OFFSET, + .cmd = HCLGE_OPC_DFX_NCSI_REG } }, + { .reg_type = "rtc", + .dfx_msg = &hclge_dbg_rtc_reg[0], + .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_rtc_reg), + .offset = HCLGE_DBG_DFX_RTC_OFFSET, + .cmd = HCLGE_OPC_DFX_RTC_REG } }, + { .reg_type = "ppp", + .dfx_msg = &hclge_dbg_ppp_reg[0], + .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_ppp_reg), + .offset = HCLGE_DBG_DFX_PPP_OFFSET, + .cmd = HCLGE_OPC_DFX_PPP_REG } }, + { .reg_type = "rcb", + .dfx_msg = &hclge_dbg_rcb_reg[0], + .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_rcb_reg), + .offset = HCLGE_DBG_DFX_RCB_OFFSET, + .cmd = HCLGE_OPC_DFX_RCB_REG } }, + { .reg_type = "tqp", + .dfx_msg = &hclge_dbg_tqp_reg[0], + .reg_msg = { .msg_num = ARRAY_SIZE(hclge_dbg_tqp_reg), + .offset = HCLGE_DBG_DFX_TQP_OFFSET, + .cmd = HCLGE_OPC_DFX_TQP_REG } }, +}; + static int hclge_dbg_get_dfx_bd_num(struct hclge_dev *hdev, int offset) { - struct hclge_desc desc[4]; +#define HCLGE_GET_DFX_REG_TYPE_CNT 4 + + struct hclge_desc desc[HCLGE_GET_DFX_REG_TYPE_CNT]; + int entries_per_desc; + int index; int ret; ret = hclge_query_bd_num_cmd_send(hdev, desc); if (ret) { dev_err(&hdev->pdev->dev, - "get dfx bdnum fail, status is %d.\n", ret); + "get dfx bdnum fail, ret = %d\n", ret); return ret; } - return (int)desc[offset / 6].data[offset % 6]; + entries_per_desc = ARRAY_SIZE(desc[0].data); + index = offset % entries_per_desc; + return (int)desc[offset / entries_per_desc].data[index]; } static int hclge_dbg_cmd_send(struct hclge_dev *hdev, @@ -42,35 +110,40 @@ static int hclge_dbg_cmd_send(struct hclge_dev *hdev, } ret = hclge_cmd_send(&hdev->hw, desc_src, bd_num); - if (ret) { + if (ret) dev_err(&hdev->pdev->dev, - "read reg cmd send fail, status is %d.\n", ret); - return ret; - } - + "cmd(0x%x) send fail, ret = %d\n", cmd, ret); return ret; } static void hclge_dbg_dump_reg_common(struct hclge_dev *hdev, - struct hclge_dbg_dfx_message *dfx_message, - const char *cmd_buf, int msg_num, - int offset, enum hclge_opcode_type cmd) + struct hclge_dbg_reg_type_info *reg_info, + const char *cmd_buf) { -#define BD_DATA_NUM 6 +#define IDX_OFFSET 1 + const char *s = &cmd_buf[strlen(reg_info->reg_type) + IDX_OFFSET]; + struct hclge_dbg_dfx_message *dfx_message = reg_info->dfx_msg; + struct hclge_dbg_reg_common_msg *reg_msg = ®_info->reg_msg; struct hclge_desc *desc_src; struct hclge_desc *desc; + int entries_per_desc; int bd_num, buf_len; + int index = 0; + int min_num; int ret, i; - int index; - int max; - ret = kstrtouint(cmd_buf, 10, &index); - index = (ret != 0) ? 0 : index; + if (*s) { + ret = kstrtouint(s, 0, &index); + index = (ret != 0) ? 0 : index; + } - bd_num = hclge_dbg_get_dfx_bd_num(hdev, offset); - if (bd_num <= 0) + bd_num = hclge_dbg_get_dfx_bd_num(hdev, reg_msg->offset); + if (bd_num <= 0) { + dev_err(&hdev->pdev->dev, "get cmd(%d) bd num(%d) failed\n", + reg_msg->offset, bd_num); return; + } buf_len = sizeof(struct hclge_desc) * bd_num; desc_src = kzalloc(buf_len, GFP_KERNEL); @@ -80,22 +153,23 @@ static void hclge_dbg_dump_reg_common(struct hclge_dev *hdev, } desc = desc_src; - ret = hclge_dbg_cmd_send(hdev, desc, index, bd_num, cmd); - if (ret != HCLGE_CMD_EXEC_SUCCESS) { + ret = hclge_dbg_cmd_send(hdev, desc, index, bd_num, reg_msg->cmd); + if (ret) { kfree(desc_src); return; } - max = (bd_num * BD_DATA_NUM) <= msg_num ? - (bd_num * BD_DATA_NUM) : msg_num; + entries_per_desc = ARRAY_SIZE(desc->data); + min_num = min_t(int, bd_num * entries_per_desc, reg_msg->msg_num); desc = desc_src; - for (i = 0; i < max; i++) { - ((i > 0) && ((i % BD_DATA_NUM) == 0)) ? desc++ : desc; + for (i = 0; i < min_num; i++) { + if (i > 0 && (i % entries_per_desc) == 0) + desc++; if (dfx_message->flag) dev_info(&hdev->pdev->dev, "%s: 0x%x\n", dfx_message->message, - desc->data[i % BD_DATA_NUM]); + desc->data[i % entries_per_desc]); dfx_message++; } @@ -205,95 +279,25 @@ static void hclge_dbg_dump_dcb(struct hclge_dev *hdev, const char *cmd_buf) static void hclge_dbg_dump_reg_cmd(struct hclge_dev *hdev, const char *cmd_buf) { - int msg_num; + struct hclge_dbg_reg_type_info *reg_info = &hclge_dbg_reg_info[0]; + bool has_dump = false; + int i; - if (strncmp(&cmd_buf[9], "bios common", 11) == 0) { - msg_num = sizeof(hclge_dbg_bios_common_reg) / - sizeof(struct hclge_dbg_dfx_message); - hclge_dbg_dump_reg_common(hdev, hclge_dbg_bios_common_reg, - &cmd_buf[21], msg_num, - HCLGE_DBG_DFX_BIOS_OFFSET, - HCLGE_OPC_DFX_BIOS_COMMON_REG); - } else if (strncmp(&cmd_buf[9], "ssu", 3) == 0) { - msg_num = sizeof(hclge_dbg_ssu_reg_0) / - sizeof(struct hclge_dbg_dfx_message); - hclge_dbg_dump_reg_common(hdev, hclge_dbg_ssu_reg_0, - &cmd_buf[13], msg_num, - HCLGE_DBG_DFX_SSU_0_OFFSET, - HCLGE_OPC_DFX_SSU_REG_0); + for (i = 0; i < ARRAY_SIZE(hclge_dbg_reg_info); i++) { + reg_info = &hclge_dbg_reg_info[i]; + if (!strncmp(cmd_buf, reg_info->reg_type, + strlen(reg_info->reg_type))) { + hclge_dbg_dump_reg_common(hdev, reg_info, cmd_buf); + has_dump = true; + } + } - msg_num = sizeof(hclge_dbg_ssu_reg_1) / - sizeof(struct hclge_dbg_dfx_message); - hclge_dbg_dump_reg_common(hdev, hclge_dbg_ssu_reg_1, - &cmd_buf[13], msg_num, - HCLGE_DBG_DFX_SSU_1_OFFSET, - HCLGE_OPC_DFX_SSU_REG_1); + if (strncmp(cmd_buf, "dcb", 3) == 0) { + hclge_dbg_dump_dcb(hdev, &cmd_buf[sizeof("dcb")]); + has_dump = true; + } - msg_num = sizeof(hclge_dbg_ssu_reg_2) / - sizeof(struct hclge_dbg_dfx_message); - hclge_dbg_dump_reg_common(hdev, hclge_dbg_ssu_reg_2, - &cmd_buf[13], msg_num, - HCLGE_DBG_DFX_SSU_2_OFFSET, - HCLGE_OPC_DFX_SSU_REG_2); - } else if (strncmp(&cmd_buf[9], "igu egu", 7) == 0) { - msg_num = sizeof(hclge_dbg_igu_egu_reg) / - sizeof(struct hclge_dbg_dfx_message); - hclge_dbg_dump_reg_common(hdev, hclge_dbg_igu_egu_reg, - &cmd_buf[17], msg_num, - HCLGE_DBG_DFX_IGU_OFFSET, - HCLGE_OPC_DFX_IGU_EGU_REG); - } else if (strncmp(&cmd_buf[9], "rpu", 3) == 0) { - msg_num = sizeof(hclge_dbg_rpu_reg_0) / - sizeof(struct hclge_dbg_dfx_message); - hclge_dbg_dump_reg_common(hdev, hclge_dbg_rpu_reg_0, - &cmd_buf[13], msg_num, - HCLGE_DBG_DFX_RPU_0_OFFSET, - HCLGE_OPC_DFX_RPU_REG_0); - - msg_num = sizeof(hclge_dbg_rpu_reg_1) / - sizeof(struct hclge_dbg_dfx_message); - hclge_dbg_dump_reg_common(hdev, hclge_dbg_rpu_reg_1, - &cmd_buf[13], msg_num, - HCLGE_DBG_DFX_RPU_1_OFFSET, - HCLGE_OPC_DFX_RPU_REG_1); - } else if (strncmp(&cmd_buf[9], "ncsi", 4) == 0) { - msg_num = sizeof(hclge_dbg_ncsi_reg) / - sizeof(struct hclge_dbg_dfx_message); - hclge_dbg_dump_reg_common(hdev, hclge_dbg_ncsi_reg, - &cmd_buf[14], msg_num, - HCLGE_DBG_DFX_NCSI_OFFSET, - HCLGE_OPC_DFX_NCSI_REG); - } else if (strncmp(&cmd_buf[9], "rtc", 3) == 0) { - msg_num = sizeof(hclge_dbg_rtc_reg) / - sizeof(struct hclge_dbg_dfx_message); - hclge_dbg_dump_reg_common(hdev, hclge_dbg_rtc_reg, - &cmd_buf[13], msg_num, - HCLGE_DBG_DFX_RTC_OFFSET, - HCLGE_OPC_DFX_RTC_REG); - } else if (strncmp(&cmd_buf[9], "ppp", 3) == 0) { - msg_num = sizeof(hclge_dbg_ppp_reg) / - sizeof(struct hclge_dbg_dfx_message); - hclge_dbg_dump_reg_common(hdev, hclge_dbg_ppp_reg, - &cmd_buf[13], msg_num, - HCLGE_DBG_DFX_PPP_OFFSET, - HCLGE_OPC_DFX_PPP_REG); - } else if (strncmp(&cmd_buf[9], "rcb", 3) == 0) { - msg_num = sizeof(hclge_dbg_rcb_reg) / - sizeof(struct hclge_dbg_dfx_message); - hclge_dbg_dump_reg_common(hdev, hclge_dbg_rcb_reg, - &cmd_buf[13], msg_num, - HCLGE_DBG_DFX_RCB_OFFSET, - HCLGE_OPC_DFX_RCB_REG); - } else if (strncmp(&cmd_buf[9], "tqp", 3) == 0) { - msg_num = sizeof(hclge_dbg_tqp_reg) / - sizeof(struct hclge_dbg_dfx_message); - hclge_dbg_dump_reg_common(hdev, hclge_dbg_tqp_reg, - &cmd_buf[13], msg_num, - HCLGE_DBG_DFX_TQP_OFFSET, - HCLGE_OPC_DFX_TQP_REG); - } else if (strncmp(&cmd_buf[9], "dcb", 3) == 0) { - hclge_dbg_dump_dcb(hdev, &cmd_buf[13]); - } else { + if (!has_dump) { dev_info(&hdev->pdev->dev, "unknown command\n"); return; } @@ -327,7 +331,7 @@ static void hclge_dbg_dump_tc(struct hclge_dev *hdev) ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { - dev_err(&hdev->pdev->dev, "dump tc fail, status is %d.\n", ret); + dev_err(&hdev->pdev->dev, "dump tc fail, ret = %d\n", ret); return; } @@ -429,7 +433,7 @@ static void hclge_dbg_dump_tm_pg(struct hclge_dev *hdev) return; err_tm_pg_cmd_send: - dev_err(&hdev->pdev->dev, "dump tm_pg fail(0x%x), status is %d\n", + dev_err(&hdev->pdev->dev, "dump tm_pg fail(0x%x), ret = %d\n", cmd, ret); } @@ -541,7 +545,7 @@ static void hclge_dbg_dump_tm(struct hclge_dev *hdev) return; err_tm_cmd_send: - dev_err(&hdev->pdev->dev, "dump tm fail(0x%x), status is %d\n", + dev_err(&hdev->pdev->dev, "dump tm fail(0x%x), ret = %d\n", cmd, ret); } @@ -560,7 +564,7 @@ static void hclge_dbg_dump_tm_map(struct hclge_dev *hdev, int pri_id, ret; u32 i; - ret = kstrtouint(&cmd_buf[12], 10, &queue_id); + ret = kstrtouint(cmd_buf, 0, &queue_id); queue_id = (ret != 0) ? 0 : queue_id; cmd = HCLGE_OPC_TM_NQ_TO_QS_LINK; @@ -630,7 +634,7 @@ static void hclge_dbg_dump_tm_map(struct hclge_dev *hdev, return; err_tm_map_cmd_send: - dev_err(&hdev->pdev->dev, "dump tqp map fail(0x%x), status is %d\n", + dev_err(&hdev->pdev->dev, "dump tqp map fail(0x%x), ret = %d\n", cmd, ret); } @@ -644,7 +648,7 @@ static void hclge_dbg_dump_qos_pause_cfg(struct hclge_dev *hdev) ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { - dev_err(&hdev->pdev->dev, "dump checksum fail, status is %d.\n", + dev_err(&hdev->pdev->dev, "dump checksum fail, ret = %d\n", ret); return; } @@ -668,7 +672,7 @@ static void hclge_dbg_dump_qos_pri_map(struct hclge_dev *hdev) ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { dev_err(&hdev->pdev->dev, - "dump qos pri map fail, status is %d.\n", ret); + "dump qos pri map fail, ret = %d\n", ret); return; } @@ -770,7 +774,8 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev) rx_priv_wl = (struct hclge_rx_priv_wl_buf *)desc[1].data; for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++) dev_info(&hdev->pdev->dev, - "rx_priv_wl_tc_%d: high: 0x%x, low: 0x%x\n", i + 4, + "rx_priv_wl_tc_%d: high: 0x%x, low: 0x%x\n", + i + HCLGE_TC_NUM_ONE_DESC, rx_priv_wl->tc_wl[i].high, rx_priv_wl->tc_wl[i].low); cmd = HCLGE_OPC_RX_COM_THRD_ALLOC; @@ -792,14 +797,15 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev) rx_com_thrd = (struct hclge_rx_com_thrd *)desc[1].data; for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++) dev_info(&hdev->pdev->dev, - "rx_com_thrd_tc_%d: high: 0x%x, low: 0x%x\n", i + 4, + "rx_com_thrd_tc_%d: high: 0x%x, low: 0x%x\n", + i + HCLGE_TC_NUM_ONE_DESC, rx_com_thrd->com_thrd[i].high, rx_com_thrd->com_thrd[i].low); return; err_qos_cmd_send: dev_err(&hdev->pdev->dev, - "dump qos buf cfg fail(0x%x), status is %d\n", cmd, ret); + "dump qos buf cfg fail(0x%x), ret = %d\n", cmd, ret); } static void hclge_dbg_dump_mng_table(struct hclge_dev *hdev) @@ -957,7 +963,7 @@ void hclge_dbg_get_m7_stats_info(struct hclge_dev *hdev) ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { dev_err(&hdev->pdev->dev, - "get firmware statistics bd number failed, ret=%d\n", + "get firmware statistics bd number failed, ret = %d\n", ret); return; } @@ -978,7 +984,7 @@ void hclge_dbg_get_m7_stats_info(struct hclge_dev *hdev) if (ret) { kfree(desc_src); dev_err(&hdev->pdev->dev, - "get firmware statistics failed, ret=%d\n", ret); + "get firmware statistics failed, ret = %d\n", ret); return; } @@ -1092,6 +1098,9 @@ static void hclge_dbg_dump_mac_tnl_status(struct hclge_dev *hdev) int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) { +#define DUMP_REG "dump reg" +#define DUMP_TM_MAP "dump tm map" + struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; @@ -1099,8 +1108,8 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) hclge_dbg_fd_tcam(hdev); } else if (strncmp(cmd_buf, "dump tc", 7) == 0) { hclge_dbg_dump_tc(hdev); - } else if (strncmp(cmd_buf, "dump tm map", 11) == 0) { - hclge_dbg_dump_tm_map(hdev, cmd_buf); + } else if (strncmp(cmd_buf, DUMP_TM_MAP, strlen(DUMP_TM_MAP)) == 0) { + hclge_dbg_dump_tm_map(hdev, &cmd_buf[sizeof(DUMP_TM_MAP)]); } else if (strncmp(cmd_buf, "dump tm", 7) == 0) { hclge_dbg_dump_tm(hdev); } else if (strncmp(cmd_buf, "dump qos pause cfg", 18) == 0) { @@ -1111,8 +1120,8 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf) hclge_dbg_dump_qos_buf_cfg(hdev); } else if (strncmp(cmd_buf, "dump mng tbl", 12) == 0) { hclge_dbg_dump_mng_table(hdev); - } else if (strncmp(cmd_buf, "dump reg", 8) == 0) { - hclge_dbg_dump_reg_cmd(hdev, cmd_buf); + } else if (strncmp(cmd_buf, DUMP_REG, strlen(DUMP_REG)) == 0) { + hclge_dbg_dump_reg_cmd(hdev, &cmd_buf[sizeof(DUMP_REG)]); } else if (strncmp(cmd_buf, "dump reset info", 15) == 0) { hclge_dbg_dump_rst_info(hdev); } else if (strncmp(cmd_buf, "dump m7 info", 12) == 0) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h index d055fda41775..38b79321c4c4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h @@ -4,6 +4,9 @@ #ifndef __HCLGE_DEBUGFS_H #define __HCLGE_DEBUGFS_H +#include +#include "hclge_cmd.h" + #define HCLGE_DBG_BUF_LEN 256 #define HCLGE_DBG_MNG_TBL_MAX 64 @@ -63,9 +66,23 @@ struct hclge_dbg_bitmap_cmd { }; }; +struct hclge_dbg_reg_common_msg { + int msg_num; + int offset; + enum hclge_opcode_type cmd; +}; + +#define HCLGE_DBG_MAX_DFX_MSG_LEN 60 struct hclge_dbg_dfx_message { int flag; - char message[60]; + char message[HCLGE_DBG_MAX_DFX_MSG_LEN]; +}; + +#define HCLGE_DBG_MAC_REG_TYPE_LEN 32 +struct hclge_dbg_reg_type_info { + const char *reg_type; + struct hclge_dbg_dfx_message *dfx_msg; + struct hclge_dbg_reg_common_msg reg_msg; }; #pragma pack() diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index 2425b3f53ad8..58c6231aaa00 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -930,32 +930,44 @@ static int hclge_config_ppu_error_interrupts(struct hclge_dev *hdev, u32 cmd, /* configure PPU error interrupts */ if (cmd == HCLGE_PPU_MPF_ECC_INT_CMD) { hclge_cmd_setup_basic_desc(&desc[0], cmd, false); - desc[0].flag |= HCLGE_CMD_FLAG_NEXT; + desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); hclge_cmd_setup_basic_desc(&desc[1], cmd, false); if (en) { - desc[0].data[0] = HCLGE_PPU_MPF_ABNORMAL_INT0_EN; - desc[0].data[1] = HCLGE_PPU_MPF_ABNORMAL_INT1_EN; - desc[1].data[3] = HCLGE_PPU_MPF_ABNORMAL_INT3_EN; - desc[1].data[4] = HCLGE_PPU_MPF_ABNORMAL_INT2_EN; + desc[0].data[0] = + cpu_to_le32(HCLGE_PPU_MPF_ABNORMAL_INT0_EN); + desc[0].data[1] = + cpu_to_le32(HCLGE_PPU_MPF_ABNORMAL_INT1_EN); + desc[1].data[3] = + cpu_to_le32(HCLGE_PPU_MPF_ABNORMAL_INT3_EN); + desc[1].data[4] = + cpu_to_le32(HCLGE_PPU_MPF_ABNORMAL_INT2_EN); } - desc[1].data[0] = HCLGE_PPU_MPF_ABNORMAL_INT0_EN_MASK; - desc[1].data[1] = HCLGE_PPU_MPF_ABNORMAL_INT1_EN_MASK; - desc[1].data[2] = HCLGE_PPU_MPF_ABNORMAL_INT2_EN_MASK; - desc[1].data[3] |= HCLGE_PPU_MPF_ABNORMAL_INT3_EN_MASK; + desc[1].data[0] = + cpu_to_le32(HCLGE_PPU_MPF_ABNORMAL_INT0_EN_MASK); + desc[1].data[1] = + cpu_to_le32(HCLGE_PPU_MPF_ABNORMAL_INT1_EN_MASK); + desc[1].data[2] = + cpu_to_le32(HCLGE_PPU_MPF_ABNORMAL_INT2_EN_MASK); + desc[1].data[3] |= + cpu_to_le32(HCLGE_PPU_MPF_ABNORMAL_INT3_EN_MASK); desc_num = 2; } else if (cmd == HCLGE_PPU_MPF_OTHER_INT_CMD) { hclge_cmd_setup_basic_desc(&desc[0], cmd, false); if (en) - desc[0].data[0] = HCLGE_PPU_MPF_ABNORMAL_INT2_EN2; + desc[0].data[0] = + cpu_to_le32(HCLGE_PPU_MPF_ABNORMAL_INT2_EN2); - desc[0].data[2] = HCLGE_PPU_MPF_ABNORMAL_INT2_EN2_MASK; + desc[0].data[2] = + cpu_to_le32(HCLGE_PPU_MPF_ABNORMAL_INT2_EN2_MASK); } else if (cmd == HCLGE_PPU_PF_OTHER_INT_CMD) { hclge_cmd_setup_basic_desc(&desc[0], cmd, false); if (en) - desc[0].data[0] = HCLGE_PPU_PF_ABNORMAL_INT_EN; + desc[0].data[0] = + cpu_to_le32(HCLGE_PPU_PF_ABNORMAL_INT_EN); - desc[0].data[2] = HCLGE_PPU_PF_ABNORMAL_INT_EN_MASK; + desc[0].data[2] = + cpu_to_le32(HCLGE_PPU_PF_ABNORMAL_INT_EN_MASK); } else { dev_err(dev, "Invalid cmd to configure PPU error interrupts\n"); return -EINVAL; @@ -1313,10 +1325,12 @@ static int hclge_handle_pf_ras_error(struct hclge_dev *hdev, /* log PPU(RCB) errors */ desc_data = (__le32 *)&desc[3]; 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_ppu_pf_abnormal_int[0], status, &ae_dev->hw_err_reset_req); + hclge_report_hw_error(hdev, HNAE3_PPU_POISON_ERROR); + } /* clear all PF RAS errors */ hclge_cmd_reuse_desc(&desc[0], false); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h index 7ea8bb28a0cb..876fd81ad2f1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h @@ -5,6 +5,7 @@ #define __HCLGE_ERR_H #include "hclge_main.h" +#include "hnae3.h" #define HCLGE_MPF_RAS_INT_MIN_BD_NUM 10 #define HCLGE_PF_RAS_INT_MIN_BD_NUM 4 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index dde17be33767..ce4b2280a8b0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -53,6 +53,8 @@ #define HCLGE_DFX_TQP_BD_OFFSET 11 #define HCLGE_DFX_SSU_2_BD_OFFSET 12 +#define HCLGE_LINK_STATUS_MS 10 + static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mps); static int hclge_init_vlan_config(struct hclge_dev *hdev); static void hclge_sync_vlan_filter(struct hclge_dev *hdev); @@ -742,6 +744,12 @@ static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset) count += 2; handle->flags |= HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK; handle->flags |= HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK; + + if (hdev->hw.mac.phydev) { + count += 1; + handle->flags |= HNAE3_SUPPORT_PHY_LOOPBACK; + } + } else if (stringset == ETH_SS_STATS) { count = ARRAY_SIZE(g_mac_stats_string) + hclge_tqps_get_sset_count(handle, stringset); @@ -3265,6 +3273,38 @@ static int hclge_func_reset_sync_vf(struct hclge_dev *hdev) 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) { struct hclge_desc desc; @@ -3471,6 +3511,7 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev) hdev->rst_stats.flr_rst_cnt++; break; case HNAE3_IMP_RESET: + hclge_handle_imp_error(hdev); reg_val = hclge_read_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); @@ -3495,11 +3536,10 @@ static bool hclge_reset_err_handle(struct hclge_dev *hdev) dev_info(&hdev->pdev->dev, "Reset pending %lu\n", hdev->reset_pending); return true; - } else if ((hdev->reset_type != HNAE3_IMP_RESET) && - (hclge_read_dev(&hdev->hw, HCLGE_GLOBAL_RESET_REG) & - BIT(HCLGE_IMP_RESET_BIT))) { + } else if (hclge_read_dev(&hdev->hw, HCLGE_MISC_VECTOR_INT_STS) & + HCLGE_RESET_INT_M) { dev_info(&hdev->pdev->dev, - "reset failed because IMP Reset is pending\n"); + "reset failed because new reset interrupt\n"); hclge_clear_reset_cause(hdev); return false; } else if (hdev->reset_fail_cnt < MAX_RESET_FAIL_CNT) { @@ -6171,6 +6211,89 @@ static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable) "mac enable fail, ret =%d.\n", ret); } +static int hclge_config_switch_param(struct hclge_dev *hdev, int vfid, + u8 switch_param, u8 param_mask) +{ + struct hclge_mac_vlan_switch_cmd *req; + struct hclge_desc desc; + u32 func_id; + int ret; + + func_id = hclge_get_port_number(HOST_PORT, 0, vfid, 0); + req = (struct hclge_mac_vlan_switch_cmd *)desc.data; + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MAC_VLAN_SWITCH_PARAM, + false); + req->roce_sel = HCLGE_MAC_VLAN_NIC_SEL; + req->func_id = cpu_to_le32(func_id); + req->switch_param = switch_param; + req->param_mask = param_mask; + + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) + dev_err(&hdev->pdev->dev, + "set mac vlan switch parameter fail, ret = %d\n", ret); + return ret; +} + +static void hclge_phy_link_status_wait(struct hclge_dev *hdev, + int link_ret) +{ +#define HCLGE_PHY_LINK_STATUS_NUM 200 + + struct phy_device *phydev = hdev->hw.mac.phydev; + int i = 0; + int ret; + + do { + ret = phy_read_status(phydev); + if (ret) { + dev_err(&hdev->pdev->dev, + "phy update link status fail, ret = %d\n", ret); + return; + } + + if (phydev->link == link_ret) + break; + + msleep(HCLGE_LINK_STATUS_MS); + } while (++i < HCLGE_PHY_LINK_STATUS_NUM); +} + +static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret) +{ +#define HCLGE_MAC_LINK_STATUS_NUM 100 + + int i = 0; + int ret; + + do { + ret = hclge_get_mac_link_status(hdev); + if (ret < 0) + return ret; + else if (ret == link_ret) + return 0; + + msleep(HCLGE_LINK_STATUS_MS); + } while (++i < HCLGE_MAC_LINK_STATUS_NUM); + return -EBUSY; +} + +static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en, + bool is_phy) +{ +#define HCLGE_LINK_STATUS_DOWN 0 +#define HCLGE_LINK_STATUS_UP 1 + + int link_ret; + + link_ret = en ? HCLGE_LINK_STATUS_UP : HCLGE_LINK_STATUS_DOWN; + + if (is_phy) + hclge_phy_link_status_wait(hdev, link_ret); + + return hclge_mac_link_status_wait(hdev, link_ret); +} + static int hclge_set_app_loopback(struct hclge_dev *hdev, bool en) { struct hclge_config_mac_mode_cmd *req; @@ -6213,14 +6336,8 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en, #define HCLGE_SERDES_RETRY_MS 10 #define HCLGE_SERDES_RETRY_NUM 100 -#define HCLGE_MAC_LINK_STATUS_MS 10 -#define HCLGE_MAC_LINK_STATUS_NUM 100 -#define HCLGE_MAC_LINK_STATUS_DOWN 0 -#define HCLGE_MAC_LINK_STATUS_UP 1 - struct hclge_serdes_lb_cmd *req; struct hclge_desc desc; - int mac_link_ret = 0; int ret, i = 0; u8 loop_mode_b; @@ -6243,10 +6360,8 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en, if (en) { req->enable = loop_mode_b; req->mask = loop_mode_b; - mac_link_ret = HCLGE_MAC_LINK_STATUS_UP; } else { req->mask = loop_mode_b; - mac_link_ret = HCLGE_MAC_LINK_STATUS_DOWN; } ret = hclge_cmd_send(&hdev->hw, &desc, 1); @@ -6279,18 +6394,70 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en, hclge_cfg_mac_mode(hdev, en); - i = 0; - do { - /* serdes Internal loopback, independent of the network cable.*/ - msleep(HCLGE_MAC_LINK_STATUS_MS); - ret = hclge_get_mac_link_status(hdev); - if (ret == mac_link_ret) - return 0; - } while (++i < HCLGE_MAC_LINK_STATUS_NUM); + ret = hclge_mac_phy_link_status_wait(hdev, en, FALSE); + if (ret) + dev_err(&hdev->pdev->dev, + "serdes loopback config mac mode timeout\n"); - dev_err(&hdev->pdev->dev, "config mac mode timeout\n"); + return ret; +} - return -EBUSY; +static int hclge_enable_phy_loopback(struct hclge_dev *hdev, + struct phy_device *phydev) +{ + int ret; + + if (!phydev->suspended) { + ret = phy_suspend(phydev); + if (ret) + return ret; + } + + ret = phy_resume(phydev); + if (ret) + return ret; + + return phy_loopback(phydev, true); +} + +static int hclge_disable_phy_loopback(struct hclge_dev *hdev, + struct phy_device *phydev) +{ + int ret; + + ret = phy_loopback(phydev, false); + if (ret) + return ret; + + return phy_suspend(phydev); +} + +static int hclge_set_phy_loopback(struct hclge_dev *hdev, bool en) +{ + struct phy_device *phydev = hdev->hw.mac.phydev; + int ret; + + if (!phydev) + return -ENOTSUPP; + + if (en) + ret = hclge_enable_phy_loopback(hdev, phydev); + else + ret = hclge_disable_phy_loopback(hdev, phydev); + if (ret) { + dev_err(&hdev->pdev->dev, + "set phy loopback fail, ret = %d\n", ret); + return ret; + } + + hclge_cfg_mac_mode(hdev, en); + + ret = hclge_mac_phy_link_status_wait(hdev, en, TRUE); + if (ret) + dev_err(&hdev->pdev->dev, + "phy loopback config mac mode timeout\n"); + + return ret; } static int hclge_tqp_enable(struct hclge_dev *hdev, unsigned int tqp_id, @@ -6322,6 +6489,20 @@ static int hclge_set_loopback(struct hnae3_handle *handle, struct hclge_dev *hdev = vport->back; int i, ret; + /* Loopback can be enabled in three places: SSU, MAC, and serdes. By + * default, SSU loopback is enabled, so if the SMAC and the DMAC are + * the same, the packets are looped back in the SSU. If SSU loopback + * is disabled, packets can reach MAC even if SMAC is the same as DMAC. + */ + if (hdev->pdev->revision >= 0x21) { + u8 switch_param = en ? 0 : BIT(HCLGE_SWITCH_ALW_LPBK_B); + + ret = hclge_config_switch_param(hdev, PF_VPORT_ID, switch_param, + HCLGE_SWITCH_ALW_LPBK_MASK); + if (ret) + return ret; + } + switch (loop_mode) { case HNAE3_LOOP_APP: ret = hclge_set_app_loopback(hdev, en); @@ -6330,6 +6511,9 @@ static int hclge_set_loopback(struct hnae3_handle *handle, case HNAE3_LOOP_PARALLEL_SERDES: ret = hclge_set_serdes_loopback(hdev, en, loop_mode); break; + case HNAE3_LOOP_PHY: + ret = hclge_set_phy_loopback(hdev, en); + break; default: ret = -ENOTSUPP; dev_err(&hdev->pdev->dev, @@ -7237,7 +7421,7 @@ static int hclge_set_mac_addr(struct hnae3_handle *handle, void *p, is_broadcast_ether_addr(new_addr) || is_multicast_ether_addr(new_addr)) { dev_err(&hdev->pdev->dev, - "Change uc mac err! invalid mac:%p.\n", + "Change uc mac err! invalid mac:%pM.\n", new_addr); return -EINVAL; } @@ -7342,7 +7526,7 @@ static void hclge_enable_vlan_filter(struct hnae3_handle *handle, bool enable) } static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, u16 vfid, - bool is_kill, u16 vlan, u8 qos, + bool is_kill, u16 vlan, __be16 proto) { #define HCLGE_MAX_VF_BYTES 16 @@ -7453,7 +7637,7 @@ static int hclge_set_port_vlan_filter(struct hclge_dev *hdev, __be16 proto, } static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto, - u16 vport_id, u16 vlan_id, u8 qos, + u16 vport_id, u16 vlan_id, bool is_kill) { u16 vport_idx, vport_num = 0; @@ -7463,7 +7647,7 @@ static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto, return 0; ret = hclge_set_vf_vlan_common(hdev, vport_id, is_kill, vlan_id, - 0, proto); + proto); if (ret) { dev_err(&hdev->pdev->dev, "Set %d vport vlan filter config fail, ret =%d.\n", @@ -7750,7 +7934,7 @@ static int hclge_add_vport_all_vlan_table(struct hclge_vport *vport) if (!vlan->hd_tbl_status) { ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q), vport->vport_id, - vlan->vlan_id, 0, false); + vlan->vlan_id, false); if (ret) { dev_err(&hdev->pdev->dev, "restore vport vlan list failed, ret=%d\n", @@ -7776,7 +7960,7 @@ static void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id, hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q), vport->vport_id, - vlan_id, 0, + vlan_id, true); list_del(&vlan->node); @@ -7796,7 +7980,7 @@ void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list) hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q), vport->vport_id, - vlan->vlan_id, 0, + vlan->vlan_id, true); vlan->hd_tbl_status = false; @@ -7843,7 +8027,7 @@ static void hclge_restore_vlan_table(struct hnae3_handle *handle) if (state != HNAE3_PORT_BASE_VLAN_DISABLE) { hclge_set_vlan_filter_hw(hdev, htons(vlan_proto), - vport->vport_id, vlan_id, qos, + vport->vport_id, vlan_id, false); continue; } @@ -7853,7 +8037,7 @@ static void hclge_restore_vlan_table(struct hnae3_handle *handle) hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q), vport->vport_id, - vlan->vlan_id, 0, + vlan->vlan_id, false); } } @@ -7893,12 +8077,12 @@ static int hclge_update_vlan_filter_entries(struct hclge_vport *vport, htons(new_info->vlan_proto), vport->vport_id, new_info->vlan_tag, - new_info->qos, false); + false); } ret = hclge_set_vlan_filter_hw(hdev, htons(old_info->vlan_proto), vport->vport_id, old_info->vlan_tag, - old_info->qos, true); + true); if (ret) return ret; @@ -7925,7 +8109,7 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state, htons(vlan_info->vlan_proto), vport->vport_id, vlan_info->vlan_tag, - vlan_info->qos, false); + false); if (ret) return ret; @@ -7934,7 +8118,7 @@ int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state, htons(old_vlan_info->vlan_proto), vport->vport_id, old_vlan_info->vlan_tag, - old_vlan_info->qos, true); + true); if (ret) return ret; @@ -8055,7 +8239,7 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto, */ if (handle->port_base_vlan_state == HNAE3_PORT_BASE_VLAN_DISABLE) { ret = hclge_set_vlan_filter_hw(hdev, proto, vport->vport_id, - vlan_id, 0, is_kill); + vlan_id, is_kill); writen_to_tbl = true; } @@ -8091,7 +8275,7 @@ static void hclge_sync_vlan_filter(struct hclge_dev *hdev) while (vlan_id != VLAN_N_VID) { ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q), vport->vport_id, vlan_id, - 0, true); + true); if (ret && ret != -EINVAL) return; @@ -8262,11 +8446,12 @@ int hclge_reset_tqp(struct hnae3_handle *handle, u16 queue_id) } while (reset_try_times++ < HCLGE_TQP_RESET_TRY_TIMES) { - /* Wait for tqp hw reset */ - msleep(20); reset_status = hclge_get_reset_status(hdev, queue_gid); if (reset_status) break; + + /* Wait for tqp hw reset */ + usleep_range(1000, 1200); } if (reset_try_times >= HCLGE_TQP_RESET_TRY_TIMES) { @@ -8300,11 +8485,12 @@ void hclge_reset_vf_queue(struct hclge_vport *vport, u16 queue_id) } while (reset_try_times++ < HCLGE_TQP_RESET_TRY_TIMES) { - /* Wait for tqp hw reset */ - msleep(20); reset_status = hclge_get_reset_status(hdev, queue_gid); if (reset_status) break; + + /* Wait for tqp hw reset */ + usleep_range(1000, 1200); } if (reset_try_times >= HCLGE_TQP_RESET_TRY_TIMES) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 7ff03b9605e4..870550fa9ff1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -119,7 +119,7 @@ #define HCLGE_DEFAULT_UMV_SPACE_PER_PF \ (HCLGE_UMV_TBL_SIZE / HCLGE_MAX_PF_NUM) -#define HCLGE_TQP_RESET_TRY_TIMES 10 +#define HCLGE_TQP_RESET_TRY_TIMES 200 #define HCLGE_PHY_PAGE_MDIX 0 #define HCLGE_PHY_PAGE_COPPER 0 @@ -148,6 +148,8 @@ enum HLCGE_PORT_TYPE { NETWORK_PORT }; +#define PF_VPORT_ID 0 + #define HCLGE_PF_ID_S 0 #define HCLGE_PF_ID_M GENMASK(2, 0) #define HCLGE_VF_ID_S 3 @@ -164,6 +166,7 @@ enum HLCGE_PORT_TYPE { #define HCLGE_GLOBAL_RESET_BIT 0 #define HCLGE_CORE_RESET_BIT 1 #define HCLGE_IMP_RESET_BIT 2 +#define HCLGE_RESET_INT_M GENMASK(2, 0) #define HCLGE_FUN_RST_ING 0x20C00 #define HCLGE_FUN_RST_ING_B 0 @@ -178,6 +181,8 @@ enum HLCGE_PORT_TYPE { #define HCLGE_VECTOR0_RX_CMDQ_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 \ (ETH_HLEN + ETH_FCS_LEN + 2 * VLAN_HLEN + ETH_DATA_LEN) @@ -986,4 +991,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); int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, struct hclge_desc *desc); +void hclge_report_hw_error(struct hclge_dev *hdev, + enum hnae3_hw_error_type type); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c index 6a96987bd8f0..a108191c9e50 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c @@ -277,9 +277,9 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev) switch (msg_q[0]) { case HCLGE_MBX_LINK_STAT_CHANGE: - link_status = le16_to_cpu(msg_q[1]); + link_status = msg_q[1]; memcpy(&speed, &msg_q[2], sizeof(speed)); - duplex = (u8)le16_to_cpu(msg_q[4]); + duplex = (u8)msg_q[4]; /* update upper layer with new link link status */ hclgevf_update_link_status(hdev, link_status); @@ -287,7 +287,7 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev) break; case HCLGE_MBX_LINK_STAT_MODE: - idx = (u8)le16_to_cpu(msg_q[1]); + idx = (u8)msg_q[1]; if (idx) memcpy(&hdev->hw.mac.supported, &msg_q[2], sizeof(unsigned long)); @@ -301,14 +301,14 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev) * has been completely reset. After this stack should * eventually be re-initialized. */ - reset_type = le16_to_cpu(msg_q[1]); + reset_type = (enum hnae3_reset_type)msg_q[1]; set_bit(reset_type, &hdev->reset_pending); set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state); hclgevf_reset_task_schedule(hdev); break; case HCLGE_MBX_PUSH_VLAN_INFO: - state = le16_to_cpu(msg_q[1]); + state = msg_q[1]; vlan_info = &msg_q[1]; hclgevf_update_port_base_vlan_info(hdev, state, (u8 *)vlan_info, 8);