From bc47b7dc2b0180a0d6e7ad218e6c8f5e4fca07a9 Mon Sep 17 00:00:00 2001 From: Peiyang Wang Date: Fri, 25 Apr 2025 11:41:40 +0800 Subject: [PATCH 1/5] net: hns3: add support for vf multiple tcs driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID44N0 ---------------------------------------------------------------------- Add ieee_setets and ieee_getets supported for vf. Configures and queries vf multi-TC parameters, including the number of vf TCs, scheduling mode, and bandwidth weight. The number of TCs, scheduling mode, and bandwidth weight configured for the vf must be the same as those configured for the pf. When multiple TCs are configured for a vf, the pf does not allow the modification of TC parameters until all vfs are configured to work in single-TC mode. Signed-off-by: Jian Shen Signed-off-by: Hao Lan Signed-off-by: Peiyang Wang Signed-off-by: Donghua Huang --- drivers/net/ethernet/hisilicon/hns3/Makefile | 2 + .../net/ethernet/hisilicon/hns3/hclge_mbx.h | 11 +- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 5 + .../hns3/hns3_common/hclge_comm_cmd.c | 3 + .../hns3/hns3_common/hclge_comm_cmd.h | 2 + .../net/ethernet/hisilicon/hns3/hns3_dcbnl.c | 2 +- .../ethernet/hisilicon/hns3/hns3_debugfs.c | 3 + .../hisilicon/hns3/hns3pf/hclge_dcb.c | 33 ++ .../hisilicon/hns3/hns3pf/hclge_dcb.h | 10 + .../hisilicon/hns3/hns3pf/hclge_main.h | 1 + .../hisilicon/hns3/hns3pf/hclge_mbx.c | 29 ++ .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 235 +++++++++++-- .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 1 + .../hisilicon/hns3/hns3vf/hclgevf_cmd.h | 7 + .../hisilicon/hns3/hns3vf/hclgevf_dcb.c | 311 ++++++++++++++++++ .../hisilicon/hns3/hns3vf/hclgevf_dcb.h | 24 ++ .../hisilicon/hns3/hns3vf/hclgevf_main.c | 34 +- .../hisilicon/hns3/hns3vf/hclgevf_main.h | 7 + 18 files changed, 682 insertions(+), 38 deletions(-) create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.c create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.h diff --git a/drivers/net/ethernet/hisilicon/hns3/Makefile b/drivers/net/ethernet/hisilicon/hns3/Makefile index 1cc61b2062c0..fb61a3b0b168 100644 --- a/drivers/net/ethernet/hisilicon/hns3/Makefile +++ b/drivers/net/ethernet/hisilicon/hns3/Makefile @@ -21,6 +21,8 @@ obj-$(CONFIG_HNS3_HCLGEVF) += hclgevf.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 +hclgevf-$(CONFIG_HNS3_DCB) += hns3vf/hclgevf_dcb.o + obj-$(CONFIG_HNS3_HCLGE) += hclge.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 \ diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h index 0de9b83c9d4e..262ca38ddb4f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h @@ -6,6 +6,7 @@ #include #include #include +#include "hnae3.h" enum HCLGE_MBX_OPCODE { HCLGE_MBX_RESET = 0x01, /* (VF -> PF) assert reset */ @@ -49,6 +50,7 @@ enum HCLGE_MBX_OPCODE { HCLGE_MBX_GET_RING_VECTOR_MAP, /* (VF -> PF) get ring-to-vector map */ HCLGE_MBX_SET_QB = 0x28, /* (VF -> PF) set queue bonding */ HCLGE_MBX_PUSH_QB_STATE, /* (PF -> VF) push qb state */ + HCLGE_MBX_SET_TC = 0x30, /* (VF -> PF) set tc */ HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf flr status */ HCLGE_MBX_PUSH_LINK_STATUS, /* (M7 -> PF) get port link status */ @@ -100,7 +102,7 @@ struct hclge_ring_chain_param { struct hclge_basic_info { u8 hw_tc_map; - u8 rsv; + u8 tc_max; __le16 mbx_api_version; __le32 pf_caps; }; @@ -228,6 +230,13 @@ struct hclge_mbx_mtu_info { __le32 mtu; }; +struct hclge_mbx_tc_info { + __le32 prio_tc_map; + u8 tc_dwrr[HNAE3_MAX_TC]; + u8 num_tc; + u8 tc_sch_mode; /* 0: sp; 1: dwrr */ +}; + #pragma pack() /* used by VF to store the received Async responses from PF */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index bccb1ddc099a..9cf58e631379 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -119,6 +119,7 @@ enum HNAE3_DEV_CAP_BITS { HNAE3_DEV_SUPPORT_VF_FAULT_B, HNAE3_DEV_SUPPORT_NOTIFY_PKT_B, HNAE3_DEV_SUPPORT_ERR_MOD_GEN_REG_B, + HNAE3_DEV_SUPPORT_VF_MULTI_TCS_B, }; #define hnae3_ae_dev_fd_supported(ae_dev) \ @@ -202,8 +203,12 @@ enum HNAE3_DEV_CAP_BITS { #define hnae3_ae_dev_gen_reg_dfx_supported(hdev) \ test_bit(HNAE3_DEV_SUPPORT_ERR_MOD_GEN_REG_B, (hdev)->ae_dev->caps) +#define hnae3_ae_dev_vf_multi_tcs_supported(hdev) \ + test_bit(HNAE3_DEV_SUPPORT_VF_MULTI_TCS_B, (hdev)->ae_dev->caps) + enum HNAE3_PF_CAP_BITS { HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B = 0, + HNAE3_PF_SUPPORT_VF_MULTI_TCS_B = 1, }; #define ring_ptr_move_fw(ring, p) \ ((ring)->p = ((ring)->p + 1) % (ring)->desc_num) 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 aaa7862d8e18..7c7d51d65bfa 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 @@ -92,6 +92,7 @@ int hclge_comm_firmware_compat_config(struct hnae3_ae_dev *ae_dev, hnae3_set_bit(compat, HCLGE_COMM_MAC_STATS_EXT_EN_B, 1); hnae3_set_bit(compat, HCLGE_COMM_SYNC_RX_RING_HEAD_EN_B, 1); hnae3_set_bit(compat, HCLGE_COMM_LLRS_FEC_EN_B, 1); + hnae3_set_bit(compat, HCLGE_COMM_VF_MULTI_TC_EN_B, 1); req->compat = cpu_to_le32(compat); } @@ -160,6 +161,7 @@ static const struct hclge_comm_caps_bit_map hclge_pf_cmd_caps[] = { {HCLGE_COMM_CAP_VF_FAULT_B, HNAE3_DEV_SUPPORT_VF_FAULT_B}, {HCLGE_COMM_CAP_NOTIFY_PKT_B, HNAE3_DEV_SUPPORT_NOTIFY_PKT_B}, {HCLGE_COMM_CAP_ERR_MOD_GEN_REG_B, HNAE3_DEV_SUPPORT_ERR_MOD_GEN_REG_B}, + {HCLGE_COMM_CAP_VF_MULTI_TCS, HNAE3_DEV_SUPPORT_VF_MULTI_TCS_B}, }; static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = { @@ -173,6 +175,7 @@ static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = { {HCLGE_COMM_CAP_RXD_ADV_LAYOUT_B, HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B}, {HCLGE_COMM_CAP_CQ_B, HNAE3_DEV_SUPPORT_CQ_B}, {HCLGE_COMM_CAP_GRO_B, HNAE3_DEV_SUPPORT_GRO_B}, + {HCLGE_COMM_CAP_VF_MULTI_TCS, HNAE3_DEV_SUPPORT_VF_MULTI_TCS_B}, }; static void 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 44a484342b4c..4fd6df3bd2ec 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 @@ -21,6 +21,7 @@ #define HCLGE_COMM_MAC_STATS_EXT_EN_B 3 #define HCLGE_COMM_SYNC_RX_RING_HEAD_EN_B 4 #define HCLGE_COMM_LLRS_FEC_EN_B 5 +#define HCLGE_COMM_VF_MULTI_TC_EN_B 7 #define hclge_comm_dev_phy_imp_supported(ae_dev) \ test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, (ae_dev)->caps) @@ -377,6 +378,7 @@ enum HCLGE_COMM_CAP_BITS { HCLGE_COMM_CAP_NOTIFY_PKT_B = 29, HCLGE_COMM_CAP_TM_FLUSH_B = 31, HCLGE_COMM_CAP_ERR_MOD_GEN_REG_B = 32, + HCLGE_COMM_CAP_VF_MULTI_TCS = 34, }; enum HCLGE_COMM_API_CAP_BITS { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c b/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c index 19fef1d41701..dc6d4191ed91 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c @@ -147,7 +147,7 @@ void hns3_dcbnl_setup(struct hnae3_handle *handle) { struct net_device *dev = handle->kinfo.netdev; - if ((!handle->kinfo.dcb_ops) || (handle->flags & HNAE3_SUPPORT_VF)) + if (!handle->kinfo.dcb_ops) return; dev->dcbnl_ops = &hns3_dcbnl_ops; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index 71a650f8e02e..e917b097865a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -375,6 +375,9 @@ static struct hns3_dbg_cap_info hns3_dbg_cap[] = { }, { .name = "support vf fault detect", .cap_bit = HNAE3_DEV_SUPPORT_VF_FAULT_B, + }, { + .name = "support vf multi tcs", + .cap_bit = HNAE3_DEV_SUPPORT_VF_MULTI_TCS_B, } }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index 140db47c2055..a189fd52feb8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -81,6 +81,14 @@ static int hclge_dcb_common_validate(struct hclge_dev *hdev, u8 num_tc, { int i; + /* Based on hardware limitation, VFs share the configuration of PF. */ + if (hnae3_ae_dev_vf_multi_tcs_supported(hdev) && + !bitmap_empty(hdev->vf_multi_tcs_en, HCLGE_VPORT_NUM)) { + dev_err(&hdev->pdev->dev, + "the tc resource is still being used by VF\n"); + return -EOPNOTSUPP; + } + if (num_tc > hdev->tc_max) { dev_err(&hdev->pdev->dev, "tc num checking failed, %u > tc_max(%u)\n", @@ -198,6 +206,24 @@ static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets, return 0; } +static bool hclge_ets_not_need_config(struct hclge_dev *hdev, + struct ieee_ets *ets) +{ + struct ieee_ets current_ets, request_ets; + + /* following parameters are not supported, so ignore to compare */ + request_ets = *ets; + request_ets.cbs = 0; + memset(&request_ets.tc_rx_bw, 0, IEEE_8021QAZ_MAX_TCS); + memset(&request_ets.tc_reco_bw, 0, IEEE_8021QAZ_MAX_TCS); + memset(&request_ets.tc_reco_tsa, 0, IEEE_8021QAZ_MAX_TCS); + memset(&request_ets.reco_prio_tc, 0, IEEE_8021QAZ_MAX_TCS); + + hclge_tm_info_to_ieee_ets(hdev, ¤t_ets); + + return memcmp(¤t_ets, &request_ets, sizeof(struct ieee_ets)) == 0; +} + static int hclge_map_update(struct hclge_dev *hdev) { int ret; @@ -262,6 +288,9 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) h->kinfo.tc_info.mqprio_active) return -EINVAL; + if (hclge_ets_not_need_config(hdev, ets)) + return 0; + ret = hclge_ets_validate(hdev, ets, &num_tc, &map_changed); if (ret) return ret; @@ -274,6 +303,7 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) return ret; } + mutex_lock(&hdev->vport_lock); hclge_tm_schd_info_update(hdev, num_tc); h->kinfo.tc_info.dcb_ets_active = num_tc > 1; @@ -286,12 +316,15 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) if (ret) goto err_out; + mutex_unlock(&hdev->vport_lock); return hclge_notify_init_up(hdev); } + mutex_unlock(&hdev->vport_lock); return hclge_tm_dwrr_cfg(hdev); err_out: + mutex_unlock(&hdev->vport_lock); if (!map_changed) return ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h index 23e35c643c15..bc7e95781828 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h @@ -6,10 +6,20 @@ #include "hclge_main.h" +struct hclge_mbx_tc_info; + #ifdef CONFIG_HNS3_DCB void hclge_dcb_ops_set(struct hclge_dev *hdev); +int hclge_mbx_set_vf_multi_tc(struct hclge_vport *vport, + struct hclge_mbx_tc_info *tc_info); #else static inline void hclge_dcb_ops_set(struct hclge_dev *hdev) {} +static inline int hclge_mbx_set_vf_multi_tc(struct hclge_vport *vport, + struct hclge_mbx_tc_info *tc_info) +{ + return -EOPNOTSUPP; +} + #endif #define HCLGE_BYTE_BITS 8ULL diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index a4171f59105c..01be6b0cb264 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -970,6 +970,7 @@ struct hclge_dev { unsigned long vf_vlan_full[BITS_TO_LONGS(HCLGE_VPORT_NUM)]; unsigned long vport_config_block[BITS_TO_LONGS(HCLGE_VPORT_NUM)]; + unsigned long vf_multi_tcs_en[BITS_TO_LONGS(HCLGE_VPORT_NUM)]; struct hclge_fd_cfg fd_cfg; struct hlist_head fd_rule_list; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index fdba02a46968..53282d540253 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -5,6 +5,8 @@ #include "hclge_mbx.h" #include "hnae3.h" #include "hclge_comm_rss.h" +#include "hclge_dcb.h" +#include "hclge_tm.h" #define CREATE_TRACE_POINTS #include "hclge_trace.h" @@ -492,6 +494,7 @@ static void hclge_get_basic_info(struct hclge_vport *vport, { struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; struct hnae3_ae_dev *ae_dev = vport->back->ae_dev; + struct hclge_dev *hdev = vport->back; struct hclge_basic_info *basic_info; unsigned int i; u32 pf_caps; @@ -503,6 +506,12 @@ static void hclge_get_basic_info(struct hclge_vport *vport, pf_caps = le32_to_cpu(basic_info->pf_caps); if (test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps)) hnae3_set_bit(pf_caps, HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B, 1); + if (test_bit(HNAE3_DEV_SUPPORT_VF_MULTI_TCS_B, ae_dev->caps)) { + hnae3_set_bit(pf_caps, HNAE3_PF_SUPPORT_VF_MULTI_TCS_B, 1); + basic_info->tc_max = hdev->tc_max; + } else { + basic_info->tc_max = 1; + } basic_info->pf_caps = cpu_to_le32(pf_caps); resp_msg->len = HCLGE_MBX_MAX_RESP_DATA_SIZE; @@ -1032,12 +1041,16 @@ hclge_mbx_get_vf_flr_status_handler(struct hclge_mbx_ops_param *param) static int hclge_mbx_vf_uninit_handler(struct hclge_mbx_ops_param *param) { + struct hclge_dev *hdev = param->vport->back; + hclge_rm_vport_all_mac_table(param->vport, true, HCLGE_MAC_ADDR_UC); hclge_rm_vport_all_mac_table(param->vport, true, HCLGE_MAC_ADDR_MC); hclge_rm_vport_all_vlan_table(param->vport, true); param->vport->mps = 0; + clear_bit(param->vport->vport_id, hdev->vf_multi_tcs_en); + hclge_tm_vport_tc_info_update(param->vport); return 0; } @@ -1077,6 +1090,21 @@ static int hclge_mbx_handle_vf_qb_handler(struct hclge_mbx_ops_param *param) return 0; } +static int hclge_mbx_set_vf_multi_tc_handler(struct hclge_mbx_ops_param *param) +{ + struct hclge_mbx_tc_info *tc_info; + int ret; + + tc_info = (struct hclge_mbx_tc_info *)param->req->msg.data; + + ret = hclge_mbx_set_vf_multi_tc(param->vport, tc_info); + if (ret) + dev_err(¶m->vport->back->pdev->dev, + "failed to set VF multi TCs, ret = %d\n", ret); + + return ret; +} + static const hclge_mbx_ops_fn hclge_mbx_ops_list[HCLGE_MBX_OPCODE_MAX] = { [HCLGE_MBX_RESET] = hclge_mbx_reset_handler, [HCLGE_MBX_SET_UNICAST] = hclge_mbx_set_unicast_handler, @@ -1105,6 +1133,7 @@ static const hclge_mbx_ops_fn hclge_mbx_ops_list[HCLGE_MBX_OPCODE_MAX] = { [HCLGE_MBX_GET_VF_FLR_STATUS] = hclge_mbx_get_vf_flr_status_handler, [HCLGE_MBX_PUSH_LINK_STATUS] = hclge_mbx_push_link_status_handler, [HCLGE_MBX_NCSI_ERROR] = hclge_mbx_ncsi_error_handler, + [HCLGE_MBX_SET_TC] = hclge_mbx_set_vf_multi_tc_handler, }; static void hclge_mbx_request_handling(struct hclge_mbx_ops_param *param) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index da3d135a6e25..001b0c8a447c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -3,6 +3,7 @@ #include +#include "hclge_mbx.h" #include "hclge_cmd.h" #include "hclge_main.h" #include "hclge_tm.h" @@ -672,28 +673,58 @@ static u16 hclge_vport_get_tqp_num(struct hclge_vport *vport) return sum; } -static void hclge_tm_update_kinfo_rss_size(struct hclge_vport *vport) +static void hclge_tm_update_pf_tc_info(struct hclge_vport *vport, + u16 *vport_max_rss_size) +{ + struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; + struct hclge_dev *hdev = vport->back; + + vport->qs_offset = 0; + *vport_max_rss_size = hdev->pf_rss_size_max; + kinfo->tc_info.num_tc = + min_t(u16, vport->alloc_tqps, hdev->tm_info.num_tc); + kinfo->tc_info.max_tc = hdev->tc_max; +} + +static void hclge_tm_update_vf_tc_info(struct hclge_vport *vport, + u16 *vport_max_rss_size) { struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; struct hclge_dev *hdev = vport->back; - u16 vport_max_rss_size; - u16 max_rss_size; - /* TC configuration is shared by PF/VF in one port, only allow - * one tc for VF for simplicity. VF's vport_id is non zero. + *vport_max_rss_size = hdev->vf_rss_size_max; + + /* If the VF supports multiple TCs, the VF has + * HNAE3_MAX_TC qsets. If the VF does not support + * multiple TCs, the VF has only one qset. */ - if (vport->vport_id) { - kinfo->tc_info.max_tc = 1; - kinfo->tc_info.num_tc = 1; + if (hnae3_ae_dev_vf_multi_tcs_supported(hdev)) { + vport->qs_offset = HNAE3_MAX_TC * vport->vport_id; + kinfo->tc_info.max_tc = hdev->tc_max; + } else { vport->qs_offset = HNAE3_MAX_TC + vport->vport_id - HCLGE_VF_VPORT_START_NUM; - vport_max_rss_size = hdev->vf_rss_size_max; - } else { - kinfo->tc_info.max_tc = hdev->tc_max; + kinfo->tc_info.max_tc = 1; + } + + if (!test_bit(vport->vport_id, hdev->vf_multi_tcs_en)) + kinfo->tc_info.num_tc = 1; + else kinfo->tc_info.num_tc = min_t(u16, vport->alloc_tqps, hdev->tm_info.num_tc); - vport->qs_offset = 0; - vport_max_rss_size = hdev->pf_rss_size_max; +} + +static void hclge_tm_update_kinfo_rss_size(struct hclge_vport *vport) +{ + struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; + struct hclge_dev *hdev = vport->back; + u16 vport_max_rss_size; + u16 max_rss_size; + + if (vport->vport_id) { + hclge_tm_update_vf_tc_info(vport, &vport_max_rss_size); + } else { + hclge_tm_update_pf_tc_info(vport, &vport_max_rss_size); } max_rss_size = min_t(u16, vport_max_rss_size, @@ -712,7 +743,7 @@ static void hclge_tm_update_kinfo_rss_size(struct hclge_vport *vport) } } -static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport) +void hclge_tm_vport_tc_info_update(struct hclge_vport *vport) { struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; struct hclge_dev *hdev = vport->back; @@ -1180,9 +1211,28 @@ static int hclge_tm_pri_shaper_cfg(struct hclge_dev *hdev) return 0; } +int hclge_tm_vf_tc_dwrr_cfg(struct hclge_vport *vport) +{ + struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; + struct hclge_dev *hdev = vport->back; + struct hclge_pg_info *pg_info; + u8 dwrr; + int ret; + u32 i; + + for (i = 0; i < kinfo->tc_info.max_tc; i++) { + pg_info = &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid]; + dwrr = i < kinfo->tc_info.num_tc ? pg_info->tc_dwrr[i] : 0; + ret = hclge_tm_qs_weight_cfg(hdev, vport->qs_offset + i, dwrr); + if (ret) + return ret; + } + + return 0; +} + static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev) { - struct hclge_vport *vport = hdev->vport; struct hclge_pg_info *pg_info; u8 dwrr; int ret; @@ -1198,15 +1248,22 @@ static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev) return ret; for (k = 0; k < hdev->num_alloc_vport; k++) { - struct hnae3_knic_private_info *kinfo = &vport[k].nic.kinfo; + struct hclge_vport *vport = &hdev->vport[k]; + struct hnae3_tc_info *tc_info; - if (i >= kinfo->tc_info.max_tc) + tc_info = &vport->nic.kinfo.tc_info; + if (i >= tc_info->max_tc) continue; - dwrr = i < kinfo->tc_info.num_tc ? vport[k].dwrr : 0; - ret = hclge_tm_qs_weight_cfg( - hdev, vport[k].qs_offset + i, - dwrr); + if (test_bit(vport->vport_id, hdev->vf_multi_tcs_en)) + dwrr = pg_info->tc_dwrr[i]; + else if (i < tc_info->num_tc) + dwrr = vport->dwrr; + else + dwrr = 0; + + ret = hclge_tm_qs_weight_cfg(hdev, vport->qs_offset + i, + dwrr); if (ret) return ret; } @@ -2033,16 +2090,27 @@ int hclge_tm_get_q_to_tc(struct hclge_dev *hdev, u16 q_id, u8 *tc_id) #define HCLGE_TM_TC_MASK 0x7 struct hclge_tqp_tx_queue_tc_cmd *tc; - struct hclge_vport *vport; struct hclge_desc desc; int ret; - vport = container_of(hdev->htqp[q_id].q.handle, - struct hclge_vport, nic); tc = (struct hclge_tqp_tx_queue_tc_cmd *)desc.data; hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TQP_TX_QUEUE_TC, true); - tc->queue_id = cpu_to_le16(hdev->htqp[q_id].q.tqp_index); - tc->func_id = (u8)vport->vport_id; + if (hnae3_ae_dev_vf_multi_tcs_supported(hdev)) { + struct hnae3_queue *tqp = &hdev->htqp[q_id].q; + struct hclge_vport *vport; + + if (!hdev->htqp[q_id].alloced) { + dev_err(&hdev->pdev->dev, + "q_id %u is not alloced\n", q_id); + return -EINVAL; + } + vport = container_of(tqp->handle, struct hclge_vport, nic); + tc->queue_id = cpu_to_le16(tqp->tqp_index); + tc->func_id = (u8)vport->vport_id; + } else { + tc->queue_id = cpu_to_le16(q_id); + tc->func_id = 0; + } ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) { @@ -2218,3 +2286,118 @@ void hclge_reset_tc_config(struct hclge_dev *hdev) hclge_tm_schd_info_update(hdev, 0); hclge_comm_rss_indir_init_cfg(hdev->ae_dev, &hdev->rss_cfg); } + +static int hclge_vf_prio_tc_validate(struct hclge_dev *hdev, + struct hclge_mbx_tc_info *tc_info) +{ +#define HCLGE_PRI_SHIFT 4 + + u32 prio_tc_map = 0; + u8 i; + + for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) + prio_tc_map |= + (u32)hdev->tm_info.prio_tc[i] << (i * HCLGE_PRI_SHIFT); + + if (prio_tc_map != __le32_to_cpu(tc_info->prio_tc_map)) { + dev_err(&hdev->pdev->dev, + "failed to check vf prio tc map, not match pf\n"); + return -EINVAL; + } + + return 0; +} + +static int hclge_vf_sch_mode_validate(struct hclge_dev *hdev, + struct hclge_mbx_tc_info *tc_info) +{ + struct hclge_tm_info *tm_info = &hdev->tm_info; + u8 sch_mode; + u8 i; + + if (tc_info->num_tc != tm_info->num_tc) { + dev_err(&hdev->pdev->dev, + "failed to check vf tc num %u, not match pf tc num %u\n", + tc_info->num_tc, tm_info->num_tc); + return -EINVAL; + } + + for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) { + sch_mode = tc_info->tc_sch_mode & BIT(i) ? + HCLGE_SCH_MODE_DWRR : HCLGE_SCH_MODE_SP; + if (sch_mode != tm_info->tc_info[i].tc_sch_mode) { + dev_err(&hdev->pdev->dev, + "failed to check vf tc[%u] sch mode\n", i); + return -EINVAL; + } + + if (tm_info->pg_info[0].tc_dwrr[i] != tc_info->tc_dwrr[i]) { + dev_err(&hdev->pdev->dev, + "failed to check vf tc[%u] dwrr bw %u\n", + i, tc_info->tc_dwrr[i]); + return -EINVAL; + } + } + + return 0; +} + +static int hclge_vf_tc_info_validate(struct hclge_dev *hdev, + struct hclge_mbx_tc_info *tc_info) +{ + int ret; + + ret = hclge_vf_prio_tc_validate(hdev, tc_info); + if (ret) + return ret; + + return hclge_vf_sch_mode_validate(hdev, tc_info); +} + +int hclge_mbx_set_vf_multi_tc(struct hclge_vport *vport, + struct hclge_mbx_tc_info *tc_info) +{ + struct hnae3_handle *pf_handle = &vport->back->vport[0].nic; + struct hclge_dev *hdev = vport->back; + int ret; + + if (!hnae3_ae_dev_vf_multi_tcs_supported(hdev)) + return -EOPNOTSUPP; + + if (!pf_handle->kinfo.tc_info.dcb_ets_active) + return -EOPNOTSUPP; + + mutex_lock(&hdev->vport_lock); + if (test_bit(vport->vport_id, hdev->vf_multi_tcs_en)) { + if (tc_info->num_tc != 1) { + ret = -EINVAL; + dev_err(&hdev->pdev->dev, + "tc number (%u) != 1\n", tc_info->num_tc); + goto out; + } + } else { + ret = hclge_vf_tc_info_validate(hdev, tc_info); + if (ret) + goto out; + } + + /* need updating vf_multi_tcs_en first, because the tc_info updating + * depend on it. + */ + change_bit(vport->vport_id, hdev->vf_multi_tcs_en); + hclge_tm_vport_tc_info_update(vport); + + ret = hclge_vport_q_to_qs_map(hdev, vport); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to set vf multi tcs, reset original status\n"); + change_bit(vport->vport_id, hdev->vf_multi_tcs_en); + hclge_tm_vport_tc_info_update(vport); + goto out; + } + ret = hclge_tm_vf_tc_dwrr_cfg(vport); + +out: + mutex_unlock(&hdev->vport_lock); + 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 b3c81050394e..390f292eafbb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -290,4 +290,5 @@ int hclge_tm_set_tc_rate_limit(struct hclge_dev *hdev, struct hnae3_tc_info *tc_info); u32 hclge_tm_rate_2_port_rate(u64 rate); void hclge_reset_tc_config(struct hclge_dev *hdev); +void hclge_tm_vport_tc_info_update(struct hclge_vport *vport); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h index 537b887fa0a2..dcfe369da1e6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h @@ -90,6 +90,13 @@ struct hclgevf_cfg_com_tqp_queue_cmd { u8 rsv[19]; }; +struct hclgevf_tx_ring_tx_cmd { + __le16 tqp_id; + __le16 rsv1; + u8 tc_id; + u8 rsv2[19]; +}; + struct hclgevf_cfg_tx_queue_pointer_cmd { __le16 tqp_id; __le16 tx_tail; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.c new file mode 100644 index 000000000000..16b5d0b3a273 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.c @@ -0,0 +1,311 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2024 Hisilicon Limited. + +#include "hclgevf_main.h" +#include "hclgevf_dcb.h" +#include "hnae3.h" + +#define BW_PERCENT 100 + +static void hclgevf_ieee_ets_to_prio_tc_map(struct hclge_mbx_tc_info *tc_info, + struct ieee_ets *ets) +{ +#define HCLGEVF_PRI_SHIFT 4 + u32 prio_tc_map = 0; + u32 i; + + for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) + prio_tc_map |= (ets->prio_tc[i] & 0xF) << + (i * HCLGEVF_PRI_SHIFT); + + tc_info->prio_tc_map = cpu_to_le32(prio_tc_map); +} + +static u8 hclgevf_get_ets_tc_num(struct ieee_ets *ets) +{ + u8 max_tc_id = 0; + u8 i; + + for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) { + if (ets->prio_tc[i] > max_tc_id) + max_tc_id = ets->prio_tc[i]; + } + + /* return max tc number, max tc id need to plus 1 */ + return max_tc_id + 1; +} + +static int hclgevf_ieee_ets_to_mbx_tc_info(struct hclge_mbx_tc_info *tc_info, + struct ieee_ets *ets) +{ + u8 i; + + tc_info->num_tc = hclgevf_get_ets_tc_num(ets); + tc_info->tc_sch_mode = 0; + for (i = 0; i < HNAE3_MAX_TC; i++) { + switch (ets->tc_tsa[i]) { + case IEEE_8021QAZ_TSA_STRICT: + tc_info->tc_dwrr[i] = 0; + break; + case IEEE_8021QAZ_TSA_ETS: + tc_info->tc_sch_mode |= BIT(i); + tc_info->tc_dwrr[i] = ets->tc_tx_bw[i]; + break; + default: + return -EINVAL; + } + } + + hclgevf_ieee_ets_to_prio_tc_map(tc_info, ets); + + return 0; +} + +void hclgevf_update_tc_info(struct hclgevf_dev *hdev) +{ + struct hnae3_knic_private_info *kinfo = &hdev->nic.kinfo; + u8 i; + + hdev->hw_tc_map = 0; + for (i = 0; i < kinfo->tc_info.num_tc; i++) { + hdev->hw_tc_map |= BIT(i); + kinfo->tc_info.tqp_offset[i] = i * kinfo->rss_size; + kinfo->tc_info.tqp_count[i] = kinfo->rss_size; + } + + for (i = kinfo->tc_info.num_tc; i < HNAE3_MAX_TC; i++) { + /* Set to default queue if TC is disable */ + kinfo->tc_info.tqp_offset[i] = 0; + kinfo->tc_info.tqp_count[i] = 1; + } +} + +static int hclgevf_tx_ring_tc_config_cmd(struct hclgevf_dev *hdev, u16 txq_id, + u8 tc_id) +{ + struct hclgevf_tx_ring_tx_cmd *req; + struct hclge_desc desc; + + req = (struct hclgevf_tx_ring_tx_cmd *)desc.data; + + hclgevf_cmd_setup_basic_desc(&desc, HCLGE_OPC_TQP_TX_QUEUE_TC, false); + req->tqp_id = cpu_to_le16(txq_id & HCLGEVF_RING_ID_MASK); + req->tc_id = tc_id; + + return hclgevf_cmd_send(&hdev->hw, &desc, 1); +} + +int hclgevf_tx_ring_tc_config(struct hclgevf_dev *hdev) +{ + struct hnae3_knic_private_info *kinfo = &hdev->nic.kinfo; + u16 i, j, qid; + int ret; + + for (i = 0; i < kinfo->tc_info.num_tc; i++) { + for (j = 0; j < kinfo->tc_info.tqp_count[i]; j++) { + qid = kinfo->tc_info.tqp_offset[i] + j; + ret = hclgevf_tx_ring_tc_config_cmd(hdev, qid, i); + if (ret) + return ret; + } + } + return 0; +} + +static int hclgevf_update_rss_tc_config(struct hclgevf_dev *hdev) +{ + struct hnae3_knic_private_info *kinfo = &hdev->nic.kinfo; + int ret; + + hclgevf_update_rss_size(&hdev->nic, kinfo->req_rss_size); + hclgevf_update_tc_info(hdev); + hclge_comm_rss_indir_init_cfg(hdev->ae_dev, &hdev->rss_cfg); + ret = hclge_comm_set_rss_indir_table(hdev->ae_dev, &hdev->hw.hw, + hdev->rss_cfg.rss_indirection_tbl); + if (ret) + return ret; + + return hclgevf_init_rss_tc_mode(hdev, kinfo->rss_size); +} + +static void hclgevf_tm_info_to_ieee_ets(struct hclgevf_dev *hdev, + struct ieee_ets *ets) +{ + struct hnae3_knic_private_info *kinfo = &hdev->nic.kinfo; + u32 i; + + memset(ets, 0, sizeof(*ets)); + ets->willing = 1; + ets->ets_cap = kinfo->tc_info.max_tc; + + for (i = 0; i < HNAE3_MAX_TC; i++) { + ets->prio_tc[i] = kinfo->tc_info.prio_tc[i]; + if (i < hdev->tc_info.num_tc) + ets->tc_tx_bw[i] = hdev->tc_info.tc_dwrr[i]; + else + ets->tc_tx_bw[i] = 0; + + if (hdev->tc_info.tc_sch_mode & BIT(i)) + ets->tc_tsa[i] = IEEE_8021QAZ_TSA_ETS; + else + ets->tc_tsa[i] = IEEE_8021QAZ_TSA_STRICT; + } +} + +static int hclgevf_ieee_getets(struct hnae3_handle *h, struct ieee_ets *ets) +{ + struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(h); + + hclgevf_tm_info_to_ieee_ets(hdev, ets); + + return 0; +} + +static int hclgevf_set_vf_multi_tc(struct hclgevf_dev *hdev, struct ieee_ets *ets) +{ + struct hnae3_knic_private_info *kinfo = &hdev->nic.kinfo; + struct hclge_vf_to_pf_msg send_msg; + struct hclge_mbx_tc_info *tc_info; + int ret; + + hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_TC, 0); + + tc_info = (struct hclge_mbx_tc_info *)send_msg.data; + ret = hclgevf_ieee_ets_to_mbx_tc_info(tc_info, ets); + if (ret) + return ret; + + ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0); + if (ret) + return ret; + + kinfo->tc_info.num_tc = tc_info->num_tc; + memcpy(kinfo->tc_info.prio_tc, ets->prio_tc, + sizeof_field(struct hnae3_tc_info, prio_tc)); + hdev->tc_info = *tc_info; + + return hclgevf_update_rss_tc_config(hdev); +} + +static int hclgevf_ets_validate(struct hclgevf_dev *hdev, struct ieee_ets *ets) +{ + struct hnae3_knic_private_info *kinfo = &hdev->nic.kinfo; + u8 num_tc = hclgevf_get_ets_tc_num(ets); + bool has_ets_tc = false; + u32 total_ets_bw = 0; + int i; + + if (num_tc > kinfo->tc_info.max_tc || num_tc > hdev->num_tqps) { + dev_err(&hdev->pdev->dev, "failed to check ets tc num: %u\n", + num_tc); + return -EINVAL; + } + + for (i = 0; i < HNAE3_MAX_TC; i++) { + if (ets->tc_tsa[i] != IEEE_8021QAZ_TSA_STRICT && + ets->tc_tsa[i] != IEEE_8021QAZ_TSA_ETS) { + dev_err(&hdev->pdev->dev, + "failed to check ets sched type %d\n", i); + return -EINVAL; + } + if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) { + if (!ets->tc_tx_bw[i] || i >= num_tc) { + dev_err(&hdev->pdev->dev, + "tc%d ets error, num_tc is %u\n", + i, num_tc); + return -EINVAL; + } + total_ets_bw += ets->tc_tx_bw[i]; + has_ets_tc = true; + } + } + + if (has_ets_tc && total_ets_bw != BW_PERCENT) + return -EINVAL; + + return 0; +} + +static bool hclgevf_compare_ieee_ets(struct hclgevf_dev *hdev, + struct ieee_ets *ets) +{ + struct ieee_ets current_ets, request_ets; + + /* following parameters are not supported, so ignore to compare */ + request_ets = *ets; + request_ets.cbs = 0; + memset(&request_ets.tc_rx_bw, 0, IEEE_8021QAZ_MAX_TCS); + memset(&request_ets.tc_reco_bw, 0, IEEE_8021QAZ_MAX_TCS); + memset(&request_ets.tc_reco_tsa, 0, IEEE_8021QAZ_MAX_TCS); + memset(&request_ets.reco_prio_tc, 0, IEEE_8021QAZ_MAX_TCS); + + hclgevf_tm_info_to_ieee_ets(hdev, ¤t_ets); + + return memcmp(¤t_ets, &request_ets, sizeof(struct ieee_ets)) == 0; +} + +static bool hclgevf_ets_not_need_config(struct hclgevf_dev *hdev, + struct ieee_ets *ets) +{ + struct hnae3_knic_private_info *kinfo = &hdev->nic.kinfo; + u8 num_tc = hclgevf_get_ets_tc_num(ets); + + if (num_tc == kinfo->tc_info.num_tc && num_tc == 1) + return true; + + return hclgevf_compare_ieee_ets(hdev, ets); +} + +static int hclgevf_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) +{ + struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(h); + int ret1; + int ret; + + if (!test_bit(HCLGEVF_STATE_DOWN, &hdev->state)) + return -EBUSY; + + ret = hclgevf_ets_validate(hdev, ets); + if (ret) + return -EINVAL; + + if (hclgevf_ets_not_need_config(hdev, ets)) + return 0; + + ret = hclgevf_notify_client(hdev, HNAE3_UNINIT_CLIENT); + if (ret) + return ret; + + ret1 = hclgevf_set_vf_multi_tc(hdev, ets); + ret = hclgevf_notify_client(hdev, HNAE3_INIT_CLIENT); + if (ret) + return ret; + + return ret1; +} + +static u8 hclgevf_getdcbx(struct hnae3_handle *h) +{ + return DCB_CAP_DCBX_VER_IEEE; +} + +static const struct hnae3_dcb_ops hclgevf_dcb_ops = { + .ieee_getets = hclgevf_ieee_getets, + .ieee_setets = hclgevf_ieee_setets, + .getdcbx = hclgevf_getdcbx, +}; + +void hclgevf_dcb_init(struct hclgevf_dev *hdev) +{ + struct hnae3_knic_private_info *kinfo = &hdev->nic.kinfo; + + if (!hnae3_ae_dev_vf_multi_tcs_supported(hdev)) + return; + + memset(&hdev->tc_info, 0, sizeof(hdev->tc_info)); + hdev->tc_info.num_tc = 1; + hdev->tc_info.tc_dwrr[0] = BW_PERCENT; + hdev->tc_info.tc_sch_mode = BIT(0); + hdev->hw_tc_map = 1; + kinfo->dcb_ops = &hclgevf_dcb_ops; +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.h new file mode 100644 index 000000000000..e1835a317cfb --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +// Copyright (c) 2024 Hisilicon Limited. + +#ifndef __HCLGEVF_DCB_H__ +#define __HCLGEVF_DCB_H__ + +#include "hclgevf_main.h" + +#ifdef CONFIG_HNS3_DCB +void hclgevf_dcb_init(struct hclgevf_dev *hdev); +int hclgevf_tx_ring_tc_config(struct hclgevf_dev *hdev); +void hclgevf_update_tc_info(struct hclgevf_dev *hdev); + +#else +static inline void hclgevf_dcb_init(struct hclgevf_dev *hdev) {} +static inline int hclgevf_tx_ring_tc_config(struct hclgevf_dev *hdev) +{ + return 0; +} + +static inline void hclgevf_update_tc_info(struct hclgevf_dev *hdev) {} +#endif + +#endif /* __HCLGEVF_DCB_H__ */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 7ccf6625b27e..34e17b13bbcf 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -12,6 +12,7 @@ #include "hclgevf_devlink.h" #include "hclge_comm_rss.h" #include "hclgevf_trace.h" +#include "hclgevf_dcb.h" #define HCLGEVF_NAME "hclgevf" @@ -143,8 +144,7 @@ static void hclgevf_get_stats(struct hnae3_handle *handle, u64 *data) hclge_comm_tqps_get_stats(handle, data); } -static void hclgevf_build_send_msg(struct hclge_vf_to_pf_msg *msg, u8 code, - u8 subcode) +void hclgevf_build_send_msg(struct hclge_vf_to_pf_msg *msg, u8 code, u8 subcode) { if (msg) { memset(msg, 0, sizeof(struct hclge_vf_to_pf_msg)); @@ -174,10 +174,13 @@ static int hclgevf_get_basic_info(struct hclgevf_dev *hdev) basic_info = (struct hclge_basic_info *)resp_msg; hdev->hw_tc_map = basic_info->hw_tc_map; + hdev->nic.kinfo.tc_info.max_tc = basic_info->tc_max; hdev->mbx_api_version = le16_to_cpu(basic_info->mbx_api_version); caps = le32_to_cpu(basic_info->pf_caps); if (test_bit(HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B, &caps)) set_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps); + if (!test_bit(HNAE3_PF_SUPPORT_VF_MULTI_TCS_B, &caps)) + clear_bit(HNAE3_DEV_SUPPORT_VF_MULTI_TCS_B, ae_dev->caps); return 0; } @@ -1406,8 +1409,10 @@ static int hclgevf_reset_tqp(struct hnae3_handle *handle) ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, &return_status, sizeof(return_status)); - if (ret || return_status == HCLGEVF_RESET_ALL_QUEUE_DONE) + if (ret) return ret; + if (return_status == HCLGEVF_RESET_ALL_QUEUE_DONE) + goto map_tc; for (i = 1; i < handle->kinfo.num_tqps; i++) { hclgevf_build_send_msg(&send_msg, HCLGE_MBX_QUEUE_RESET, 0); @@ -1416,8 +1421,14 @@ static int hclgevf_reset_tqp(struct hnae3_handle *handle) if (ret) return ret; } +map_tc: + /* restore the tc map for tx ring */ + ret = hclgevf_tx_ring_tc_config(hdev); + if (ret) + dev_err(&hdev->pdev->dev, "failed to set tqp tc, ret = %d\n", + ret); - return 0; + return ret; } static int hclgevf_set_mtu(struct hnae3_handle *handle, int new_mtu) @@ -1433,8 +1444,8 @@ static int hclgevf_set_mtu(struct hnae3_handle *handle, int new_mtu) return hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0); } -static int hclgevf_notify_client(struct hclgevf_dev *hdev, - enum hnae3_reset_notify_type type) +int hclgevf_notify_client(struct hclgevf_dev *hdev, + enum hnae3_reset_notify_type type) { struct hnae3_client *client = hdev->nic_client; struct hnae3_handle *handle = &hdev->nic; @@ -2175,6 +2186,8 @@ static int hclgevf_configure(struct hclgevf_dev *hdev) if (ret) return ret; + hclgevf_dcb_init(hdev); + /* get current port based vlan state from PF */ ret = hclgevf_get_port_base_vlan_filter_state(hdev); if (ret) @@ -2256,7 +2269,7 @@ static int hclgevf_config_gro(struct hclgevf_dev *hdev) return ret; } -static int hclgevf_init_rss_tc_mode(struct hclgevf_dev *hdev, u16 rss_size) +int hclgevf_init_rss_tc_mode(struct hclgevf_dev *hdev, u16 rss_size) { u16 tc_offset[HNAE3_MAX_TC] = {0}; u16 tc_valid[HNAE3_MAX_TC] = {0}; @@ -3209,8 +3222,7 @@ static void hclgevf_get_tqps_and_rss_info(struct hnae3_handle *handle, *max_rss_size = hdev->rss_size_max; } -static void hclgevf_update_rss_size(struct hnae3_handle *handle, - u32 new_tqps_num) +void hclgevf_update_rss_size(struct hnae3_handle *handle, u32 new_tqps_num) { struct hnae3_knic_private_info *kinfo = &handle->kinfo; struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); @@ -3232,6 +3244,8 @@ static void hclgevf_update_rss_size(struct hnae3_handle *handle, kinfo->rss_size = max_rss_size; kinfo->num_tqps = kinfo->tc_info.num_tc * kinfo->rss_size; + + hdev->rss_cfg.rss_size = kinfo->rss_size; } static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, @@ -3246,7 +3260,7 @@ static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, int ret; hclgevf_update_rss_size(handle, new_tqps_num); - + hclgevf_update_tc_info(hdev); ret = hclgevf_init_rss_tc_mode(hdev, kinfo->rss_size); if (ret) return ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index b518ecafa005..4573bef8df7f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -225,6 +225,7 @@ struct hclgevf_dev { unsigned long reset_pending; enum hnae3_reset_type reset_type; struct timer_list reset_timer; + struct hclge_mbx_tc_info tc_info; #define HCLGEVF_RESET_REQUESTED 0 #define HCLGEVF_RESET_PENDING 1 @@ -303,4 +304,10 @@ 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); +int hclgevf_notify_client(struct hclgevf_dev *hdev, + enum hnae3_reset_notify_type type); +void hclgevf_update_rss_size(struct hnae3_handle *handle, u32 new_tqps_num); +int hclgevf_init_rss_tc_mode(struct hclgevf_dev *hdev, u16 rss_size); +void hclgevf_build_send_msg(struct hclge_vf_to_pf_msg *msg, u8 code, + u8 subcode); #endif -- Gitee From 320a36a3c3bacd371fa996b2c9abdba0d7b4c9b3 Mon Sep 17 00:00:00 2001 From: Peiyang Wang Date: Thu, 22 May 2025 15:52:03 +0800 Subject: [PATCH 2/5] net: hns3: add support for vf get dscp configuration from pf driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID44N0 ---------------------------------------------------------------------- The vf supports two modes DSCP and priority. After configures DSCP parameters in the pf, the pf synchronizes the DSCP parameters to the vf. When multiple TCs are configured for a vf, vf can use the dscp parameter of the pf to select a queue for data flows. The query and configuration interfaces on the vf side are not provided. The vf supports dscp only when the vf supports multi-TCs. Signed-off-by: Jian Shen Signed-off-by: Hao Lan Signed-off-by: Peiyang Wang Signed-off-by: Donghua Huang --- .../net/ethernet/hisilicon/hns3/hclge_mbx.h | 5 ++ drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../hns3/hns3_common/hclge_comm_cmd.h | 3 + .../hisilicon/hns3/hns3pf/hclge_dcb.c | 33 +++++++ .../hisilicon/hns3/hns3pf/hclge_main.h | 1 + .../hisilicon/hns3/hns3pf/hclge_mbx.c | 21 +++++ .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 43 +++++++++ .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 4 + .../hisilicon/hns3/hns3vf/hclgevf_dcb.c | 1 + .../hisilicon/hns3/hns3vf/hclgevf_main.c | 89 ++++++++++++++++++- .../hisilicon/hns3/hns3vf/hclgevf_main.h | 1 + .../hisilicon/hns3/hns3vf/hclgevf_mbx.c | 16 ++++ 12 files changed, 217 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h index 262ca38ddb4f..9892aec521f6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h @@ -51,6 +51,7 @@ enum HCLGE_MBX_OPCODE { HCLGE_MBX_SET_QB = 0x28, /* (VF -> PF) set queue bonding */ HCLGE_MBX_PUSH_QB_STATE, /* (PF -> VF) push qb state */ HCLGE_MBX_SET_TC = 0x30, /* (VF -> PF) set tc */ + HCLGE_MBX_EVENT_NOTIFY, /* (PF -> VF) event notify */ HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf flr status */ HCLGE_MBX_PUSH_LINK_STATUS, /* (M7 -> PF) get port link status */ @@ -87,6 +88,10 @@ enum hclge_mbx_qb_cfg_subcode { HCLGE_MBX_QB_GET_STATE /* query whether qb enabled */ }; +enum hclge_mbx_event_notify_type { + HCLGE_MBX_DSCP_CHANGE = 0, +}; + #define HCLGE_MBX_MAX_MSG_SIZE 14 #define HCLGE_MBX_MAX_RESP_DATA_SIZE 8U #define HCLGE_MBX_MAX_RING_CHAIN_PARAM_NUM 4 diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 9cf58e631379..7d70bf0d50bd 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -895,6 +895,7 @@ struct hnae3_tc_info { #define HNAE3_MAX_DSCP 64 #define HNAE3_PRIO_ID_INVALID 0xff +#define HNAE3_PRIO_ID_MAP_INVALID 0xf struct hnae3_knic_private_info { struct net_device *netdev; /* Set by KNIC client when init instance */ u16 rss_size; /* Allocated RSS queues */ 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 4fd6df3bd2ec..6764fbceb33a 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 @@ -270,6 +270,9 @@ enum hclge_opcode_type { HCLGE_OPC_IMP_STATS_INFO = 0x7013, HCLGE_OPC_IMP_COMPAT_CFG = 0x701A, + /* dscp pri map command */ + HCLGE_OPC_DSCP_PRI_MAP = 0x7039, + /* SFP command */ HCLGE_OPC_GET_SFP_EEPROM = 0x7100, HCLGE_OPC_GET_SFP_EXIST = 0x7101, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index a189fd52feb8..490b21cd424d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -4,6 +4,7 @@ #include "hclge_main.h" #include "hclge_dcb.h" #include "hclge_tm.h" +#include "hclge_mbx.h" #include "hnae3.h" #define BW_PERCENT 100 @@ -424,12 +425,34 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) return last_bad_ret; } +static void hclge_notify_dscp_change(struct hclge_dev *hdev) +{ + struct hclge_vport *vport; + int ret; + int i; + + if (!hnae3_ae_dev_vf_multi_tcs_supported(hdev)) + return; + + for (i = 0; i < pci_num_vf(hdev->pdev); i++) { + vport = &hdev->vport[i + HCLGE_VF_VPORT_START_NUM]; + + if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) + continue; + + ret = hclge_mbx_event_notify(vport, BIT(HCLGE_MBX_DSCP_CHANGE)); + if (ret) + break; + } +} + static int hclge_ieee_setapp(struct hnae3_handle *h, struct dcb_app *app) { struct hclge_vport *vport = hclge_get_vport(h); struct net_device *netdev = h->kinfo.netdev; struct hclge_dev *hdev = vport->back; struct dcb_app old_app; + int ret1; int ret; if (app->selector != IEEE_8021QAZ_APP_SEL_DSCP || @@ -467,6 +490,11 @@ static int hclge_ieee_setapp(struct hnae3_handle *h, struct dcb_app *app) else ret = dcb_ieee_delapp(netdev, &old_app); + ret1 = hclge_dscp_to_pri_map(hdev); + if (ret1) + return ret1; + hclge_notify_dscp_change(hdev); + return ret; } @@ -508,6 +536,11 @@ static int hclge_ieee_delapp(struct hnae3_handle *h, struct dcb_app *app) ret = hclge_up_to_tc_map(hdev); } + ret = hclge_dscp_to_pri_map(hdev); + if (ret) + return ret; + hclge_notify_dscp_change(hdev); + return ret; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 01be6b0cb264..ebef8599efd2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -1203,4 +1203,5 @@ void hclge_get_media_type(struct hnae3_handle *handle, u8 *media_type, u8 *module_type); int hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable); int hclge_query_scc_version(struct hclge_dev *hdev, u32 *scc_version); +int hclge_mbx_event_notify(struct hclge_vport *vport, u64 event_bits); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 53282d540253..d18ec66e282a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -605,6 +605,24 @@ int hclge_push_vf_link_status(struct hclge_vport *vport) HCLGE_MBX_LINK_STAT_CHANGE, vport->vport_id); } +int hclge_mbx_event_notify(struct hclge_vport *vport, u64 event_bits) +{ + __le64 msg_data = cpu_to_le64(event_bits); + struct hclge_dev *hdev = vport->back; + u8 dest_vfid = (u8)vport->vport_id; + int ret; + + /* send this requested info to VF */ + ret = hclge_send_mbx_msg(vport, (u8 *)&msg_data, sizeof(__le64), + HCLGE_MBX_EVENT_NOTIFY, dest_vfid); + if (ret) + dev_err(&hdev->pdev->dev, + "failed to notify vf %u event %#llx, ret = %d\n", + vport->vport_id - HCLGE_VF_VPORT_START_NUM, event_bits, + ret); + return ret; +} + static void hclge_get_link_mode(struct hclge_vport *vport, struct hclge_mbx_vf_to_pf_cmd *mbx_req) { @@ -673,6 +691,9 @@ static void hclge_notify_vf_config(struct hclge_vport *vport) struct hclge_port_base_vlan_config *vlan_cfg; int ret; + if (hnae3_ae_dev_vf_multi_tcs_supported(hdev)) + hclge_mbx_event_notify(vport, BIT(HCLGE_MBX_DSCP_CHANGE)); + hclge_push_vf_link_status(vport); if (test_bit(HCLGE_VPORT_NEED_NOTIFY_RESET, &vport->need_notify)) { ret = hclge_inform_vf_reset(vport, HNAE3_VF_PF_FUNC_RESET); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 001b0c8a447c..dc5fa3c991a0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -269,12 +269,17 @@ int hclge_up_to_tc_map(struct hclge_dev *hdev) static void hclge_dscp_to_prio_map_init(struct hclge_dev *hdev) { + int ret; u8 i; hdev->vport[0].nic.kinfo.tc_map_mode = HNAE3_TC_MAP_MODE_PRIO; hdev->vport[0].nic.kinfo.dscp_app_cnt = 0; for (i = 0; i < HNAE3_MAX_DSCP; i++) hdev->vport[0].nic.kinfo.dscp_prio[i] = HNAE3_PRIO_ID_INVALID; + ret = hclge_dscp_to_pri_map(hdev); + if (ret) + dev_err(&hdev->pdev->dev, "failed to init dscp-prio map %d\n", + ret); } int hclge_dscp_to_tc_map(struct hclge_dev *hdev) @@ -308,6 +313,40 @@ int hclge_dscp_to_tc_map(struct hclge_dev *hdev) return hclge_cmd_send(&hdev->hw, desc, HCLGE_DSCP_MAP_TC_BD_NUM); } +int hclge_dscp_to_pri_map(struct hclge_dev *hdev) +{ + struct hclge_desc desc[HCLGE_DSCP_MAP_PRI_BD_NUM]; + u8 *req0 = (u8 *)desc[0].data; + u8 *req1 = (u8 *)desc[1].data; + u8 pri_id, i, j; + + if (!hnae3_ae_dev_vf_multi_tcs_supported(hdev)) + return 0; + + hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_DSCP_PRI_MAP, false); + desc[0].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT); + hclge_cmd_setup_basic_desc(&desc[1], HCLGE_OPC_DSCP_PRI_MAP, false); + + /* The low 32 dscp setting use bd0, high 32 dscp setting use bd1 */ + for (i = 0; i < HNAE3_MAX_DSCP / HCLGE_DSCP_MAP_PRI_BD_NUM; i++) { + pri_id = hdev->vport[0].nic.kinfo.dscp_prio[i]; + if (pri_id == HNAE3_PRIO_ID_INVALID) + pri_id = HNAE3_PRIO_ID_MAP_INVALID; + /* Each dscp setting has 4 bits, so each byte saves two dscp + * setting + */ + req0[i >> 1] |= pri_id << HCLGE_DSCP_PRI_SHIFT(i); + + j = i + HNAE3_MAX_DSCP / HCLGE_DSCP_MAP_PRI_BD_NUM; + pri_id = hdev->vport[0].nic.kinfo.dscp_prio[j]; + if (pri_id == HNAE3_PRIO_ID_INVALID) + pri_id = HNAE3_PRIO_ID_MAP_INVALID; + req1[i >> 1] |= pri_id << HCLGE_DSCP_PRI_SHIFT(i); + } + + return hclge_cmd_send(&hdev->hw, desc, HCLGE_DSCP_MAP_PRI_BD_NUM); +} + static int hclge_tm_pg_to_pri_map_cfg(struct hclge_dev *hdev, u8 pg_id, u8 pri_bit_map) { @@ -1378,6 +1417,10 @@ static int hclge_tm_map_cfg(struct hclge_dev *hdev) ret = hclge_dscp_to_tc_map(hdev); if (ret) return ret; + + ret = hclge_dscp_to_pri_map(hdev); + if (ret) + return ret; } ret = hclge_tm_pg_to_pri_map(hdev); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h index 390f292eafbb..df37026a6113 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -30,6 +30,9 @@ enum hclge_opcode_type; #define HCLGE_TM_PF_MAX_PRI_NUM 8 #define HCLGE_TM_PF_MAX_QSET_NUM 8 +#define HCLGE_DSCP_MAP_PRI_BD_NUM 2 +#define HCLGE_DSCP_PRI_SHIFT(n) (((n) & 1) * 4) + #define HCLGE_DSCP_MAP_TC_BD_NUM 2 #define HCLGE_DSCP_TC_SHIFT(n) (((n) & 1) * 4) @@ -291,4 +294,5 @@ int hclge_tm_set_tc_rate_limit(struct hclge_dev *hdev, u32 hclge_tm_rate_2_port_rate(u64 rate); void hclge_reset_tc_config(struct hclge_dev *hdev); void hclge_tm_vport_tc_info_update(struct hclge_vport *vport); +int hclge_dscp_to_pri_map(struct hclge_dev *hdev); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.c index 16b5d0b3a273..7b33866bb1bb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.c @@ -308,4 +308,5 @@ void hclgevf_dcb_init(struct hclgevf_dev *hdev) hdev->tc_info.tc_sch_mode = BIT(0); hdev->hw_tc_map = 1; kinfo->dcb_ops = &hclgevf_dcb_ops; + hclgevf_get_dscp_to_pri_map(hdev); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 34e17b13bbcf..f168651f5879 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -2203,7 +2203,11 @@ static int hclgevf_configure(struct hclgevf_dev *hdev) if (ret) return ret; - return hclgevf_get_pf_media_type(hdev); + ret = hclgevf_get_pf_media_type(hdev); + if (ret) + return ret; + + return hclgevf_get_dscp_to_pri_map(hdev); } static int hclgevf_alloc_hdev(struct hnae3_ae_dev *ae_dev) @@ -2953,6 +2957,67 @@ static void hclgevf_uninit_rxd_adv_layout(struct hclgevf_dev *hdev) hclgevf_write_dev(&hdev->hw, HCLGEVF_RXD_ADV_LAYOUT_EN_REG, 0); } +int hclgevf_get_dscp_to_pri_map(struct hclgevf_dev *hdev) +{ +#define HCLGEVF_DSCP_MAP_PRI_BD_NUM 2 +#define HCLGEVF_DSCP_PRI_SHIFT(n) (((n) & 1) * 4) +#define HCLGEVF_PRI_MASK 0xF + + struct hnae3_knic_private_info *kinfo = &hdev->nic.kinfo; + struct hclge_desc desc[HCLGEVF_DSCP_MAP_PRI_BD_NUM]; + u8 dscp_prio[HNAE3_MAX_DSCP] = {0}; + u8 *req0 = (u8 *)desc[0].data; + u8 *req1 = (u8 *)desc[1].data; + bool is_app_dscp = false; + u8 dscp_app_cnt = 0; + u8 i, j; + int ret; + + if (!hnae3_ae_dev_vf_multi_tcs_supported(hdev)) + return 0; + + hclgevf_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_DSCP_PRI_MAP, true); + desc[0].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT); + hclgevf_cmd_setup_basic_desc(&desc[1], HCLGE_OPC_DSCP_PRI_MAP, true); + + ret = hclgevf_cmd_send(&hdev->hw, desc, HCLGEVF_DSCP_MAP_PRI_BD_NUM); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to get dscp pri map, ret = %d\n", ret); + return ret; + } + + /* The low 32 dscp setting use bd0, high 32 dscp setting use bd1 */ + for (i = 0; i < HNAE3_MAX_DSCP / HCLGEVF_DSCP_MAP_PRI_BD_NUM; i++) { + /* Each dscp setting has 4 bits, so each byte saves two dscp + * setting + */ + dscp_prio[i] = (req0[i >> 1] >> HCLGEVF_DSCP_PRI_SHIFT(i)) & + HCLGEVF_PRI_MASK; + + j = i + HNAE3_MAX_DSCP / HCLGEVF_DSCP_MAP_PRI_BD_NUM; + dscp_prio[j] = (req1[i >> 1] >> HCLGEVF_DSCP_PRI_SHIFT(i)) & + HCLGEVF_PRI_MASK; + } + dscp_app_cnt = 0; + for (i = 0; i < HNAE3_MAX_DSCP; i++) { + if (dscp_prio[i] >= HNAE3_MAX_USER_PRIO) + dscp_prio[i] = HNAE3_PRIO_ID_INVALID; + else + dscp_app_cnt++; + if (!is_app_dscp && dscp_prio[i] > 0 && + dscp_prio[i] < HNAE3_MAX_USER_PRIO) + is_app_dscp = true; + } + + kinfo->dscp_app_cnt = dscp_app_cnt; + memcpy(kinfo->dscp_prio, dscp_prio, HNAE3_MAX_DSCP); + kinfo->tc_map_mode = is_app_dscp ? HNAE3_TC_MAP_MODE_DSCP : + HNAE3_TC_MAP_MODE_PRIO; + + return 0; +} + static int hclgevf_reset_hdev(struct hclgevf_dev *hdev) { struct pci_dev *pdev = hdev->pdev; @@ -2997,6 +3062,10 @@ static int hclgevf_reset_hdev(struct hclgevf_dev *hdev) if (ret) return ret; + ret = hclgevf_get_dscp_to_pri_map(hdev); + if (ret) + return ret; + set_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state); hclgevf_init_rxd_adv_layout(hdev); @@ -3428,6 +3497,23 @@ void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state, rtnl_unlock(); } +static int hclgevf_get_dscp_prio(struct hnae3_handle *h, u8 dscp, u8 *tc_mode, + u8 *priority) +{ + struct hnae3_knic_private_info *kinfo = &h->kinfo; + + if (dscp >= HNAE3_MAX_DSCP) + return -EINVAL; + + if (tc_mode) + *tc_mode = kinfo->tc_map_mode; + if (priority) + *priority = kinfo->dscp_prio[dscp] == HNAE3_PRIO_ID_INVALID ? 0 : + kinfo->dscp_prio[dscp]; + + return 0; +} + static const struct hnae3_ae_ops hclgevf_ops = { .init_ae_dev = hclgevf_init_ae_dev, .uninit_ae_dev = hclgevf_uninit_ae_dev, @@ -3487,6 +3573,7 @@ static const struct hnae3_ae_ops hclgevf_ops = { .get_cmdq_stat = hclgevf_get_cmdq_stat, .request_flush_qb_config = hclgevf_set_fd_qb, .query_fd_qb_state = hclgevf_query_fd_qb_state, + .get_dscp_prio = hclgevf_get_dscp_prio, }; static struct hnae3_ae_algo ae_algovf = { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index 4573bef8df7f..5faf05b05921 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -310,4 +310,5 @@ void hclgevf_update_rss_size(struct hnae3_handle *handle, u32 new_tqps_num); int hclgevf_init_rss_tc_mode(struct hclgevf_dev *hdev, u16 rss_size); void hclgevf_build_send_msg(struct hclge_vf_to_pf_msg *msg, u8 code, u8 subcode); +int hclgevf_get_dscp_to_pri_map(struct hclgevf_dev *hdev); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c index 464d5188ad63..30d24bc90170 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c @@ -272,6 +272,7 @@ void hclgevf_mbx_handler(struct hclgevf_dev *hdev) case HCLGE_MBX_PUSH_VLAN_INFO: case HCLGE_MBX_PUSH_PROMISC_INFO: case HCLGE_MBX_PUSH_QB_STATE: + case HCLGE_MBX_EVENT_NOTIFY: hclgevf_handle_mbx_msg(hdev, req); break; default: @@ -310,6 +311,16 @@ static void hclgevf_parse_qb_info(struct hclgevf_dev *hdev, u16 qb_state) hdev->qb_cfg.hw_qb_en = qb_state > HCLGEVF_HW_QB_OFF; } +static int hclgevf_mbx_parse_event_info(struct hclgevf_dev *hdev, u64 events) +{ + int ret = 0; + + if (events & BIT(HCLGE_MBX_DSCP_CHANGE)) + ret = hclgevf_get_dscp_to_pri_map(hdev); + + return ret; +} + void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev) { struct hclge_mbx_port_base_vlan *vlan_info; @@ -318,6 +329,7 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev) enum hnae3_reset_type reset_type; u16 link_status, state; __le16 *msg_q; + u64 events; u16 opcode; u8 duplex; u32 speed; @@ -391,6 +403,10 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev) case HCLGE_MBX_PUSH_QB_STATE: hclgevf_parse_qb_info(hdev, msg_q[1]); break; + case HCLGE_MBX_EVENT_NOTIFY: + events = *(u64 *)(msg_q + 1); + hclgevf_mbx_parse_event_info(hdev, events); + break; default: dev_err(&hdev->pdev->dev, "fetched unsupported(%u) message from arq\n", -- Gitee From 4ae306c4001bac895897f80d17a8cff52b23d1b5 Mon Sep 17 00:00:00 2001 From: Peiyang Wang Date: Tue, 20 May 2025 11:18:02 +0800 Subject: [PATCH 3/5] net: hns3: support dpdk using vf multiple tcs driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID44N0 ---------------------------------------------------------------------- When dpdk configures vf multiple tcs, it needs to know the multi-TC configuration of the pf. Addting mbx messages to support above scenario. Signed-off-by: Peiyang Wang Signed-off-by: Donghua Huang --- .../net/ethernet/hisilicon/hns3/hclge_mbx.h | 6 +++ .../hisilicon/hns3/hns3pf/hclge_main.c | 5 ++ .../hisilicon/hns3/hns3pf/hclge_mbx.c | 52 +++++++++++++++++++ .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 12 +++-- .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 1 + 5 files changed, 73 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h index 9892aec521f6..6d6e74d60a23 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h @@ -50,6 +50,7 @@ enum HCLGE_MBX_OPCODE { HCLGE_MBX_GET_RING_VECTOR_MAP, /* (VF -> PF) get ring-to-vector map */ HCLGE_MBX_SET_QB = 0x28, /* (VF -> PF) set queue bonding */ HCLGE_MBX_PUSH_QB_STATE, /* (PF -> VF) push qb state */ + HCLGE_MBX_GET_TC = 0x2F, /* (VF -> PF) get tc */ HCLGE_MBX_SET_TC = 0x30, /* (VF -> PF) set tc */ HCLGE_MBX_EVENT_NOTIFY, /* (PF -> VF) event notify */ @@ -92,6 +93,11 @@ enum hclge_mbx_event_notify_type { HCLGE_MBX_DSCP_CHANGE = 0, }; +enum hclge_mbx_multi_vf_tcs_info_subcode { + HCLGE_MBX_MULTI_VF_TC_PRI_MAP = 0, /* query tc to pri map */ + HCLGE_MBX_MULTI_VF_TC_ETS_INFO, /* query tc ets info */ +}; + #define HCLGE_MBX_MAX_MSG_SIZE 14 #define HCLGE_MBX_MAX_RESP_DATA_SIZE 8U #define HCLGE_MBX_MAX_RING_CHAIN_PARAM_NUM 4 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 1525f3c948cb..58102c5b6d65 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -8792,6 +8792,7 @@ static void hclge_ae_stop(struct hnae3_handle *handle) int hclge_vport_start(struct hclge_vport *vport) { + struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; struct hclge_dev *hdev = vport->back; set_bit(HCLGE_VPORT_STATE_INITED, &vport->state); @@ -8812,6 +8813,10 @@ int hclge_vport_start(struct hclge_vport *vport) clear_bit(vport->vport_id, hdev->vport_config_block); + if (hnae3_ae_dev_vf_multi_tcs_supported(hdev) && vport->vport_id > 0 && + kinfo->tc_info.num_tc > 1) + set_bit(vport->vport_id, hdev->vf_multi_tcs_en); + return 0; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index d18ec66e282a..b8928496f0e8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -11,6 +11,8 @@ #define CREATE_TRACE_POINTS #include "hclge_trace.h" +#define HCLGE_MBX_TC_ETS_INVALID 255 + static u16 hclge_errno_to_resp(int errno) { int resp = abs(errno); @@ -509,6 +511,8 @@ static void hclge_get_basic_info(struct hclge_vport *vport, if (test_bit(HNAE3_DEV_SUPPORT_VF_MULTI_TCS_B, ae_dev->caps)) { hnae3_set_bit(pf_caps, HNAE3_PF_SUPPORT_VF_MULTI_TCS_B, 1); basic_info->tc_max = hdev->tc_max; + clear_bit(vport->vport_id, hdev->vf_multi_tcs_en); + hclge_tm_vport_tc_info_update(vport); } else { basic_info->tc_max = 1; } @@ -1052,11 +1056,14 @@ static int hclge_mbx_get_link_mode_handler(struct hclge_mbx_ops_param *param) static int hclge_mbx_get_vf_flr_status_handler(struct hclge_mbx_ops_param *param) { + struct hclge_vport *vport = param->vport; + hclge_rm_vport_all_mac_table(param->vport, false, HCLGE_MAC_ADDR_UC); hclge_rm_vport_all_mac_table(param->vport, false, HCLGE_MAC_ADDR_MC); hclge_rm_vport_all_vlan_table(param->vport, false); + clear_bit(vport->vport_id, vport->back->vf_multi_tcs_en); return 0; } @@ -1111,6 +1118,50 @@ static int hclge_mbx_handle_vf_qb_handler(struct hclge_mbx_ops_param *param) return 0; } +static void +hclge_vf_get_tc_ets_info(struct hclge_vport *vport, + struct hclge_respond_to_vf_msg *resp_msg) +{ + struct hclge_dev *hdev = vport->back; + struct hclge_pg_info *pg_info; + int i; + + for (i = 0; i < HNAE3_MAX_TC; i++) { + pg_info = &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid]; + if (i >= hdev->tm_info.num_tc) { + resp_msg->data[i] = HCLGE_MBX_TC_ETS_INVALID; + continue; + } + + resp_msg->data[i] = pg_info->tc_dwrr[i]; + } + resp_msg->len = HNAE3_MAX_TC; +} + +static int +hclge_mbx_get_vf_multi_tc_handler(struct hclge_mbx_ops_param *param) +{ + struct hclge_vport *vport = param->vport; + struct hclge_dev *hdev = vport->back; + __le32 prio_tc_map = 0; + + switch (param->req->msg.subcode) { + case HCLGE_MBX_MULTI_VF_TC_PRI_MAP: + prio_tc_map = cpu_to_le32(hclge_tm_get_prio_tc_map(hdev)); + memcpy(param->resp_msg->data, &prio_tc_map, + sizeof(prio_tc_map)); + param->resp_msg->len = sizeof(prio_tc_map); + break; + case HCLGE_MBX_MULTI_VF_TC_ETS_INFO: + hclge_vf_get_tc_ets_info(vport, param->resp_msg); + break; + default: + return -EINVAL; + } + + return 0; +} + static int hclge_mbx_set_vf_multi_tc_handler(struct hclge_mbx_ops_param *param) { struct hclge_mbx_tc_info *tc_info; @@ -1155,6 +1206,7 @@ static const hclge_mbx_ops_fn hclge_mbx_ops_list[HCLGE_MBX_OPCODE_MAX] = { [HCLGE_MBX_PUSH_LINK_STATUS] = hclge_mbx_push_link_status_handler, [HCLGE_MBX_NCSI_ERROR] = hclge_mbx_ncsi_error_handler, [HCLGE_MBX_SET_TC] = hclge_mbx_set_vf_multi_tc_handler, + [HCLGE_MBX_GET_TC] = hclge_mbx_get_vf_multi_tc_handler, }; static void hclge_mbx_request_handling(struct hclge_mbx_ops_param *param) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index dc5fa3c991a0..235865584150 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -2330,11 +2330,9 @@ void hclge_reset_tc_config(struct hclge_dev *hdev) hclge_comm_rss_indir_init_cfg(hdev->ae_dev, &hdev->rss_cfg); } -static int hclge_vf_prio_tc_validate(struct hclge_dev *hdev, - struct hclge_mbx_tc_info *tc_info) +u32 hclge_tm_get_prio_tc_map(struct hclge_dev *hdev) { #define HCLGE_PRI_SHIFT 4 - u32 prio_tc_map = 0; u8 i; @@ -2342,6 +2340,14 @@ static int hclge_vf_prio_tc_validate(struct hclge_dev *hdev, prio_tc_map |= (u32)hdev->tm_info.prio_tc[i] << (i * HCLGE_PRI_SHIFT); + return prio_tc_map; +} + +static int hclge_vf_prio_tc_validate(struct hclge_dev *hdev, + struct hclge_mbx_tc_info *tc_info) +{ + u32 prio_tc_map = hclge_tm_get_prio_tc_map(hdev); + if (prio_tc_map != __le32_to_cpu(tc_info->prio_tc_map)) { dev_err(&hdev->pdev->dev, "failed to check vf prio tc map, not match pf\n"); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h index df37026a6113..cca4166cd70f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -294,5 +294,6 @@ int hclge_tm_set_tc_rate_limit(struct hclge_dev *hdev, u32 hclge_tm_rate_2_port_rate(u64 rate); void hclge_reset_tc_config(struct hclge_dev *hdev); void hclge_tm_vport_tc_info_update(struct hclge_vport *vport); +u32 hclge_tm_get_prio_tc_map(struct hclge_dev *hdev); int hclge_dscp_to_pri_map(struct hclge_dev *hdev); #endif -- Gitee From 07a9ebae55dc7bf09f7da53c7eb92b9660e8a71b Mon Sep 17 00:00:00 2001 From: Peiyang Wang Date: Tue, 20 May 2025 11:14:34 +0800 Subject: [PATCH 4/5] net: hns3: remap vf's queue and qset when vport start driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID44N0 ---------------------------------------------------------------------- When re-enable vf, the resource of the vf's TM module need to be remapped. So, remapping vf's queue and qset in hclge_vport_start function to support above scenario. Signed-off-by: Peiyang Wang Signed-off-by: Donghua Huang --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 7 +++++++ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 3 +-- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 58102c5b6d65..f86d2ec244ec 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -8794,6 +8794,7 @@ int hclge_vport_start(struct hclge_vport *vport) { struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; struct hclge_dev *hdev = vport->back; + int ret = 0; set_bit(HCLGE_VPORT_STATE_INITED, &vport->state); set_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); @@ -8817,6 +8818,12 @@ int hclge_vport_start(struct hclge_vport *vport) kinfo->tc_info.num_tc > 1) set_bit(vport->vport_id, hdev->vf_multi_tcs_en); + ret = hclge_vport_q_to_qs_map(hdev, vport); + if (ret) + dev_warn(&hdev->pdev->dev, + "vport%u failed to map q and qs, ret=%d\n", + vport->vport_id, ret); + return 0; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 235865584150..09b136153bf4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -1016,8 +1016,7 @@ static int hclge_tm_pg_dwrr_cfg(struct hclge_dev *hdev) return 0; } -static int hclge_vport_q_to_qs_map(struct hclge_dev *hdev, - struct hclge_vport *vport) +int hclge_vport_q_to_qs_map(struct hclge_dev *hdev, struct hclge_vport *vport) { struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; struct hnae3_tc_info *tc_info = &kinfo->tc_info; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h index cca4166cd70f..0b10c8dd82c9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -294,6 +294,7 @@ int hclge_tm_set_tc_rate_limit(struct hclge_dev *hdev, u32 hclge_tm_rate_2_port_rate(u64 rate); void hclge_reset_tc_config(struct hclge_dev *hdev); void hclge_tm_vport_tc_info_update(struct hclge_vport *vport); +int hclge_vport_q_to_qs_map(struct hclge_dev *hdev, struct hclge_vport *vport); u32 hclge_tm_get_prio_tc_map(struct hclge_dev *hdev); int hclge_dscp_to_pri_map(struct hclge_dev *hdev); #endif -- Gitee From 1a805c4f23f1232486d04aa46223615f8d273e6c Mon Sep 17 00:00:00 2001 From: Peiyang Wang Date: Mon, 10 Feb 2025 16:43:47 +0800 Subject: [PATCH 5/5] net: hns3: the multi-tcs VF can be configured only when the interface is down driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID44N0 ---------------------------------------------------------------------- The multi-tcs VF can be configured only when the interface is down Signed-off-by: Peiyang Wang Signed-off-by: Donghua Huang --- .../net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.c index 7b33866bb1bb..dc7be6e82742 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.c @@ -259,7 +259,6 @@ static bool hclgevf_ets_not_need_config(struct hclgevf_dev *hdev, static int hclgevf_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) { struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(h); - int ret1; int ret; if (!test_bit(HCLGEVF_STATE_DOWN, &hdev->state)) @@ -272,16 +271,7 @@ static int hclgevf_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) if (hclgevf_ets_not_need_config(hdev, ets)) return 0; - ret = hclgevf_notify_client(hdev, HNAE3_UNINIT_CLIENT); - if (ret) - return ret; - - ret1 = hclgevf_set_vf_multi_tc(hdev, ets); - ret = hclgevf_notify_client(hdev, HNAE3_INIT_CLIENT); - if (ret) - return ret; - - return ret1; + return hclgevf_set_vf_multi_tc(hdev, ets); } static u8 hclgevf_getdcbx(struct hnae3_handle *h) -- Gitee