diff options
Diffstat (limited to 'drivers/net/ethernet/hisilicon/hns3')
21 files changed, 1037 insertions, 725 deletions
diff --git a/drivers/net/ethernet/hisilicon/hns3/Makefile b/drivers/net/ethernet/hisilicon/hns3/Makefile index 6efea4662858..e214bfaece1f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/Makefile +++ b/drivers/net/ethernet/hisilicon/hns3/Makefile @@ -17,11 +17,11 @@ hns3-$(CONFIG_HNS3_DCB) += hns3_dcbnl.o obj-$(CONFIG_HNS3_HCLGEVF) += hclgevf.o -hclgevf-objs = hns3vf/hclgevf_main.o hns3vf/hclgevf_mbx.o hns3vf/hclgevf_devlink.o \ +hclgevf-objs = hns3vf/hclgevf_main.o hns3vf/hclgevf_mbx.o hns3vf/hclgevf_devlink.o hns3vf/hclgevf_regs.o \ hns3_common/hclge_comm_cmd.o hns3_common/hclge_comm_rss.o hns3_common/hclge_comm_tqp_stats.o obj-$(CONFIG_HNS3_HCLGE) += hclge.o -hclge-objs = hns3pf/hclge_main.o hns3pf/hclge_mdio.o hns3pf/hclge_tm.o \ +hclge-objs = hns3pf/hclge_main.o hns3pf/hclge_mdio.o hns3pf/hclge_tm.o hns3pf/hclge_regs.o \ hns3pf/hclge_mbx.o hns3pf/hclge_err.o hns3pf/hclge_debugfs.o hns3pf/hclge_ptp.o hns3pf/hclge_devlink.o \ hns3_common/hclge_comm_cmd.o hns3_common/hclge_comm_rss.o hns3_common/hclge_comm_tqp_stats.o diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index b99d75260d59..a4b43bcd2f0c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -31,6 +31,7 @@ #include <linux/pci.h> #include <linux/pkt_sched.h> #include <linux/types.h> +#include <linux/bitmap.h> #include <net/pkt_cls.h> #include <net/pkt_sched.h> @@ -101,6 +102,7 @@ enum HNAE3_DEV_CAP_BITS { HNAE3_DEV_SUPPORT_FEC_STATS_B, HNAE3_DEV_SUPPORT_LANE_NUM_B, HNAE3_DEV_SUPPORT_WOL_B, + HNAE3_DEV_SUPPORT_TM_FLUSH_B, }; #define hnae3_ae_dev_fd_supported(ae_dev) \ @@ -172,6 +174,9 @@ enum HNAE3_DEV_CAP_BITS { #define hnae3_ae_dev_wol_supported(ae_dev) \ test_bit(HNAE3_DEV_SUPPORT_WOL_B, (ae_dev)->caps) +#define hnae3_ae_dev_tm_flush_supported(hdev) \ + test_bit(HNAE3_DEV_SUPPORT_TM_FLUSH_B, (hdev)->ae_dev->caps) + enum HNAE3_PF_CAP_BITS { HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B = 0, }; @@ -377,6 +382,7 @@ struct hnae3_dev_specs { u16 umv_size; u16 mc_mac_size; u32 mac_stats_num; + u8 tnl_num; }; struct hnae3_client_ops { @@ -407,7 +413,7 @@ struct hnae3_ae_dev { unsigned long hw_err_reset_req; struct hnae3_dev_specs dev_specs; u32 dev_version; - unsigned long caps[BITS_TO_LONGS(HNAE3_DEV_CAPS_MAX_NUM)]; + DECLARE_BITMAP(caps, HNAE3_DEV_CAPS_MAX_NUM); void *priv; }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c index b85c412683dd..dcecb23daac6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c @@ -156,6 +156,7 @@ static const struct hclge_comm_caps_bit_map hclge_pf_cmd_caps[] = { {HCLGE_COMM_CAP_FEC_STATS_B, HNAE3_DEV_SUPPORT_FEC_STATS_B}, {HCLGE_COMM_CAP_LANE_NUM_B, HNAE3_DEV_SUPPORT_LANE_NUM_B}, {HCLGE_COMM_CAP_WOL_B, HNAE3_DEV_SUPPORT_WOL_B}, + {HCLGE_COMM_CAP_TM_FLUSH_B, HNAE3_DEV_SUPPORT_TM_FLUSH_B}, }; static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = { @@ -172,6 +173,20 @@ static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = { }; static void +hclge_comm_capability_to_bitmap(unsigned long *bitmap, __le32 *caps) +{ + const unsigned int words = HCLGE_COMM_QUERY_CAP_LENGTH; + u32 val[HCLGE_COMM_QUERY_CAP_LENGTH]; + unsigned int i; + + for (i = 0; i < words; i++) + val[i] = __le32_to_cpu(caps[i]); + + bitmap_from_arr32(bitmap, val, + HCLGE_COMM_QUERY_CAP_LENGTH * BITS_PER_TYPE(u32)); +} + +static void hclge_comm_parse_capability(struct hnae3_ae_dev *ae_dev, bool is_pf, struct hclge_comm_query_version_cmd *cmd) { @@ -179,11 +194,12 @@ hclge_comm_parse_capability(struct hnae3_ae_dev *ae_dev, bool is_pf, is_pf ? hclge_pf_cmd_caps : hclge_vf_cmd_caps; u32 size = is_pf ? ARRAY_SIZE(hclge_pf_cmd_caps) : ARRAY_SIZE(hclge_vf_cmd_caps); - u32 caps, i; + DECLARE_BITMAP(caps, HCLGE_COMM_QUERY_CAP_LENGTH * BITS_PER_TYPE(u32)); + u32 i; - caps = __le32_to_cpu(cmd->caps[0]); + hclge_comm_capability_to_bitmap(caps, cmd->caps); for (i = 0; i < size; i++) - if (hnae3_get_bit(caps, caps_map[i].imp_bit)) + if (test_bit(caps_map[i].imp_bit, caps)) set_bit(caps_map[i].local_bit, ae_dev->caps); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h index 18f1b4bf362d..2b7197ce0ae8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h @@ -153,6 +153,7 @@ enum hclge_opcode_type { HCLGE_OPC_TM_INTERNAL_STS = 0x0850, HCLGE_OPC_TM_INTERNAL_CNT = 0x0851, HCLGE_OPC_TM_INTERNAL_STS_1 = 0x0852, + HCLGE_OPC_TM_FLUSH = 0x0872, /* Packet buffer allocate commands */ HCLGE_OPC_TX_BUFF_ALLOC = 0x0901, @@ -349,6 +350,7 @@ enum HCLGE_COMM_CAP_BITS { HCLGE_COMM_CAP_FEC_STATS_B = 25, HCLGE_COMM_CAP_LANE_NUM_B = 27, HCLGE_COMM_CAP_WOL_B = 28, + HCLGE_COMM_CAP_TM_FLUSH_B = 31, }; enum HCLGE_COMM_API_CAP_BITS { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 6546cfe7f7cc..f276b5ecb431 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -411,6 +411,9 @@ static struct hns3_dbg_cap_info hns3_dbg_cap[] = { }, { .name = "support wake on lan", .cap_bit = HNAE3_DEV_SUPPORT_WOL_B, + }, { + .name = "support tm flush", + .cap_bit = HNAE3_DEV_SUPPORT_TM_FLUSH_B, } }; @@ -461,9 +464,9 @@ static void hns3_dbg_fill_content(char *content, u16 len, if (result) { if (item_len < strlen(result[i])) break; - strscpy(pos, result[i], strlen(result[i])); + memcpy(pos, result[i], strlen(result[i])); } else { - strscpy(pos, items[i].name, strlen(items[i].name)); + memcpy(pos, items[i].name, strlen(items[i].name)); } pos += item_len; len -= item_len; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 9f6890059666..eac2d0573241 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -18,6 +18,7 @@ #include <net/gre.h> #include <net/gro.h> #include <net/ip6_checksum.h> +#include <net/page_pool/helpers.h> #include <net/pkt_cls.h> #include <net/pkt_sched.h> #include <net/tcp.h> @@ -5854,6 +5855,9 @@ void hns3_external_lb_prepare(struct net_device *ndev, bool if_running) if (!if_running) return; + if (test_and_set_bit(HNS3_NIC_STATE_DOWN, &priv->state)) + return; + netif_carrier_off(ndev); netif_tx_disable(ndev); @@ -5882,7 +5886,16 @@ void hns3_external_lb_restore(struct net_device *ndev, bool if_running) if (!if_running) return; - hns3_nic_reset_all_ring(priv->ae_handle); + if (hns3_nic_resetting(ndev)) + return; + + if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) + return; + + if (hns3_nic_reset_all_ring(priv->ae_handle)) + return; + + clear_bit(HNS3_NIC_STATE_DOWN, &priv->state); for (i = 0; i < priv->vector_num; i++) hns3_vector_enable(&priv->tqp_vector[i]); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 88af34bbee34..acd756b0c7c9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -6,7 +6,7 @@ #include <linux/dim.h> #include <linux/if_vlan.h> -#include <net/page_pool.h> +#include <net/page_pool/types.h> #include <asm/barrier.h> #include "hnae3.h" diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 407d30ee55d2..36858a72d771 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -569,8 +569,8 @@ static void hns3_get_strings(struct net_device *netdev, u32 stringset, u8 *data) static u64 *hns3_get_stats_tqps(struct hnae3_handle *handle, u64 *data) { - struct hns3_nic_priv *nic_priv = (struct hns3_nic_priv *)handle->priv; struct hnae3_knic_private_info *kinfo = &handle->kinfo; + struct hns3_nic_priv *nic_priv = handle->priv; struct hns3_enet_ring *ring; u8 *stat; int i, j; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 91c173f40701..4d15eb73b972 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -826,7 +826,9 @@ struct hclge_dev_specs_1_cmd { u8 rsv0[2]; __le16 umv_size; __le16 mc_mac_size; - u8 rsv1[12]; + u8 rsv1[6]; + u8 tnl_num; + u8 rsv2[5]; }; /* mac speed type defined in firmware command */ @@ -886,8 +888,4 @@ struct hclge_query_wol_supported_cmd { struct hclge_hw; int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num); -enum hclge_comm_cmd_status hclge_cmd_mdio_write(struct hclge_hw *hw, - struct hclge_desc *desc); -enum hclge_comm_cmd_status hclge_cmd_mdio_read(struct hclge_hw *hw, - struct hclge_desc *desc); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index c4aded65e848..fad5a5ff3cda 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -52,7 +52,10 @@ static void hclge_tm_info_to_ieee_ets(struct hclge_dev *hdev, for (i = 0; i < HNAE3_MAX_TC; i++) { ets->prio_tc[i] = hdev->tm_info.prio_tc[i]; - ets->tc_tx_bw[i] = hdev->tm_info.pg_info[0].tc_dwrr[i]; + if (i < hdev->tm_info.num_tc) + ets->tc_tx_bw[i] = hdev->tm_info.pg_info[0].tc_dwrr[i]; + else + ets->tc_tx_bw[i] = 0; if (hdev->tm_info.tc_info[i].tc_sch_mode == HCLGE_SCH_MODE_SP) @@ -123,7 +126,8 @@ static u8 hclge_ets_tc_changed(struct hclge_dev *hdev, struct ieee_ets *ets, } static int hclge_ets_sch_mode_validate(struct hclge_dev *hdev, - struct ieee_ets *ets, bool *changed) + struct ieee_ets *ets, bool *changed, + u8 tc_num) { bool has_ets_tc = false; u32 total_ets_bw = 0; @@ -137,6 +141,13 @@ static int hclge_ets_sch_mode_validate(struct hclge_dev *hdev, *changed = true; break; case IEEE_8021QAZ_TSA_ETS: + if (i >= tc_num) { + dev_err(&hdev->pdev->dev, + "tc%u is disabled, cannot set ets bw\n", + i); + return -EINVAL; + } + /* The hardware will switch to sp mode if bandwidth is * 0, so limit ets bandwidth must be greater than 0. */ @@ -176,7 +187,7 @@ static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets, if (ret) return ret; - ret = hclge_ets_sch_mode_validate(hdev, ets, changed); + ret = hclge_ets_sch_mode_validate(hdev, ets, changed, tc_num); if (ret) return ret; @@ -216,6 +227,10 @@ static int hclge_notify_down_uinit(struct hclge_dev *hdev) if (ret) return ret; + ret = hclge_tm_flush_cfg(hdev, true); + if (ret) + return ret; + return hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT); } @@ -227,6 +242,10 @@ static int hclge_notify_init_up(struct hclge_dev *hdev) if (ret) return ret; + ret = hclge_tm_flush_cfg(hdev, false); + if (ret) + return ret; + return hclge_notify_client(hdev, HNAE3_UP_CLIENT); } @@ -313,6 +332,7 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) struct net_device *netdev = h->kinfo.netdev; struct hclge_dev *hdev = vport->back; u8 i, j, pfc_map, *prio_tc; + int last_bad_ret = 0; int ret; if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) @@ -350,13 +370,28 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) if (ret) return ret; - ret = hclge_buffer_alloc(hdev); - if (ret) { - hclge_notify_client(hdev, HNAE3_UP_CLIENT); + ret = hclge_tm_flush_cfg(hdev, true); + if (ret) return ret; - } - return hclge_notify_client(hdev, HNAE3_UP_CLIENT); + /* No matter whether the following operations are performed + * successfully or not, disabling the tm flush and notify + * the network status to up are necessary. + * Do not return immediately. + */ + ret = hclge_buffer_alloc(hdev); + if (ret) + last_bad_ret = ret; + + ret = hclge_tm_flush_cfg(hdev, false); + if (ret) + last_bad_ret = ret; + + ret = hclge_notify_client(hdev, HNAE3_UP_CLIENT); + if (ret) + last_bad_ret = ret; + + return last_bad_ret; } static int hclge_ieee_setapp(struct hnae3_handle *h, struct dcb_app *app) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 233c132dc513..f01a7a9ee02c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -7,6 +7,7 @@ #include "hclge_debugfs.h" #include "hclge_err.h" #include "hclge_main.h" +#include "hclge_regs.h" #include "hclge_tm.h" #include "hnae3.h" @@ -111,9 +112,9 @@ static void hclge_dbg_fill_content(char *content, u16 len, if (result) { if (item_len < strlen(result[i])) break; - strscpy(pos, result[i], strlen(result[i])); + memcpy(pos, result[i], strlen(result[i])); } else { - strscpy(pos, items[i].name, strlen(items[i].name)); + memcpy(pos, items[i].name, strlen(items[i].name)); } pos += item_len; len -= item_len; @@ -693,8 +694,7 @@ static int hclge_dbg_dump_tc(struct hclge_dev *hdev, char *buf, int len) for (i = 0; i < HNAE3_MAX_TC; i++) { sch_mode_str = ets_weight->tc_weight[i] ? "dwrr" : "sp"; pos += scnprintf(buf + pos, len - pos, "%u %4s %3u\n", - i, sch_mode_str, - hdev->tm_info.pg_info[0].tc_dwrr[i]); + i, sch_mode_str, ets_weight->tc_weight[i]); } return 0; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index bf675c15fbb9..0f50dba6cc47 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -20,6 +20,7 @@ #include "hclge_main.h" #include "hclge_mbx.h" #include "hclge_mdio.h" +#include "hclge_regs.h" #include "hclge_tm.h" #include "hclge_err.h" #include "hnae3.h" @@ -40,20 +41,6 @@ #define HCLGE_PF_RESET_SYNC_TIME 20 #define HCLGE_PF_RESET_SYNC_CNT 1500 -/* Get DFX BD number offset */ -#define HCLGE_DFX_BIOS_BD_OFFSET 1 -#define HCLGE_DFX_SSU_0_BD_OFFSET 2 -#define HCLGE_DFX_SSU_1_BD_OFFSET 3 -#define HCLGE_DFX_IGU_BD_OFFSET 4 -#define HCLGE_DFX_RPU_0_BD_OFFSET 5 -#define HCLGE_DFX_RPU_1_BD_OFFSET 6 -#define HCLGE_DFX_NCSI_BD_OFFSET 7 -#define HCLGE_DFX_RTC_BD_OFFSET 8 -#define HCLGE_DFX_PPP_BD_OFFSET 9 -#define HCLGE_DFX_RCB_BD_OFFSET 10 -#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); @@ -72,6 +59,8 @@ static void hclge_restore_hw_table(struct hclge_dev *hdev); static void hclge_sync_promisc_mode(struct hclge_dev *hdev); static void hclge_sync_fd_table(struct hclge_dev *hdev); static void hclge_update_fec_stats(struct hclge_dev *hdev); +static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret, + int wait_cnt); static struct hnae3_ae_algo ae_algo; @@ -92,62 +81,6 @@ static const struct pci_device_id ae_algo_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, ae_algo_pci_tbl); -static const u32 cmdq_reg_addr_list[] = {HCLGE_COMM_NIC_CSQ_BASEADDR_L_REG, - HCLGE_COMM_NIC_CSQ_BASEADDR_H_REG, - HCLGE_COMM_NIC_CSQ_DEPTH_REG, - HCLGE_COMM_NIC_CSQ_TAIL_REG, - HCLGE_COMM_NIC_CSQ_HEAD_REG, - HCLGE_COMM_NIC_CRQ_BASEADDR_L_REG, - HCLGE_COMM_NIC_CRQ_BASEADDR_H_REG, - HCLGE_COMM_NIC_CRQ_DEPTH_REG, - HCLGE_COMM_NIC_CRQ_TAIL_REG, - HCLGE_COMM_NIC_CRQ_HEAD_REG, - HCLGE_COMM_VECTOR0_CMDQ_SRC_REG, - HCLGE_COMM_CMDQ_INTR_STS_REG, - HCLGE_COMM_CMDQ_INTR_EN_REG, - HCLGE_COMM_CMDQ_INTR_GEN_REG}; - -static const u32 common_reg_addr_list[] = {HCLGE_MISC_VECTOR_REG_BASE, - HCLGE_PF_OTHER_INT_REG, - HCLGE_MISC_RESET_STS_REG, - HCLGE_MISC_VECTOR_INT_STS, - HCLGE_GLOBAL_RESET_REG, - HCLGE_FUN_RST_ING, - HCLGE_GRO_EN_REG}; - -static const u32 ring_reg_addr_list[] = {HCLGE_RING_RX_ADDR_L_REG, - HCLGE_RING_RX_ADDR_H_REG, - HCLGE_RING_RX_BD_NUM_REG, - HCLGE_RING_RX_BD_LENGTH_REG, - HCLGE_RING_RX_MERGE_EN_REG, - HCLGE_RING_RX_TAIL_REG, - HCLGE_RING_RX_HEAD_REG, - HCLGE_RING_RX_FBD_NUM_REG, - HCLGE_RING_RX_OFFSET_REG, - HCLGE_RING_RX_FBD_OFFSET_REG, - HCLGE_RING_RX_STASH_REG, - HCLGE_RING_RX_BD_ERR_REG, - HCLGE_RING_TX_ADDR_L_REG, - HCLGE_RING_TX_ADDR_H_REG, - HCLGE_RING_TX_BD_NUM_REG, - HCLGE_RING_TX_PRIORITY_REG, - HCLGE_RING_TX_TC_REG, - HCLGE_RING_TX_MERGE_EN_REG, - HCLGE_RING_TX_TAIL_REG, - HCLGE_RING_TX_HEAD_REG, - HCLGE_RING_TX_FBD_NUM_REG, - HCLGE_RING_TX_OFFSET_REG, - HCLGE_RING_TX_EBD_NUM_REG, - HCLGE_RING_TX_EBD_OFFSET_REG, - HCLGE_RING_TX_BD_ERR_REG, - HCLGE_RING_EN_REG}; - -static const u32 tqp_intr_reg_addr_list[] = {HCLGE_TQP_INTR_CTRL_REG, - HCLGE_TQP_INTR_GL0_REG, - HCLGE_TQP_INTR_GL1_REG, - HCLGE_TQP_INTR_GL2_REG, - HCLGE_TQP_INTR_RL_REG}; - static const char hns3_nic_test_strs[][ETH_GSTRING_LEN] = { "External Loopback test", "App Loopback test", @@ -373,36 +306,6 @@ static const struct hclge_mac_mgr_tbl_entry_cmd hclge_mgr_table[] = { }, }; -static const u32 hclge_dfx_bd_offset_list[] = { - HCLGE_DFX_BIOS_BD_OFFSET, - HCLGE_DFX_SSU_0_BD_OFFSET, - HCLGE_DFX_SSU_1_BD_OFFSET, - HCLGE_DFX_IGU_BD_OFFSET, - HCLGE_DFX_RPU_0_BD_OFFSET, - HCLGE_DFX_RPU_1_BD_OFFSET, - HCLGE_DFX_NCSI_BD_OFFSET, - HCLGE_DFX_RTC_BD_OFFSET, - HCLGE_DFX_PPP_BD_OFFSET, - HCLGE_DFX_RCB_BD_OFFSET, - HCLGE_DFX_TQP_BD_OFFSET, - HCLGE_DFX_SSU_2_BD_OFFSET -}; - -static const enum hclge_opcode_type hclge_dfx_reg_opcode_list[] = { - HCLGE_OPC_DFX_BIOS_COMMON_REG, - HCLGE_OPC_DFX_SSU_REG_0, - HCLGE_OPC_DFX_SSU_REG_1, - HCLGE_OPC_DFX_IGU_EGU_REG, - HCLGE_OPC_DFX_RPU_REG_0, - HCLGE_OPC_DFX_RPU_REG_1, - HCLGE_OPC_DFX_NCSI_REG, - HCLGE_OPC_DFX_RTC_REG, - HCLGE_OPC_DFX_PPP_REG, - HCLGE_OPC_DFX_RCB_REG, - HCLGE_OPC_DFX_TQP_REG, - HCLGE_OPC_DFX_SSU_REG_2 -}; - static const struct key_info meta_data_key_info[] = { { PACKET_TYPE_ID, 6 }, { IP_FRAGEMENT, 1 }, @@ -1423,6 +1326,7 @@ static void hclge_set_default_dev_specs(struct hclge_dev *hdev) ae_dev->dev_specs.max_frm_size = HCLGE_MAC_MAX_FRAME; ae_dev->dev_specs.max_qset_num = HCLGE_MAX_QSET_NUM; ae_dev->dev_specs.umv_size = HCLGE_DEFAULT_UMV_SPACE_PER_PF; + ae_dev->dev_specs.tnl_num = 0; } static void hclge_parse_dev_specs(struct hclge_dev *hdev, @@ -1446,6 +1350,7 @@ static void hclge_parse_dev_specs(struct hclge_dev *hdev, ae_dev->dev_specs.max_frm_size = le16_to_cpu(req1->max_frm_size); ae_dev->dev_specs.umv_size = le16_to_cpu(req1->umv_size); ae_dev->dev_specs.mc_mac_size = le16_to_cpu(req1->mc_mac_size); + ae_dev->dev_specs.tnl_num = req1->tnl_num; } static void hclge_check_dev_specs(struct hclge_dev *hdev) @@ -7315,14 +7220,14 @@ static int hclge_parse_cls_flower(struct hclge_dev *hdev, struct flow_dissector *dissector = flow->match.dissector; if (dissector->used_keys & - ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | - BIT(FLOW_DISSECTOR_KEY_BASIC) | - BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_VLAN) | - BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | - BIT(FLOW_DISSECTOR_KEY_PORTS))) { - dev_err(&hdev->pdev->dev, "unsupported key set: %#x\n", + ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | + BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | + BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | + BIT_ULL(FLOW_DISSECTOR_KEY_PORTS))) { + dev_err(&hdev->pdev->dev, "unsupported key set: %#llx\n", dissector->used_keys); return -EOPNOTSUPP; } @@ -7558,6 +7463,8 @@ static void hclge_enable_fd(struct hnae3_handle *handle, bool enable) static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable) { +#define HCLGE_LINK_STATUS_WAIT_CNT 3 + struct hclge_desc desc; struct hclge_config_mac_mode_cmd *req = (struct hclge_config_mac_mode_cmd *)desc.data; @@ -7582,9 +7489,15 @@ static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable) req->txrx_pad_fcs_loop_en = cpu_to_le32(loop_en); ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) + if (ret) { dev_err(&hdev->pdev->dev, "mac enable fail, ret =%d.\n", ret); + return; + } + + if (!enable) + hclge_mac_link_status_wait(hdev, HCLGE_LINK_STATUS_DOWN, + HCLGE_LINK_STATUS_WAIT_CNT); } static int hclge_config_switch_param(struct hclge_dev *hdev, int vfid, @@ -7647,10 +7560,9 @@ static void hclge_phy_link_status_wait(struct hclge_dev *hdev, } while (++i < HCLGE_PHY_LINK_STATUS_NUM); } -static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret) +static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret, + int wait_cnt) { -#define HCLGE_MAC_LINK_STATUS_NUM 100 - int link_status; int i = 0; int ret; @@ -7663,13 +7575,15 @@ static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret) return 0; msleep(HCLGE_LINK_STATUS_MS); - } while (++i < HCLGE_MAC_LINK_STATUS_NUM); + } while (++i < wait_cnt); return -EBUSY; } static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en, bool is_phy) { +#define HCLGE_MAC_LINK_STATUS_NUM 100 + int link_ret; link_ret = en ? HCLGE_LINK_STATUS_UP : HCLGE_LINK_STATUS_DOWN; @@ -7677,7 +7591,8 @@ static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en, if (is_phy) hclge_phy_link_status_wait(hdev, link_ret); - return hclge_mac_link_status_wait(hdev, link_ret); + return hclge_mac_link_status_wait(hdev, link_ret, + HCLGE_MAC_LINK_STATUS_NUM); } static int hclge_set_app_loopback(struct hclge_dev *hdev, bool en) @@ -10915,9 +10830,12 @@ int hclge_cfg_flowctrl(struct hclge_dev *hdev) u32 rx_pause, tx_pause; u8 flowctl; - if (!phydev->link || !phydev->autoneg) + if (!phydev->link) return 0; + if (!phydev->autoneg) + return hclge_mac_pause_setup_hw(hdev); + local_advertising = linkmode_adv_to_lcl_adv_t(phydev->advertising); if (phydev->pause) @@ -12368,463 +12286,6 @@ out: return ret; } -static int hclge_get_regs_num(struct hclge_dev *hdev, u32 *regs_num_32_bit, - u32 *regs_num_64_bit) -{ - struct hclge_desc desc; - u32 total_num; - int ret; - - hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_REG_NUM, true); - ret = hclge_cmd_send(&hdev->hw, &desc, 1); - if (ret) { - dev_err(&hdev->pdev->dev, - "Query register number cmd failed, ret = %d.\n", ret); - return ret; - } - - *regs_num_32_bit = le32_to_cpu(desc.data[0]); - *regs_num_64_bit = le32_to_cpu(desc.data[1]); - - total_num = *regs_num_32_bit + *regs_num_64_bit; - if (!total_num) - return -EINVAL; - - return 0; -} - -static int hclge_get_32_bit_regs(struct hclge_dev *hdev, u32 regs_num, - void *data) -{ -#define HCLGE_32_BIT_REG_RTN_DATANUM 8 -#define HCLGE_32_BIT_DESC_NODATA_LEN 2 - - struct hclge_desc *desc; - u32 *reg_val = data; - __le32 *desc_data; - int nodata_num; - int cmd_num; - int i, k, n; - int ret; - - if (regs_num == 0) - return 0; - - nodata_num = HCLGE_32_BIT_DESC_NODATA_LEN; - cmd_num = DIV_ROUND_UP(regs_num + nodata_num, - HCLGE_32_BIT_REG_RTN_DATANUM); - desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL); - if (!desc) - return -ENOMEM; - - hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_32_BIT_REG, true); - ret = hclge_cmd_send(&hdev->hw, desc, cmd_num); - if (ret) { - dev_err(&hdev->pdev->dev, - "Query 32 bit register cmd failed, ret = %d.\n", ret); - kfree(desc); - return ret; - } - - for (i = 0; i < cmd_num; i++) { - if (i == 0) { - desc_data = (__le32 *)(&desc[i].data[0]); - n = HCLGE_32_BIT_REG_RTN_DATANUM - nodata_num; - } else { - desc_data = (__le32 *)(&desc[i]); - n = HCLGE_32_BIT_REG_RTN_DATANUM; - } - for (k = 0; k < n; k++) { - *reg_val++ = le32_to_cpu(*desc_data++); - - regs_num--; - if (!regs_num) - break; - } - } - - kfree(desc); - return 0; -} - -static int hclge_get_64_bit_regs(struct hclge_dev *hdev, u32 regs_num, - void *data) -{ -#define HCLGE_64_BIT_REG_RTN_DATANUM 4 -#define HCLGE_64_BIT_DESC_NODATA_LEN 1 - - struct hclge_desc *desc; - u64 *reg_val = data; - __le64 *desc_data; - int nodata_len; - int cmd_num; - int i, k, n; - int ret; - - if (regs_num == 0) - return 0; - - nodata_len = HCLGE_64_BIT_DESC_NODATA_LEN; - cmd_num = DIV_ROUND_UP(regs_num + nodata_len, - HCLGE_64_BIT_REG_RTN_DATANUM); - desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL); - if (!desc) - return -ENOMEM; - - hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_64_BIT_REG, true); - ret = hclge_cmd_send(&hdev->hw, desc, cmd_num); - if (ret) { - dev_err(&hdev->pdev->dev, - "Query 64 bit register cmd failed, ret = %d.\n", ret); - kfree(desc); - return ret; - } - - for (i = 0; i < cmd_num; i++) { - if (i == 0) { - desc_data = (__le64 *)(&desc[i].data[0]); - n = HCLGE_64_BIT_REG_RTN_DATANUM - nodata_len; - } else { - desc_data = (__le64 *)(&desc[i]); - n = HCLGE_64_BIT_REG_RTN_DATANUM; - } - for (k = 0; k < n; k++) { - *reg_val++ = le64_to_cpu(*desc_data++); - - regs_num--; - if (!regs_num) - break; - } - } - - kfree(desc); - return 0; -} - -#define MAX_SEPARATE_NUM 4 -#define SEPARATOR_VALUE 0xFDFCFBFA -#define REG_NUM_PER_LINE 4 -#define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(u32)) -#define REG_SEPARATOR_LINE 1 -#define REG_NUM_REMAIN_MASK 3 - -int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, struct hclge_desc *desc) -{ - int i; - - /* initialize command BD except the last one */ - for (i = 0; i < HCLGE_GET_DFX_REG_TYPE_CNT - 1; i++) { - hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_DFX_BD_NUM, - true); - desc[i].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT); - } - - /* initialize the last command BD */ - hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_DFX_BD_NUM, true); - - return hclge_cmd_send(&hdev->hw, desc, HCLGE_GET_DFX_REG_TYPE_CNT); -} - -static int hclge_get_dfx_reg_bd_num(struct hclge_dev *hdev, - int *bd_num_list, - u32 type_num) -{ - u32 entries_per_desc, desc_index, index, offset, i; - struct hclge_desc desc[HCLGE_GET_DFX_REG_TYPE_CNT]; - int ret; - - ret = hclge_query_bd_num_cmd_send(hdev, desc); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get dfx bd num fail, status is %d.\n", ret); - return ret; - } - - entries_per_desc = ARRAY_SIZE(desc[0].data); - for (i = 0; i < type_num; i++) { - offset = hclge_dfx_bd_offset_list[i]; - index = offset % entries_per_desc; - desc_index = offset / entries_per_desc; - bd_num_list[i] = le32_to_cpu(desc[desc_index].data[index]); - } - - return ret; -} - -static int hclge_dfx_reg_cmd_send(struct hclge_dev *hdev, - struct hclge_desc *desc_src, int bd_num, - enum hclge_opcode_type cmd) -{ - struct hclge_desc *desc = desc_src; - int i, ret; - - hclge_cmd_setup_basic_desc(desc, cmd, true); - for (i = 0; i < bd_num - 1; i++) { - desc->flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT); - desc++; - hclge_cmd_setup_basic_desc(desc, cmd, true); - } - - desc = desc_src; - ret = hclge_cmd_send(&hdev->hw, desc, bd_num); - if (ret) - dev_err(&hdev->pdev->dev, - "Query dfx reg cmd(0x%x) send fail, status is %d.\n", - cmd, ret); - - return ret; -} - -static int hclge_dfx_reg_fetch_data(struct hclge_desc *desc_src, int bd_num, - void *data) -{ - int entries_per_desc, reg_num, separator_num, desc_index, index, i; - struct hclge_desc *desc = desc_src; - u32 *reg = data; - - entries_per_desc = ARRAY_SIZE(desc->data); - reg_num = entries_per_desc * bd_num; - separator_num = REG_NUM_PER_LINE - (reg_num & REG_NUM_REMAIN_MASK); - for (i = 0; i < reg_num; i++) { - index = i % entries_per_desc; - desc_index = i / entries_per_desc; - *reg++ = le32_to_cpu(desc[desc_index].data[index]); - } - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - - return reg_num + separator_num; -} - -static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len) -{ - u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); - int data_len_per_desc, bd_num, i; - int *bd_num_list; - u32 data_len; - int ret; - - bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL); - if (!bd_num_list) - return -ENOMEM; - - ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get dfx reg bd num fail, status is %d.\n", ret); - goto out; - } - - data_len_per_desc = sizeof_field(struct hclge_desc, data); - *len = 0; - for (i = 0; i < dfx_reg_type_num; i++) { - bd_num = bd_num_list[i]; - data_len = data_len_per_desc * bd_num; - *len += (data_len / REG_LEN_PER_LINE + 1) * REG_LEN_PER_LINE; - } - -out: - kfree(bd_num_list); - return ret; -} - -static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data) -{ - u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); - int bd_num, bd_num_max, buf_len, i; - struct hclge_desc *desc_src; - int *bd_num_list; - u32 *reg = data; - int ret; - - bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL); - if (!bd_num_list) - return -ENOMEM; - - ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get dfx reg bd num fail, status is %d.\n", ret); - goto out; - } - - bd_num_max = bd_num_list[0]; - for (i = 1; i < dfx_reg_type_num; i++) - bd_num_max = max_t(int, bd_num_max, bd_num_list[i]); - - buf_len = sizeof(*desc_src) * bd_num_max; - desc_src = kzalloc(buf_len, GFP_KERNEL); - if (!desc_src) { - ret = -ENOMEM; - goto out; - } - - for (i = 0; i < dfx_reg_type_num; i++) { - bd_num = bd_num_list[i]; - ret = hclge_dfx_reg_cmd_send(hdev, desc_src, bd_num, - hclge_dfx_reg_opcode_list[i]); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get dfx reg fail, status is %d.\n", ret); - break; - } - - reg += hclge_dfx_reg_fetch_data(desc_src, bd_num, reg); - } - - kfree(desc_src); -out: - kfree(bd_num_list); - return ret; -} - -static int hclge_fetch_pf_reg(struct hclge_dev *hdev, void *data, - struct hnae3_knic_private_info *kinfo) -{ -#define HCLGE_RING_REG_OFFSET 0x200 -#define HCLGE_RING_INT_REG_OFFSET 0x4 - - int i, j, reg_num, separator_num; - int data_num_sum; - u32 *reg = data; - - /* fetching per-PF registers valus from PF PCIe register space */ - reg_num = ARRAY_SIZE(cmdq_reg_addr_list); - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); - for (i = 0; i < reg_num; i++) - *reg++ = hclge_read_dev(&hdev->hw, cmdq_reg_addr_list[i]); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - data_num_sum = reg_num + separator_num; - - reg_num = ARRAY_SIZE(common_reg_addr_list); - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); - for (i = 0; i < reg_num; i++) - *reg++ = hclge_read_dev(&hdev->hw, common_reg_addr_list[i]); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - data_num_sum += reg_num + separator_num; - - reg_num = ARRAY_SIZE(ring_reg_addr_list); - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); - for (j = 0; j < kinfo->num_tqps; j++) { - for (i = 0; i < reg_num; i++) - *reg++ = hclge_read_dev(&hdev->hw, - ring_reg_addr_list[i] + - HCLGE_RING_REG_OFFSET * j); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - } - data_num_sum += (reg_num + separator_num) * kinfo->num_tqps; - - reg_num = ARRAY_SIZE(tqp_intr_reg_addr_list); - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); - for (j = 0; j < hdev->num_msi_used - 1; j++) { - for (i = 0; i < reg_num; i++) - *reg++ = hclge_read_dev(&hdev->hw, - tqp_intr_reg_addr_list[i] + - HCLGE_RING_INT_REG_OFFSET * j); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - } - data_num_sum += (reg_num + separator_num) * (hdev->num_msi_used - 1); - - return data_num_sum; -} - -static int hclge_get_regs_len(struct hnae3_handle *handle) -{ - int cmdq_lines, common_lines, ring_lines, tqp_intr_lines; - struct hnae3_knic_private_info *kinfo = &handle->kinfo; - struct hclge_vport *vport = hclge_get_vport(handle); - struct hclge_dev *hdev = vport->back; - int regs_num_32_bit, regs_num_64_bit, dfx_regs_len; - int regs_lines_32_bit, regs_lines_64_bit; - int ret; - - ret = hclge_get_regs_num(hdev, ®s_num_32_bit, ®s_num_64_bit); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get register number failed, ret = %d.\n", ret); - return ret; - } - - ret = hclge_get_dfx_reg_len(hdev, &dfx_regs_len); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get dfx reg len failed, ret = %d.\n", ret); - return ret; - } - - cmdq_lines = sizeof(cmdq_reg_addr_list) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - common_lines = sizeof(common_reg_addr_list) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - ring_lines = sizeof(ring_reg_addr_list) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - tqp_intr_lines = sizeof(tqp_intr_reg_addr_list) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - regs_lines_32_bit = regs_num_32_bit * sizeof(u32) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - regs_lines_64_bit = regs_num_64_bit * sizeof(u64) / REG_LEN_PER_LINE + - REG_SEPARATOR_LINE; - - return (cmdq_lines + common_lines + ring_lines * kinfo->num_tqps + - tqp_intr_lines * (hdev->num_msi_used - 1) + regs_lines_32_bit + - regs_lines_64_bit) * REG_LEN_PER_LINE + dfx_regs_len; -} - -static void hclge_get_regs(struct hnae3_handle *handle, u32 *version, - void *data) -{ - struct hnae3_knic_private_info *kinfo = &handle->kinfo; - struct hclge_vport *vport = hclge_get_vport(handle); - struct hclge_dev *hdev = vport->back; - u32 regs_num_32_bit, regs_num_64_bit; - int i, reg_num, separator_num, ret; - u32 *reg = data; - - *version = hdev->fw_version; - - ret = hclge_get_regs_num(hdev, ®s_num_32_bit, ®s_num_64_bit); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get register number failed, ret = %d.\n", ret); - return; - } - - reg += hclge_fetch_pf_reg(hdev, reg, kinfo); - - ret = hclge_get_32_bit_regs(hdev, regs_num_32_bit, reg); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get 32 bit register failed, ret = %d.\n", ret); - return; - } - reg_num = regs_num_32_bit; - reg += reg_num; - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - - ret = hclge_get_64_bit_regs(hdev, regs_num_64_bit, reg); - if (ret) { - dev_err(&hdev->pdev->dev, - "Get 64 bit register failed, ret = %d.\n", ret); - return; - } - reg_num = regs_num_64_bit * 2; - reg += reg_num; - separator_num = MAX_SEPARATE_NUM - (reg_num & REG_NUM_REMAIN_MASK); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - - ret = hclge_get_dfx_reg(hdev, reg); - if (ret) - dev_err(&hdev->pdev->dev, - "Get dfx register failed, ret = %d.\n", ret); -} - static int hclge_set_led_status(struct hclge_dev *hdev, u8 locate_led_status) { struct hclge_set_led_state_cmd *req; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 6a43d1515585..ec233ec57222 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -1142,11 +1142,8 @@ int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid, u16 state, struct hclge_vlan_info *vlan_info); 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); -void hclge_inform_vf_promisc_info(struct hclge_vport *vport); int hclge_dbg_dump_rst_info(struct hclge_dev *hdev, char *buf, int len); int hclge_push_vf_link_status(struct hclge_vport *vport); int hclge_enable_vport_vlan_filter(struct hclge_vport *vport, bool request_en); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c new file mode 100644 index 000000000000..43c1c18fa81f --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c @@ -0,0 +1,668 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2023 Hisilicon Limited. + +#include "hclge_cmd.h" +#include "hclge_main.h" +#include "hclge_regs.h" +#include "hnae3.h" + +static const u32 cmdq_reg_addr_list[] = {HCLGE_COMM_NIC_CSQ_BASEADDR_L_REG, + HCLGE_COMM_NIC_CSQ_BASEADDR_H_REG, + HCLGE_COMM_NIC_CSQ_DEPTH_REG, + HCLGE_COMM_NIC_CSQ_TAIL_REG, + HCLGE_COMM_NIC_CSQ_HEAD_REG, + HCLGE_COMM_NIC_CRQ_BASEADDR_L_REG, + HCLGE_COMM_NIC_CRQ_BASEADDR_H_REG, + HCLGE_COMM_NIC_CRQ_DEPTH_REG, + HCLGE_COMM_NIC_CRQ_TAIL_REG, + HCLGE_COMM_NIC_CRQ_HEAD_REG, + HCLGE_COMM_VECTOR0_CMDQ_SRC_REG, + HCLGE_COMM_CMDQ_INTR_STS_REG, + HCLGE_COMM_CMDQ_INTR_EN_REG, + HCLGE_COMM_CMDQ_INTR_GEN_REG}; + +static const u32 common_reg_addr_list[] = {HCLGE_MISC_VECTOR_REG_BASE, + HCLGE_PF_OTHER_INT_REG, + HCLGE_MISC_RESET_STS_REG, + HCLGE_MISC_VECTOR_INT_STS, + HCLGE_GLOBAL_RESET_REG, + HCLGE_FUN_RST_ING, + HCLGE_GRO_EN_REG}; + +static const u32 ring_reg_addr_list[] = {HCLGE_RING_RX_ADDR_L_REG, + HCLGE_RING_RX_ADDR_H_REG, + HCLGE_RING_RX_BD_NUM_REG, + HCLGE_RING_RX_BD_LENGTH_REG, + HCLGE_RING_RX_MERGE_EN_REG, + HCLGE_RING_RX_TAIL_REG, + HCLGE_RING_RX_HEAD_REG, + HCLGE_RING_RX_FBD_NUM_REG, + HCLGE_RING_RX_OFFSET_REG, + HCLGE_RING_RX_FBD_OFFSET_REG, + HCLGE_RING_RX_STASH_REG, + HCLGE_RING_RX_BD_ERR_REG, + HCLGE_RING_TX_ADDR_L_REG, + HCLGE_RING_TX_ADDR_H_REG, + HCLGE_RING_TX_BD_NUM_REG, + HCLGE_RING_TX_PRIORITY_REG, + HCLGE_RING_TX_TC_REG, + HCLGE_RING_TX_MERGE_EN_REG, + HCLGE_RING_TX_TAIL_REG, + HCLGE_RING_TX_HEAD_REG, + HCLGE_RING_TX_FBD_NUM_REG, + HCLGE_RING_TX_OFFSET_REG, + HCLGE_RING_TX_EBD_NUM_REG, + HCLGE_RING_TX_EBD_OFFSET_REG, + HCLGE_RING_TX_BD_ERR_REG, + HCLGE_RING_EN_REG}; + +static const u32 tqp_intr_reg_addr_list[] = {HCLGE_TQP_INTR_CTRL_REG, + HCLGE_TQP_INTR_GL0_REG, + HCLGE_TQP_INTR_GL1_REG, + HCLGE_TQP_INTR_GL2_REG, + HCLGE_TQP_INTR_RL_REG}; + +/* Get DFX BD number offset */ +#define HCLGE_DFX_BIOS_BD_OFFSET 1 +#define HCLGE_DFX_SSU_0_BD_OFFSET 2 +#define HCLGE_DFX_SSU_1_BD_OFFSET 3 +#define HCLGE_DFX_IGU_BD_OFFSET 4 +#define HCLGE_DFX_RPU_0_BD_OFFSET 5 +#define HCLGE_DFX_RPU_1_BD_OFFSET 6 +#define HCLGE_DFX_NCSI_BD_OFFSET 7 +#define HCLGE_DFX_RTC_BD_OFFSET 8 +#define HCLGE_DFX_PPP_BD_OFFSET 9 +#define HCLGE_DFX_RCB_BD_OFFSET 10 +#define HCLGE_DFX_TQP_BD_OFFSET 11 +#define HCLGE_DFX_SSU_2_BD_OFFSET 12 + +static const u32 hclge_dfx_bd_offset_list[] = { + HCLGE_DFX_BIOS_BD_OFFSET, + HCLGE_DFX_SSU_0_BD_OFFSET, + HCLGE_DFX_SSU_1_BD_OFFSET, + HCLGE_DFX_IGU_BD_OFFSET, + HCLGE_DFX_RPU_0_BD_OFFSET, + HCLGE_DFX_RPU_1_BD_OFFSET, + HCLGE_DFX_NCSI_BD_OFFSET, + HCLGE_DFX_RTC_BD_OFFSET, + HCLGE_DFX_PPP_BD_OFFSET, + HCLGE_DFX_RCB_BD_OFFSET, + HCLGE_DFX_TQP_BD_OFFSET, + HCLGE_DFX_SSU_2_BD_OFFSET +}; + +static const enum hclge_opcode_type hclge_dfx_reg_opcode_list[] = { + HCLGE_OPC_DFX_BIOS_COMMON_REG, + HCLGE_OPC_DFX_SSU_REG_0, + HCLGE_OPC_DFX_SSU_REG_1, + HCLGE_OPC_DFX_IGU_EGU_REG, + HCLGE_OPC_DFX_RPU_REG_0, + HCLGE_OPC_DFX_RPU_REG_1, + HCLGE_OPC_DFX_NCSI_REG, + HCLGE_OPC_DFX_RTC_REG, + HCLGE_OPC_DFX_PPP_REG, + HCLGE_OPC_DFX_RCB_REG, + HCLGE_OPC_DFX_TQP_REG, + HCLGE_OPC_DFX_SSU_REG_2 +}; + +enum hclge_reg_tag { + HCLGE_REG_TAG_CMDQ = 0, + HCLGE_REG_TAG_COMMON, + HCLGE_REG_TAG_RING, + HCLGE_REG_TAG_TQP_INTR, + HCLGE_REG_TAG_QUERY_32_BIT, + HCLGE_REG_TAG_QUERY_64_BIT, + HCLGE_REG_TAG_DFX_BIOS_COMMON, + HCLGE_REG_TAG_DFX_SSU_0, + HCLGE_REG_TAG_DFX_SSU_1, + HCLGE_REG_TAG_DFX_IGU_EGU, + HCLGE_REG_TAG_DFX_RPU_0, + HCLGE_REG_TAG_DFX_RPU_1, + HCLGE_REG_TAG_DFX_NCSI, + HCLGE_REG_TAG_DFX_RTC, + HCLGE_REG_TAG_DFX_PPP, + HCLGE_REG_TAG_DFX_RCB, + HCLGE_REG_TAG_DFX_TQP, + HCLGE_REG_TAG_DFX_SSU_2, + HCLGE_REG_TAG_RPU_TNL, +}; + +#pragma pack(4) +struct hclge_reg_tlv { + u16 tag; + u16 len; +}; + +struct hclge_reg_header { + u64 magic_number; + u8 is_vf; + u8 rsv[7]; +}; + +#pragma pack() + +#define HCLGE_REG_TLV_SIZE sizeof(struct hclge_reg_tlv) +#define HCLGE_REG_HEADER_SIZE sizeof(struct hclge_reg_header) +#define HCLGE_REG_TLV_SPACE (sizeof(struct hclge_reg_tlv) / sizeof(u32)) +#define HCLGE_REG_HEADER_SPACE (sizeof(struct hclge_reg_header) / sizeof(u32)) +#define HCLGE_REG_MAGIC_NUMBER 0x686e733372656773 /* meaning is hns3regs */ + +#define HCLGE_REG_RPU_TNL_ID_0 1 + +static u32 hclge_reg_get_header(void *data) +{ + struct hclge_reg_header *header = data; + + header->magic_number = HCLGE_REG_MAGIC_NUMBER; + header->is_vf = 0x0; + + return HCLGE_REG_HEADER_SPACE; +} + +static u32 hclge_reg_get_tlv(u32 tag, u32 regs_num, void *data) +{ + struct hclge_reg_tlv *tlv = data; + + tlv->tag = tag; + tlv->len = regs_num * sizeof(u32) + HCLGE_REG_TLV_SIZE; + + return HCLGE_REG_TLV_SPACE; +} + +static int hclge_get_32_bit_regs(struct hclge_dev *hdev, u32 regs_num, + void *data) +{ +#define HCLGE_32_BIT_REG_RTN_DATANUM 8 +#define HCLGE_32_BIT_DESC_NODATA_LEN 2 + + struct hclge_desc *desc; + u32 *reg_val = data; + __le32 *desc_data; + int nodata_num; + int cmd_num; + int i, k, n; + int ret; + + if (regs_num == 0) + return 0; + + nodata_num = HCLGE_32_BIT_DESC_NODATA_LEN; + cmd_num = DIV_ROUND_UP(regs_num + nodata_num, + HCLGE_32_BIT_REG_RTN_DATANUM); + desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + + hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_32_BIT_REG, true); + ret = hclge_cmd_send(&hdev->hw, desc, cmd_num); + if (ret) { + dev_err(&hdev->pdev->dev, + "Query 32 bit register cmd failed, ret = %d.\n", ret); + kfree(desc); + return ret; + } + + for (i = 0; i < cmd_num; i++) { + if (i == 0) { + desc_data = (__le32 *)(&desc[i].data[0]); + n = HCLGE_32_BIT_REG_RTN_DATANUM - nodata_num; + } else { + desc_data = (__le32 *)(&desc[i]); + n = HCLGE_32_BIT_REG_RTN_DATANUM; + } + for (k = 0; k < n; k++) { + *reg_val++ = le32_to_cpu(*desc_data++); + + regs_num--; + if (!regs_num) + break; + } + } + + kfree(desc); + return 0; +} + +static int hclge_get_64_bit_regs(struct hclge_dev *hdev, u32 regs_num, + void *data) +{ +#define HCLGE_64_BIT_REG_RTN_DATANUM 4 +#define HCLGE_64_BIT_DESC_NODATA_LEN 1 + + struct hclge_desc *desc; + u64 *reg_val = data; + __le64 *desc_data; + int nodata_len; + int cmd_num; + int i, k, n; + int ret; + + if (regs_num == 0) + return 0; + + nodata_len = HCLGE_64_BIT_DESC_NODATA_LEN; + cmd_num = DIV_ROUND_UP(regs_num + nodata_len, + HCLGE_64_BIT_REG_RTN_DATANUM); + desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + + hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_64_BIT_REG, true); + ret = hclge_cmd_send(&hdev->hw, desc, cmd_num); + if (ret) { + dev_err(&hdev->pdev->dev, + "Query 64 bit register cmd failed, ret = %d.\n", ret); + kfree(desc); + return ret; + } + + for (i = 0; i < cmd_num; i++) { + if (i == 0) { + desc_data = (__le64 *)(&desc[i].data[0]); + n = HCLGE_64_BIT_REG_RTN_DATANUM - nodata_len; + } else { + desc_data = (__le64 *)(&desc[i]); + n = HCLGE_64_BIT_REG_RTN_DATANUM; + } + for (k = 0; k < n; k++) { + *reg_val++ = le64_to_cpu(*desc_data++); + + regs_num--; + if (!regs_num) + break; + } + } + + kfree(desc); + return 0; +} + +int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, struct hclge_desc *desc) +{ + int i; + + /* initialize command BD except the last one */ + for (i = 0; i < HCLGE_GET_DFX_REG_TYPE_CNT - 1; i++) { + hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_DFX_BD_NUM, + true); + desc[i].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT); + } + + /* initialize the last command BD */ + hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_DFX_BD_NUM, true); + + return hclge_cmd_send(&hdev->hw, desc, HCLGE_GET_DFX_REG_TYPE_CNT); +} + +static int hclge_get_dfx_reg_bd_num(struct hclge_dev *hdev, + int *bd_num_list, + u32 type_num) +{ + u32 entries_per_desc, desc_index, index, offset, i; + struct hclge_desc desc[HCLGE_GET_DFX_REG_TYPE_CNT]; + int ret; + + ret = hclge_query_bd_num_cmd_send(hdev, desc); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get dfx bd num fail, status is %d.\n", ret); + return ret; + } + + entries_per_desc = ARRAY_SIZE(desc[0].data); + for (i = 0; i < type_num; i++) { + offset = hclge_dfx_bd_offset_list[i]; + index = offset % entries_per_desc; + desc_index = offset / entries_per_desc; + bd_num_list[i] = le32_to_cpu(desc[desc_index].data[index]); + } + + return ret; +} + +static int hclge_dfx_reg_cmd_send(struct hclge_dev *hdev, + struct hclge_desc *desc_src, int bd_num, + enum hclge_opcode_type cmd) +{ + struct hclge_desc *desc = desc_src; + int i, ret; + + hclge_cmd_setup_basic_desc(desc, cmd, true); + for (i = 0; i < bd_num - 1; i++) { + desc->flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT); + desc++; + hclge_cmd_setup_basic_desc(desc, cmd, true); + } + + desc = desc_src; + ret = hclge_cmd_send(&hdev->hw, desc, bd_num); + if (ret) + dev_err(&hdev->pdev->dev, + "Query dfx reg cmd(0x%x) send fail, status is %d.\n", + cmd, ret); + + return ret; +} + +/* tnl_id = 0 means get sum of all tnl reg's value */ +static int hclge_dfx_reg_rpu_tnl_cmd_send(struct hclge_dev *hdev, u32 tnl_id, + struct hclge_desc *desc, int bd_num) +{ + int i, ret; + + for (i = 0; i < bd_num; i++) { + hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_DFX_RPU_REG_0, + true); + if (i != bd_num - 1) + desc[i].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT); + } + + desc[0].data[0] = cpu_to_le32(tnl_id); + ret = hclge_cmd_send(&hdev->hw, desc, bd_num); + if (ret) + dev_err(&hdev->pdev->dev, + "failed to query dfx rpu tnl reg, ret = %d\n", + ret); + return ret; +} + +static int hclge_dfx_reg_fetch_data(struct hclge_desc *desc_src, int bd_num, + void *data) +{ + int entries_per_desc, reg_num, desc_index, index, i; + struct hclge_desc *desc = desc_src; + u32 *reg = data; + + entries_per_desc = ARRAY_SIZE(desc->data); + reg_num = entries_per_desc * bd_num; + for (i = 0; i < reg_num; i++) { + index = i % entries_per_desc; + desc_index = i / entries_per_desc; + *reg++ = le32_to_cpu(desc[desc_index].data[index]); + } + + return reg_num; +} + +static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len) +{ + u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); + int data_len_per_desc; + int *bd_num_list; + int ret; + u32 i; + + bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL); + if (!bd_num_list) + return -ENOMEM; + + ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get dfx reg bd num fail, status is %d.\n", ret); + goto out; + } + + data_len_per_desc = sizeof_field(struct hclge_desc, data); + *len = 0; + for (i = 0; i < dfx_reg_type_num; i++) + *len += bd_num_list[i] * data_len_per_desc + HCLGE_REG_TLV_SIZE; + + /** + * the num of dfx_rpu_0 is reused by each dfx_rpu_tnl + * HCLGE_DFX_BD_OFFSET is starting at 1, but the array subscript is + * starting at 0, so offset need '- 1'. + */ + *len += (bd_num_list[HCLGE_DFX_RPU_0_BD_OFFSET - 1] * data_len_per_desc + + HCLGE_REG_TLV_SIZE) * ae_dev->dev_specs.tnl_num; + +out: + kfree(bd_num_list); + return ret; +} + +static int hclge_get_dfx_rpu_tnl_reg(struct hclge_dev *hdev, u32 *reg, + struct hclge_desc *desc_src, + int bd_num) +{ + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); + int ret = 0; + u8 i; + + for (i = HCLGE_REG_RPU_TNL_ID_0; i <= ae_dev->dev_specs.tnl_num; i++) { + ret = hclge_dfx_reg_rpu_tnl_cmd_send(hdev, i, desc_src, bd_num); + if (ret) + break; + + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_RPU_TNL, + ARRAY_SIZE(desc_src->data) * bd_num, + reg); + reg += hclge_dfx_reg_fetch_data(desc_src, bd_num, reg); + } + + return ret; +} + +static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data) +{ + u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list); + int bd_num, bd_num_max, buf_len; + struct hclge_desc *desc_src; + int *bd_num_list; + u32 *reg = data; + int ret; + u32 i; + + bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL); + if (!bd_num_list) + return -ENOMEM; + + ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get dfx reg bd num fail, status is %d.\n", ret); + goto out; + } + + bd_num_max = bd_num_list[0]; + for (i = 1; i < dfx_reg_type_num; i++) + bd_num_max = max_t(int, bd_num_max, bd_num_list[i]); + + buf_len = sizeof(*desc_src) * bd_num_max; + desc_src = kzalloc(buf_len, GFP_KERNEL); + if (!desc_src) { + ret = -ENOMEM; + goto out; + } + + for (i = 0; i < dfx_reg_type_num; i++) { + bd_num = bd_num_list[i]; + ret = hclge_dfx_reg_cmd_send(hdev, desc_src, bd_num, + hclge_dfx_reg_opcode_list[i]); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get dfx reg fail, status is %d.\n", ret); + goto free; + } + + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_DFX_BIOS_COMMON + i, + ARRAY_SIZE(desc_src->data) * bd_num, + reg); + reg += hclge_dfx_reg_fetch_data(desc_src, bd_num, reg); + } + + /** + * HCLGE_DFX_BD_OFFSET is starting at 1, but the array subscript is + * starting at 0, so offset need '- 1'. + */ + bd_num = bd_num_list[HCLGE_DFX_RPU_0_BD_OFFSET - 1]; + ret = hclge_get_dfx_rpu_tnl_reg(hdev, reg, desc_src, bd_num); + +free: + kfree(desc_src); +out: + kfree(bd_num_list); + return ret; +} + +static int hclge_fetch_pf_reg(struct hclge_dev *hdev, void *data, + struct hnae3_knic_private_info *kinfo) +{ +#define HCLGE_RING_REG_OFFSET 0x200 +#define HCLGE_RING_INT_REG_OFFSET 0x4 + + int i, j, reg_num; + int data_num_sum; + u32 *reg = data; + + /* fetching per-PF registers valus from PF PCIe register space */ + reg_num = ARRAY_SIZE(cmdq_reg_addr_list); + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_CMDQ, reg_num, reg); + for (i = 0; i < reg_num; i++) + *reg++ = hclge_read_dev(&hdev->hw, cmdq_reg_addr_list[i]); + data_num_sum = reg_num + HCLGE_REG_TLV_SPACE; + + reg_num = ARRAY_SIZE(common_reg_addr_list); + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_COMMON, reg_num, reg); + for (i = 0; i < reg_num; i++) + *reg++ = hclge_read_dev(&hdev->hw, common_reg_addr_list[i]); + data_num_sum += reg_num + HCLGE_REG_TLV_SPACE; + + reg_num = ARRAY_SIZE(ring_reg_addr_list); + for (j = 0; j < kinfo->num_tqps; j++) { + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_RING, reg_num, reg); + for (i = 0; i < reg_num; i++) + *reg++ = hclge_read_dev(&hdev->hw, + ring_reg_addr_list[i] + + HCLGE_RING_REG_OFFSET * j); + } + data_num_sum += (reg_num + HCLGE_REG_TLV_SPACE) * kinfo->num_tqps; + + reg_num = ARRAY_SIZE(tqp_intr_reg_addr_list); + for (j = 0; j < hdev->num_msi_used - 1; j++) { + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_TQP_INTR, reg_num, reg); + for (i = 0; i < reg_num; i++) + *reg++ = hclge_read_dev(&hdev->hw, + tqp_intr_reg_addr_list[i] + + HCLGE_RING_INT_REG_OFFSET * j); + } + data_num_sum += (reg_num + HCLGE_REG_TLV_SPACE) * + (hdev->num_msi_used - 1); + + return data_num_sum; +} + +static int hclge_get_regs_num(struct hclge_dev *hdev, u32 *regs_num_32_bit, + u32 *regs_num_64_bit) +{ + struct hclge_desc desc; + u32 total_num; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_REG_NUM, true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "Query register number cmd failed, ret = %d.\n", ret); + return ret; + } + + *regs_num_32_bit = le32_to_cpu(desc.data[0]); + *regs_num_64_bit = le32_to_cpu(desc.data[1]); + + total_num = *regs_num_32_bit + *regs_num_64_bit; + if (!total_num) + return -EINVAL; + + return 0; +} + +int hclge_get_regs_len(struct hnae3_handle *handle) +{ + struct hnae3_knic_private_info *kinfo = &handle->kinfo; + struct hclge_vport *vport = hclge_get_vport(handle); + int regs_num_32_bit, regs_num_64_bit, dfx_regs_len; + int cmdq_len, common_len, ring_len, tqp_intr_len; + int regs_len_32_bit, regs_len_64_bit; + struct hclge_dev *hdev = vport->back; + int ret; + + ret = hclge_get_regs_num(hdev, ®s_num_32_bit, ®s_num_64_bit); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get register number failed, ret = %d.\n", ret); + return ret; + } + + ret = hclge_get_dfx_reg_len(hdev, &dfx_regs_len); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get dfx reg len failed, ret = %d.\n", ret); + return ret; + } + + cmdq_len = HCLGE_REG_TLV_SIZE + sizeof(cmdq_reg_addr_list); + common_len = HCLGE_REG_TLV_SIZE + sizeof(common_reg_addr_list); + ring_len = HCLGE_REG_TLV_SIZE + sizeof(ring_reg_addr_list); + tqp_intr_len = HCLGE_REG_TLV_SIZE + sizeof(tqp_intr_reg_addr_list); + regs_len_32_bit = HCLGE_REG_TLV_SIZE + regs_num_32_bit * sizeof(u32); + regs_len_64_bit = HCLGE_REG_TLV_SIZE + regs_num_64_bit * sizeof(u64); + + /* return the total length of all register values */ + return HCLGE_REG_HEADER_SIZE + cmdq_len + common_len + ring_len * + kinfo->num_tqps + tqp_intr_len * (hdev->num_msi_used - 1) + + regs_len_32_bit + regs_len_64_bit + dfx_regs_len; +} + +void hclge_get_regs(struct hnae3_handle *handle, u32 *version, + void *data) +{ +#define HCLGE_REG_64_BIT_SPACE_MULTIPLE 2 + + struct hnae3_knic_private_info *kinfo = &handle->kinfo; + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + u32 regs_num_32_bit, regs_num_64_bit; + u32 *reg = data; + int ret; + + *version = hdev->fw_version; + + ret = hclge_get_regs_num(hdev, ®s_num_32_bit, ®s_num_64_bit); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get register number failed, ret = %d.\n", ret); + return; + } + + reg += hclge_reg_get_header(reg); + reg += hclge_fetch_pf_reg(hdev, reg, kinfo); + + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_QUERY_32_BIT, + regs_num_32_bit, reg); + ret = hclge_get_32_bit_regs(hdev, regs_num_32_bit, reg); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get 32 bit register failed, ret = %d.\n", ret); + return; + } + reg += regs_num_32_bit; + + reg += hclge_reg_get_tlv(HCLGE_REG_TAG_QUERY_64_BIT, + regs_num_64_bit * + HCLGE_REG_64_BIT_SPACE_MULTIPLE, reg); + ret = hclge_get_64_bit_regs(hdev, regs_num_64_bit, reg); + if (ret) { + dev_err(&hdev->pdev->dev, + "Get 64 bit register failed, ret = %d.\n", ret); + return; + } + reg += regs_num_64_bit * HCLGE_REG_64_BIT_SPACE_MULTIPLE; + + ret = hclge_get_dfx_reg(hdev, reg); + if (ret) + dev_err(&hdev->pdev->dev, + "Get dfx register failed, ret = %d.\n", ret); +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.h new file mode 100644 index 000000000000..b6bc1ecb8054 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +// Copyright (c) 2023 Hisilicon Limited. + +#ifndef __HCLGE_REGS_H +#define __HCLGE_REGS_H +#include <linux/types.h> +#include "hclge_comm_cmd.h" + +struct hnae3_handle; +struct hclge_dev; + +int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, + struct hclge_desc *desc); +int hclge_get_regs_len(struct hnae3_handle *handle); +void hclge_get_regs(struct hnae3_handle *handle, u32 *version, + void *data); +#endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 922c0da3660c..c58c31221762 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -785,6 +785,7 @@ static void hclge_tm_tc_info_init(struct hclge_dev *hdev) static void hclge_tm_pg_info_init(struct hclge_dev *hdev) { #define BW_PERCENT 100 +#define DEFAULT_BW_WEIGHT 1 u8 i; @@ -806,7 +807,7 @@ static void hclge_tm_pg_info_init(struct hclge_dev *hdev) for (k = 0; k < hdev->tm_info.num_tc; k++) hdev->tm_info.pg_info[i].tc_dwrr[k] = BW_PERCENT; for (; k < HNAE3_MAX_TC; k++) - hdev->tm_info.pg_info[i].tc_dwrr[k] = 0; + hdev->tm_info.pg_info[i].tc_dwrr[k] = DEFAULT_BW_WEIGHT; } } @@ -1484,7 +1485,11 @@ int hclge_tm_schd_setup_hw(struct hclge_dev *hdev) return ret; /* Cfg schd mode for each level schd */ - return hclge_tm_schd_mode_hw(hdev); + ret = hclge_tm_schd_mode_hw(hdev); + if (ret) + return ret; + + return hclge_tm_flush_cfg(hdev, false); } static int hclge_pause_param_setup_hw(struct hclge_dev *hdev) @@ -1548,7 +1553,7 @@ static int hclge_bp_setup_hw(struct hclge_dev *hdev, u8 tc) return 0; } -static int hclge_mac_pause_setup_hw(struct hclge_dev *hdev) +int hclge_mac_pause_setup_hw(struct hclge_dev *hdev) { bool tx_en, rx_en; @@ -2113,3 +2118,28 @@ int hclge_tm_get_port_shaper(struct hclge_dev *hdev, return 0; } + +int hclge_tm_flush_cfg(struct hclge_dev *hdev, bool enable) +{ + struct hclge_desc desc; + int ret; + + if (!hnae3_ae_dev_tm_flush_supported(hdev)) + return 0; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_FLUSH, false); + + desc.data[0] = cpu_to_le32(enable ? HCLGE_TM_FLUSH_EN_MSK : 0); + + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to config tm flush, ret = %d\n", ret); + return ret; + } + + if (enable) + msleep(HCLGE_TM_FLUSH_TIME_MS); + + return ret; +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h index dd6f1fd486cf..53eec6df5194 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -33,6 +33,9 @@ enum hclge_opcode_type; #define HCLGE_DSCP_MAP_TC_BD_NUM 2 #define HCLGE_DSCP_TC_SHIFT(n) (((n) & 1) * 4) +#define HCLGE_TM_FLUSH_TIME_MS 10 +#define HCLGE_TM_FLUSH_EN_MSK BIT(0) + struct hclge_pg_to_pri_link_cmd { u8 pg_id; u8 rsvd1[3]; @@ -242,6 +245,7 @@ int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap, u8 pfc_bitmap); int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx); int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr); +int hclge_mac_pause_setup_hw(struct hclge_dev *hdev); void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats); void hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats); int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate); @@ -272,4 +276,5 @@ int hclge_tm_get_port_shaper(struct hclge_dev *hdev, struct hclge_tm_shaper_para *para); int hclge_up_to_tc_map(struct hclge_dev *hdev); int hclge_dscp_to_tc_map(struct hclge_dev *hdev); +int hclge_tm_flush_cfg(struct hclge_dev *hdev, bool enable); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 34f02ca8d1d2..7a2f9233d695 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -6,6 +6,7 @@ #include <net/rtnetlink.h> #include "hclgevf_cmd.h" #include "hclgevf_main.h" +#include "hclgevf_regs.h" #include "hclge_mbx.h" #include "hnae3.h" #include "hclgevf_devlink.h" @@ -33,58 +34,6 @@ static const struct pci_device_id ae_algovf_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, ae_algovf_pci_tbl); -static const u32 cmdq_reg_addr_list[] = {HCLGE_COMM_NIC_CSQ_BASEADDR_L_REG, - HCLGE_COMM_NIC_CSQ_BASEADDR_H_REG, - HCLGE_COMM_NIC_CSQ_DEPTH_REG, - HCLGE_COMM_NIC_CSQ_TAIL_REG, - HCLGE_COMM_NIC_CSQ_HEAD_REG, - HCLGE_COMM_NIC_CRQ_BASEADDR_L_REG, - HCLGE_COMM_NIC_CRQ_BASEADDR_H_REG, - HCLGE_COMM_NIC_CRQ_DEPTH_REG, - HCLGE_COMM_NIC_CRQ_TAIL_REG, - HCLGE_COMM_NIC_CRQ_HEAD_REG, - HCLGE_COMM_VECTOR0_CMDQ_SRC_REG, - HCLGE_COMM_VECTOR0_CMDQ_STATE_REG, - HCLGE_COMM_CMDQ_INTR_EN_REG, - HCLGE_COMM_CMDQ_INTR_GEN_REG}; - -static const u32 common_reg_addr_list[] = {HCLGEVF_MISC_VECTOR_REG_BASE, - HCLGEVF_RST_ING, - HCLGEVF_GRO_EN_REG}; - -static const u32 ring_reg_addr_list[] = {HCLGEVF_RING_RX_ADDR_L_REG, - HCLGEVF_RING_RX_ADDR_H_REG, - HCLGEVF_RING_RX_BD_NUM_REG, - HCLGEVF_RING_RX_BD_LENGTH_REG, - HCLGEVF_RING_RX_MERGE_EN_REG, - HCLGEVF_RING_RX_TAIL_REG, - HCLGEVF_RING_RX_HEAD_REG, - HCLGEVF_RING_RX_FBD_NUM_REG, - HCLGEVF_RING_RX_OFFSET_REG, - HCLGEVF_RING_RX_FBD_OFFSET_REG, - HCLGEVF_RING_RX_STASH_REG, - HCLGEVF_RING_RX_BD_ERR_REG, - HCLGEVF_RING_TX_ADDR_L_REG, - HCLGEVF_RING_TX_ADDR_H_REG, - HCLGEVF_RING_TX_BD_NUM_REG, - HCLGEVF_RING_TX_PRIORITY_REG, - HCLGEVF_RING_TX_TC_REG, - HCLGEVF_RING_TX_MERGE_EN_REG, - HCLGEVF_RING_TX_TAIL_REG, - HCLGEVF_RING_TX_HEAD_REG, - HCLGEVF_RING_TX_FBD_NUM_REG, - HCLGEVF_RING_TX_OFFSET_REG, - HCLGEVF_RING_TX_EBD_NUM_REG, - HCLGEVF_RING_TX_EBD_OFFSET_REG, - HCLGEVF_RING_TX_BD_ERR_REG, - HCLGEVF_RING_EN_REG}; - -static const u32 tqp_intr_reg_addr_list[] = {HCLGEVF_TQP_INTR_CTRL_REG, - HCLGEVF_TQP_INTR_GL0_REG, - HCLGEVF_TQP_INTR_GL1_REG, - HCLGEVF_TQP_INTR_GL2_REG, - HCLGEVF_TQP_INTR_RL_REG}; - /* hclgevf_cmd_send - send command to command queue * @hw: pointer to the hw struct * @desc: prefilled descriptor for describing the command @@ -111,7 +60,7 @@ void hclgevf_arq_init(struct hclgevf_dev *hdev) spin_unlock(&cmdq->crq.lock); } -static struct hclgevf_dev *hclgevf_ae_get_hdev(struct hnae3_handle *handle) +struct hclgevf_dev *hclgevf_ae_get_hdev(struct hnae3_handle *handle) { if (!handle->client) return container_of(handle, struct hclgevf_dev, nic); @@ -3258,72 +3207,6 @@ static void hclgevf_get_link_mode(struct hnae3_handle *handle, *advertising = hdev->hw.mac.advertising; } -#define MAX_SEPARATE_NUM 4 -#define SEPARATOR_VALUE 0xFDFCFBFA -#define REG_NUM_PER_LINE 4 -#define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(u32)) - -static int hclgevf_get_regs_len(struct hnae3_handle *handle) -{ - int cmdq_lines, common_lines, ring_lines, tqp_intr_lines; - struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); - - cmdq_lines = sizeof(cmdq_reg_addr_list) / REG_LEN_PER_LINE + 1; - common_lines = sizeof(common_reg_addr_list) / REG_LEN_PER_LINE + 1; - ring_lines = sizeof(ring_reg_addr_list) / REG_LEN_PER_LINE + 1; - tqp_intr_lines = sizeof(tqp_intr_reg_addr_list) / REG_LEN_PER_LINE + 1; - - return (cmdq_lines + common_lines + ring_lines * hdev->num_tqps + - tqp_intr_lines * (hdev->num_msi_used - 1)) * REG_LEN_PER_LINE; -} - -static void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version, - void *data) -{ - struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); - int i, j, reg_um, separator_num; - u32 *reg = data; - - *version = hdev->fw_version; - - /* fetching per-VF registers values from VF PCIe register space */ - reg_um = sizeof(cmdq_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; - for (i = 0; i < reg_um; i++) - *reg++ = hclgevf_read_dev(&hdev->hw, cmdq_reg_addr_list[i]); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - - reg_um = sizeof(common_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; - for (i = 0; i < reg_um; i++) - *reg++ = hclgevf_read_dev(&hdev->hw, common_reg_addr_list[i]); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - - reg_um = sizeof(ring_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; - for (j = 0; j < hdev->num_tqps; j++) { - for (i = 0; i < reg_um; i++) - *reg++ = hclgevf_read_dev(&hdev->hw, - ring_reg_addr_list[i] + - HCLGEVF_TQP_REG_SIZE * j); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - } - - reg_um = sizeof(tqp_intr_reg_addr_list) / sizeof(u32); - separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE; - for (j = 0; j < hdev->num_msi_used - 1; j++) { - for (i = 0; i < reg_um; i++) - *reg++ = hclgevf_read_dev(&hdev->hw, - tqp_intr_reg_addr_list[i] + - 4 * j); - for (i = 0; i < separator_num; i++) - *reg++ = SEPARATOR_VALUE; - } -} - void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state, struct hclge_mbx_port_base_vlan *port_base_vlan) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index 59ca6c794d6d..81c16b8c8da2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -294,4 +294,5 @@ void hclgevf_reset_task_schedule(struct hclgevf_dev *hdev); void hclgevf_mbx_task_schedule(struct hclgevf_dev *hdev); void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state, struct hclge_mbx_port_base_vlan *port_base_vlan); +struct hclgevf_dev *hclgevf_ae_get_hdev(struct hnae3_handle *handle); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c new file mode 100644 index 000000000000..65b9dcd38137 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2023 Hisilicon Limited. + +#include "hclgevf_main.h" +#include "hclgevf_regs.h" +#include "hnae3.h" + +static const u32 cmdq_reg_addr_list[] = {HCLGE_COMM_NIC_CSQ_BASEADDR_L_REG, + HCLGE_COMM_NIC_CSQ_BASEADDR_H_REG, + HCLGE_COMM_NIC_CSQ_DEPTH_REG, + HCLGE_COMM_NIC_CSQ_TAIL_REG, + HCLGE_COMM_NIC_CSQ_HEAD_REG, + HCLGE_COMM_NIC_CRQ_BASEADDR_L_REG, + HCLGE_COMM_NIC_CRQ_BASEADDR_H_REG, + HCLGE_COMM_NIC_CRQ_DEPTH_REG, + HCLGE_COMM_NIC_CRQ_TAIL_REG, + HCLGE_COMM_NIC_CRQ_HEAD_REG, + HCLGE_COMM_VECTOR0_CMDQ_SRC_REG, + HCLGE_COMM_VECTOR0_CMDQ_STATE_REG, + HCLGE_COMM_CMDQ_INTR_EN_REG, + HCLGE_COMM_CMDQ_INTR_GEN_REG}; + +static const u32 common_reg_addr_list[] = {HCLGEVF_MISC_VECTOR_REG_BASE, + HCLGEVF_RST_ING, + HCLGEVF_GRO_EN_REG}; + +static const u32 ring_reg_addr_list[] = {HCLGEVF_RING_RX_ADDR_L_REG, + HCLGEVF_RING_RX_ADDR_H_REG, + HCLGEVF_RING_RX_BD_NUM_REG, + HCLGEVF_RING_RX_BD_LENGTH_REG, + HCLGEVF_RING_RX_MERGE_EN_REG, + HCLGEVF_RING_RX_TAIL_REG, + HCLGEVF_RING_RX_HEAD_REG, + HCLGEVF_RING_RX_FBD_NUM_REG, + HCLGEVF_RING_RX_OFFSET_REG, + HCLGEVF_RING_RX_FBD_OFFSET_REG, + HCLGEVF_RING_RX_STASH_REG, + HCLGEVF_RING_RX_BD_ERR_REG, + HCLGEVF_RING_TX_ADDR_L_REG, + HCLGEVF_RING_TX_ADDR_H_REG, + HCLGEVF_RING_TX_BD_NUM_REG, + HCLGEVF_RING_TX_PRIORITY_REG, + HCLGEVF_RING_TX_TC_REG, + HCLGEVF_RING_TX_MERGE_EN_REG, + HCLGEVF_RING_TX_TAIL_REG, + HCLGEVF_RING_TX_HEAD_REG, + HCLGEVF_RING_TX_FBD_NUM_REG, + HCLGEVF_RING_TX_OFFSET_REG, + HCLGEVF_RING_TX_EBD_NUM_REG, + HCLGEVF_RING_TX_EBD_OFFSET_REG, + HCLGEVF_RING_TX_BD_ERR_REG, + HCLGEVF_RING_EN_REG}; + +static const u32 tqp_intr_reg_addr_list[] = {HCLGEVF_TQP_INTR_CTRL_REG, + HCLGEVF_TQP_INTR_GL0_REG, + HCLGEVF_TQP_INTR_GL1_REG, + HCLGEVF_TQP_INTR_GL2_REG, + HCLGEVF_TQP_INTR_RL_REG}; + +enum hclgevf_reg_tag { + HCLGEVF_REG_TAG_CMDQ = 0, + HCLGEVF_REG_TAG_COMMON, + HCLGEVF_REG_TAG_RING, + HCLGEVF_REG_TAG_TQP_INTR, +}; + +#pragma pack(4) +struct hclgevf_reg_tlv { + u16 tag; + u16 len; +}; + +struct hclgevf_reg_header { + u64 magic_number; + u8 is_vf; + u8 rsv[7]; +}; + +#pragma pack() + +#define HCLGEVF_REG_TLV_SIZE sizeof(struct hclgevf_reg_tlv) +#define HCLGEVF_REG_HEADER_SIZE sizeof(struct hclgevf_reg_header) +#define HCLGEVF_REG_TLV_SPACE (sizeof(struct hclgevf_reg_tlv) / sizeof(u32)) +#define HCLGEVF_REG_HEADER_SPACE (sizeof(struct hclgevf_reg_header) / sizeof(u32)) +#define HCLGEVF_REG_MAGIC_NUMBER 0x686e733372656773 /* meaning is hns3regs */ + +static u32 hclgevf_reg_get_header(void *data) +{ + struct hclgevf_reg_header *header = data; + + header->magic_number = HCLGEVF_REG_MAGIC_NUMBER; + header->is_vf = 0x1; + + return HCLGEVF_REG_HEADER_SPACE; +} + +static u32 hclgevf_reg_get_tlv(u32 tag, u32 regs_num, void *data) +{ + struct hclgevf_reg_tlv *tlv = data; + + tlv->tag = tag; + tlv->len = regs_num * sizeof(u32) + HCLGEVF_REG_TLV_SIZE; + + return HCLGEVF_REG_TLV_SPACE; +} + +int hclgevf_get_regs_len(struct hnae3_handle *handle) +{ + struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + int cmdq_len, common_len, ring_len, tqp_intr_len; + + cmdq_len = HCLGEVF_REG_TLV_SIZE + sizeof(cmdq_reg_addr_list); + common_len = HCLGEVF_REG_TLV_SIZE + sizeof(common_reg_addr_list); + ring_len = HCLGEVF_REG_TLV_SIZE + sizeof(ring_reg_addr_list); + tqp_intr_len = HCLGEVF_REG_TLV_SIZE + sizeof(tqp_intr_reg_addr_list); + + /* return the total length of all register values */ + return HCLGEVF_REG_HEADER_SIZE + cmdq_len + common_len + + tqp_intr_len * (hdev->num_msi_used - 1) + + ring_len * hdev->num_tqps; +} + +void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version, + void *data) +{ +#define HCLGEVF_RING_REG_OFFSET 0x200 +#define HCLGEVF_RING_INT_REG_OFFSET 0x4 + + struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + int i, j, reg_um; + u32 *reg = data; + + *version = hdev->fw_version; + reg += hclgevf_reg_get_header(reg); + + /* fetching per-VF registers values from VF PCIe register space */ + reg_um = sizeof(cmdq_reg_addr_list) / sizeof(u32); + reg += hclgevf_reg_get_tlv(HCLGEVF_REG_TAG_CMDQ, reg_um, reg); + for (i = 0; i < reg_um; i++) + *reg++ = hclgevf_read_dev(&hdev->hw, cmdq_reg_addr_list[i]); + + reg_um = sizeof(common_reg_addr_list) / sizeof(u32); + reg += hclgevf_reg_get_tlv(HCLGEVF_REG_TAG_COMMON, reg_um, reg); + for (i = 0; i < reg_um; i++) + *reg++ = hclgevf_read_dev(&hdev->hw, common_reg_addr_list[i]); + + reg_um = sizeof(ring_reg_addr_list) / sizeof(u32); + for (j = 0; j < hdev->num_tqps; j++) { + reg += hclgevf_reg_get_tlv(HCLGEVF_REG_TAG_RING, reg_um, reg); + for (i = 0; i < reg_um; i++) + *reg++ = hclgevf_read_dev(&hdev->hw, + ring_reg_addr_list[i] + + HCLGEVF_RING_REG_OFFSET * j); + } + + reg_um = sizeof(tqp_intr_reg_addr_list) / sizeof(u32); + for (j = 0; j < hdev->num_msi_used - 1; j++) { + reg += hclgevf_reg_get_tlv(HCLGEVF_REG_TAG_TQP_INTR, reg_um, reg); + for (i = 0; i < reg_um; i++) + *reg++ = hclgevf_read_dev(&hdev->hw, + tqp_intr_reg_addr_list[i] + + HCLGEVF_RING_INT_REG_OFFSET * j); + } +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.h new file mode 100644 index 000000000000..77bdcf60a1af --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2023 Hisilicon Limited. */ + +#ifndef __HCLGEVF_REGS_H +#define __HCLGEVF_REGS_H +#include <linux/types.h> + +struct hnae3_handle; + +int hclgevf_get_regs_len(struct hnae3_handle *handle); +void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version, + void *data); +#endif |