From ef6f2f5cdbe2ef2e7bfd340a80652db91e894949 Mon Sep 17 00:00:00 2001 From: Xiaoyun Wang Date: Tue, 17 Mar 2020 23:01:17 +0800 Subject: [PATCH] net/hinic: support flow control The patch supports pause flow control, including getting or setting rx_pasue, tx_pause and auto_neg, auto_neg is just for Electric port type. Signed-off-by: Xiaoyun Wang --- drivers/net/hinic/base/hinic_pmd_niccfg.c | 29 ++++++++ drivers/net/hinic/base/hinic_pmd_niccfg.h | 2 + drivers/net/hinic/hinic_pmd_ethdev.c | 89 ++++++++++++++++++++++- drivers/net/hinic/hinic_pmd_ethdev.h | 3 + drivers/net/hinic/hinic_pmd_tx.c | 1 + 5 files changed, 123 insertions(+), 1 deletion(-) diff --git a/drivers/net/hinic/base/hinic_pmd_niccfg.c b/drivers/net/hinic/base/hinic_pmd_niccfg.c index 6b1b7deb4f..0899a9cb3d 100644 --- a/drivers/net/hinic/base/hinic_pmd_niccfg.c +++ b/drivers/net/hinic/base/hinic_pmd_niccfg.c @@ -668,6 +668,35 @@ int hinic_set_pause_config(void *hwdev, struct nic_pause_config nic_pause) return 0; } +int hinic_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause) +{ + struct hinic_pause_config pause_info; + u16 out_size = sizeof(pause_info); + int err; + + if (!hwdev || !nic_pause) + return -EINVAL; + + memset(&pause_info, 0, sizeof(pause_info)); + pause_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; + pause_info.func_id = hinic_global_func_id(hwdev); + + err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PAUSE_INFO, + &pause_info, sizeof(pause_info), + &pause_info, &out_size); + if (err || !out_size || pause_info.mgmt_msg_head.status) { + PMD_DRV_LOG(ERR, "Failed to get pause info, err: %d, status: 0x%x, out size: 0x%x\n", + err, pause_info.mgmt_msg_head.status, out_size); + return -EINVAL; + } + + nic_pause->auto_neg = pause_info.auto_neg; + nic_pause->rx_pause = pause_info.rx_pause; + nic_pause->tx_pause = pause_info.tx_pause; + + return 0; +} + int hinic_dcb_set_ets(void *hwdev, u8 *up_tc, u8 *pg_bw, u8 *pgid, u8 *up_bw, u8 *prio) { diff --git a/drivers/net/hinic/base/hinic_pmd_niccfg.h b/drivers/net/hinic/base/hinic_pmd_niccfg.h index be6b320b31..846b5973ec 100644 --- a/drivers/net/hinic/base/hinic_pmd_niccfg.h +++ b/drivers/net/hinic/base/hinic_pmd_niccfg.h @@ -850,6 +850,8 @@ int hinic_set_rx_vhd_mode(void *hwdev, u16 vhd_mode, u16 rx_buf_sz); int hinic_set_pause_config(void *hwdev, struct nic_pause_config nic_pause); +int hinic_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause); + int hinic_reset_port_link_cfg(void *hwdev); int hinic_dcb_set_ets(void *hwdev, u8 *up_tc, u8 *pg_bw, u8 *pgid, u8 *up_bw, diff --git a/drivers/net/hinic/hinic_pmd_ethdev.c b/drivers/net/hinic/hinic_pmd_ethdev.c index 22e3efa267..23724a0228 100644 --- a/drivers/net/hinic/hinic_pmd_ethdev.c +++ b/drivers/net/hinic/hinic_pmd_ethdev.c @@ -1833,6 +1833,81 @@ static int hinic_dev_promiscuous_disable(struct rte_eth_dev *dev) return rc; } +static int hinic_flow_ctrl_get(struct rte_eth_dev *dev, + struct rte_eth_fc_conf *fc_conf) +{ + struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); + struct nic_pause_config nic_pause; + int err; + + memset(&nic_pause, 0, sizeof(nic_pause)); + + err = hinic_get_pause_info(nic_dev->hwdev, &nic_pause); + if (err) + return err; + + if (nic_dev->pause_set || !nic_pause.auto_neg) { + nic_pause.rx_pause = nic_dev->nic_pause.rx_pause; + nic_pause.tx_pause = nic_dev->nic_pause.tx_pause; + } + + fc_conf->autoneg = nic_pause.auto_neg; + + if (nic_pause.tx_pause && nic_pause.rx_pause) + fc_conf->mode = RTE_FC_FULL; + else if (nic_pause.tx_pause) + fc_conf->mode = RTE_FC_TX_PAUSE; + else if (nic_pause.rx_pause) + fc_conf->mode = RTE_FC_RX_PAUSE; + else + fc_conf->mode = RTE_FC_NONE; + + PMD_DRV_LOG(INFO, "Get pause options, tx: %s, rx: %s, auto: %s\n", + nic_pause.tx_pause ? "on" : "off", + nic_pause.rx_pause ? "on" : "off", + nic_pause.auto_neg ? "on" : "off"); + + return 0; +} + +static int hinic_flow_ctrl_set(struct rte_eth_dev *dev, + struct rte_eth_fc_conf *fc_conf) +{ + struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); + struct nic_pause_config nic_pause; + int err; + + nic_pause.auto_neg = fc_conf->autoneg; + + if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || + (fc_conf->mode & RTE_FC_TX_PAUSE)) + nic_pause.tx_pause = true; + else + nic_pause.tx_pause = false; + + if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || + (fc_conf->mode & RTE_FC_RX_PAUSE)) + nic_pause.rx_pause = true; + else + nic_pause.rx_pause = false; + + err = hinic_set_pause_config(nic_dev->hwdev, nic_pause); + if (err) + return err; + + nic_dev->pause_set = true; + nic_dev->nic_pause.auto_neg = nic_pause.auto_neg; + nic_dev->nic_pause.rx_pause = nic_pause.rx_pause; + nic_dev->nic_pause.tx_pause = nic_pause.tx_pause; + + PMD_DRV_LOG(INFO, "Get pause options, tx: %s, rx: %s, auto: %s\n", + nic_pause.tx_pause ? "on" : "off", + nic_pause.rx_pause ? "on" : "off", + nic_pause.auto_neg ? "on" : "off"); + + return 0; +} + /** * DPDK callback to update the RSS hash key and RSS hash type. * @@ -2453,12 +2528,22 @@ static int hinic_dev_filter_ctrl(struct rte_eth_dev *dev, static int hinic_set_default_pause_feature(struct hinic_nic_dev *nic_dev) { struct nic_pause_config pause_config = {0}; + int err; pause_config.auto_neg = 0; pause_config.rx_pause = HINIC_DEFAUT_PAUSE_CONFIG; pause_config.tx_pause = HINIC_DEFAUT_PAUSE_CONFIG; - return hinic_set_pause_config(nic_dev->hwdev, pause_config); + err = hinic_set_pause_config(nic_dev->hwdev, pause_config); + if (err) + return err; + + nic_dev->pause_set = true; + nic_dev->nic_pause.auto_neg = pause_config.auto_neg; + nic_dev->nic_pause.rx_pause = pause_config.rx_pause; + nic_dev->nic_pause.tx_pause = pause_config.tx_pause; + + return 0; } static int hinic_set_default_dcb_feature(struct hinic_nic_dev *nic_dev) @@ -2886,6 +2971,8 @@ static const struct eth_dev_ops hinic_pmd_ops = { .allmulticast_disable = hinic_dev_allmulticast_disable, .promiscuous_enable = hinic_dev_promiscuous_enable, .promiscuous_disable = hinic_dev_promiscuous_disable, + .flow_ctrl_get = hinic_flow_ctrl_get, + .flow_ctrl_set = hinic_flow_ctrl_set, .rss_hash_update = hinic_rss_hash_update, .rss_hash_conf_get = hinic_rss_conf_get, .reta_update = hinic_rss_indirtbl_update, diff --git a/drivers/net/hinic/hinic_pmd_ethdev.h b/drivers/net/hinic/hinic_pmd_ethdev.h index d67e2161c1..3322fb90b4 100644 --- a/drivers/net/hinic/hinic_pmd_ethdev.h +++ b/drivers/net/hinic/hinic_pmd_ethdev.h @@ -263,6 +263,9 @@ struct hinic_nic_dev { u8 num_rss; u8 rx_queue_list[HINIC_MAX_RX_QUEUES]; + bool pause_set; + struct nic_pause_config nic_pause; + u32 vfta[HINIC_VFTA_SIZE]; /* VLAN bitmap */ struct rte_ether_addr default_addr; diff --git a/drivers/net/hinic/hinic_pmd_tx.c b/drivers/net/hinic/hinic_pmd_tx.c index 64ec2c1198..f24e3e4202 100644 --- a/drivers/net/hinic/hinic_pmd_tx.c +++ b/drivers/net/hinic/hinic_pmd_tx.c @@ -16,6 +16,7 @@ #include "base/hinic_pmd_hwif.h" #include "base/hinic_pmd_wq.h" #include "base/hinic_pmd_nicio.h" +#include "base/hinic_pmd_niccfg.h" #include "hinic_pmd_ethdev.h" #include "hinic_pmd_tx.h" -- 2.20.1