diff options
Diffstat (limited to 'drivers/net/ethernet/hisilicon')
29 files changed, 1490 insertions, 162 deletions
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/Makefile b/drivers/net/ethernet/hisilicon/hibmcge/Makefile index 7ea15f9ef849..1a9da564b306 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/Makefile +++ b/drivers/net/ethernet/hisilicon/hibmcge/Makefile @@ -6,4 +6,4 @@ obj-$(CONFIG_HIBMCGE) += hibmcge.o hibmcge-objs = hbg_main.o hbg_hw.o hbg_mdio.o hbg_irq.o hbg_txrx.o hbg_ethtool.o \ - hbg_debugfs.o hbg_err.o + hbg_debugfs.o hbg_err.o hbg_diagnose.o diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h index b4300d8ea4ad..7725cb0c5c8a 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h @@ -36,6 +36,8 @@ enum hbg_nic_state { HBG_NIC_STATE_EVENT_HANDLING = 0, HBG_NIC_STATE_RESETTING, HBG_NIC_STATE_RESET_FAIL, + HBG_NIC_STATE_NEED_RESET, /* trigger a reset in scheduled task */ + HBG_NIC_STATE_NP_LINK_FAIL, }; enum hbg_reset_type { @@ -81,6 +83,7 @@ enum hbg_hw_event_type { HBG_HW_EVENT_NONE = 0, HBG_HW_EVENT_INIT, /* driver is loading */ HBG_HW_EVENT_RESET, + HBG_HW_EVENT_CORE_RESET, }; struct hbg_dev_specs { @@ -104,14 +107,17 @@ struct hbg_irq_info { u32 mask; bool re_enable; bool need_print; - u64 count; + bool need_reset; - void (*irq_handle)(struct hbg_priv *priv, struct hbg_irq_info *info); + void (*irq_handle)(struct hbg_priv *priv, + const struct hbg_irq_info *info); }; struct hbg_vector { char name[HBG_VECTOR_NUM][32]; - struct hbg_irq_info *info_array; + + u64 *stats_array; + const struct hbg_irq_info *info_array; u32 info_array_len; }; @@ -142,6 +148,118 @@ struct hbg_user_def { struct ethtool_pauseparam pause_param; }; +struct hbg_stats { + u64 rx_desc_drop; + u64 rx_desc_l2_err_cnt; + u64 rx_desc_pkt_len_err_cnt; + u64 rx_desc_l3l4_err_cnt; + u64 rx_desc_l3_wrong_head_cnt; + u64 rx_desc_l3_csum_err_cnt; + u64 rx_desc_l3_len_err_cnt; + u64 rx_desc_l3_zero_ttl_cnt; + u64 rx_desc_l3_other_cnt; + u64 rx_desc_l4_err_cnt; + u64 rx_desc_l4_wrong_head_cnt; + u64 rx_desc_l4_len_err_cnt; + u64 rx_desc_l4_csum_err_cnt; + u64 rx_desc_l4_zero_port_num_cnt; + u64 rx_desc_l4_other_cnt; + u64 rx_desc_frag_cnt; + u64 rx_desc_ip_ver_err_cnt; + u64 rx_desc_ipv4_pkt_cnt; + u64 rx_desc_ipv6_pkt_cnt; + u64 rx_desc_no_ip_pkt_cnt; + u64 rx_desc_ip_pkt_cnt; + u64 rx_desc_tcp_pkt_cnt; + u64 rx_desc_udp_pkt_cnt; + u64 rx_desc_vlan_pkt_cnt; + u64 rx_desc_icmp_pkt_cnt; + u64 rx_desc_arp_pkt_cnt; + u64 rx_desc_rarp_pkt_cnt; + u64 rx_desc_multicast_pkt_cnt; + u64 rx_desc_broadcast_pkt_cnt; + u64 rx_desc_ipsec_pkt_cnt; + u64 rx_desc_ip_opt_pkt_cnt; + u64 rx_desc_key_not_match_cnt; + + u64 rx_octets_total_ok_cnt; + u64 rx_uc_pkt_cnt; + u64 rx_mc_pkt_cnt; + u64 rx_bc_pkt_cnt; + u64 rx_vlan_pkt_cnt; + u64 rx_octets_bad_cnt; + u64 rx_octets_total_filt_cnt; + u64 rx_filt_pkt_cnt; + u64 rx_trans_pkt_cnt; + u64 rx_framesize_64; + u64 rx_framesize_65_127; + u64 rx_framesize_128_255; + u64 rx_framesize_256_511; + u64 rx_framesize_512_1023; + u64 rx_framesize_1024_1518; + u64 rx_framesize_bt_1518; + u64 rx_fcs_error_cnt; + u64 rx_data_error_cnt; + u64 rx_align_error_cnt; + u64 rx_pause_macctl_frame_cnt; + u64 rx_unknown_macctl_frame_cnt; + /* crc ok, > max_frm_size, < 2max_frm_size */ + u64 rx_frame_long_err_cnt; + /* crc fail, > max_frm_size, < 2max_frm_size */ + u64 rx_jabber_err_cnt; + /* > 2max_frm_size */ + u64 rx_frame_very_long_err_cnt; + /* < 64byte, >= short_runts_thr */ + u64 rx_frame_runt_err_cnt; + /* < short_runts_thr */ + u64 rx_frame_short_err_cnt; + /* PCU: dropped when the RX FIFO is full.*/ + u64 rx_overflow_cnt; + /* GMAC: the count of overflows of the RX FIFO */ + u64 rx_overrun_cnt; + /* PCU: the count of buffer alloc errors in RX */ + u64 rx_bufrq_err_cnt; + /* PCU: the count of write descriptor errors in RX */ + u64 rx_we_err_cnt; + /* GMAC: the count of pkts that contain PAD but length is not 64 */ + u64 rx_lengthfield_err_cnt; + u64 rx_fail_comma_cnt; + + u64 rx_dma_err_cnt; + u64 rx_fifo_less_empty_thrsld_cnt; + + u64 tx_octets_total_ok_cnt; + u64 tx_uc_pkt_cnt; + u64 tx_mc_pkt_cnt; + u64 tx_bc_pkt_cnt; + u64 tx_vlan_pkt_cnt; + u64 tx_octets_bad_cnt; + u64 tx_trans_pkt_cnt; + u64 tx_pause_frame_cnt; + u64 tx_framesize_64; + u64 tx_framesize_65_127; + u64 tx_framesize_128_255; + u64 tx_framesize_256_511; + u64 tx_framesize_512_1023; + u64 tx_framesize_1024_1518; + u64 tx_framesize_bt_1518; + /* GMAC: the count of times that frames fail to be transmitted + * due to internal errors. + */ + u64 tx_underrun_err_cnt; + u64 tx_add_cs_fail_cnt; + /* PCU: the count of buffer free errors in TX */ + u64 tx_bufrl_err_cnt; + u64 tx_crc_err_cnt; + u64 tx_drop_cnt; + u64 tx_excessive_length_drop_cnt; + + u64 tx_timeout_cnt; + u64 tx_dma_err_cnt; + + u64 np_link_fail_cnt; +}; + struct hbg_priv { struct net_device *netdev; struct pci_dev *pdev; @@ -155,6 +273,12 @@ struct hbg_priv { struct hbg_mac_filter filter; enum hbg_reset_type reset_type; struct hbg_user_def user_def; + struct hbg_stats stats; + unsigned long last_update_stats_time; + struct delayed_work service_task; }; +void hbg_err_reset_task_schedule(struct hbg_priv *priv); +void hbg_np_link_fail_task_schedule(struct hbg_priv *priv); + #endif diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.c index 8473c43d171a..01ad82d2f5cc 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.c @@ -61,18 +61,19 @@ static int hbg_dbg_irq_info(struct seq_file *s, void *unused) { struct net_device *netdev = dev_get_drvdata(s->private); struct hbg_priv *priv = netdev_priv(netdev); - struct hbg_irq_info *info; + const struct hbg_irq_info *info; u32 i; for (i = 0; i < priv->vectors.info_array_len; i++) { info = &priv->vectors.info_array[i]; seq_printf(s, - "%-20s: enabled: %-5s, logged: %-5s, count: %llu\n", + "%-20s: enabled: %-5s, reset: %-5s, logged: %-5s, count: %llu\n", info->name, str_true_false(hbg_hw_irq_is_enabled(priv, info->mask)), + str_true_false(info->need_reset), str_true_false(info->need_print), - info->count); + priv->vectors.stats_array[i]); } return 0; @@ -105,6 +106,7 @@ static int hbg_dbg_nic_state(struct seq_file *s, void *unused) { struct net_device *netdev = dev_get_drvdata(s->private); struct hbg_priv *priv = netdev_priv(netdev); + bool np_link_fail; seq_printf(s, "event handling state: %s\n", state_str_true_false(priv, HBG_NIC_STATE_EVENT_HANDLING)); @@ -114,6 +116,12 @@ static int hbg_dbg_nic_state(struct seq_file *s, void *unused) state_str_true_false(priv, HBG_NIC_STATE_RESET_FAIL)); seq_printf(s, "last reset type: %s\n", reset_type_str[priv->reset_type]); + seq_printf(s, "need reset state: %s\n", + state_str_true_false(priv, HBG_NIC_STATE_NEED_RESET)); + + np_link_fail = !hbg_reg_read_field(priv, HBG_REG_AN_NEG_STATE_ADDR, + HBG_REG_AN_NEG_STATE_NP_LINK_OK_B); + seq_printf(s, "np_link fail state: %s\n", str_true_false(np_link_fail)); return 0; } diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_diagnose.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_diagnose.c new file mode 100644 index 000000000000..f23fb5920c3c --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_diagnose.c @@ -0,0 +1,348 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2025 Hisilicon Limited. + +#include <linux/iopoll.h> +#include <linux/phy.h> +#include "hbg_common.h" +#include "hbg_ethtool.h" +#include "hbg_hw.h" +#include "hbg_diagnose.h" + +#define HBG_MSG_DATA_MAX_NUM 64 + +struct hbg_diagnose_message { + u32 opcode; + u32 status; + u32 data_num; + struct hbg_priv *priv; + + u32 data[HBG_MSG_DATA_MAX_NUM]; +}; + +#define HBG_HW_PUSH_WAIT_TIMEOUT_US (2 * 1000 * 1000) +#define HBG_HW_PUSH_WAIT_INTERVAL_US (1 * 1000) + +enum hbg_push_cmd { + HBG_PUSH_CMD_IRQ = 0, + HBG_PUSH_CMD_STATS, + HBG_PUSH_CMD_LINK, +}; + +struct hbg_push_stats_info { + /* id is used to match the name of the current stats item. + * and is used for pretty print on BMC + */ + u32 id; + u64 offset; +}; + +struct hbg_push_irq_info { + /* id is used to match the name of the current irq. + * and is used for pretty print on BMC + */ + u32 id; + u32 mask; +}; + +#define HBG_PUSH_IRQ_I(name, id) {id, HBG_INT_MSK_##name##_B} +static const struct hbg_push_irq_info hbg_push_irq_list[] = { + HBG_PUSH_IRQ_I(RX, 0), + HBG_PUSH_IRQ_I(TX, 1), + HBG_PUSH_IRQ_I(TX_PKT_CPL, 2), + HBG_PUSH_IRQ_I(MAC_MII_FIFO_ERR, 3), + HBG_PUSH_IRQ_I(MAC_PCS_RX_FIFO_ERR, 4), + HBG_PUSH_IRQ_I(MAC_PCS_TX_FIFO_ERR, 5), + HBG_PUSH_IRQ_I(MAC_APP_RX_FIFO_ERR, 6), + HBG_PUSH_IRQ_I(MAC_APP_TX_FIFO_ERR, 7), + HBG_PUSH_IRQ_I(SRAM_PARITY_ERR, 8), + HBG_PUSH_IRQ_I(TX_AHB_ERR, 9), + HBG_PUSH_IRQ_I(RX_BUF_AVL, 10), + HBG_PUSH_IRQ_I(REL_BUF_ERR, 11), + HBG_PUSH_IRQ_I(TXCFG_AVL, 12), + HBG_PUSH_IRQ_I(TX_DROP, 13), + HBG_PUSH_IRQ_I(RX_DROP, 14), + HBG_PUSH_IRQ_I(RX_AHB_ERR, 15), + HBG_PUSH_IRQ_I(MAC_FIFO_ERR, 16), + HBG_PUSH_IRQ_I(RBREQ_ERR, 17), + HBG_PUSH_IRQ_I(WE_ERR, 18), +}; + +#define HBG_PUSH_STATS_I(name, id) {id, HBG_STATS_FIELD_OFF(name)} +static const struct hbg_push_stats_info hbg_push_stats_list[] = { + HBG_PUSH_STATS_I(rx_desc_drop, 0), + HBG_PUSH_STATS_I(rx_desc_l2_err_cnt, 1), + HBG_PUSH_STATS_I(rx_desc_pkt_len_err_cnt, 2), + HBG_PUSH_STATS_I(rx_desc_l3_wrong_head_cnt, 3), + HBG_PUSH_STATS_I(rx_desc_l3_csum_err_cnt, 4), + HBG_PUSH_STATS_I(rx_desc_l3_len_err_cnt, 5), + HBG_PUSH_STATS_I(rx_desc_l3_zero_ttl_cnt, 6), + HBG_PUSH_STATS_I(rx_desc_l3_other_cnt, 7), + HBG_PUSH_STATS_I(rx_desc_l4_err_cnt, 8), + HBG_PUSH_STATS_I(rx_desc_l4_wrong_head_cnt, 9), + HBG_PUSH_STATS_I(rx_desc_l4_len_err_cnt, 10), + HBG_PUSH_STATS_I(rx_desc_l4_csum_err_cnt, 11), + HBG_PUSH_STATS_I(rx_desc_l4_zero_port_num_cnt, 12), + HBG_PUSH_STATS_I(rx_desc_l4_other_cnt, 13), + HBG_PUSH_STATS_I(rx_desc_frag_cnt, 14), + HBG_PUSH_STATS_I(rx_desc_ip_ver_err_cnt, 15), + HBG_PUSH_STATS_I(rx_desc_ipv4_pkt_cnt, 16), + HBG_PUSH_STATS_I(rx_desc_ipv6_pkt_cnt, 17), + HBG_PUSH_STATS_I(rx_desc_no_ip_pkt_cnt, 18), + HBG_PUSH_STATS_I(rx_desc_ip_pkt_cnt, 19), + HBG_PUSH_STATS_I(rx_desc_tcp_pkt_cnt, 20), + HBG_PUSH_STATS_I(rx_desc_udp_pkt_cnt, 21), + HBG_PUSH_STATS_I(rx_desc_vlan_pkt_cnt, 22), + HBG_PUSH_STATS_I(rx_desc_icmp_pkt_cnt, 23), + HBG_PUSH_STATS_I(rx_desc_arp_pkt_cnt, 24), + HBG_PUSH_STATS_I(rx_desc_rarp_pkt_cnt, 25), + HBG_PUSH_STATS_I(rx_desc_multicast_pkt_cnt, 26), + HBG_PUSH_STATS_I(rx_desc_broadcast_pkt_cnt, 27), + HBG_PUSH_STATS_I(rx_desc_ipsec_pkt_cnt, 28), + HBG_PUSH_STATS_I(rx_desc_ip_opt_pkt_cnt, 29), + HBG_PUSH_STATS_I(rx_desc_key_not_match_cnt, 30), + HBG_PUSH_STATS_I(rx_octets_total_ok_cnt, 31), + HBG_PUSH_STATS_I(rx_uc_pkt_cnt, 32), + HBG_PUSH_STATS_I(rx_mc_pkt_cnt, 33), + HBG_PUSH_STATS_I(rx_bc_pkt_cnt, 34), + HBG_PUSH_STATS_I(rx_vlan_pkt_cnt, 35), + HBG_PUSH_STATS_I(rx_octets_bad_cnt, 36), + HBG_PUSH_STATS_I(rx_octets_total_filt_cnt, 37), + HBG_PUSH_STATS_I(rx_filt_pkt_cnt, 38), + HBG_PUSH_STATS_I(rx_trans_pkt_cnt, 39), + HBG_PUSH_STATS_I(rx_framesize_64, 40), + HBG_PUSH_STATS_I(rx_framesize_65_127, 41), + HBG_PUSH_STATS_I(rx_framesize_128_255, 42), + HBG_PUSH_STATS_I(rx_framesize_256_511, 43), + HBG_PUSH_STATS_I(rx_framesize_512_1023, 44), + HBG_PUSH_STATS_I(rx_framesize_1024_1518, 45), + HBG_PUSH_STATS_I(rx_framesize_bt_1518, 46), + HBG_PUSH_STATS_I(rx_fcs_error_cnt, 47), + HBG_PUSH_STATS_I(rx_data_error_cnt, 48), + HBG_PUSH_STATS_I(rx_align_error_cnt, 49), + HBG_PUSH_STATS_I(rx_frame_long_err_cnt, 50), + HBG_PUSH_STATS_I(rx_jabber_err_cnt, 51), + HBG_PUSH_STATS_I(rx_pause_macctl_frame_cnt, 52), + HBG_PUSH_STATS_I(rx_unknown_macctl_frame_cnt, 53), + HBG_PUSH_STATS_I(rx_frame_very_long_err_cnt, 54), + HBG_PUSH_STATS_I(rx_frame_runt_err_cnt, 55), + HBG_PUSH_STATS_I(rx_frame_short_err_cnt, 56), + HBG_PUSH_STATS_I(rx_overflow_cnt, 57), + HBG_PUSH_STATS_I(rx_bufrq_err_cnt, 58), + HBG_PUSH_STATS_I(rx_we_err_cnt, 59), + HBG_PUSH_STATS_I(rx_overrun_cnt, 60), + HBG_PUSH_STATS_I(rx_lengthfield_err_cnt, 61), + HBG_PUSH_STATS_I(rx_fail_comma_cnt, 62), + HBG_PUSH_STATS_I(rx_dma_err_cnt, 63), + HBG_PUSH_STATS_I(rx_fifo_less_empty_thrsld_cnt, 64), + HBG_PUSH_STATS_I(tx_octets_total_ok_cnt, 65), + HBG_PUSH_STATS_I(tx_uc_pkt_cnt, 66), + HBG_PUSH_STATS_I(tx_mc_pkt_cnt, 67), + HBG_PUSH_STATS_I(tx_bc_pkt_cnt, 68), + HBG_PUSH_STATS_I(tx_vlan_pkt_cnt, 69), + HBG_PUSH_STATS_I(tx_octets_bad_cnt, 70), + HBG_PUSH_STATS_I(tx_trans_pkt_cnt, 71), + HBG_PUSH_STATS_I(tx_pause_frame_cnt, 72), + HBG_PUSH_STATS_I(tx_framesize_64, 73), + HBG_PUSH_STATS_I(tx_framesize_65_127, 74), + HBG_PUSH_STATS_I(tx_framesize_128_255, 75), + HBG_PUSH_STATS_I(tx_framesize_256_511, 76), + HBG_PUSH_STATS_I(tx_framesize_512_1023, 77), + HBG_PUSH_STATS_I(tx_framesize_1024_1518, 78), + HBG_PUSH_STATS_I(tx_framesize_bt_1518, 79), + HBG_PUSH_STATS_I(tx_underrun_err_cnt, 80), + HBG_PUSH_STATS_I(tx_add_cs_fail_cnt, 81), + HBG_PUSH_STATS_I(tx_bufrl_err_cnt, 82), + HBG_PUSH_STATS_I(tx_crc_err_cnt, 83), + HBG_PUSH_STATS_I(tx_drop_cnt, 84), + HBG_PUSH_STATS_I(tx_excessive_length_drop_cnt, 85), + HBG_PUSH_STATS_I(tx_dma_err_cnt, 86), +}; + +static int hbg_push_msg_send(struct hbg_priv *priv, + struct hbg_diagnose_message *msg) +{ + u32 header = 0; + u32 i; + + if (msg->data_num == 0) + return 0; + + for (i = 0; i < msg->data_num && i < HBG_MSG_DATA_MAX_NUM; i++) + hbg_reg_write(priv, + HBG_REG_MSG_DATA_BASE_ADDR + i * sizeof(u32), + msg->data[i]); + + hbg_field_modify(header, HBG_REG_MSG_HEADER_OPCODE_M, msg->opcode); + hbg_field_modify(header, HBG_REG_MSG_HEADER_DATA_NUM_M, msg->data_num); + hbg_field_modify(header, HBG_REG_MSG_HEADER_RESP_CODE_M, ETIMEDOUT); + + /* start status */ + hbg_field_modify(header, HBG_REG_MSG_HEADER_STATUS_M, 1); + + /* write header msg to start push */ + hbg_reg_write(priv, HBG_REG_MSG_HEADER_ADDR, header); + + /* wait done */ + readl_poll_timeout(priv->io_base + HBG_REG_MSG_HEADER_ADDR, header, + !FIELD_GET(HBG_REG_MSG_HEADER_STATUS_M, header), + HBG_HW_PUSH_WAIT_INTERVAL_US, + HBG_HW_PUSH_WAIT_TIMEOUT_US); + + msg->status = FIELD_GET(HBG_REG_MSG_HEADER_STATUS_M, header); + return -(int)FIELD_GET(HBG_REG_MSG_HEADER_RESP_CODE_M, header); +} + +static int hbg_push_data(struct hbg_priv *priv, + u32 opcode, u32 *data, u32 data_num) +{ + struct hbg_diagnose_message msg = {0}; + u32 data_left_num; + u32 i, j; + int ret; + + msg.priv = priv; + msg.opcode = opcode; + for (i = 0; i < data_num / HBG_MSG_DATA_MAX_NUM + 1; i++) { + if (i * HBG_MSG_DATA_MAX_NUM >= data_num) + break; + + data_left_num = data_num - i * HBG_MSG_DATA_MAX_NUM; + for (j = 0; j < data_left_num && j < HBG_MSG_DATA_MAX_NUM; j++) + msg.data[j] = data[i * HBG_MSG_DATA_MAX_NUM + j]; + + msg.data_num = j; + ret = hbg_push_msg_send(priv, &msg); + if (ret) + return ret; + } + + return 0; +} + +static int hbg_push_data_u64(struct hbg_priv *priv, u32 opcode, + u64 *data, u32 data_num) +{ + /* The length of u64 is twice that of u32, + * the data_num must be multiplied by 2. + */ + return hbg_push_data(priv, opcode, (u32 *)data, data_num * 2); +} + +static u64 hbg_get_irq_stats(struct hbg_vector *vectors, u32 mask) +{ + u32 i = 0; + + for (i = 0; i < vectors->info_array_len; i++) + if (vectors->info_array[i].mask == mask) + return vectors->stats_array[i]; + + return 0; +} + +static int hbg_push_irq_cnt(struct hbg_priv *priv) +{ + /* An id needs to be added for each data. + * Therefore, the data_num must be multiplied by 2. + */ + u32 data_num = ARRAY_SIZE(hbg_push_irq_list) * 2; + struct hbg_vector *vectors = &priv->vectors; + const struct hbg_push_irq_info *info; + u32 i, j = 0; + u64 *data; + int ret; + + data = kcalloc(data_num, sizeof(u64), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* An id needs to be added for each data. + * So i + 2 for each loop. + */ + for (i = 0; i < data_num; i += 2) { + info = &hbg_push_irq_list[j++]; + data[i] = info->id; + data[i + 1] = hbg_get_irq_stats(vectors, info->mask); + } + + ret = hbg_push_data_u64(priv, HBG_PUSH_CMD_IRQ, data, data_num); + kfree(data); + return ret; +} + +static int hbg_push_link_status(struct hbg_priv *priv) +{ + u32 link_status[2]; + + /* phy link status */ + link_status[0] = priv->mac.phydev->link; + /* mac link status */ + link_status[1] = hbg_reg_read_field(priv, HBG_REG_AN_NEG_STATE_ADDR, + HBG_REG_AN_NEG_STATE_NP_LINK_OK_B); + + return hbg_push_data(priv, HBG_PUSH_CMD_LINK, + link_status, ARRAY_SIZE(link_status)); +} + +static int hbg_push_stats(struct hbg_priv *priv) +{ + /* An id needs to be added for each data. + * Therefore, the data_num must be multiplied by 2. + */ + u64 data_num = ARRAY_SIZE(hbg_push_stats_list) * 2; + struct hbg_stats *stats = &priv->stats; + const struct hbg_push_stats_info *info; + u32 i, j = 0; + u64 *data; + int ret; + + data = kcalloc(data_num, sizeof(u64), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* An id needs to be added for each data. + * So i + 2 for each loop. + */ + for (i = 0; i < data_num; i += 2) { + info = &hbg_push_stats_list[j++]; + data[i] = info->id; + data[i + 1] = HBG_STATS_R(stats, info->offset); + } + + ret = hbg_push_data_u64(priv, HBG_PUSH_CMD_STATS, data, data_num); + kfree(data); + return ret; +} + +void hbg_diagnose_message_push(struct hbg_priv *priv) +{ + int ret; + + if (test_bit(HBG_NIC_STATE_RESETTING, &priv->state)) + return; + + /* only 1 is the right value */ + if (hbg_reg_read(priv, HBG_REG_PUSH_REQ_ADDR) != 1) + return; + + ret = hbg_push_irq_cnt(priv); + if (ret) { + dev_err(&priv->pdev->dev, + "failed to push irq cnt, ret = %d\n", ret); + goto push_done; + } + + ret = hbg_push_link_status(priv); + if (ret) { + dev_err(&priv->pdev->dev, + "failed to push link status, ret = %d\n", ret); + goto push_done; + } + + ret = hbg_push_stats(priv); + if (ret) + dev_err(&priv->pdev->dev, + "failed to push stats, ret = %d\n", ret); + +push_done: + hbg_reg_write(priv, HBG_REG_PUSH_REQ_ADDR, 0); +} diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_diagnose.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_diagnose.h new file mode 100644 index 000000000000..ba04c6d8c03d --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_diagnose.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2025 Hisilicon Limited. */ + +#ifndef __HBG_DIAGNOSE_H +#define __HBG_DIAGNOSE_H + +#include "hbg_common.h" + +void hbg_diagnose_message_push(struct hbg_priv *priv); + +#endif diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c index 4d1f4a33391a..ff3295b60a69 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c @@ -26,12 +26,15 @@ static void hbg_restore_mac_table(struct hbg_priv *priv) static void hbg_restore_user_def_settings(struct hbg_priv *priv) { + /* The index of host mac is always 0. */ + u64 rx_pause_addr = ether_addr_to_u64(priv->filter.mac_table[0].addr); struct ethtool_pauseparam *pause_param = &priv->user_def.pause_param; hbg_restore_mac_table(priv); hbg_hw_set_mtu(priv, priv->netdev->mtu); hbg_hw_set_pause_enable(priv, pause_param->tx_pause, pause_param->rx_pause); + hbg_hw_set_rx_pause_mac_addr(priv, rx_pause_addr); } int hbg_rebuild(struct hbg_priv *priv) @@ -58,6 +61,8 @@ static int hbg_reset_prepare(struct hbg_priv *priv, enum hbg_reset_type type) return -EBUSY; } + netif_device_detach(priv->netdev); + priv->reset_type = type; set_bit(HBG_NIC_STATE_RESETTING, &priv->state); clear_bit(HBG_NIC_STATE_RESET_FAIL, &priv->state); @@ -88,6 +93,8 @@ static int hbg_reset_done(struct hbg_priv *priv, enum hbg_reset_type type) return ret; } + netif_device_attach(priv->netdev); + dev_info(&priv->pdev->dev, "reset done\n"); return ret; } @@ -105,6 +112,58 @@ int hbg_reset(struct hbg_priv *priv) return hbg_reset_done(priv, HBG_RESET_TYPE_FUNCTION); } +void hbg_err_reset(struct hbg_priv *priv) +{ + bool running; + + rtnl_lock(); + running = netif_running(priv->netdev); + if (running) + dev_close(priv->netdev); + + if (hbg_reset(priv)) + goto err_unlock; + + if (running) + dev_open(priv->netdev, NULL); + +err_unlock: + rtnl_unlock(); +} + +static pci_ers_result_t hbg_pci_err_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + + netif_device_detach(netdev); + + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + + pci_disable_device(pdev); + return PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t hbg_pci_err_slot_reset(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct hbg_priv *priv = netdev_priv(netdev); + + if (pci_enable_device(pdev)) { + dev_err(&pdev->dev, + "failed to re-enable PCI device after reset\n"); + return PCI_ERS_RESULT_DISCONNECT; + } + + pci_set_master(pdev); + pci_restore_state(pdev); + pci_save_state(pdev); + + hbg_err_reset(priv); + return PCI_ERS_RESULT_RECOVERED; +} + static void hbg_pci_err_reset_prepare(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); @@ -124,6 +183,8 @@ static void hbg_pci_err_reset_done(struct pci_dev *pdev) } static const struct pci_error_handlers hbg_pci_err_handler = { + .error_detected = hbg_pci_err_detected, + .slot_reset = hbg_pci_err_slot_reset, .reset_prepare = hbg_pci_err_reset_prepare, .reset_done = hbg_pci_err_reset_done, }; diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.h index d7828e446308..fb9fbe7004e8 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.h +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.h @@ -9,5 +9,6 @@ void hbg_set_pci_err_handler(struct pci_driver *pdrv); int hbg_reset(struct hbg_priv *priv); int hbg_rebuild(struct hbg_priv *priv); +void hbg_err_reset(struct hbg_priv *priv); #endif diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c index 00364a438ec2..55520053270a 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c @@ -9,6 +9,136 @@ #include "hbg_ethtool.h" #include "hbg_hw.h" +struct hbg_ethtool_stats { + char name[ETH_GSTRING_LEN]; + unsigned long offset; + u32 reg; /* set to 0 if stats is not updated via dump reg */ +}; + +#define HBG_STATS_I(stats) { #stats, HBG_STATS_FIELD_OFF(stats), 0} +#define HBG_STATS_REG_I(stats, reg) { #stats, HBG_STATS_FIELD_OFF(stats), reg} + +static const struct hbg_ethtool_stats hbg_ethtool_stats_info[] = { + HBG_STATS_I(rx_desc_l2_err_cnt), + HBG_STATS_I(rx_desc_pkt_len_err_cnt), + HBG_STATS_I(rx_desc_l3_wrong_head_cnt), + HBG_STATS_I(rx_desc_l3_csum_err_cnt), + HBG_STATS_I(rx_desc_l3_len_err_cnt), + HBG_STATS_I(rx_desc_l3_zero_ttl_cnt), + HBG_STATS_I(rx_desc_l3_other_cnt), + HBG_STATS_I(rx_desc_l4_wrong_head_cnt), + HBG_STATS_I(rx_desc_l4_len_err_cnt), + HBG_STATS_I(rx_desc_l4_csum_err_cnt), + HBG_STATS_I(rx_desc_l4_zero_port_num_cnt), + HBG_STATS_I(rx_desc_l4_other_cnt), + HBG_STATS_I(rx_desc_ip_ver_err_cnt), + HBG_STATS_I(rx_desc_ipv4_pkt_cnt), + HBG_STATS_I(rx_desc_ipv6_pkt_cnt), + HBG_STATS_I(rx_desc_no_ip_pkt_cnt), + HBG_STATS_I(rx_desc_ip_pkt_cnt), + HBG_STATS_I(rx_desc_tcp_pkt_cnt), + HBG_STATS_I(rx_desc_udp_pkt_cnt), + HBG_STATS_I(rx_desc_vlan_pkt_cnt), + HBG_STATS_I(rx_desc_icmp_pkt_cnt), + HBG_STATS_I(rx_desc_arp_pkt_cnt), + HBG_STATS_I(rx_desc_rarp_pkt_cnt), + HBG_STATS_I(rx_desc_multicast_pkt_cnt), + HBG_STATS_I(rx_desc_broadcast_pkt_cnt), + HBG_STATS_I(rx_desc_ipsec_pkt_cnt), + HBG_STATS_I(rx_desc_ip_opt_pkt_cnt), + HBG_STATS_I(rx_desc_key_not_match_cnt), + + HBG_STATS_REG_I(rx_octets_bad_cnt, HBG_REG_RX_OCTETS_BAD_ADDR), + HBG_STATS_REG_I(rx_octets_total_filt_cnt, + HBG_REG_RX_OCTETS_TOTAL_FILT_ADDR), + HBG_STATS_REG_I(rx_uc_pkt_cnt, HBG_REG_RX_UC_PKTS_ADDR), + HBG_STATS_REG_I(rx_vlan_pkt_cnt, HBG_REG_RX_TAGGED_ADDR), + HBG_STATS_REG_I(rx_filt_pkt_cnt, HBG_REG_RX_FILT_PKT_CNT_ADDR), + HBG_STATS_REG_I(rx_data_error_cnt, HBG_REG_RX_DATA_ERR_ADDR), + HBG_STATS_REG_I(rx_frame_long_err_cnt, HBG_REG_RX_LONG_ERRORS_ADDR), + HBG_STATS_REG_I(rx_jabber_err_cnt, HBG_REG_RX_JABBER_ERRORS_ADDR), + HBG_STATS_REG_I(rx_frame_very_long_err_cnt, + HBG_REG_RX_VERY_LONG_ERR_CNT_ADDR), + HBG_STATS_REG_I(rx_frame_runt_err_cnt, HBG_REG_RX_RUNT_ERR_CNT_ADDR), + HBG_STATS_REG_I(rx_frame_short_err_cnt, HBG_REG_RX_SHORT_ERR_CNT_ADDR), + HBG_STATS_REG_I(rx_overflow_cnt, HBG_REG_RX_OVER_FLOW_CNT_ADDR), + HBG_STATS_REG_I(rx_bufrq_err_cnt, HBG_REG_RX_BUFRQ_ERR_CNT_ADDR), + HBG_STATS_REG_I(rx_we_err_cnt, HBG_REG_RX_WE_ERR_CNT_ADDR), + HBG_STATS_REG_I(rx_overrun_cnt, HBG_REG_RX_OVERRUN_CNT_ADDR), + HBG_STATS_REG_I(rx_lengthfield_err_cnt, + HBG_REG_RX_LENGTHFIELD_ERR_CNT_ADDR), + HBG_STATS_REG_I(rx_fail_comma_cnt, HBG_REG_RX_FAIL_COMMA_CNT_ADDR), + HBG_STATS_I(rx_dma_err_cnt), + HBG_STATS_I(rx_fifo_less_empty_thrsld_cnt), + + HBG_STATS_REG_I(tx_uc_pkt_cnt, HBG_REG_TX_UC_PKTS_ADDR), + HBG_STATS_REG_I(tx_vlan_pkt_cnt, HBG_REG_TX_TAGGED_ADDR), + HBG_STATS_REG_I(tx_octets_bad_cnt, HBG_REG_OCTETS_TRANSMITTED_BAD_ADDR), + + HBG_STATS_REG_I(tx_underrun_err_cnt, HBG_REG_TX_UNDERRUN_ADDR), + HBG_STATS_REG_I(tx_add_cs_fail_cnt, HBG_REG_TX_CS_FAIL_CNT_ADDR), + HBG_STATS_REG_I(tx_bufrl_err_cnt, HBG_REG_TX_BUFRL_ERR_CNT_ADDR), + HBG_STATS_REG_I(tx_crc_err_cnt, HBG_REG_TX_CRC_ERROR_ADDR), + HBG_STATS_REG_I(tx_drop_cnt, HBG_REG_TX_DROP_CNT_ADDR), + HBG_STATS_REG_I(tx_excessive_length_drop_cnt, + HBG_REG_TX_EXCESSIVE_LENGTH_DROP_ADDR), + HBG_STATS_I(tx_dma_err_cnt), + HBG_STATS_I(tx_timeout_cnt), +}; + +static const struct hbg_ethtool_stats hbg_ethtool_rmon_stats_info[] = { + HBG_STATS_I(rx_desc_frag_cnt), + HBG_STATS_REG_I(rx_framesize_64, HBG_REG_RX_PKTS_64OCTETS_ADDR), + HBG_STATS_REG_I(rx_framesize_65_127, + HBG_REG_RX_PKTS_65TO127OCTETS_ADDR), + HBG_STATS_REG_I(rx_framesize_128_255, + HBG_REG_RX_PKTS_128TO255OCTETS_ADDR), + HBG_STATS_REG_I(rx_framesize_256_511, + HBG_REG_RX_PKTS_256TO511OCTETS_ADDR), + HBG_STATS_REG_I(rx_framesize_512_1023, + HBG_REG_RX_PKTS_512TO1023OCTETS_ADDR), + HBG_STATS_REG_I(rx_framesize_1024_1518, + HBG_REG_RX_PKTS_1024TO1518OCTETS_ADDR), + HBG_STATS_REG_I(rx_framesize_bt_1518, + HBG_REG_RX_PKTS_1519TOMAXOCTETS_ADDR), + HBG_STATS_REG_I(tx_framesize_64, HBG_REG_TX_PKTS_64OCTETS_ADDR), + HBG_STATS_REG_I(tx_framesize_65_127, + HBG_REG_TX_PKTS_65TO127OCTETS_ADDR), + HBG_STATS_REG_I(tx_framesize_128_255, + HBG_REG_TX_PKTS_128TO255OCTETS_ADDR), + HBG_STATS_REG_I(tx_framesize_256_511, + HBG_REG_TX_PKTS_256TO511OCTETS_ADDR), + HBG_STATS_REG_I(tx_framesize_512_1023, + HBG_REG_TX_PKTS_512TO1023OCTETS_ADDR), + HBG_STATS_REG_I(tx_framesize_1024_1518, + HBG_REG_TX_PKTS_1024TO1518OCTETS_ADDR), + HBG_STATS_REG_I(tx_framesize_bt_1518, + HBG_REG_TX_PKTS_1519TOMAXOCTETS_ADDR), +}; + +static const struct hbg_ethtool_stats hbg_ethtool_mac_stats_info[] = { + HBG_STATS_REG_I(rx_mc_pkt_cnt, HBG_REG_RX_MC_PKTS_ADDR), + HBG_STATS_REG_I(rx_bc_pkt_cnt, HBG_REG_RX_BC_PKTS_ADDR), + HBG_STATS_REG_I(rx_align_error_cnt, HBG_REG_RX_ALIGN_ERRORS_ADDR), + HBG_STATS_REG_I(rx_octets_total_ok_cnt, + HBG_REG_RX_OCTETS_TOTAL_OK_ADDR), + HBG_STATS_REG_I(rx_trans_pkt_cnt, HBG_REG_RX_TRANS_PKG_CNT_ADDR), + HBG_STATS_REG_I(rx_fcs_error_cnt, HBG_REG_RX_FCS_ERRORS_ADDR), + HBG_STATS_REG_I(tx_mc_pkt_cnt, HBG_REG_TX_MC_PKTS_ADDR), + HBG_STATS_REG_I(tx_bc_pkt_cnt, HBG_REG_TX_BC_PKTS_ADDR), + HBG_STATS_REG_I(tx_octets_total_ok_cnt, + HBG_REG_OCTETS_TRANSMITTED_OK_ADDR), + HBG_STATS_REG_I(tx_trans_pkt_cnt, HBG_REG_TX_TRANS_PKG_CNT_ADDR), +}; + +static const struct hbg_ethtool_stats hbg_ethtool_ctrl_stats_info[] = { + HBG_STATS_REG_I(rx_pause_macctl_frame_cnt, + HBG_REG_RX_PAUSE_MACCTL_FRAMCOUNTER_ADDR), + HBG_STATS_REG_I(tx_pause_frame_cnt, HBG_REG_TX_PAUSE_FRAMES_ADDR), + HBG_STATS_REG_I(rx_unknown_macctl_frame_cnt, + HBG_REG_RX_UNKNOWN_MACCTL_FRAMCOUNTER_ADDR), +}; + enum hbg_reg_dump_type { HBG_DUMP_REG_TYPE_SPEC = 0, HBG_DUMP_REG_TYPE_MDIO, @@ -180,6 +310,170 @@ static int hbg_ethtool_reset(struct net_device *netdev, u32 *flags) return hbg_reset(priv); } +static void hbg_update_stats_by_info(struct hbg_priv *priv, + const struct hbg_ethtool_stats *info, + u32 info_len) +{ + const struct hbg_ethtool_stats *stats; + u32 i; + + if (test_bit(HBG_NIC_STATE_RESETTING, &priv->state)) + return; + + for (i = 0; i < info_len; i++) { + stats = &info[i]; + if (!stats->reg) + continue; + + HBG_STATS_U(&priv->stats, stats->offset, + hbg_reg_read(priv, stats->reg)); + } +} + +void hbg_update_stats(struct hbg_priv *priv) +{ + hbg_update_stats_by_info(priv, hbg_ethtool_stats_info, + ARRAY_SIZE(hbg_ethtool_stats_info)); + hbg_update_stats_by_info(priv, hbg_ethtool_rmon_stats_info, + ARRAY_SIZE(hbg_ethtool_rmon_stats_info)); + hbg_update_stats_by_info(priv, hbg_ethtool_mac_stats_info, + ARRAY_SIZE(hbg_ethtool_mac_stats_info)); + hbg_update_stats_by_info(priv, hbg_ethtool_ctrl_stats_info, + ARRAY_SIZE(hbg_ethtool_ctrl_stats_info)); +} + +static int hbg_ethtool_get_sset_count(struct net_device *netdev, int stringset) +{ + if (stringset != ETH_SS_STATS) + return -EOPNOTSUPP; + + return ARRAY_SIZE(hbg_ethtool_stats_info); +} + +static void hbg_ethtool_get_strings(struct net_device *netdev, + u32 stringset, u8 *data) +{ + u32 i; + + if (stringset != ETH_SS_STATS) + return; + + for (i = 0; i < ARRAY_SIZE(hbg_ethtool_stats_info); i++) + ethtool_puts(&data, hbg_ethtool_stats_info[i].name); +} + +static void hbg_ethtool_get_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 *data) +{ + struct hbg_priv *priv = netdev_priv(netdev); + u32 i; + + hbg_update_stats(priv); + for (i = 0; i < ARRAY_SIZE(hbg_ethtool_stats_info); i++) + *data++ = HBG_STATS_R(&priv->stats, + hbg_ethtool_stats_info[i].offset); +} + +static void hbg_ethtool_get_pause_stats(struct net_device *netdev, + struct ethtool_pause_stats *epstats) +{ + struct hbg_priv *priv = netdev_priv(netdev); + struct hbg_stats *stats = &priv->stats; + + hbg_update_stats(priv); + epstats->rx_pause_frames = stats->rx_pause_macctl_frame_cnt; + epstats->tx_pause_frames = stats->tx_pause_frame_cnt; +} + +static void hbg_ethtool_get_eth_mac_stats(struct net_device *netdev, + struct ethtool_eth_mac_stats *emstats) +{ + struct hbg_priv *priv = netdev_priv(netdev); + struct hbg_stats *stats = &priv->stats; + + hbg_update_stats(priv); + emstats->FramesTransmittedOK = stats->tx_trans_pkt_cnt; + emstats->FramesReceivedOK = stats->rx_trans_pkt_cnt; + emstats->FrameCheckSequenceErrors = stats->rx_fcs_error_cnt; + emstats->AlignmentErrors = stats->rx_align_error_cnt; + emstats->OctetsTransmittedOK = stats->tx_octets_total_ok_cnt; + emstats->OctetsReceivedOK = stats->rx_octets_total_ok_cnt; + + emstats->MulticastFramesXmittedOK = stats->tx_mc_pkt_cnt; + emstats->BroadcastFramesXmittedOK = stats->tx_bc_pkt_cnt; + emstats->MulticastFramesReceivedOK = stats->rx_mc_pkt_cnt; + emstats->BroadcastFramesReceivedOK = stats->rx_bc_pkt_cnt; + emstats->InRangeLengthErrors = stats->rx_fcs_error_cnt + + stats->rx_jabber_err_cnt + + stats->rx_unknown_macctl_frame_cnt + + stats->rx_bufrq_err_cnt + + stats->rx_we_err_cnt; + emstats->OutOfRangeLengthField = stats->rx_frame_short_err_cnt + + stats->rx_frame_runt_err_cnt + + stats->rx_lengthfield_err_cnt + + stats->rx_frame_long_err_cnt + + stats->rx_frame_very_long_err_cnt; + emstats->FrameTooLongErrors = stats->rx_frame_long_err_cnt + + stats->rx_frame_very_long_err_cnt; +} + +static void +hbg_ethtool_get_eth_ctrl_stats(struct net_device *netdev, + struct ethtool_eth_ctrl_stats *ecstats) +{ + struct hbg_priv *priv = netdev_priv(netdev); + struct hbg_stats *s = &priv->stats; + + hbg_update_stats(priv); + ecstats->MACControlFramesTransmitted = s->tx_pause_frame_cnt; + ecstats->MACControlFramesReceived = s->rx_pause_macctl_frame_cnt; + ecstats->UnsupportedOpcodesReceived = s->rx_unknown_macctl_frame_cnt; +} + +static const struct ethtool_rmon_hist_range hbg_rmon_ranges[] = { + { 0, 64 }, + { 65, 127 }, + { 128, 255 }, + { 256, 511 }, + { 512, 1023 }, + { 1024, 1518 }, + { 1519, 4095 }, +}; + +static void +hbg_ethtool_get_rmon_stats(struct net_device *netdev, + struct ethtool_rmon_stats *rmon_stats, + const struct ethtool_rmon_hist_range **ranges) +{ + struct hbg_priv *priv = netdev_priv(netdev); + struct hbg_stats *stats = &priv->stats; + + hbg_update_stats(priv); + rmon_stats->undersize_pkts = stats->rx_frame_short_err_cnt + + stats->rx_frame_runt_err_cnt + + stats->rx_lengthfield_err_cnt; + rmon_stats->oversize_pkts = stats->rx_frame_long_err_cnt + + stats->rx_frame_very_long_err_cnt; + rmon_stats->fragments = stats->rx_desc_frag_cnt; + rmon_stats->hist[0] = stats->rx_framesize_64; + rmon_stats->hist[1] = stats->rx_framesize_65_127; + rmon_stats->hist[2] = stats->rx_framesize_128_255; + rmon_stats->hist[3] = stats->rx_framesize_256_511; + rmon_stats->hist[4] = stats->rx_framesize_512_1023; + rmon_stats->hist[5] = stats->rx_framesize_1024_1518; + rmon_stats->hist[6] = stats->rx_framesize_bt_1518; + + rmon_stats->hist_tx[0] = stats->tx_framesize_64; + rmon_stats->hist_tx[1] = stats->tx_framesize_65_127; + rmon_stats->hist_tx[2] = stats->tx_framesize_128_255; + rmon_stats->hist_tx[3] = stats->tx_framesize_256_511; + rmon_stats->hist_tx[4] = stats->tx_framesize_512_1023; + rmon_stats->hist_tx[5] = stats->tx_framesize_1024_1518; + rmon_stats->hist_tx[6] = stats->tx_framesize_bt_1518; + + *ranges = hbg_rmon_ranges; +} + static const struct ethtool_ops hbg_ethtool_ops = { .get_link = ethtool_op_get_link, .get_link_ksettings = phy_ethtool_get_link_ksettings, @@ -190,6 +484,13 @@ static const struct ethtool_ops hbg_ethtool_ops = { .set_pauseparam = hbg_ethtool_set_pauseparam, .reset = hbg_ethtool_reset, .nway_reset = phy_ethtool_nway_reset, + .get_sset_count = hbg_ethtool_get_sset_count, + .get_strings = hbg_ethtool_get_strings, + .get_ethtool_stats = hbg_ethtool_get_stats, + .get_pause_stats = hbg_ethtool_get_pause_stats, + .get_eth_mac_stats = hbg_ethtool_get_eth_mac_stats, + .get_eth_ctrl_stats = hbg_ethtool_get_eth_ctrl_stats, + .get_rmon_stats = hbg_ethtool_get_rmon_stats, }; void hbg_ethtool_set_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.h index 628707ec2686..e173155b146a 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.h +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.h @@ -6,6 +6,11 @@ #include <linux/netdevice.h> +#define HBG_STATS_FIELD_OFF(f) (offsetof(struct hbg_stats, f)) +#define HBG_STATS_R(p, offset) (*(u64 *)((u8 *)(p) + (offset))) +#define HBG_STATS_U(p, offset, val) (HBG_STATS_R(p, offset) += (val)) + void hbg_ethtool_set_ops(struct net_device *netdev); +void hbg_update_stats(struct hbg_priv *priv); #endif diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c index e7798f213645..9b65eef62b3f 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c @@ -213,10 +213,20 @@ void hbg_hw_fill_buffer(struct hbg_priv *priv, u32 buffer_dma_addr) void hbg_hw_adjust_link(struct hbg_priv *priv, u32 speed, u32 duplex) { + hbg_hw_mac_enable(priv, HBG_STATUS_DISABLE); + hbg_reg_write_field(priv, HBG_REG_PORT_MODE_ADDR, HBG_REG_PORT_MODE_M, speed); hbg_reg_write_field(priv, HBG_REG_DUPLEX_TYPE_ADDR, HBG_REG_DUPLEX_B, duplex); + + hbg_hw_event_notify(priv, HBG_HW_EVENT_CORE_RESET); + + hbg_hw_mac_enable(priv, HBG_STATUS_ENABLE); + + if (!hbg_reg_read_field(priv, HBG_REG_AN_NEG_STATE_ADDR, + HBG_REG_AN_NEG_STATE_NP_LINK_OK_B)) + hbg_np_link_fail_task_schedule(priv); } /* only support uc filter */ @@ -224,6 +234,10 @@ void hbg_hw_set_mac_filter_enable(struct hbg_priv *priv, u32 enable) { hbg_reg_write_field(priv, HBG_REG_REC_FILT_CTRL_ADDR, HBG_REG_REC_FILT_CTRL_UC_MATCH_EN_B, enable); + + /* only uc filter is supported, so set all bits of mc mask reg to 1 */ + hbg_reg_write64(priv, HBG_REG_STATION_ADDR_LOW_MSK_0, U64_MAX); + hbg_reg_write64(priv, HBG_REG_STATION_ADDR_LOW_MSK_1, U64_MAX); } void hbg_hw_set_pause_enable(struct hbg_priv *priv, u32 tx_en, u32 rx_en) @@ -232,6 +246,9 @@ void hbg_hw_set_pause_enable(struct hbg_priv *priv, u32 tx_en, u32 rx_en) HBG_REG_PAUSE_ENABLE_TX_B, tx_en); hbg_reg_write_field(priv, HBG_REG_PAUSE_ENABLE_ADDR, HBG_REG_PAUSE_ENABLE_RX_B, rx_en); + + hbg_reg_write_field(priv, HBG_REG_REC_FILT_CTRL_ADDR, + HBG_REG_REC_FILT_CTRL_PAUSE_FRM_PASS_B, rx_en); } void hbg_hw_get_pause_enable(struct hbg_priv *priv, u32 *tx_en, u32 *rx_en) diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c index 25dd25f096fe..8af0bc4cca21 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c @@ -6,54 +6,65 @@ #include "hbg_hw.h" static void hbg_irq_handle_err(struct hbg_priv *priv, - struct hbg_irq_info *irq_info) + const struct hbg_irq_info *irq_info) { if (irq_info->need_print) dev_err(&priv->pdev->dev, "receive error interrupt: %s\n", irq_info->name); + + if (irq_info->need_reset) + hbg_err_reset_task_schedule(priv); } static void hbg_irq_handle_tx(struct hbg_priv *priv, - struct hbg_irq_info *irq_info) + const struct hbg_irq_info *irq_info) { napi_schedule(&priv->tx_ring.napi); } static void hbg_irq_handle_rx(struct hbg_priv *priv, - struct hbg_irq_info *irq_info) + const struct hbg_irq_info *irq_info) { napi_schedule(&priv->rx_ring.napi); } -#define HBG_TXRX_IRQ_I(name, handle) \ - {#name, HBG_INT_MSK_##name##_B, false, false, 0, handle} -#define HBG_ERR_IRQ_I(name, need_print) \ - {#name, HBG_INT_MSK_##name##_B, true, need_print, 0, hbg_irq_handle_err} - -static struct hbg_irq_info hbg_irqs[] = { - HBG_TXRX_IRQ_I(RX, hbg_irq_handle_rx), - HBG_TXRX_IRQ_I(TX, hbg_irq_handle_tx), - HBG_ERR_IRQ_I(MAC_MII_FIFO_ERR, true), - HBG_ERR_IRQ_I(MAC_PCS_RX_FIFO_ERR, true), - HBG_ERR_IRQ_I(MAC_PCS_TX_FIFO_ERR, true), - HBG_ERR_IRQ_I(MAC_APP_RX_FIFO_ERR, true), - HBG_ERR_IRQ_I(MAC_APP_TX_FIFO_ERR, true), - HBG_ERR_IRQ_I(SRAM_PARITY_ERR, true), - HBG_ERR_IRQ_I(TX_AHB_ERR, true), - HBG_ERR_IRQ_I(RX_BUF_AVL, false), - HBG_ERR_IRQ_I(REL_BUF_ERR, true), - HBG_ERR_IRQ_I(TXCFG_AVL, false), - HBG_ERR_IRQ_I(TX_DROP, false), - HBG_ERR_IRQ_I(RX_DROP, false), - HBG_ERR_IRQ_I(RX_AHB_ERR, true), - HBG_ERR_IRQ_I(MAC_FIFO_ERR, false), - HBG_ERR_IRQ_I(RBREQ_ERR, false), - HBG_ERR_IRQ_I(WE_ERR, false), +static void hbg_irq_handle_rx_buf_val(struct hbg_priv *priv, + const struct hbg_irq_info *irq_info) +{ + priv->stats.rx_fifo_less_empty_thrsld_cnt++; +} + +#define HBG_IRQ_I(name, handle) \ + {#name, HBG_INT_MSK_##name##_B, false, false, false, handle} +#define HBG_ERR_IRQ_I(name, need_print, ndde_reset) \ + {#name, HBG_INT_MSK_##name##_B, true, need_print, \ + ndde_reset, hbg_irq_handle_err} + +static const struct hbg_irq_info hbg_irqs[] = { + HBG_IRQ_I(RX, hbg_irq_handle_rx), + HBG_IRQ_I(TX, hbg_irq_handle_tx), + HBG_ERR_IRQ_I(TX_PKT_CPL, true, true), + HBG_ERR_IRQ_I(MAC_MII_FIFO_ERR, true, true), + HBG_ERR_IRQ_I(MAC_PCS_RX_FIFO_ERR, true, true), + HBG_ERR_IRQ_I(MAC_PCS_TX_FIFO_ERR, true, true), + HBG_ERR_IRQ_I(MAC_APP_RX_FIFO_ERR, true, true), + HBG_ERR_IRQ_I(MAC_APP_TX_FIFO_ERR, true, true), + HBG_ERR_IRQ_I(SRAM_PARITY_ERR, true, false), + HBG_ERR_IRQ_I(TX_AHB_ERR, true, true), + HBG_IRQ_I(RX_BUF_AVL, hbg_irq_handle_rx_buf_val), + HBG_ERR_IRQ_I(REL_BUF_ERR, true, false), + HBG_ERR_IRQ_I(TXCFG_AVL, false, false), + HBG_ERR_IRQ_I(TX_DROP, false, false), + HBG_ERR_IRQ_I(RX_DROP, false, false), + HBG_ERR_IRQ_I(RX_AHB_ERR, true, false), + HBG_ERR_IRQ_I(MAC_FIFO_ERR, true, true), + HBG_ERR_IRQ_I(RBREQ_ERR, true, true), + HBG_ERR_IRQ_I(WE_ERR, true, true), }; static irqreturn_t hbg_irq_handle(int irq_num, void *p) { - struct hbg_irq_info *info; + const struct hbg_irq_info *info; struct hbg_priv *priv = p; u32 status; u32 i; @@ -68,7 +79,7 @@ static irqreturn_t hbg_irq_handle(int irq_num, void *p) hbg_hw_irq_enable(priv, info->mask, false); hbg_hw_irq_clear(priv, info->mask); - info->count++; + priv->vectors.stats_array[i]++; if (info->irq_handle) info->irq_handle(priv, info); @@ -121,6 +132,12 @@ int hbg_irq_init(struct hbg_priv *priv) irq_names_map[i]); } + vectors->stats_array = devm_kcalloc(&priv->pdev->dev, + ARRAY_SIZE(hbg_irqs), + sizeof(u64), GFP_KERNEL); + if (!vectors->stats_array) + return -ENOMEM; + vectors->info_array = hbg_irqs; vectors->info_array_len = ARRAY_SIZE(hbg_irqs); return 0; diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c index bb0f25ac9760..2e64dc1ab355 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c @@ -5,7 +5,9 @@ #include <linux/if_vlan.h> #include <linux/netdevice.h> #include <linux/pci.h> +#include <linux/phy.h> #include "hbg_common.h" +#include "hbg_diagnose.h" #include "hbg_err.h" #include "hbg_ethtool.h" #include "hbg_hw.h" @@ -14,9 +16,12 @@ #include "hbg_txrx.h" #include "hbg_debugfs.h" +#define HBG_SUPPORT_FEATURES (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \ + NETIF_F_RXCSUM) + static void hbg_all_irq_enable(struct hbg_priv *priv, bool enabled) { - struct hbg_irq_info *info; + const struct hbg_irq_info *info; u32 i; for (i = 0; i < priv->vectors.info_array_len; i++) { @@ -198,12 +203,12 @@ static int hbg_net_change_mtu(struct net_device *netdev, int new_mtu) if (netif_running(netdev)) return -EBUSY; - hbg_hw_set_mtu(priv, new_mtu); - WRITE_ONCE(netdev->mtu, new_mtu); - dev_dbg(&priv->pdev->dev, "change mtu from %u to %u\n", netdev->mtu, new_mtu); + hbg_hw_set_mtu(priv, new_mtu); + WRITE_ONCE(netdev->mtu, new_mtu); + return 0; } @@ -214,6 +219,10 @@ static void hbg_net_tx_timeout(struct net_device *netdev, unsigned int txqueue) char *buf = ring->tout_log_buf; u32 pos = 0; + priv->stats.tx_timeout_cnt++; + + pos += scnprintf(buf + pos, HBG_TX_TIMEOUT_BUF_LEN - pos, + "tx_timeout cnt: %llu\n", priv->stats.tx_timeout_cnt); pos += scnprintf(buf + pos, HBG_TX_TIMEOUT_BUF_LEN - pos, "ring used num: %u, fifo used num: %u\n", hbg_get_queue_used_num(ring), @@ -226,6 +235,39 @@ static void hbg_net_tx_timeout(struct net_device *netdev, unsigned int txqueue) netdev_info(netdev, "%s", buf); } +static void hbg_net_get_stats(struct net_device *netdev, + struct rtnl_link_stats64 *stats) +{ + struct hbg_priv *priv = netdev_priv(netdev); + struct hbg_stats *h_stats = &priv->stats; + + hbg_update_stats(priv); + dev_get_tstats64(netdev, stats); + + /* fifo empty */ + stats->tx_fifo_errors += h_stats->tx_drop_cnt; + + stats->tx_dropped += h_stats->tx_excessive_length_drop_cnt + + h_stats->tx_drop_cnt; + stats->tx_errors += h_stats->tx_add_cs_fail_cnt + + h_stats->tx_bufrl_err_cnt + + h_stats->tx_underrun_err_cnt + + h_stats->tx_crc_err_cnt; + stats->rx_errors += h_stats->rx_data_error_cnt; + stats->multicast += h_stats->rx_mc_pkt_cnt; + stats->rx_dropped += h_stats->rx_desc_drop; + stats->rx_length_errors += h_stats->rx_frame_very_long_err_cnt + + h_stats->rx_frame_long_err_cnt + + h_stats->rx_frame_runt_err_cnt + + h_stats->rx_frame_short_err_cnt + + h_stats->rx_lengthfield_err_cnt; + stats->rx_frame_errors += h_stats->rx_desc_l2_err_cnt + + h_stats->rx_desc_l3l4_err_cnt; + stats->rx_fifo_errors += h_stats->rx_overflow_cnt + + h_stats->rx_overrun_cnt; + stats->rx_crc_errors += h_stats->rx_fcs_error_cnt; +} + static const struct net_device_ops hbg_netdev_ops = { .ndo_open = hbg_net_open, .ndo_stop = hbg_net_stop, @@ -235,8 +277,62 @@ static const struct net_device_ops hbg_netdev_ops = { .ndo_change_mtu = hbg_net_change_mtu, .ndo_tx_timeout = hbg_net_tx_timeout, .ndo_set_rx_mode = hbg_net_set_rx_mode, + .ndo_get_stats64 = hbg_net_get_stats, + .ndo_eth_ioctl = phy_do_ioctl_running, }; +static void hbg_service_task(struct work_struct *work) +{ + struct hbg_priv *priv = container_of(work, struct hbg_priv, + service_task.work); + + if (test_and_clear_bit(HBG_NIC_STATE_NEED_RESET, &priv->state)) + hbg_err_reset(priv); + + if (test_and_clear_bit(HBG_NIC_STATE_NP_LINK_FAIL, &priv->state)) + hbg_fix_np_link_fail(priv); + + hbg_diagnose_message_push(priv); + + /* The type of statistics register is u32, + * To prevent the statistics register from overflowing, + * the driver dumps the statistics every 30 seconds. + */ + if (time_after(jiffies, priv->last_update_stats_time + 30 * HZ)) { + hbg_update_stats(priv); + priv->last_update_stats_time = jiffies; + } + + schedule_delayed_work(&priv->service_task, + msecs_to_jiffies(MSEC_PER_SEC)); +} + +void hbg_err_reset_task_schedule(struct hbg_priv *priv) +{ + set_bit(HBG_NIC_STATE_NEED_RESET, &priv->state); + schedule_delayed_work(&priv->service_task, 0); +} + +void hbg_np_link_fail_task_schedule(struct hbg_priv *priv) +{ + set_bit(HBG_NIC_STATE_NP_LINK_FAIL, &priv->state); + schedule_delayed_work(&priv->service_task, 0); +} + +static void hbg_cancel_delayed_work_sync(void *data) +{ + cancel_delayed_work_sync(data); +} + +static int hbg_delaywork_init(struct hbg_priv *priv) +{ + INIT_DELAYED_WORK(&priv->service_task, hbg_service_task); + schedule_delayed_work(&priv->service_task, 0); + return devm_add_action_or_reset(&priv->pdev->dev, + hbg_cancel_delayed_work_sync, + &priv->service_task); +} + static int hbg_mac_filter_init(struct hbg_priv *priv) { struct hbg_dev_specs *dev_specs = &priv->dev_specs; @@ -291,6 +387,10 @@ static int hbg_init(struct hbg_priv *priv) if (ret) return ret; + ret = hbg_delaywork_init(priv); + if (ret) + return ret; + hbg_debugfs_init(priv); hbg_init_user_def(priv); return 0; @@ -349,6 +449,9 @@ static int hbg_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) return ret; + /* set default features */ + netdev->features |= HBG_SUPPORT_FEATURES; + netdev->hw_features |= HBG_SUPPORT_FEATURES; netdev->priv_flags |= IFF_UNICAST_FLT; netdev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS; diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c index db6bc4cfb971..42b0083c9193 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c @@ -2,6 +2,7 @@ // Copyright (c) 2024 Hisilicon Limited. #include <linux/phy.h> +#include <linux/rtnetlink.h> #include "hbg_common.h" #include "hbg_hw.h" #include "hbg_mdio.h" @@ -17,6 +18,8 @@ #define HBG_MDIO_OP_TIMEOUT_US (1 * 1000 * 1000) #define HBG_MDIO_OP_INTERVAL_US (5 * 1000) +#define HBG_NP_LINK_FAIL_RETRY_TIMES 5 + static void hbg_mdio_set_command(struct hbg_mac *mac, u32 cmd) { hbg_reg_write(HBG_MAC_GET_PRIV(mac), HBG_REG_MDIO_COMMAND_ADDR, cmd); @@ -127,6 +130,34 @@ static void hbg_flowctrl_cfg(struct hbg_priv *priv) hbg_hw_set_pause_enable(priv, tx_pause, rx_pause); } +void hbg_fix_np_link_fail(struct hbg_priv *priv) +{ + struct device *dev = &priv->pdev->dev; + + rtnl_lock(); + + if (priv->stats.np_link_fail_cnt >= HBG_NP_LINK_FAIL_RETRY_TIMES) { + dev_err(dev, "failed to fix the MAC link status\n"); + priv->stats.np_link_fail_cnt = 0; + goto unlock; + } + + if (!priv->mac.phydev->link) + goto unlock; + + priv->stats.np_link_fail_cnt++; + dev_err(dev, "failed to link between MAC and PHY, try to fix...\n"); + + /* Replace phy_reset() with phy_stop() and phy_start(), + * as suggested by Andrew. + */ + hbg_phy_stop(priv); + hbg_phy_start(priv); + +unlock: + rtnl_unlock(); +} + static void hbg_phy_adjust_link(struct net_device *netdev) { struct hbg_priv *priv = netdev_priv(netdev); diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.h index febd02a309c7..f3771c1bbd34 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.h +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.h @@ -9,4 +9,6 @@ int hbg_mdio_init(struct hbg_priv *priv); void hbg_phy_start(struct hbg_priv *priv); void hbg_phy_stop(struct hbg_priv *priv); +void hbg_fix_np_link_fail(struct hbg_priv *priv); + #endif diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h index f12efc12f3c5..a6e7f5e62b48 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h @@ -18,6 +18,13 @@ #define HBG_REG_TX_FIFO_NUM_ADDR 0x0030 #define HBG_REG_RX_FIFO_NUM_ADDR 0x0034 #define HBG_REG_VLAN_LAYERS_ADDR 0x0038 +#define HBG_REG_PUSH_REQ_ADDR 0x00F0 +#define HBG_REG_MSG_HEADER_ADDR 0x00F4 +#define HBG_REG_MSG_HEADER_OPCODE_M GENMASK(7, 0) +#define HBG_REG_MSG_HEADER_STATUS_M GENMASK(11, 8) +#define HBG_REG_MSG_HEADER_DATA_NUM_M GENMASK(19, 12) +#define HBG_REG_MSG_HEADER_RESP_CODE_M GENMASK(27, 20) +#define HBG_REG_MSG_DATA_BASE_ADDR 0x0100 /* MDIO */ #define HBG_REG_MDIO_BASE 0x8000 @@ -54,12 +61,56 @@ #define HBG_REG_PAUSE_ENABLE_RX_B BIT(0) #define HBG_REG_PAUSE_ENABLE_TX_B BIT(1) #define HBG_REG_AN_NEG_STATE_ADDR (HBG_REG_SGMII_BASE + 0x0058) +#define HBG_REG_AN_NEG_STATE_NP_LINK_OK_B BIT(15) #define HBG_REG_TRANSMIT_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x0060) #define HBG_REG_TRANSMIT_CTRL_PAD_EN_B BIT(7) #define HBG_REG_TRANSMIT_CTRL_CRC_ADD_B BIT(6) #define HBG_REG_TRANSMIT_CTRL_AN_EN_B BIT(5) #define HBG_REG_REC_FILT_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x0064) #define HBG_REG_REC_FILT_CTRL_UC_MATCH_EN_B BIT(0) +#define HBG_REG_REC_FILT_CTRL_PAUSE_FRM_PASS_B BIT(4) +#define HBG_REG_RX_OCTETS_TOTAL_OK_ADDR (HBG_REG_SGMII_BASE + 0x0080) +#define HBG_REG_RX_OCTETS_BAD_ADDR (HBG_REG_SGMII_BASE + 0x0084) +#define HBG_REG_RX_UC_PKTS_ADDR (HBG_REG_SGMII_BASE + 0x0088) +#define HBG_REG_RX_MC_PKTS_ADDR (HBG_REG_SGMII_BASE + 0x008C) +#define HBG_REG_RX_BC_PKTS_ADDR (HBG_REG_SGMII_BASE + 0x0090) +#define HBG_REG_RX_PKTS_64OCTETS_ADDR (HBG_REG_SGMII_BASE + 0x0094) +#define HBG_REG_RX_PKTS_65TO127OCTETS_ADDR (HBG_REG_SGMII_BASE + 0x0098) +#define HBG_REG_RX_PKTS_128TO255OCTETS_ADDR (HBG_REG_SGMII_BASE + 0x009C) +#define HBG_REG_RX_PKTS_256TO511OCTETS_ADDR (HBG_REG_SGMII_BASE + 0x00A0) +#define HBG_REG_RX_PKTS_512TO1023OCTETS_ADDR (HBG_REG_SGMII_BASE + 0x00A4) +#define HBG_REG_RX_PKTS_1024TO1518OCTETS_ADDR (HBG_REG_SGMII_BASE + 0x00A8) +#define HBG_REG_RX_PKTS_1519TOMAXOCTETS_ADDR (HBG_REG_SGMII_BASE + 0x00AC) +#define HBG_REG_RX_FCS_ERRORS_ADDR (HBG_REG_SGMII_BASE + 0x00B0) +#define HBG_REG_RX_TAGGED_ADDR (HBG_REG_SGMII_BASE + 0x00B4) +#define HBG_REG_RX_DATA_ERR_ADDR (HBG_REG_SGMII_BASE + 0x00B8) +#define HBG_REG_RX_ALIGN_ERRORS_ADDR (HBG_REG_SGMII_BASE + 0x00BC) +#define HBG_REG_RX_LONG_ERRORS_ADDR (HBG_REG_SGMII_BASE + 0x00C0) +#define HBG_REG_RX_JABBER_ERRORS_ADDR (HBG_REG_SGMII_BASE + 0x00C4) +#define HBG_REG_RX_PAUSE_MACCTL_FRAMCOUNTER_ADDR (HBG_REG_SGMII_BASE + 0x00C8) +#define HBG_REG_RX_UNKNOWN_MACCTL_FRAMCOUNTER_ADDR (HBG_REG_SGMII_BASE + 0x00CC) +#define HBG_REG_RX_VERY_LONG_ERR_CNT_ADDR (HBG_REG_SGMII_BASE + 0x00D0) +#define HBG_REG_RX_RUNT_ERR_CNT_ADDR (HBG_REG_SGMII_BASE + 0x00D4) +#define HBG_REG_RX_SHORT_ERR_CNT_ADDR (HBG_REG_SGMII_BASE + 0x00D8) +#define HBG_REG_RX_FILT_PKT_CNT_ADDR (HBG_REG_SGMII_BASE + 0x00E8) +#define HBG_REG_RX_OCTETS_TOTAL_FILT_ADDR (HBG_REG_SGMII_BASE + 0x00EC) +#define HBG_REG_OCTETS_TRANSMITTED_OK_ADDR (HBG_REG_SGMII_BASE + 0x0100) +#define HBG_REG_OCTETS_TRANSMITTED_BAD_ADDR (HBG_REG_SGMII_BASE + 0x0104) +#define HBG_REG_TX_UC_PKTS_ADDR (HBG_REG_SGMII_BASE + 0x0108) +#define HBG_REG_TX_MC_PKTS_ADDR (HBG_REG_SGMII_BASE + 0x010C) +#define HBG_REG_TX_BC_PKTS_ADDR (HBG_REG_SGMII_BASE + 0x0110) +#define HBG_REG_TX_PKTS_64OCTETS_ADDR (HBG_REG_SGMII_BASE + 0x0114) +#define HBG_REG_TX_PKTS_65TO127OCTETS_ADDR (HBG_REG_SGMII_BASE + 0x0118) +#define HBG_REG_TX_PKTS_128TO255OCTETS_ADDR (HBG_REG_SGMII_BASE + 0x011C) +#define HBG_REG_TX_PKTS_256TO511OCTETS_ADDR (HBG_REG_SGMII_BASE + 0x0120) +#define HBG_REG_TX_PKTS_512TO1023OCTETS_ADDR (HBG_REG_SGMII_BASE + 0x0124) +#define HBG_REG_TX_PKTS_1024TO1518OCTETS_ADDR (HBG_REG_SGMII_BASE + 0x0128) +#define HBG_REG_TX_PKTS_1519TOMAXOCTETS_ADDR (HBG_REG_SGMII_BASE + 0x012C) +#define HBG_REG_TX_EXCESSIVE_LENGTH_DROP_ADDR (HBG_REG_SGMII_BASE + 0x014C) +#define HBG_REG_TX_UNDERRUN_ADDR (HBG_REG_SGMII_BASE + 0x0150) +#define HBG_REG_TX_TAGGED_ADDR (HBG_REG_SGMII_BASE + 0x0154) +#define HBG_REG_TX_CRC_ERROR_ADDR (HBG_REG_SGMII_BASE + 0x0158) +#define HBG_REG_TX_PAUSE_FRAMES_ADDR (HBG_REG_SGMII_BASE + 0x015C) #define HBG_REG_LINE_LOOP_BACK_ADDR (HBG_REG_SGMII_BASE + 0x01A8) #define HBG_REG_CF_CRC_STRIP_ADDR (HBG_REG_SGMII_BASE + 0x01B0) #define HBG_REG_CF_CRC_STRIP_B BIT(0) @@ -69,6 +120,9 @@ #define HBG_REG_RECV_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x01E0) #define HBG_REG_RECV_CTRL_STRIP_PAD_EN_B BIT(3) #define HBG_REG_VLAN_CODE_ADDR (HBG_REG_SGMII_BASE + 0x01E8) +#define HBG_REG_RX_OVERRUN_CNT_ADDR (HBG_REG_SGMII_BASE + 0x01EC) +#define HBG_REG_RX_LENGTHFIELD_ERR_CNT_ADDR (HBG_REG_SGMII_BASE + 0x01F4) +#define HBG_REG_RX_FAIL_COMMA_CNT_ADDR (HBG_REG_SGMII_BASE + 0x01F8) #define HBG_REG_STATION_ADDR_LOW_0_ADDR (HBG_REG_SGMII_BASE + 0x0200) #define HBG_REG_STATION_ADDR_HIGH_0_ADDR (HBG_REG_SGMII_BASE + 0x0204) #define HBG_REG_STATION_ADDR_LOW_1_ADDR (HBG_REG_SGMII_BASE + 0x0208) @@ -81,6 +135,8 @@ #define HBG_REG_STATION_ADDR_HIGH_4_ADDR (HBG_REG_SGMII_BASE + 0x0224) #define HBG_REG_STATION_ADDR_LOW_5_ADDR (HBG_REG_SGMII_BASE + 0x0228) #define HBG_REG_STATION_ADDR_HIGH_5_ADDR (HBG_REG_SGMII_BASE + 0x022C) +#define HBG_REG_STATION_ADDR_LOW_MSK_0 (HBG_REG_SGMII_BASE + 0x0230) +#define HBG_REG_STATION_ADDR_LOW_MSK_1 (HBG_REG_SGMII_BASE + 0x0238) /* PCU */ #define HBG_REG_TX_FIFO_THRSLD_ADDR (HBG_REG_SGMII_BASE + 0x0420) @@ -103,6 +159,7 @@ #define HBG_INT_MSK_MAC_PCS_TX_FIFO_ERR_B BIT(17) #define HBG_INT_MSK_MAC_PCS_RX_FIFO_ERR_B BIT(16) #define HBG_INT_MSK_MAC_MII_FIFO_ERR_B BIT(15) +#define HBG_INT_MSK_TX_PKT_CPL_B BIT(14) #define HBG_INT_MSK_TX_B BIT(1) /* just used in driver */ #define HBG_INT_MSK_RX_B BIT(0) /* just used in driver */ #define HBG_REG_CF_INTRPT_STAT_ADDR (HBG_REG_SGMII_BASE + 0x0434) @@ -111,12 +168,17 @@ #define HBG_REG_RX_BUS_ERR_ADDR_ADDR (HBG_REG_SGMII_BASE + 0x0440) #define HBG_REG_MAX_FRAME_LEN_ADDR (HBG_REG_SGMII_BASE + 0x0444) #define HBG_REG_MAX_FRAME_LEN_M GENMASK(15, 0) +#define HBG_REG_TX_DROP_CNT_ADDR (HBG_REG_SGMII_BASE + 0x0448) +#define HBG_REG_RX_OVER_FLOW_CNT_ADDR (HBG_REG_SGMII_BASE + 0x044C) #define HBG_REG_DEBUG_ST_MCH_ADDR (HBG_REG_SGMII_BASE + 0x0450) #define HBG_REG_FIFO_CURR_STATUS_ADDR (HBG_REG_SGMII_BASE + 0x0454) #define HBG_REG_FIFO_HIST_STATUS_ADDR (HBG_REG_SGMII_BASE + 0x0458) #define HBG_REG_CF_CFF_DATA_NUM_ADDR (HBG_REG_SGMII_BASE + 0x045C) #define HBG_REG_CF_CFF_DATA_NUM_ADDR_TX_M GENMASK(8, 0) #define HBG_REG_CF_CFF_DATA_NUM_ADDR_RX_M GENMASK(24, 16) +#define HBG_REG_TX_CS_FAIL_CNT_ADDR (HBG_REG_SGMII_BASE + 0x0460) +#define HBG_REG_RX_TRANS_PKG_CNT_ADDR (HBG_REG_SGMII_BASE + 0x0464) +#define HBG_REG_TX_TRANS_PKG_CNT_ADDR (HBG_REG_SGMII_BASE + 0x0468) #define HBG_REG_CF_TX_PAUSE_ADDR (HBG_REG_SGMII_BASE + 0x0470) #define HBG_REG_TX_CFF_ADDR_0_ADDR (HBG_REG_SGMII_BASE + 0x0488) #define HBG_REG_TX_CFF_ADDR_1_ADDR (HBG_REG_SGMII_BASE + 0x048C) @@ -136,6 +198,9 @@ #define HBG_REG_RX_CTRL_RXBUF_1ST_SKIP_SIZE2_M GENMASK(3, 0) #define HBG_REG_RX_PKT_MODE_ADDR (HBG_REG_SGMII_BASE + 0x04F4) #define HBG_REG_RX_PKT_MODE_PARSE_MODE_M GENMASK(22, 21) +#define HBG_REG_RX_BUFRQ_ERR_CNT_ADDR (HBG_REG_SGMII_BASE + 0x058C) +#define HBG_REG_TX_BUFRL_ERR_CNT_ADDR (HBG_REG_SGMII_BASE + 0x0590) +#define HBG_REG_RX_WE_ERR_CNT_ADDR (HBG_REG_SGMII_BASE + 0x0594) #define HBG_REG_DBG_ST0_ADDR (HBG_REG_SGMII_BASE + 0x05E4) #define HBG_REG_DBG_ST1_ADDR (HBG_REG_SGMII_BASE + 0x05E8) #define HBG_REG_DBG_ST2_ADDR (HBG_REG_SGMII_BASE + 0x05EC) @@ -178,5 +243,48 @@ struct hbg_rx_desc { }; #define HBG_RX_DESC_W2_PKT_LEN_M GENMASK(31, 16) +#define HBG_RX_DESC_W2_PORT_NUM_M GENMASK(15, 12) +#define HBG_RX_DESC_W4_IP_TCP_UDP_M GENMASK(31, 30) +#define HBG_RX_DESC_W4_IPSEC_B BIT(29) +#define HBG_RX_DESC_W4_IP_VERSION_B BIT(28) +#define HBG_RX_DESC_W4_L4_ERR_CODE_M GENMASK(26, 23) +#define HBG_RX_DESC_W4_FRAG_B BIT(22) +#define HBG_RX_DESC_W4_OPT_B BIT(21) +#define HBG_RX_DESC_W4_IP_VERSION_ERR_B BIT(20) +#define HBG_RX_DESC_W4_BRD_CST_B BIT(19) +#define HBG_RX_DESC_W4_MUL_CST_B BIT(18) +#define HBG_RX_DESC_W4_ARP_B BIT(17) +#define HBG_RX_DESC_W4_RARP_B BIT(16) +#define HBG_RX_DESC_W4_ICMP_B BIT(15) +#define HBG_RX_DESC_W4_VLAN_FLAG_B BIT(14) +#define HBG_RX_DESC_W4_DROP_B BIT(13) +#define HBG_RX_DESC_W4_L3_ERR_CODE_M GENMASK(12, 9) +#define HBG_RX_DESC_W4_L2_ERR_B BIT(8) +#define HBG_RX_DESC_W4_IDX_MATCH_B BIT(7) + +enum hbg_l3_err_code { + HBG_L3_OK = 0, + HBG_L3_WRONG_HEAD, + HBG_L3_CSUM_ERR, + HBG_L3_LEN_ERR, + HBG_L3_ZERO_TTL, + HBG_L3_RSVD, +}; + +enum hbg_l4_err_code { + HBG_L4_OK = 0, + HBG_L4_WRONG_HEAD, + HBG_L4_LEN_ERR, + HBG_L4_CSUM_ERR, + HBG_L4_ZERO_PORT_NUM, + HBG_L4_RSVD, +}; + +enum hbg_pkt_type_code { + HBG_NO_IP_PKT = 0, + HBG_IP_PKT, + HBG_TCP_PKT, + HBG_UDP_PKT, +}; #endif diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c index f4f256a0dfea..8d814c8f19ea 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c @@ -38,8 +38,14 @@ static int hbg_dma_map(struct hbg_buffer *buffer) buffer->skb_dma = dma_map_single(&priv->pdev->dev, buffer->skb->data, buffer->skb_len, buffer_to_dma_dir(buffer)); - if (unlikely(dma_mapping_error(&priv->pdev->dev, buffer->skb_dma))) + if (unlikely(dma_mapping_error(&priv->pdev->dev, buffer->skb_dma))) { + if (buffer->dir == HBG_DIR_RX) + priv->stats.rx_dma_err_cnt++; + else + priv->stats.tx_dma_err_cnt++; + return -ENOMEM; + } return 0; } @@ -195,6 +201,173 @@ static int hbg_napi_tx_recycle(struct napi_struct *napi, int budget) return packet_done; } +static bool hbg_rx_check_l3l4_error(struct hbg_priv *priv, + struct hbg_rx_desc *desc, + struct sk_buff *skb) +{ + bool rx_checksum_offload = !!(priv->netdev->features & NETIF_F_RXCSUM); + + skb->ip_summed = rx_checksum_offload ? + CHECKSUM_UNNECESSARY : CHECKSUM_NONE; + + if (likely(!FIELD_GET(HBG_RX_DESC_W4_L3_ERR_CODE_M, desc->word4) && + !FIELD_GET(HBG_RX_DESC_W4_L4_ERR_CODE_M, desc->word4))) + return true; + + switch (FIELD_GET(HBG_RX_DESC_W4_L3_ERR_CODE_M, desc->word4)) { + case HBG_L3_OK: + break; + case HBG_L3_WRONG_HEAD: + priv->stats.rx_desc_l3_wrong_head_cnt++; + return false; + case HBG_L3_CSUM_ERR: + skb->ip_summed = CHECKSUM_NONE; + priv->stats.rx_desc_l3_csum_err_cnt++; + + /* Don't drop packets on csum validation failure, + * suggest by Jakub + */ + break; + case HBG_L3_LEN_ERR: + priv->stats.rx_desc_l3_len_err_cnt++; + return false; + case HBG_L3_ZERO_TTL: + priv->stats.rx_desc_l3_zero_ttl_cnt++; + return false; + default: + priv->stats.rx_desc_l3_other_cnt++; + return false; + } + + switch (FIELD_GET(HBG_RX_DESC_W4_L4_ERR_CODE_M, desc->word4)) { + case HBG_L4_OK: + break; + case HBG_L4_WRONG_HEAD: + priv->stats.rx_desc_l4_wrong_head_cnt++; + return false; + case HBG_L4_LEN_ERR: + priv->stats.rx_desc_l4_len_err_cnt++; + return false; + case HBG_L4_CSUM_ERR: + skb->ip_summed = CHECKSUM_NONE; + priv->stats.rx_desc_l4_csum_err_cnt++; + + /* Don't drop packets on csum validation failure, + * suggest by Jakub + */ + break; + case HBG_L4_ZERO_PORT_NUM: + priv->stats.rx_desc_l4_zero_port_num_cnt++; + return false; + default: + priv->stats.rx_desc_l4_other_cnt++; + return false; + } + + return true; +} + +static void hbg_update_rx_ip_protocol_stats(struct hbg_priv *priv, + struct hbg_rx_desc *desc) +{ + if (unlikely(!FIELD_GET(HBG_RX_DESC_W4_IP_TCP_UDP_M, desc->word4))) { + priv->stats.rx_desc_no_ip_pkt_cnt++; + return; + } + + if (unlikely(FIELD_GET(HBG_RX_DESC_W4_IP_VERSION_ERR_B, desc->word4))) { + priv->stats.rx_desc_ip_ver_err_cnt++; + return; + } + + /* 0:ipv4, 1:ipv6 */ + if (FIELD_GET(HBG_RX_DESC_W4_IP_VERSION_B, desc->word4)) + priv->stats.rx_desc_ipv6_pkt_cnt++; + else + priv->stats.rx_desc_ipv4_pkt_cnt++; + + switch (FIELD_GET(HBG_RX_DESC_W4_IP_TCP_UDP_M, desc->word4)) { + case HBG_IP_PKT: + priv->stats.rx_desc_ip_pkt_cnt++; + if (FIELD_GET(HBG_RX_DESC_W4_OPT_B, desc->word4)) + priv->stats.rx_desc_ip_opt_pkt_cnt++; + if (FIELD_GET(HBG_RX_DESC_W4_FRAG_B, desc->word4)) + priv->stats.rx_desc_frag_cnt++; + + if (FIELD_GET(HBG_RX_DESC_W4_ICMP_B, desc->word4)) + priv->stats.rx_desc_icmp_pkt_cnt++; + else if (FIELD_GET(HBG_RX_DESC_W4_IPSEC_B, desc->word4)) + priv->stats.rx_desc_ipsec_pkt_cnt++; + break; + case HBG_TCP_PKT: + priv->stats.rx_desc_tcp_pkt_cnt++; + break; + case HBG_UDP_PKT: + priv->stats.rx_desc_udp_pkt_cnt++; + break; + default: + priv->stats.rx_desc_no_ip_pkt_cnt++; + break; + } +} + +static void hbg_update_rx_protocol_stats(struct hbg_priv *priv, + struct hbg_rx_desc *desc) +{ + if (unlikely(!FIELD_GET(HBG_RX_DESC_W4_IDX_MATCH_B, desc->word4))) { + priv->stats.rx_desc_key_not_match_cnt++; + return; + } + + if (FIELD_GET(HBG_RX_DESC_W4_BRD_CST_B, desc->word4)) + priv->stats.rx_desc_broadcast_pkt_cnt++; + else if (FIELD_GET(HBG_RX_DESC_W4_MUL_CST_B, desc->word4)) + priv->stats.rx_desc_multicast_pkt_cnt++; + + if (FIELD_GET(HBG_RX_DESC_W4_VLAN_FLAG_B, desc->word4)) + priv->stats.rx_desc_vlan_pkt_cnt++; + + if (FIELD_GET(HBG_RX_DESC_W4_ARP_B, desc->word4)) { + priv->stats.rx_desc_arp_pkt_cnt++; + return; + } else if (FIELD_GET(HBG_RX_DESC_W4_RARP_B, desc->word4)) { + priv->stats.rx_desc_rarp_pkt_cnt++; + return; + } + + hbg_update_rx_ip_protocol_stats(priv, desc); +} + +static bool hbg_rx_pkt_check(struct hbg_priv *priv, struct hbg_rx_desc *desc, + struct sk_buff *skb) +{ + if (unlikely(FIELD_GET(HBG_RX_DESC_W2_PKT_LEN_M, desc->word2) > + priv->dev_specs.max_frame_len)) { + priv->stats.rx_desc_pkt_len_err_cnt++; + return false; + } + + if (unlikely(FIELD_GET(HBG_RX_DESC_W2_PORT_NUM_M, desc->word2) != + priv->dev_specs.mac_id || + FIELD_GET(HBG_RX_DESC_W4_DROP_B, desc->word4))) { + priv->stats.rx_desc_drop++; + return false; + } + + if (unlikely(FIELD_GET(HBG_RX_DESC_W4_L2_ERR_B, desc->word4))) { + priv->stats.rx_desc_l2_err_cnt++; + return false; + } + + if (unlikely(!hbg_rx_check_l3l4_error(priv, desc, skb))) { + priv->stats.rx_desc_l3l4_err_cnt++; + return false; + } + + hbg_update_rx_protocol_stats(priv, desc); + return true; +} + static int hbg_rx_fill_one_buffer(struct hbg_priv *priv) { struct hbg_ring *ring = &priv->rx_ring; @@ -257,8 +430,12 @@ static int hbg_napi_rx_poll(struct napi_struct *napi, int budget) rx_desc = (struct hbg_rx_desc *)buffer->skb->data; pkt_len = FIELD_GET(HBG_RX_DESC_W2_PKT_LEN_M, rx_desc->word2); - hbg_dma_unmap(buffer); + if (unlikely(!hbg_rx_pkt_check(priv, rx_desc, buffer->skb))) { + hbg_buffer_free(buffer); + goto next_buffer; + } + hbg_dma_unmap(buffer); skb_reserve(buffer->skb, HBG_PACKET_HEAD_SIZE + NET_IP_ALIGN); skb_put(buffer->skb, pkt_len); buffer->skb->protocol = eth_type_trans(buffer->skb, diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c index a376d4bdf281..18376bcc718a 100644 --- a/drivers/net/ethernet/hisilicon/hip04_eth.c +++ b/drivers/net/ethernet/hisilicon/hip04_eth.c @@ -934,8 +934,6 @@ static int hip04_mac_probe(struct platform_device *pdev) priv->chan = arg.args[1] * RX_DESC_NUM; priv->group = arg.args[2]; - hrtimer_init(&priv->tx_coalesce_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - /* BQL will try to keep the TX queue as short as possible, but it can't * be faster than tx_coalesce_usecs, so we need a fast timeout here, * but also long enough to gather up enough frames to ensure we don't @@ -944,7 +942,7 @@ static int hip04_mac_probe(struct platform_device *pdev) */ priv->tx_coalesce_frames = TX_DESC_NUM * 3 / 4; priv->tx_coalesce_usecs = 200; - priv->tx_coalesce_timer.function = tx_done; + hrtimer_setup(&priv->tx_coalesce_timer, tx_done, CLOCK_MONOTONIC, HRTIMER_MODE_REL); priv->map = syscon_node_to_regmap(arg.np); of_node_put(arg.np); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 42bb341fd80b..e905f10b894e 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -1402,7 +1402,7 @@ static void hns_nic_net_down(struct net_device *ndev) if (test_and_set_bit(NIC_STATE_DOWN, &priv->state)) return; - (void)del_timer_sync(&priv->service_timer); + (void) timer_delete_sync(&priv->service_timer); netif_tx_stop_all_queues(ndev); netif_carrier_off(ndev); netif_tx_disable(ndev); @@ -2075,7 +2075,7 @@ static void hns_nic_task_schedule(struct hns_nic_priv *priv) static void hns_nic_service_timer(struct timer_list *t) { - struct hns_nic_priv *priv = from_timer(priv, t, service_timer); + struct hns_nic_priv *priv = timer_container_of(priv, t, service_timer); (void)mod_timer(&priv->service_timer, jiffies + SERVICE_TIMER_HZ); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index 6c458f037262..60a586a951a0 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -266,9 +266,9 @@ static int hns_nic_config_phy_loopback(struct phy_device *phy_dev, u8 en) if (err) goto out; - err = phy_loopback(phy_dev, true); + err = phy_loopback(phy_dev, true, 0); } else { - err = phy_loopback(phy_dev, false); + err = phy_loopback(phy_dev, false, 0); if (err) goto out; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 9bbece25552b..4e5d8bc39a1b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -3,6 +3,7 @@ #include <linux/debugfs.h> #include <linux/device.h> +#include <linux/string_choices.h> #include "hnae3.h" #include "hns3_debugfs.h" @@ -60,7 +61,7 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .name = "tm_qset", .cmd = HNAE3_DBG_CMD_TM_QSET, .dentry = HNS3_DBG_DENTRY_TM, - .buf_len = HNS3_DBG_READ_LEN, + .buf_len = HNS3_DBG_READ_LEN_1MB, .init = hns3_dbg_common_file_init, }, { @@ -661,12 +662,14 @@ static void hns3_dump_rx_queue_info(struct hns3_enet_ring *ring, HNS3_RING_RX_RING_PKTNUM_RECORD_REG)); sprintf(result[j++], "%u", ring->rx_copybreak); - sprintf(result[j++], "%s", readl_relaxed(ring->tqp->io_base + - HNS3_RING_EN_REG) ? "on" : "off"); + sprintf(result[j++], "%s", + str_on_off(readl_relaxed(ring->tqp->io_base + + HNS3_RING_EN_REG))); if (hnae3_ae_dev_tqp_txrx_indep_supported(ae_dev)) - sprintf(result[j++], "%s", readl_relaxed(ring->tqp->io_base + - HNS3_RING_RX_EN_REG) ? "on" : "off"); + sprintf(result[j++], "%s", + str_on_off(readl_relaxed(ring->tqp->io_base + + HNS3_RING_RX_EN_REG))); else sprintf(result[j++], "%s", "NA"); @@ -764,12 +767,14 @@ static void hns3_dump_tx_queue_info(struct hns3_enet_ring *ring, sprintf(result[j++], "%u", readl_relaxed(ring->tqp->io_base + HNS3_RING_TX_RING_PKTNUM_RECORD_REG)); - sprintf(result[j++], "%s", readl_relaxed(ring->tqp->io_base + - HNS3_RING_EN_REG) ? "on" : "off"); + sprintf(result[j++], "%s", + str_on_off(readl_relaxed(ring->tqp->io_base + + HNS3_RING_EN_REG))); if (hnae3_ae_dev_tqp_txrx_indep_supported(ae_dev)) - sprintf(result[j++], "%s", readl_relaxed(ring->tqp->io_base + - HNS3_RING_TX_EN_REG) ? "on" : "off"); + sprintf(result[j++], "%s", + str_on_off(readl_relaxed(ring->tqp->io_base + + HNS3_RING_TX_EN_REG))); else sprintf(result[j++], "%s", "NA"); @@ -1030,7 +1035,6 @@ static void hns3_dbg_dev_caps(struct hnae3_handle *h, char *buf, int len, int *pos) { struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev); - const char * const str[] = {"no", "yes"}; unsigned long *caps = ae_dev->caps; u32 i, state; @@ -1039,7 +1043,7 @@ hns3_dbg_dev_caps(struct hnae3_handle *h, char *buf, int len, int *pos) for (i = 0; i < ARRAY_SIZE(hns3_dbg_cap); i++) { state = test_bit(hns3_dbg_cap[i].cap_bit, caps); *pos += scnprintf(buf + *pos, len - *pos, "%s: %s\n", - hns3_dbg_cap[i].name, str[state]); + hns3_dbg_cap[i].name, str_yes_no(state)); } *pos += scnprintf(buf + *pos, len - *pos, "\n"); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 9ff797fb36c4..b03b8758c777 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -473,20 +473,14 @@ static void hns3_mask_vector_irq(struct hns3_enet_tqp_vector *tqp_vector, writel(mask_en, tqp_vector->mask_addr); } -static void hns3_vector_enable(struct hns3_enet_tqp_vector *tqp_vector) +static void hns3_irq_enable(struct hns3_enet_tqp_vector *tqp_vector) { napi_enable(&tqp_vector->napi); enable_irq(tqp_vector->vector_irq); - - /* enable vector */ - hns3_mask_vector_irq(tqp_vector, 1); } -static void hns3_vector_disable(struct hns3_enet_tqp_vector *tqp_vector) +static void hns3_irq_disable(struct hns3_enet_tqp_vector *tqp_vector) { - /* disable vector */ - hns3_mask_vector_irq(tqp_vector, 0); - disable_irq(tqp_vector->vector_irq); napi_disable(&tqp_vector->napi); cancel_work_sync(&tqp_vector->rx_group.dim.work); @@ -707,11 +701,42 @@ static int hns3_set_rx_cpu_rmap(struct net_device *netdev) return 0; } +static void hns3_enable_irqs_and_tqps(struct net_device *netdev) +{ + struct hns3_nic_priv *priv = netdev_priv(netdev); + struct hnae3_handle *h = priv->ae_handle; + u16 i; + + for (i = 0; i < priv->vector_num; i++) + hns3_irq_enable(&priv->tqp_vector[i]); + + for (i = 0; i < priv->vector_num; i++) + hns3_mask_vector_irq(&priv->tqp_vector[i], 1); + + for (i = 0; i < h->kinfo.num_tqps; i++) + hns3_tqp_enable(h->kinfo.tqp[i]); +} + +static void hns3_disable_irqs_and_tqps(struct net_device *netdev) +{ + struct hns3_nic_priv *priv = netdev_priv(netdev); + struct hnae3_handle *h = priv->ae_handle; + u16 i; + + for (i = 0; i < h->kinfo.num_tqps; i++) + hns3_tqp_disable(h->kinfo.tqp[i]); + + for (i = 0; i < priv->vector_num; i++) + hns3_mask_vector_irq(&priv->tqp_vector[i], 0); + + for (i = 0; i < priv->vector_num; i++) + hns3_irq_disable(&priv->tqp_vector[i]); +} + static int hns3_nic_net_up(struct net_device *netdev) { struct hns3_nic_priv *priv = netdev_priv(netdev); struct hnae3_handle *h = priv->ae_handle; - int i, j; int ret; ret = hns3_nic_reset_all_ring(h); @@ -720,23 +745,13 @@ static int hns3_nic_net_up(struct net_device *netdev) clear_bit(HNS3_NIC_STATE_DOWN, &priv->state); - /* enable the vectors */ - for (i = 0; i < priv->vector_num; i++) - hns3_vector_enable(&priv->tqp_vector[i]); - - /* enable rcb */ - for (j = 0; j < h->kinfo.num_tqps; j++) - hns3_tqp_enable(h->kinfo.tqp[j]); + hns3_enable_irqs_and_tqps(netdev); /* start the ae_dev */ ret = h->ae_algo->ops->start ? h->ae_algo->ops->start(h) : 0; if (ret) { set_bit(HNS3_NIC_STATE_DOWN, &priv->state); - while (j--) - hns3_tqp_disable(h->kinfo.tqp[j]); - - for (j = i - 1; j >= 0; j--) - hns3_vector_disable(&priv->tqp_vector[j]); + hns3_disable_irqs_and_tqps(netdev); } return ret; @@ -823,17 +838,9 @@ static void hns3_reset_tx_queue(struct hnae3_handle *h) static void hns3_nic_net_down(struct net_device *netdev) { struct hns3_nic_priv *priv = netdev_priv(netdev); - struct hnae3_handle *h = hns3_get_handle(netdev); const struct hnae3_ae_ops *ops; - int i; - /* disable vectors */ - for (i = 0; i < priv->vector_num; i++) - hns3_vector_disable(&priv->tqp_vector[i]); - - /* disable rcb */ - for (i = 0; i < h->kinfo.num_tqps; i++) - hns3_tqp_disable(h->kinfo.tqp[i]); + hns3_disable_irqs_and_tqps(netdev); /* stop ae_dev */ ops = priv->ae_handle->ae_algo->ops; @@ -5864,8 +5871,6 @@ int hns3_set_channels(struct net_device *netdev, void hns3_external_lb_prepare(struct net_device *ndev, bool if_running) { struct hns3_nic_priv *priv = netdev_priv(ndev); - struct hnae3_handle *h = priv->ae_handle; - int i; if (!if_running) return; @@ -5876,11 +5881,7 @@ void hns3_external_lb_prepare(struct net_device *ndev, bool if_running) netif_carrier_off(ndev); netif_tx_disable(ndev); - for (i = 0; i < priv->vector_num; i++) - hns3_vector_disable(&priv->tqp_vector[i]); - - for (i = 0; i < h->kinfo.num_tqps; i++) - hns3_tqp_disable(h->kinfo.tqp[i]); + hns3_disable_irqs_and_tqps(ndev); /* delay ring buffer clearing to hns3_reset_notify_uninit_enet * during reset process, because driver may not be able @@ -5896,7 +5897,6 @@ void hns3_external_lb_restore(struct net_device *ndev, bool if_running) { struct hns3_nic_priv *priv = netdev_priv(ndev); struct hnae3_handle *h = priv->ae_handle; - int i; if (!if_running) return; @@ -5912,11 +5912,7 @@ void hns3_external_lb_restore(struct net_device *ndev, bool if_running) clear_bit(HNS3_NIC_STATE_DOWN, &priv->state); - for (i = 0; i < priv->vector_num; i++) - hns3_vector_enable(&priv->tqp_vector[i]); - - for (i = 0; i < h->kinfo.num_tqps; i++) - hns3_tqp_enable(h->kinfo.tqp[i]); + hns3_enable_irqs_and_tqps(ndev); netif_tx_wake_all_queues(ndev); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index b771a2daba43..6715222aeb66 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -3,6 +3,7 @@ #include <linux/etherdevice.h> #include <linux/string.h> +#include <linux/string_choices.h> #include <linux/phy.h> #include <linux/sfp.h> @@ -1198,7 +1199,7 @@ static int hns3_set_tx_push(struct net_device *netdev, u32 tx_push) return 0; netdev_dbg(netdev, "Changing tx push from %s to %s\n", - old_state ? "on" : "off", tx_push ? "on" : "off"); + str_on_off(old_state), str_on_off(tx_push)); if (tx_push) set_bit(HNS3_NIC_STATE_TX_PUSH_ENABLE, &priv->state); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index debf143e9940..c46490693594 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -3,6 +3,7 @@ #include <linux/device.h> #include <linux/sched/clock.h> +#include <linux/string_choices.h> #include "hclge_debugfs.h" #include "hclge_err.h" @@ -11,7 +12,6 @@ #include "hclge_tm.h" #include "hnae3.h" -static const char * const state_str[] = { "off", "on" }; static const char * const hclge_mac_state_str[] = { "TO_ADD", "TO_DEL", "ACTIVE" }; @@ -2573,7 +2573,7 @@ static int hclge_dbg_dump_loopback(struct hclge_dev *hdev, char *buf, int len) loopback_en = hnae3_get_bit(le32_to_cpu(req_app->txrx_pad_fcs_loop_en), HCLGE_MAC_APP_LP_B); pos += scnprintf(buf + pos, len - pos, "app loopback: %s\n", - state_str[loopback_en]); + str_on_off(loopback_en)); hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_COMMON_LOOPBACK, true); ret = hclge_cmd_send(&hdev->hw, &desc, 1); @@ -2586,22 +2586,22 @@ static int hclge_dbg_dump_loopback(struct hclge_dev *hdev, char *buf, int len) loopback_en = req_common->enable & HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B; pos += scnprintf(buf + pos, len - pos, "serdes serial loopback: %s\n", - state_str[loopback_en]); + str_on_off(loopback_en)); loopback_en = req_common->enable & HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B ? 1 : 0; pos += scnprintf(buf + pos, len - pos, "serdes parallel loopback: %s\n", - state_str[loopback_en]); + str_on_off(loopback_en)); if (phydev) { loopback_en = phydev->loopback_enabled; pos += scnprintf(buf + pos, len - pos, "phy loopback: %s\n", - state_str[loopback_en]); + str_on_off(loopback_en)); } else if (hnae3_dev_phy_imp_supported(hdev)) { loopback_en = req_common->enable & HCLGE_CMD_GE_PHY_INNER_LOOP_B; pos += scnprintf(buf + pos, len - pos, "phy loopback: %s\n", - state_str[loopback_en]); + str_on_off(loopback_en)); } return 0; @@ -2894,9 +2894,9 @@ static int hclge_dbg_dump_vlan_filter_config(struct hclge_dev *hdev, char *buf, egress = vlan_fe & HCLGE_FILTER_FE_NIC_EGRESS_B ? 1 : 0; *pos += scnprintf(buf, len, "I_PORT_VLAN_FILTER: %s\n", - state_str[ingress]); + str_on_off(ingress)); *pos += scnprintf(buf + *pos, len - *pos, "E_PORT_VLAN_FILTER: %s\n", - state_str[egress]); + str_on_off(egress)); hclge_dbg_fill_content(content, sizeof(content), vlan_filter_items, NULL, ARRAY_SIZE(vlan_filter_items)); @@ -2915,11 +2915,11 @@ static int hclge_dbg_dump_vlan_filter_config(struct hclge_dev *hdev, char *buf, return ret; j = 0; result[j++] = hclge_dbg_get_func_id_str(str_id, i); - result[j++] = state_str[ingress]; - result[j++] = state_str[egress]; - result[j++] = - test_bit(HNAE3_DEV_SUPPORT_PORT_VLAN_BYPASS_B, - hdev->ae_dev->caps) ? state_str[bypass] : "NA"; + result[j++] = str_on_off(ingress); + result[j++] = str_on_off(egress); + result[j++] = test_bit(HNAE3_DEV_SUPPORT_PORT_VLAN_BYPASS_B, + hdev->ae_dev->caps) ? + str_on_off(bypass) : "NA"; hclge_dbg_fill_content(content, sizeof(content), vlan_filter_items, result, ARRAY_SIZE(vlan_filter_items)); @@ -2958,19 +2958,19 @@ static int hclge_dbg_dump_vlan_offload_config(struct hclge_dev *hdev, char *buf, j = 0; result[j++] = hclge_dbg_get_func_id_str(str_id, i); result[j++] = str_pvid; - result[j++] = state_str[vlan_cfg.accept_tag1]; - result[j++] = state_str[vlan_cfg.accept_tag2]; - result[j++] = state_str[vlan_cfg.accept_untag1]; - result[j++] = state_str[vlan_cfg.accept_untag2]; - result[j++] = state_str[vlan_cfg.insert_tag1]; - result[j++] = state_str[vlan_cfg.insert_tag2]; - result[j++] = state_str[vlan_cfg.shift_tag]; - result[j++] = state_str[vlan_cfg.strip_tag1]; - result[j++] = state_str[vlan_cfg.strip_tag2]; - result[j++] = state_str[vlan_cfg.drop_tag1]; - result[j++] = state_str[vlan_cfg.drop_tag2]; - result[j++] = state_str[vlan_cfg.pri_only1]; - result[j++] = state_str[vlan_cfg.pri_only2]; + result[j++] = str_on_off(vlan_cfg.accept_tag1); + result[j++] = str_on_off(vlan_cfg.accept_tag2); + result[j++] = str_on_off(vlan_cfg.accept_untag1); + result[j++] = str_on_off(vlan_cfg.accept_untag2); + result[j++] = str_on_off(vlan_cfg.insert_tag1); + result[j++] = str_on_off(vlan_cfg.insert_tag2); + result[j++] = str_on_off(vlan_cfg.shift_tag); + result[j++] = str_on_off(vlan_cfg.strip_tag1); + result[j++] = str_on_off(vlan_cfg.strip_tag2); + result[j++] = str_on_off(vlan_cfg.drop_tag1); + result[j++] = str_on_off(vlan_cfg.drop_tag2); + result[j++] = str_on_off(vlan_cfg.pri_only1); + result[j++] = str_on_off(vlan_cfg.pri_only2); hclge_dbg_fill_content(content, sizeof(content), vlan_offload_items, result, @@ -3007,14 +3007,13 @@ static int hclge_dbg_dump_ptp_info(struct hclge_dev *hdev, char *buf, int len) pos += scnprintf(buf + pos, len - pos, "phc %s's debug info:\n", ptp->info.name); pos += scnprintf(buf + pos, len - pos, "ptp enable: %s\n", - test_bit(HCLGE_PTP_FLAG_EN, &ptp->flags) ? - "yes" : "no"); + str_yes_no(test_bit(HCLGE_PTP_FLAG_EN, &ptp->flags))); pos += scnprintf(buf + pos, len - pos, "ptp tx enable: %s\n", - test_bit(HCLGE_PTP_FLAG_TX_EN, &ptp->flags) ? - "yes" : "no"); + str_yes_no(test_bit(HCLGE_PTP_FLAG_TX_EN, + &ptp->flags))); pos += scnprintf(buf + pos, len - pos, "ptp rx enable: %s\n", - test_bit(HCLGE_PTP_FLAG_RX_EN, &ptp->flags) ? - "yes" : "no"); + str_yes_no(test_bit(HCLGE_PTP_FLAG_RX_EN, + &ptp->flags))); last_rx = jiffies_to_msecs(ptp->last_rx); pos += scnprintf(buf + pos, len - pos, "last rx time: %lu.%lu\n", diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 3f17b3073e50..a7de67699a01 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -4503,7 +4503,7 @@ static void hclge_set_def_reset_request(struct hnae3_ae_dev *ae_dev, static void hclge_reset_timer(struct timer_list *t) { - struct hclge_dev *hdev = from_timer(hdev, t, reset_timer); + struct hclge_dev *hdev = timer_container_of(hdev, t, reset_timer); /* if default_reset_request has no value, it means that this reset * request has already be handled, so just return here @@ -7875,7 +7875,7 @@ static int hclge_enable_phy_loopback(struct hclge_dev *hdev, if (ret) return ret; - return phy_loopback(phydev, true); + return phy_loopback(phydev, true, 0); } static int hclge_disable_phy_loopback(struct hclge_dev *hdev, @@ -7883,7 +7883,7 @@ static int hclge_disable_phy_loopback(struct hclge_dev *hdev, { int ret; - ret = phy_loopback(phydev, false); + ret = phy_loopback(phydev, false, 0); if (ret) return ret; @@ -8000,7 +8000,7 @@ static int hclge_set_loopback(struct hnae3_handle *handle, ret = hclge_tqp_enable(handle, en); if (ret) dev_err(&hdev->pdev->dev, "failed to %s tqp in loopback, ret = %d\n", - en ? "enable" : "disable", ret); + str_enable_disable(en), ret); return ret; } @@ -11200,9 +11200,9 @@ static void hclge_info_show(struct hclge_dev *hdev) dev_info(dev, "This is %s PF\n", hdev->flag & HCLGE_FLAG_MAIN ? "main" : "not main"); dev_info(dev, "DCB %s\n", - handle->kinfo.tc_info.dcb_ets_active ? "enable" : "disable"); + str_enable_disable(handle->kinfo.tc_info.dcb_ets_active)); dev_info(dev, "MQPRIO %s\n", - handle->kinfo.tc_info.mqprio_active ? "enable" : "disable"); + str_enable_disable(handle->kinfo.tc_info.mqprio_active)); dev_info(dev, "Default tx spare buffer size: %u\n", hdev->tx_spare_buf_size); @@ -11492,7 +11492,7 @@ static void hclge_state_uninit(struct hclge_dev *hdev) set_bit(HCLGE_STATE_REMOVING, &hdev->state); if (hdev->reset_timer.function) - del_timer_sync(&hdev->reset_timer); + timer_delete_sync(&hdev->reset_timer); if (hdev->service_task.work.func) cancel_delayed_work_sync(&hdev->service_task); } @@ -11976,7 +11976,7 @@ static int hclge_set_vf_spoofchk_hw(struct hclge_dev *hdev, int vf, bool enable) if (ret) { dev_err(&hdev->pdev->dev, "Set vf %d mac spoof check %s failed, ret=%d\n", - vf, enable ? "on" : "off", ret); + vf, str_on_off(enable), ret); return ret; } @@ -11984,7 +11984,7 @@ static int hclge_set_vf_spoofchk_hw(struct hclge_dev *hdev, int vf, bool enable) if (ret) dev_err(&hdev->pdev->dev, "Set vf %d vlan spoof check %s failed, ret=%d\n", - vf, enable ? "on" : "off", ret); + vf, str_on_off(enable), ret); return ret; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c index 80079657afeb..9a456ebf9b7c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c @@ -258,7 +258,7 @@ void hclge_mac_start_phy(struct hclge_dev *hdev) if (!phydev) return; - phy_loopback(phydev, false); + phy_loopback(phydev, false, 0); phy_start(phydev); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c index bab16c2191b2..ec581d4b696f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c @@ -2,6 +2,7 @@ // Copyright (c) 2021 Hisilicon Limited. #include <linux/skbuff.h> +#include <linux/string_choices.h> #include "hclge_main.h" #include "hnae3.h" @@ -226,7 +227,7 @@ static int hclge_ptp_int_en(struct hclge_dev *hdev, bool en) if (ret) dev_err(&hdev->pdev->dev, "failed to %s ptp interrupt, ret = %d\n", - en ? "enable" : "disable", ret); + str_enable_disable(en), ret); return ret; } @@ -439,6 +440,13 @@ static int hclge_ptp_create_clock(struct hclge_dev *hdev) ptp->info.settime64 = hclge_ptp_settime; ptp->info.n_alarm = 0; + + spin_lock_init(&ptp->lock); + ptp->io_base = hdev->hw.hw.io_base + HCLGE_PTP_REG_OFFSET; + ptp->ts_cfg.rx_filter = HWTSTAMP_FILTER_NONE; + ptp->ts_cfg.tx_type = HWTSTAMP_TX_OFF; + hdev->ptp = ptp; + ptp->clock = ptp_clock_register(&ptp->info, &hdev->pdev->dev); if (IS_ERR(ptp->clock)) { dev_err(&hdev->pdev->dev, @@ -450,12 +458,6 @@ static int hclge_ptp_create_clock(struct hclge_dev *hdev) return -ENODEV; } - spin_lock_init(&ptp->lock); - ptp->io_base = hdev->hw.hw.io_base + HCLGE_PTP_REG_OFFSET; - ptp->ts_cfg.rx_filter = HWTSTAMP_FILTER_NONE; - ptp->ts_cfg.tx_type = HWTSTAMP_TX_OFF; - hdev->ptp = ptp; - return 0; } @@ -483,7 +485,7 @@ int hclge_ptp_init(struct hclge_dev *hdev) ret = hclge_ptp_get_cycle(hdev); if (ret) - return ret; + goto out; } ret = hclge_ptp_int_en(hdev, true); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 9ba767740a04..c4f35e8e2177 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -1292,9 +1292,8 @@ static void hclgevf_sync_vlan_filter(struct hclgevf_dev *hdev) rtnl_unlock(); } -static int hclgevf_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable) +static int hclgevf_en_hw_strip_rxvtag_cmd(struct hclgevf_dev *hdev, bool enable) { - struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); struct hclge_vf_to_pf_msg send_msg; hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN, @@ -1303,6 +1302,19 @@ static int hclgevf_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable) return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0); } +static int hclgevf_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable) +{ + struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + int ret; + + ret = hclgevf_en_hw_strip_rxvtag_cmd(hdev, enable); + if (ret) + return ret; + + hdev->rxvtag_strip_en = enable; + return 0; +} + static int hclgevf_reset_tqp(struct hnae3_handle *handle) { #define HCLGEVF_RESET_ALL_QUEUE_DONE 1U @@ -2045,7 +2057,7 @@ static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev, static void hclgevf_reset_timer(struct timer_list *t) { - struct hclgevf_dev *hdev = from_timer(hdev, t, reset_timer); + struct hclgevf_dev *hdev = timer_container_of(hdev, t, reset_timer); hclgevf_clear_event_cause(hdev, HCLGEVF_VECTOR0_EVENT_RST); hclgevf_reset_task_schedule(hdev); @@ -2204,12 +2216,13 @@ static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev) tc_valid, tc_size); } -static int hclgevf_init_vlan_config(struct hclgevf_dev *hdev) +static int hclgevf_init_vlan_config(struct hclgevf_dev *hdev, + bool rxvtag_strip_en) { struct hnae3_handle *nic = &hdev->nic; int ret; - ret = hclgevf_en_hw_strip_rxvtag(nic, true); + ret = hclgevf_en_hw_strip_rxvtag(nic, rxvtag_strip_en); if (ret) { dev_err(&hdev->pdev->dev, "failed to enable rx vlan offload, ret = %d\n", ret); @@ -2879,7 +2892,7 @@ static int hclgevf_reset_hdev(struct hclgevf_dev *hdev) if (ret) return ret; - ret = hclgevf_init_vlan_config(hdev); + ret = hclgevf_init_vlan_config(hdev, hdev->rxvtag_strip_en); if (ret) { dev_err(&hdev->pdev->dev, "failed(%d) to initialize VLAN config\n", ret); @@ -2994,7 +3007,7 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) goto err_config; } - ret = hclgevf_init_vlan_config(hdev); + ret = hclgevf_init_vlan_config(hdev, true); if (ret) { dev_err(&hdev->pdev->dev, "failed(%d) to initialize VLAN config\n", ret); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index cccef3228461..0208425ab594 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -253,6 +253,7 @@ struct hclgevf_dev { int *vector_irq; bool gro_en; + bool rxvtag_strip_en; unsigned long vlan_del_fail_bmap[BITS_TO_LONGS(VLAN_N_VID)]; diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c index a1aa6c1f966e..6812be8dc64f 100644 --- a/drivers/net/ethernet/hisilicon/hns_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns_mdio.c @@ -640,7 +640,7 @@ static struct platform_driver hns_mdio_driver = { .driver = { .name = MDIO_DRV_NAME, .of_match_table = hns_mdio_match, - .acpi_match_table = ACPI_PTR(hns_mdio_acpi_match), + .acpi_match_table = hns_mdio_acpi_match, }, }; |