From: Peiyang Wang wangpeiyang1@huawei.com
driver inclusion category:feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9A3QT CVE: NA
----------------------------------------------------------------------
Traffic class is supposed to support limit rate. Different tc will be configured different rate. The followed tc command can be used.
tc qdisc add dev eth0 root mqprio num_tc 4 map 0 1 2 3 0 1 2 3 queues 8@0 8@8 8@16 8@24 hw 1 mode channel shaper bw_rlimit max_rate 10gbps 1gbps 100mbps 10mbps
As showed the aboved command, the eth0 has 4 tcs and the limit rate are 80 Gbits/sec, 8 Gbits/sec, 800 Mbits/sec and 80 Mbits/sec respectively.
Signed-off-by: Peiyang Wang wangpeiyang1@huawei.com Signed-off-by: Jiantao Xiao xiaojiantao1@h-partners.com --- .../hns3/hns3_common/hclge_comm_cmd.h | 1 + .../hisilicon/hns3/hns3pf/hclge_dcb.c | 10 +++- .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 47 +++++++++++++++++++ .../ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 8 ++++ 4 files changed, 65 insertions(+), 1 deletion(-)
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 e3d72b21aba8..44a484342b4c 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 @@ -155,6 +155,7 @@ enum hclge_opcode_type { HCLGE_OPC_TM_INTERNAL_STS = 0x0850, HCLGE_OPC_TM_INTERNAL_CNT = 0x0851, HCLGE_OPC_TM_INTERNAL_STS_1 = 0x0852, + HCLGE_OPC_TM_TC_RATE_LIMIT_CFG = 0x0871, HCLGE_OPC_TM_FLUSH = 0x0872,
/* Packet buffer allocate commands */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index 1cfd7a32e6ab..416bcac3bf70 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -613,13 +613,21 @@ static void hclge_sync_mqprio_qopt(struct hnae3_tc_info *tc_info, static int hclge_config_tc(struct hclge_dev *hdev, struct hnae3_tc_info *tc_info) { + int ret; int i;
hclge_tm_schd_info_update(hdev, tc_info->num_tc); for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) hdev->tm_info.prio_tc[i] = tc_info->prio_tc[i];
- return hclge_map_update(hdev); + ret = hclge_map_update(hdev); + if (ret) + return ret; + + if (hnae3_dev_roh_supported(hdev)) + return hclge_tm_set_tc_rate_limit(hdev, tc_info); + + return 0; }
/* Set up TC for hardware offloaded mqprio in channel mode */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 79a2472230fd..a8350940fd5e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -1668,6 +1668,49 @@ void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc) hclge_tm_schd_info_init(hdev); }
+static int hclge_tc_rate_limit_cfg(struct hclge_dev *hdev, u32 speed, u8 tc) +{ + struct hclge_tc_rate_limit_cmd *tc_rate_limit_cmd; + struct hclge_desc desc; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_TC_RATE_LIMIT_CFG, + false); + + tc_rate_limit_cmd = (struct hclge_tc_rate_limit_cmd *)desc.data; + tc_rate_limit_cmd->speed = cpu_to_le32(speed); + tc_rate_limit_cmd->tc_id = tc; + + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) + dev_err(&hdev->pdev->dev, + "failed to config tc(%u) rate limit, ret = %d\n", + tc, ret); + + return ret; +} + +int hclge_tm_set_tc_rate_limit(struct hclge_dev *hdev, + struct hnae3_tc_info *tc_info) +{ + u32 speed; + int ret; + int i; + + for (i = 0; i < tc_info->num_tc; i++) { + /* mac speed unit is Mbps, tc max_rate is Bps */ + speed = hclge_tm_rate_2_port_rate(tc_info->max_rate[i]); + if (!speed) + speed = hdev->hw.mac.max_speed; + + ret = hclge_tc_rate_limit_cfg(hdev, speed, i); + if (ret) + return ret; + } + + return 0; +} + u32 hclge_tm_rate_2_port_rate(u64 rate) { do_div(rate, TM_RATE_PORT_RATE_SCALE); @@ -1676,6 +1719,7 @@ u32 hclge_tm_rate_2_port_rate(u64 rate)
int hclge_tm_init_hw(struct hclge_dev *hdev, bool init) { + struct hnae3_tc_info *tc_info = &hdev->vport[0].nic.kinfo.tc_info; int ret;
if ((hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) && @@ -1690,6 +1734,9 @@ int hclge_tm_init_hw(struct hclge_dev *hdev, bool init) if (ret) return ret;
+ if (hnae3_dev_roh_supported(hdev)) + return hclge_tm_set_tc_rate_limit(hdev, tc_info); + return 0; }
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h index 896b3b9672eb..64b448370f93 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -214,6 +214,12 @@ struct hclge_tm_nodes_cmd { __le16 queue_num; };
+struct hclge_tc_rate_limit_cmd { + __le32 speed; /* Unit Mbps */ + u8 tc_id; + u8 rsvd[19]; +}; + struct hclge_tm_shaper_para { u32 rate; u8 ir_b; @@ -279,6 +285,8 @@ int hclge_tm_get_port_shaper(struct hclge_dev *hdev, int hclge_up_to_tc_map(struct hclge_dev *hdev); int hclge_dscp_to_tc_map(struct hclge_dev *hdev); int hclge_tm_flush_cfg(struct hclge_dev *hdev, bool enable); +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); #endif