diff --git a/drivers/net/ethernet/hisilicon/hns3/Makefile b/drivers/net/ethernet/hisilicon/hns3/Makefile index ec994681c30e907798030b5c4c60279e41417f17..0b1f6cf39dee6c8620335821351792032b9c6723 100644 --- a/drivers/net/ethernet/hisilicon/hns3/Makefile +++ b/drivers/net/ethernet/hisilicon/hns3/Makefile @@ -25,6 +25,7 @@ hclgevf-objs = hns3vf/hclgevf_main.o hns3vf/hclgevf_mbx.o hns3vf/hclgevf_devlin hclgevf-$(CONFIG_HNS3_UBL) += hns3_common/hclge_comm_unic_addr.o hns3vf/hclgevf_unic_ip.o hns3vf/hclgevf_unic_guid.o \ hns3vf/hclgevf_unic_addr.o hclgevf-$(CONFIG_UB_UDMA_HNS3) += hns3vf/hclgevf_udma.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_sysfs.o hns3pf/hclge_regs.o \ diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h index 14e830ff18924058a49f968e2c8a9d6feed3dbff..89a2e008df4efa502ea216a36dcd0c0f8d4d2dd6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h @@ -7,6 +7,8 @@ #include #include +#include "hnae3.h" + enum HCLGE_MBX_OPCODE { HCLGE_MBX_RESET = 0x01, /* (VF -> PF) assert reset */ HCLGE_MBX_ASSERTING_RESET, /* (PF -> VF) PF is asserting reset */ @@ -49,6 +51,8 @@ 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_EVENT_NOTIFY, /* (PF -> VF) event notify */ HCLGE_MBX_SET_MGUID = 0x50, /* (VF -> PF) set mc guid */ HCLGE_UNIC_MBX_SET_IP, /* (VF -> PF) set ip addr */ @@ -100,6 +104,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 @@ -115,7 +123,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; }; @@ -243,6 +251,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 55d75a83d818a2df2d2a223afc2d6aa61f1469e0..c0b2ff520f9eecb6f50674498b3245fcbda22ea6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -142,6 +142,7 @@ enum HNAE3_DEV_CAP_BITS { HNAE3_DEV_SUPPORT_TM_FLUSH_B, HNAE3_DEV_SUPPORT_VF_FAULT_B, HNAE3_DEV_SUPPORT_ERR_MOD_GEN_REG_B, + HNAE3_DEV_SUPPORT_VF_MULTI_TCS_B, }; #define hnae3_ae_dev_fd_supported(ae_dev) \ @@ -222,8 +223,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) @@ -879,6 +884,10 @@ struct hnae3_dcb_ops { int (*ieee_setpfc)(struct hnae3_handle *, struct ieee_pfc *); int (*ieee_setapp)(struct hnae3_handle *h, struct dcb_app *app); int (*ieee_delapp)(struct hnae3_handle *h, struct dcb_app *app); + int (*ieee_setmaxrate)(struct hnae3_handle *h, + struct ieee_maxrate *maxrate); + int (*ieee_getmaxrate)(struct hnae3_handle *h, + struct ieee_maxrate *maxrate); /* DCBX configuration */ u8 (*getdcbx)(struct hnae3_handle *); @@ -912,6 +921,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.c b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c index 98814708ddf3e34de2483c6f585ca6dcccc291d4..17097947fe83b9bb4ce29e092e71eab96b86c084 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 @@ -159,6 +159,7 @@ static const struct hclge_comm_caps_bit_map hclge_pf_cmd_caps[] = { {HCLGE_COMM_CAP_TM_FLUSH_B, HNAE3_DEV_SUPPORT_TM_FLUSH_B}, {HCLGE_COMM_CAP_VF_FAULT_B, HNAE3_DEV_SUPPORT_VF_FAULT_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[] = { @@ -172,6 +173,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 e9bb4d4e9aafb1eefcb1a070bc9192ebbde72912..9e904d9056fbf617077acb64d17287a26e47bad4 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 @@ -268,6 +268,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, @@ -366,6 +369,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_common/hclge_comm_rss.c b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c index b4ae2160aff4f3fb7aef8ee4056e752bc46662ae..83c0bbfbeda59c624762fd760dde80396211dcfc 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c @@ -36,11 +36,12 @@ int hclge_comm_rss_init_cfg(struct hnae3_handle *nic, struct hclge_comm_rss_cfg *rss_cfg) { u16 rss_ind_tbl_size = ae_dev->dev_specs.rss_ind_tbl_size; + struct hnae3_knic_private_info *kinfo = &nic->kinfo; int rss_algo = HCLGE_COMM_RSS_HASH_ALGO_TOEPLITZ; u16 *rss_ind_tbl; if (nic->flags & HNAE3_SUPPORT_VF) - rss_cfg->rss_size = nic->kinfo.rss_size; + rss_cfg->rss_size = kinfo->rss_size; if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) rss_algo = HCLGE_COMM_RSS_HASH_ALGO_SIMPLE; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c b/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c index 829ad48f261dded4f8e0ab16fd2113c2f7ed539b..b68b40c69c3c87d193296cbc07c5697d1b2a222b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c @@ -104,6 +104,28 @@ static u8 hns3_dcbnl_setdcbx(struct net_device *ndev, u8 mode) return 1; } +static int hns3_dcbnl_ieee_setmaxrate(struct net_device *netdev, + struct ieee_maxrate *maxrate) +{ + struct hnae3_handle *h = hns3_get_handle(netdev); + + if (h->kinfo.dcb_ops->ieee_setmaxrate) + return h->kinfo.dcb_ops->ieee_setmaxrate(h, maxrate); + + return -EOPNOTSUPP; +} + +static int hns3_dcbnl_ieee_getmaxrate(struct net_device *netdev, + struct ieee_maxrate *maxrate) +{ + struct hnae3_handle *h = hns3_get_handle(netdev); + + if (h->kinfo.dcb_ops->ieee_getmaxrate) + return h->kinfo.dcb_ops->ieee_getmaxrate(h, maxrate); + + return -EOPNOTSUPP; +} + static const struct dcbnl_rtnl_ops hns3_dcbnl_ops = { .ieee_getets = hns3_dcbnl_ieee_getets, .ieee_setets = hns3_dcbnl_ieee_setets, @@ -111,6 +133,8 @@ static const struct dcbnl_rtnl_ops hns3_dcbnl_ops = { .ieee_setpfc = hns3_dcbnl_ieee_setpfc, .ieee_setapp = hns3_dcbnl_ieee_setapp, .ieee_delapp = hns3_dcbnl_ieee_delapp, + .ieee_setmaxrate = hns3_dcbnl_ieee_setmaxrate, + .ieee_getmaxrate = hns3_dcbnl_ieee_getmaxrate, .getdcbx = hns3_dcbnl_getdcbx, .setdcbx = hns3_dcbnl_setdcbx, }; @@ -120,6 +144,8 @@ static const struct dcbnl_rtnl_ops hns3_unic_dcbnl_ops = { .ieee_setets = hns3_dcbnl_ieee_setets, .ieee_setapp = hns3_dcbnl_ieee_setapp, .ieee_delapp = hns3_dcbnl_ieee_delapp, + .ieee_setmaxrate = hns3_dcbnl_ieee_setmaxrate, + .ieee_getmaxrate = hns3_dcbnl_ieee_getmaxrate, .getdcbx = hns3_dcbnl_getdcbx, .setdcbx = hns3_dcbnl_setdcbx, }; @@ -132,7 +158,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; #ifdef CONFIG_HNS3_UBL diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c index e01b5dad4448421e81f9ce27c89042ea3b0e6233..be2272a424d2ef719188cdde097b5572975246c1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c @@ -61,7 +61,7 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { .name = "tm_qset", .cmd = HNAE3_DBG_CMD_TM_QSET, .dentry = HNS3_DBG_DENTRY_TM, - .buf_len = HNS3_DBG_READ_LEN, + .buf_len = HNS3_DBG_READ_LEN_1MB, .init = hns3_dbg_common_file_init, }, { @@ -419,6 +419,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 d7092b401cae5f83ef5569120bd2b142706904a6..321aa1f98c79d9af4856e984dac119a735f56195 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 @@ -81,6 +82,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 +207,41 @@ 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) +{ + u8 max_tc_id = 0; + u32 i; + + if (ets->ets_cap != hdev->tc_max) + return false; + + for (i = 0; i < HNAE3_MAX_TC; i++) { + if (ets->tc_tx_bw[i] != hdev->tm_info.pg_info[0].tc_dwrr[i]) + return false; + + if (ets->prio_tc[i] != hdev->tm_info.prio_tc[i]) + return false; + + if (hdev->tm_info.tc_info[i].tc_sch_mode == + HCLGE_SCH_MODE_SP) { + if (ets->tc_tsa[i] != IEEE_8021QAZ_TSA_STRICT) + return false; + } else { + if (ets->tc_tsa[i] != IEEE_8021QAZ_TSA_ETS) + return false; + } + + if (ets->prio_tc[i] > max_tc_id) + max_tc_id = ets->prio_tc[i]; + } + + if (max_tc_id + 1 != hdev->tm_info.num_tc) + return false; + + return true; +} + static int hclge_map_update(struct hclge_dev *hdev) { int ret; @@ -262,6 +306,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 +321,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 +334,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; @@ -391,12 +442,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 || @@ -434,6 +507,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; } @@ -475,6 +553,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; } @@ -509,6 +592,72 @@ static u8 hclge_setdcbx(struct hnae3_handle *h, u8 mode) return 0; } +static int hclge_ieee_getmaxrate(struct hnae3_handle *h, + struct ieee_maxrate *maxrate) +{ + struct hnae3_tc_info *tc_info = &h->kinfo.tc_info; + struct hclge_vport *vport = hclge_get_vport(h); + struct hclge_dev *hdev = vport->back; + + if (!hnae3_dev_roh_supported(hdev) && + !hnae3_dev_ubl_supported(hdev->ae_dev)) + return -EOPNOTSUPP; + + memcpy(maxrate, tc_info->max_rate, sizeof(struct ieee_maxrate)); + return 0; +} + +static int hclge_check_maxrate(struct hclge_dev *hdev, + struct ieee_maxrate *maxrate) +{ + u64 max_speed = (u64)hdev->hw.mac.max_speed * TM_RATE_PORT_RATE_SCALE; + u8 i; + + for (i = 0; i < HNAE3_MAX_TC; i++) { + /* no limit */ + if (!maxrate->tc_maxrate[i]) + continue; + if (maxrate->tc_maxrate[i] < TM_RATE_PORT_RATE_SCALE || + maxrate->tc_maxrate[i] > max_speed) { + dev_err(&hdev->pdev->dev, + "invalid max_rate[%llubps]: the range is [1Mbps, %uMbps]\n", + maxrate->tc_maxrate[i] * HCLGE_BYTE_BITS, + hdev->hw.mac.max_speed); + return -EINVAL; + } + } + return 0; +} + +static int hclge_ieee_setmaxrate(struct hnae3_handle *h, + struct ieee_maxrate *maxrate) +{ + struct hnae3_tc_info *tc_info = &h->kinfo.tc_info; + struct hclge_vport *vport = hclge_get_vport(h); + struct hclge_dev *hdev = vport->back; + struct hnae3_tc_info old_tc_info; + int ret; + + if (!hnae3_dev_roh_supported(hdev) && + !hnae3_dev_ubl_supported(hdev->ae_dev)) + return -EOPNOTSUPP; + + if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || tc_info->mqprio_active) + return -EINVAL; + + ret = hclge_check_maxrate(hdev, maxrate); + if (ret) + return ret; + + memcpy(&old_tc_info, tc_info, sizeof(struct hnae3_tc_info)); + memcpy(tc_info->max_rate, maxrate, sizeof(struct ieee_maxrate)); + ret = hclge_tm_set_tc_rate_limit(hdev, tc_info); + if (ret) + memcpy(tc_info, &old_tc_info, sizeof(struct hnae3_tc_info)); + + return ret; +} + static int hclge_mqprio_qopt_check_rate(struct hclge_dev *hdev, u64 min_rate, u64 max_rate) { @@ -701,6 +850,8 @@ static const struct hnae3_dcb_ops hns3_dcb_ops = { .getdcbx = hclge_getdcbx, .setdcbx = hclge_setdcbx, .setup_tc = hclge_setup_tc, + .ieee_setmaxrate = hclge_ieee_setmaxrate, + .ieee_getmaxrate = hclge_ieee_getmaxrate, }; void hclge_dcb_ops_set(struct hclge_dev *hdev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h index b04702e656890e124ed54f77ee531f3d8880e0a1..bc7e957818283a3f316f836176d8fce2271f7e64 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h @@ -6,10 +6,23 @@ #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 +#define HCLGE_RATE_UNIT_MBPS 1000000ULL /* 1Mbps */ + #endif /* __HCLGE_DCB_H__ */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index a0d22c00b22f99c535fc9ec35166cb3cc07bded7..1cfba2517d9ed69357a105501be95f43185c67d7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -968,6 +968,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; @@ -1229,4 +1230,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 66da617e79722c2b638d2c3f195b39f67349be0a..da02d01d6d38a53bbdecb282a544d5e2918f579c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -8,6 +8,8 @@ #include "hclge_comm_unic_addr.h" #include "hclge_unic_guid.h" #include "hclge_unic_ip.h" +#include "hclge_dcb.h" +#include "hclge_tm.h" #define CREATE_TRACE_POINTS #include "hclge_trace.h" @@ -196,10 +198,10 @@ static int hclge_get_ring_chain_from_mbx( return -EINVAL; for (i = 0; i < ring_num; i++) { - if (req->msg.param[i].tqp_index >= vport->nic.kinfo.rss_size) { + if (req->msg.param[i].tqp_index >= vport->nic.kinfo.num_tqps) { dev_err(&hdev->pdev->dev, "tqp index(%u) is out of range(0-%u)\n", req->msg.param[i].tqp_index, - vport->nic.kinfo.rss_size - 1U); + vport->nic.kinfo.num_tqps - 1U); return -EINVAL; } } @@ -495,6 +497,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; @@ -506,6 +509,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; @@ -599,6 +608,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) { @@ -667,6 +694,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); @@ -1062,6 +1092,8 @@ static int hclge_mbx_vf_uninit_handler(struct hclge_mbx_ops_param *param) } #endif 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; } @@ -1101,6 +1133,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, + "PF fail(%d) to set VF multi TCS\n", ret); + + return ret; +} + #ifdef CONFIG_HNS3_UBL static int hclge_unic_mbx_set_mc_guid_handler(struct hclge_mbx_ops_param *param) { @@ -1161,6 +1208,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 132b6446d48597598055dfbc0805b4994cb5d5fc..a5b2bca4a5e454507aa8b755f4c14119229fc65c 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" @@ -268,12 +269,18 @@ 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, ret = %d\n", + ret); } int hclge_dscp_to_tc_map(struct hclge_dev *hdev) @@ -307,6 +314,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) { @@ -679,23 +720,34 @@ static void hclge_tm_update_kinfo_rss_size(struct hclge_vport *vport) 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. - */ if (vport->vport_id) { - kinfo->tc_info.max_tc = 1; - kinfo->tc_info.num_tc = 1; - vport->qs_offset = HNAE3_MAX_TC + + /* 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 (hnae3_ae_dev_vf_multi_tcs_supported(hdev)) + vport->qs_offset = HNAE3_MAX_TC * vport->vport_id; + 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.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; } + if (vport->vport_id && + !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); + + if (vport->vport_id && !hnae3_ae_dev_vf_multi_tcs_supported(hdev)) + kinfo->tc_info.max_tc = 1; + else + kinfo->tc_info.max_tc = hdev->tc_max; + max_rss_size = min_t(u16, vport_max_rss_size, hclge_vport_get_max_rss_size(vport)); @@ -712,7 +764,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 +1232,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 +1269,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; } @@ -1321,6 +1399,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); @@ -2039,7 +2121,23 @@ int hclge_tm_get_q_to_tc(struct hclge_dev *hdev, u16 q_id, u8 *tc_id) 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(q_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) { dev_err(&hdev->pdev->dev, @@ -2198,3 +2296,118 @@ int hclge_tm_flush_cfg(struct hclge_dev *hdev, bool enable) return ret; } + +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 58222ea1906c4361b4db28d4236b46ebbdb3a9c7..61c56c8265139affc94e4e43bd863bb034a5232b 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) @@ -65,9 +68,10 @@ struct hclge_nq_to_qs_link_cmd { struct hclge_tqp_tx_queue_tc_cmd { __le16 queue_id; - __le16 rsvd; + u8 func_id; + u8 rsvd1; u8 tc_id; - u8 rev[3]; + u8 rsvd2[3]; }; struct hclge_pg_weight_cmd { @@ -288,4 +292,6 @@ int hclge_tm_flush_cfg(struct hclge_dev *hdev, bool enable); 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_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_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h index 537b887fa0a2f9af5e9fe5254597f61d73676fbd..dcfe369da1e657dc185398cf2b53fa6ea6498c9f 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 0000000000000000000000000000000000000000..1043111a69198e52066a2de479fa6c045b68577f --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_dcb.c @@ -0,0 +1,323 @@ +// 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 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)); + memcpy(&hdev->tc_info, tc_info, sizeof(*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 hnae3_knic_private_info *kinfo = &hdev->nic.kinfo; + u32 i; + + if (ets->ets_cap != kinfo->tc_info.max_tc) + return false; + + for (i = 0; i < HNAE3_MAX_TC; i++) { + if (ets->tc_tx_bw[i] != hdev->tc_info.tc_dwrr[i]) + return false; + if (ets->prio_tc[i] != kinfo->tc_info.prio_tc[i]) + return false; + + if (hdev->tc_info.tc_sch_mode & BIT(i)) { + if (ets->tc_tsa[i] != IEEE_8021QAZ_TSA_ETS) + return false; + } else { + if (ets->tc_tsa[i] != IEEE_8021QAZ_TSA_STRICT) + return false; + } + } + return true; +} + +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; + + 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_DOWN_CLIENT); + if (ret) + return ret; + 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; + + ret = hclgevf_notify_client(hdev, HNAE3_UP_CLIENT); + if (ret) + return ret; + return ret1; +} + +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 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); + kinfo->dcb_ops = &hclgevf_dcb_ops; + hclgevf_get_dscp_to_pri_map(hdev); +} 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 0000000000000000000000000000000000000000..e1835a317cfb048d19830a6a7c05c4493954e567 --- /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 9e89bd3d2ecce0eb8f5b321cebc3426fc64df24e..9f341cb10cb42235f57f44cb5bb300bddcc644e0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -17,6 +17,7 @@ #include "hclgevf_unic_guid.h" #include "hclgevf_unic_addr.h" #include "hclgevf_trace.h" +#include "hclgevf_dcb.h" #define HCLGEVF_NAME "hclgevf" @@ -191,10 +192,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; } @@ -387,12 +391,12 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev) new_tqps = kinfo->rss_size * num_tc; kinfo->num_tqps = min(new_tqps, hdev->num_tqps); - kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps, + kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps, sizeof(struct hnae3_queue *), GFP_KERNEL); if (!kinfo->tqp) return -ENOMEM; - for (i = 0; i < kinfo->num_tqps; i++) { + for (i = 0; i < hdev->num_tqps; i++) { hdev->htqp[i].q.handle = &hdev->nic; hdev->htqp[i].q.tqp_index = i; kinfo->tqp[i] = &hdev->htqp[i].q; @@ -1421,8 +1425,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); @@ -1431,8 +1437,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) @@ -1448,8 +1460,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; @@ -2197,6 +2209,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) @@ -2212,7 +2226,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) @@ -2278,12 +2296,21 @@ static int hclgevf_config_gro(struct hclgevf_dev *hdev) return ret; } +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}; + u16 tc_size[HNAE3_MAX_TC] = {0}; + + hclge_comm_get_rss_tc_info(rss_size, hdev->hw_tc_map, + tc_offset, tc_valid, tc_size); + return hclge_comm_set_rss_tc_mode(&hdev->hw.hw, tc_offset, tc_valid, + tc_size); +} + static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev) { struct hclge_comm_rss_cfg *rss_cfg = &hdev->rss_cfg; - u16 tc_offset[HCLGE_COMM_MAX_TC_NUM]; - u16 tc_valid[HCLGE_COMM_MAX_TC_NUM]; - u16 tc_size[HCLGE_COMM_MAX_TC_NUM]; int ret; if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) { @@ -2303,11 +2330,7 @@ static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev) if (ret) return ret; - hclge_comm_get_rss_tc_info(rss_cfg->rss_size, hdev->hw_tc_map, - tc_offset, tc_valid, tc_size); - - return hclge_comm_set_rss_tc_mode(&hdev->hw.hw, tc_offset, - tc_valid, tc_size); + return hclgevf_init_rss_tc_mode(hdev, rss_cfg->rss_size); } static int hclgevf_init_vlan_config(struct hclgevf_dev *hdev) @@ -3032,6 +3055,63 @@ 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; + 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++; + } + + kinfo->dscp_app_cnt = dscp_app_cnt; + memcpy(kinfo->dscp_prio, dscp_prio, HNAE3_MAX_DSCP); + kinfo->tc_map_mode = kinfo->dscp_app_cnt ? 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; @@ -3076,6 +3156,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); @@ -3275,11 +3359,7 @@ static void hclgevf_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) static u32 hclgevf_get_max_channels(struct hclgevf_dev *hdev) { - struct hnae3_handle *nic = &hdev->nic; - struct hnae3_knic_private_info *kinfo = &nic->kinfo; - - return min_t(u32, hdev->rss_size_max, - hdev->num_tqps / kinfo->tc_info.num_tc); + return min_t(u32, hdev->rss_size_max, hdev->num_tqps); } /** @@ -3312,8 +3392,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); @@ -3335,6 +3414,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, @@ -3342,9 +3423,6 @@ static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, { struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); struct hnae3_knic_private_info *kinfo = &handle->kinfo; - u16 tc_offset[HCLGE_COMM_MAX_TC_NUM]; - u16 tc_valid[HCLGE_COMM_MAX_TC_NUM]; - u16 tc_size[HCLGE_COMM_MAX_TC_NUM]; u16 cur_rss_size = kinfo->rss_size; u16 cur_tqps = kinfo->num_tqps; u32 *rss_indir; @@ -3352,11 +3430,8 @@ static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, int ret; hclgevf_update_rss_size(handle, new_tqps_num); - - hclge_comm_get_rss_tc_info(kinfo->rss_size, hdev->hw_tc_map, - tc_offset, tc_valid, tc_size); - ret = hclge_comm_set_rss_tc_mode(&hdev->hw.hw, tc_offset, - tc_valid, tc_size); + hclgevf_update_tc_info(hdev); + ret = hclgevf_init_rss_tc_mode(hdev, kinfo->rss_size); if (ret) return ret; @@ -3523,6 +3598,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, @@ -3582,6 +3674,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, #ifdef CONFIG_HNS3_UBL .add_addr = hclgevf_unic_add_addr, .rm_addr = hclgevf_unic_rm_addr, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index 314f4a61cb1c86fc63127a9f611f08618a2dea9b..92a6109672b2ddecbf8fc8708acea604a8b9eb8d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -12,6 +12,7 @@ #include "hnae3.h" #include "hclge_comm_rss.h" #include "hclge_comm_tqp_stats.h" +#include "hclgevf_dcb.h" #define HCLGEVF_MOD_VERSION "1.0" #define HCLGEVF_DRIVER_NAME "hclgevf" @@ -232,6 +233,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 @@ -319,4 +321,9 @@ void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state, struct hclgevf_dev *hclgevf_ae_get_hdev(struct hnae3_handle *handle); void hclgevf_build_send_msg(struct hclge_vf_to_pf_msg *msg, u8 code, u8 subcode); +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); +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 6ccf23ce2744055449204936ac5607e1248bfcc6..3d703e6c97c41d7a7f8baf83d37f26472eaa4c8a 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",