net/hns3: fix traffic management

In a multi-TC scenario, if the length of packets destined for different
TCs is different, for example, 64B and 1500B packets destined for TC0 and
TC1 respectively. There is a problem that the bandwidth of the TC to which
large packets are sent is preempted by the TC to which small packets are
sent on the Kunpeng 920 network engine. As a result, the TC bandwidth
accuracy is inaccurate.

To solve this problem, this patch made the following adjustments:
1/ During initialization, firmware reports the capability bit indicating
whether the TM function is supported.
2/ The command word for configuring TC and port rate limiting is added,
instead of reusing the existing command word. And firmware configured
to the correct module.
3/ When the PF driver is loaded, firmware completes the default
initialization of the TC and port.

Fixes: c09c7847d8 ("net/hns3: support traffic management")
Cc: stable@dpdk.org

Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
This commit is contained in:
Huisong Li 2021-06-21 15:38:45 +08:00 committed by Andrew Rybchenko
parent 0b3c74b9f7
commit fc18d1b4b8
7 changed files with 74 additions and 26 deletions

View File

@ -429,7 +429,8 @@ hns3_get_caps_name(uint32_t caps_id)
{ HNS3_CAPS_STASH_B, "stash" },
{ HNS3_CAPS_UDP_TUNNEL_CSUM_B, "udp_tunnel_csum" },
{ HNS3_CAPS_RAS_IMP_B, "ras_imp" },
{ HNS3_CAPS_RXD_ADV_LAYOUT_B, "rxd_adv_layout" }
{ HNS3_CAPS_RXD_ADV_LAYOUT_B, "rxd_adv_layout" },
{ HNS3_CAPS_TM_B, "tm_capability" }
};
uint32_t i;
@ -505,6 +506,8 @@ hns3_parse_capability(struct hns3_hw *hw,
HNS3_DEV_SUPPORT_OUTER_UDP_CKSUM_B, 1);
if (hns3_get_bit(caps, HNS3_CAPS_RAS_IMP_B))
hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_RAS_IMP_B, 1);
if (hns3_get_bit(caps, HNS3_CAPS_TM_B))
hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_TM_B, 1);
}
static uint32_t

View File

@ -162,6 +162,9 @@ enum hns3_opcode_type {
HNS3_OPC_TM_INTERNAL_CNT = 0x0851,
HNS3_OPC_TM_INTERNAL_STS_1 = 0x0852,
HNS3_OPC_TM_PORT_LIMIT_RATE = 0x0870,
HNS3_OPC_TM_TC_LIMIT_RATE = 0x0871,
/* Mailbox cmd */
HNS3_OPC_MBX_VF_TO_PF = 0x2001,
@ -319,6 +322,7 @@ enum HNS3_CAPS_BITS {
HNS3_CAPS_UDP_TUNNEL_CSUM_B,
HNS3_CAPS_RAS_IMP_B,
HNS3_CAPS_RXD_ADV_LAYOUT_B = 15,
HNS3_CAPS_TM_B = 17,
};
enum HNS3_API_CAP_BITS {

View File

@ -415,7 +415,7 @@ hns3_dcb_pg_shapping_cfg(struct hns3_hw *hw, enum hns3_shap_bucket bucket,
return hns3_cmd_send(hw, &desc, 1);
}
int
static int
hns3_pg_shaper_rate_cfg(struct hns3_hw *hw, uint8_t pg_id, uint32_t rate)
{
struct hns3_shaper_parameter shaper_parameter;
@ -551,7 +551,7 @@ hns3_dcb_pri_shapping_cfg(struct hns3_hw *hw, enum hns3_shap_bucket bucket,
return hns3_cmd_send(hw, &desc, 1);
}
int
static int
hns3_pri_shaper_rate_cfg(struct hns3_hw *hw, uint8_t tc_no, uint32_t rate)
{
struct hns3_shaper_parameter shaper_parameter;

View File

@ -209,8 +209,6 @@ int hns3_queue_to_tc_mapping(struct hns3_hw *hw, uint16_t nb_rx_q,
int hns3_update_queue_map_configure(struct hns3_adapter *hns);
int hns3_port_shaper_update(struct hns3_hw *hw, uint32_t speed);
int hns3_pg_shaper_rate_cfg(struct hns3_hw *hw, uint8_t pg_id, uint32_t rate);
int hns3_pri_shaper_rate_cfg(struct hns3_hw *hw, uint8_t tc_no, uint32_t rate);
uint8_t hns3_txq_mapped_tc_get(struct hns3_hw *hw, uint16_t txq_no);
#endif /* _HNS3_DCB_H_ */

View File

@ -868,6 +868,7 @@ enum {
HNS3_DEV_SUPPORT_RXD_ADV_LAYOUT_B,
HNS3_DEV_SUPPORT_OUTER_UDP_CKSUM_B,
HNS3_DEV_SUPPORT_RAS_IMP_B,
HNS3_DEV_SUPPORT_TM_B,
};
#define hns3_dev_dcb_supported(hw) \
@ -904,6 +905,9 @@ enum {
#define hns3_dev_tx_push_supported(hw) \
hns3_get_bit((hw)->capability, HNS3_DEV_SUPPORT_TX_PUSH_B)
#define hns3_dev_tm_supported(hw) \
hns3_get_bit((hw)->capability, HNS3_DEV_SUPPORT_TM_B)
#define HNS3_DEV_PRIVATE_TO_HW(adapter) \
(&((struct hns3_adapter *)adapter)->hw)
#define HNS3_DEV_PRIVATE_TO_PF(adapter) \

View File

@ -28,8 +28,12 @@ void
hns3_tm_conf_init(struct rte_eth_dev *dev)
{
struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
uint32_t max_tx_queues = hns3_tm_max_tx_queues_get(dev);
if (!hns3_dev_tm_supported(hw))
return;
pf->tm_conf.nb_leaf_nodes_max = max_tx_queues;
pf->tm_conf.nb_nodes_max = 1 + HNS3_MAX_TC_NUM + max_tx_queues;
pf->tm_conf.nb_shaper_profile_max = 1 + HNS3_MAX_TC_NUM;
@ -50,9 +54,13 @@ void
hns3_tm_conf_uninit(struct rte_eth_dev *dev)
{
struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct hns3_tm_shaper_profile *shaper_profile;
struct hns3_tm_node *tm_node;
if (!hns3_dev_tm_supported(hw))
return;
if (pf->tm_conf.nb_queue_node > 0) {
while ((tm_node = TAILQ_FIRST(&pf->tm_conf.queue_list))) {
TAILQ_REMOVE(&pf->tm_conf.queue_list, tm_node, node);
@ -912,40 +920,39 @@ static int
hns3_tm_config_port_rate(struct hns3_hw *hw,
struct hns3_tm_shaper_profile *shaper_profile)
{
struct hns3_port_limit_rate_cmd *cfg;
struct hns3_cmd_desc desc;
uint32_t firmware_rate;
uint64_t rate;
int ret;
if (shaper_profile) {
rate = shaper_profile->profile.peak.rate;
firmware_rate = hns3_tm_rate_convert_tm2firmware(rate);
} else {
firmware_rate = hw->dcb_info.pg_info[0].bw_limit;
firmware_rate = hw->max_tm_rate;
}
/*
* The TM shaper topology after device inited:
* pri0 shaper --->|
* pri1 shaper --->|
* ... |----> pg0 shaper ----> port shaper
* ... |
* priX shaper --->|
*
* Because port shaper rate maybe changed by firmware, to avoid
* concurrent configure, driver use pg0 shaper to achieve the rate limit
* of port.
*
* The finally port rate = MIN(pg0 shaper rate, port shaper rate)
*/
return hns3_pg_shaper_rate_cfg(hw, 0, firmware_rate);
hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_TM_PORT_LIMIT_RATE, false);
cfg = (struct hns3_port_limit_rate_cmd *)desc.data;
cfg->speed = rte_cpu_to_le_32(firmware_rate);
ret = hns3_cmd_send(hw, &desc, 1);
if (ret)
hns3_err(hw, "failed to config port rate, ret = %d", ret);
return ret;
}
static int
hns3_tm_config_tc_rate(struct hns3_hw *hw,
uint8_t tc_no,
hns3_tm_config_tc_rate(struct hns3_hw *hw, uint8_t tc_no,
struct hns3_tm_shaper_profile *shaper_profile)
{
struct hns3_tc_limit_rate_cmd *cfg;
struct hns3_cmd_desc desc;
uint32_t firmware_rate;
uint64_t rate;
int ret;
if (shaper_profile) {
rate = shaper_profile->profile.peak.rate;
@ -954,7 +961,17 @@ hns3_tm_config_tc_rate(struct hns3_hw *hw,
firmware_rate = hw->dcb_info.tc_info[tc_no].bw_limit;
}
return hns3_pri_shaper_rate_cfg(hw, tc_no, firmware_rate);
hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_TM_TC_LIMIT_RATE, false);
cfg = (struct hns3_tc_limit_rate_cmd *)desc.data;
cfg->speed = rte_cpu_to_le_32(firmware_rate);
cfg->tc_id = tc_no;
ret = hns3_cmd_send(hw, &desc, 1);
if (ret)
hns3_err(hw, "failed to config tc (%u) rate, ret = %d",
tc_no, ret);
return ret;
}
static bool
@ -1227,12 +1244,16 @@ static const struct rte_tm_ops hns3_tm_ops = {
};
int
hns3_tm_ops_get(struct rte_eth_dev *dev __rte_unused,
void *arg)
hns3_tm_ops_get(struct rte_eth_dev *dev, void *arg)
{
struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
if (arg == NULL)
return -EINVAL;
if (!hns3_dev_tm_supported(hw))
return -EOPNOTSUPP;
*(const void **)arg = &hns3_tm_ops;
return 0;
@ -1243,6 +1264,9 @@ hns3_tm_dev_start_proc(struct hns3_hw *hw)
{
struct hns3_pf *pf = HNS3_DEV_HW_TO_PF(hw);
if (!hns3_dev_tm_supported(hw))
return;
if (pf->tm_conf.root && !pf->tm_conf.committed)
hns3_warn(hw,
"please call hierarchy_commit() before starting the port.");
@ -1289,6 +1313,9 @@ hns3_tm_conf_update(struct hns3_hw *hw)
struct hns3_pf *pf = HNS3_DEV_HW_TO_PF(hw);
struct rte_tm_error error;
if (!hns3_dev_tm_supported(hw))
return 0;
if (pf->tm_conf.root == NULL || !pf->tm_conf.committed)
return 0;

View File

@ -9,6 +9,18 @@
#include <rte_tailq.h>
#include <rte_tm_driver.h>
struct hns3_port_limit_rate_cmd {
uint32_t speed; /* Unit Mbps */
uint32_t rsvd[5];
};
struct hns3_tc_limit_rate_cmd {
uint32_t speed; /* Unit Mbps */
uint8_t tc_id;
uint8_t rsvd[3];
uint32_t rsvd1[4];
};
enum hns3_tm_node_type {
HNS3_TM_NODE_TYPE_PORT,
HNS3_TM_NODE_TYPE_TC,