Add a precomputed ptype table and a compact CQE Rx burst function, and select the Rx path from the rx_cqe_compact_en runtime parameter.
Signed-off-by: Jiacheng Ye <[email protected]> --- doc/guides/rel_notes/release_26_11.rst | 1 + drivers/net/hinic3/base/hinic3_nic_cfg.h | 2 + drivers/net/hinic3/hinic3_ethdev.c | 105 +++-- drivers/net/hinic3/hinic3_ethdev.h | 8 +- drivers/net/hinic3/hinic3_rx.c | 574 +++++++++++++++++++---- drivers/net/hinic3/hinic3_rx.h | 217 ++++----- 6 files changed, 661 insertions(+), 246 deletions(-) diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index d4cc028120..a8a1641d2a 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -100,6 +100,7 @@ New Features * Updated RSS hash type configuration. * Added support for the SP560 NIC. * Added device parameters for runtime configuration. + * Added a compact CQE receive data path. * **Updated Intel iavf driver.** diff --git a/drivers/net/hinic3/base/hinic3_nic_cfg.h b/drivers/net/hinic3/base/hinic3_nic_cfg.h index 0de8179c19..21ea74e44d 100644 --- a/drivers/net/hinic3/base/hinic3_nic_cfg.h +++ b/drivers/net/hinic3/base/hinic3_nic_cfg.h @@ -63,6 +63,8 @@ ((hinic3_get_driver_feature(dev) & NIC_F_##feature) != 0) #define HINIC3_SUPPORT_RX_HW_COMPACT_CQE(dev) \ HINIC3_SUPPORT_FEATURE(dev, RX_HW_COMPACT_CQE) +#define HINIC3_SUPPORT_RX_SW_COMPACT_CQE(dev) \ + HINIC3_SUPPORT_FEATURE(dev, RX_SW_COMPACT_CQE) #define HINIC3_SUPPORT_TX_WQE_COMPACT_TASK(dev) \ HINIC3_SUPPORT_FEATURE(dev, TX_WQE_COMPACT_TASK) #define HINIC3_SUPPORT_VXLAN_OFFLOAD(dev) \ diff --git a/drivers/net/hinic3/hinic3_ethdev.c b/drivers/net/hinic3/hinic3_ethdev.c index e5749ec718..b272d42007 100644 --- a/drivers/net/hinic3/hinic3_ethdev.c +++ b/drivers/net/hinic3/hinic3_ethdev.c @@ -1162,11 +1162,13 @@ hinic3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t qid, uint16_t nb_desc, nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); - /* Queue depth must be equal to queue 0 */ - if (qid != 0 && nb_desc != nic_dev->rxqs[0]->q_depth) { - PMD_DRV_LOG(WARNING, "rxq%u depth:%u is not equal to queue0 depth:%u.", - qid, nb_desc, nic_dev->rxqs[0]->q_depth); - nb_desc = nic_dev->rxqs[0]->q_depth; + /* Queue depth must be equal to first queue */ + if (nic_dev->rxq_depth == 0) { + nic_dev->rxq_depth = nb_desc; + } else if (nb_desc != nic_dev->rxq_depth) { + PMD_DRV_LOG(WARNING, "rxq%u depth:%u is not equal to first queue depth:%u.", + qid, nb_desc, nic_dev->rxq_depth); + nb_desc = nic_dev->rxq_depth; } /* Queue depth must be power of 2, otherwise will be aligned up. */ @@ -1229,6 +1231,7 @@ hinic3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t qid, uint16_t nb_desc, rxq->port_id = dev->data->port_id; rxq->wait_time_cycle = HINIC3_RX_WAIT_CYCLE_THRESH; rxq->rx_deferred_start = rx_conf->rx_deferred_start; + rxq->rx_empty_loop = nic_dev->config.rx_empty_loop; /* If buf_len used for function table, need to translated. */ rx_buf_size = rte_pktmbuf_data_room_size(rxq->mb_pool) - RTE_PKTMBUF_HEADROOM; err = hinic3_convert_rx_buf_size(rx_buf_size, &buf_size); @@ -1239,7 +1242,7 @@ hinic3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t qid, uint16_t nb_desc, } /* If NIC support compact CQE, use compact wqe as default. */ - if (HINIC3_SUPPORT_RX_HW_COMPACT_CQE(nic_dev)) { + if (nic_dev->config.rx_cqe_compact_en) { rxq->wqe_type = HINIC3_COMPACT_RQ_WQE; } else { if (buf_size >= HINIC3_RX_BUF_SIZE_4K && @@ -1299,7 +1302,7 @@ hinic3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t qid, uint16_t nb_desc, goto alloc_rx_info_fail; } - if (HINIC3_SUPPORT_RX_HW_COMPACT_CQE(nic_dev)) { + if (nic_dev->config.rx_cqe_compact_en) { ci_mz = hinic3_dma_zone_reserve(dev, "hinic3_ci_mz", qid, sizeof(*rxq->rq_ci), RTE_CACHE_LINE_SIZE, (int)socket_id); @@ -1351,6 +1354,7 @@ hinic3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t qid, uint16_t nb_desc, hinic3_memzone_free(rxq->rq_mz); alloc_rq_mz_fail: + rxq->db_addr = NULL; alloc_db_err_fail: hinic3_memzone_free(rxq->pi_mz); @@ -1536,7 +1540,7 @@ hinic3_rx_queue_release(struct rte_eth_dev *dev, uint16_t queue_id) hinic3_free_rxq_mbufs(rxq); - if (HINIC3_SUPPORT_RX_HW_COMPACT_CQE(nic_dev)) + if (nic_dev->config.rx_cqe_compact_en) hinic3_memzone_free(rxq->ci_mz); else hinic3_memzone_free(rxq->cqe_mz); @@ -1699,6 +1703,9 @@ hinic3_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id) if (!rte_intr_dp_is_en(intr_handle) || !intr_handle->intr_vec) return 0; + if (HINIC3_IS_SP230_NIC(nic_dev) && !dev->data->dev_conf.intr_conf.rxq) + return 0; + msix_intr = (uint16_t)intr_handle->intr_vec[queue_id]; hinic3_set_msix_auto_mask_state(nic_dev->hwdev, msix_intr, HINIC3_SET_MSIX_AUTO_MASK); @@ -2003,7 +2010,8 @@ hinic3_init_rxq_intr(struct rte_eth_dev *dev) intr_handle = dev->intr_handle; nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); - if (!dev->data->dev_conf.intr_conf.rxq) + + if (!HINIC3_IS_SP230_NIC(nic_dev) && !dev->data->dev_conf.intr_conf.rxq) return 0; if (!rte_intr_cap_multiple(intr_handle)) { @@ -2289,6 +2297,8 @@ hinic3_dev_stop(struct rte_eth_dev *dev) /* Free mempool. */ hinic3_copy_mempool_uninit(nic_dev); + + nic_dev->rxq_depth = 0; return 0; } @@ -2326,6 +2336,8 @@ hinic3_dev_release(struct rte_eth_dev *eth_dev) rte_free(nic_dev->hwdev); nic_dev->hwdev = NULL; + rte_free(nic_dev->ptype_tbl); + nic_dev->ptype_tbl = NULL; } /** @@ -3300,6 +3312,32 @@ hinic3_dev_xstats_get_names(struct rte_eth_dev *dev, return count; } +static const uint32_t * +hinic3_dev_supported_ptypes_get(__rte_unused struct rte_eth_dev *dev, size_t *no_of_elements) +{ + static const uint32_t ptypes[] = { + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, + RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, + RTE_PTYPE_L4_TCP, + RTE_PTYPE_L4_UDP, + RTE_PTYPE_L4_SCTP, + RTE_PTYPE_L4_NONFRAG, + RTE_PTYPE_TUNNEL_IP, + RTE_PTYPE_TUNNEL_GRE, + RTE_PTYPE_TUNNEL_VXLAN, + RTE_PTYPE_TUNNEL_VXLAN_GPE, + RTE_PTYPE_TUNNEL_GENEVE, + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN, + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN, + RTE_PTYPE_INNER_L4_TCP, + RTE_PTYPE_INNER_L4_UDP, + RTE_PTYPE_INNER_L4_SCTP, + RTE_PTYPE_INNER_L4_NONFRAG, + }; + *no_of_elements = RTE_DIM(ptypes); + return ptypes; +} + static void hinic3_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, struct rte_eth_rxq_info *qinfo) @@ -3611,6 +3649,7 @@ hinic3_fec_capability_get(struct rte_eth_dev *dev, static const struct eth_dev_ops hinic3_pmd_ops = { .dev_configure = hinic3_dev_configure, .dev_infos_get = hinic3_dev_infos_get, + .dev_supported_ptypes_get = hinic3_dev_supported_ptypes_get, .fw_version_get = hinic3_fw_version_get, .dev_set_link_up = hinic3_dev_set_link_up, .dev_set_link_down = hinic3_dev_set_link_down, @@ -3662,6 +3701,7 @@ static const struct eth_dev_ops hinic3_pmd_ops = { static const struct eth_dev_ops hinic3_pmd_vf_ops = { .dev_configure = hinic3_dev_configure, .dev_infos_get = hinic3_dev_infos_get, + .dev_supported_ptypes_get = hinic3_dev_supported_ptypes_get, .fw_version_get = hinic3_fw_version_get, .dev_set_link_up = hinic3_dev_set_link_up, .dev_set_link_down = hinic3_dev_set_link_down, @@ -3713,16 +3753,6 @@ static void hinic3_nic_tx_rx_ops_init(struct hinic3_nic_dev *nic_dev) nic_dev->tx_ops->nic_tx_set_wqe_offload = hinic3_tx_set_compact_task_offload; else nic_dev->tx_ops->nic_tx_set_wqe_offload = hinic3_tx_set_normal_task_offload; - - if (HINIC3_SUPPORT_RX_HW_COMPACT_CQE(nic_dev)) { - nic_dev->rx_ops->nic_rx_get_cqe_info = hinic3_rx_get_compact_cqe_info; - nic_dev->rx_ops->nic_rx_cqe_done = hinic3_rx_integrated_cqe_done; - nic_dev->rx_ops->nic_rx_poll_rq_empty = hinic3_poll_integrated_cqe_rq_empty; - } else { - nic_dev->rx_ops->nic_rx_get_cqe_info = hinic3_rx_get_cqe_info; - nic_dev->rx_ops->nic_rx_cqe_done = hinic3_rx_separate_cqe_done; - nic_dev->rx_ops->nic_rx_poll_rq_empty = hinic3_poll_rq_empty; - } } /** @@ -3774,13 +3804,6 @@ hinic3_func_init(struct rte_eth_dev *eth_dev) goto alloc_eth_addr_fail; } - nic_dev->rx_ops = rte_zmalloc("rx_ops", sizeof(struct hinic3_nic_rx_ops), 0); - if (!nic_dev->rx_ops) { - PMD_DRV_LOG(ERR, "Allocate rx_ops memory failed"); - err = -ENOMEM; - goto alloc_rx_ops_fail; - } - nic_dev->tx_ops = rte_zmalloc("tx_ops", sizeof(struct hinic3_nic_tx_ops), 0); if (!nic_dev->tx_ops) { PMD_DRV_LOG(ERR, "Allocate tx_ops memory failed"); @@ -3891,6 +3914,11 @@ hinic3_func_init(struct rte_eth_dev *eth_dev) eth_dev->data->name); goto enable_intr_fail; } + + err = hinic3_init_rx_ptype_table(eth_dev); + if (err) + PMD_DRV_LOG(ERR, "Failed to create ptype_table."); + tcam_info = &nic_dev->tcam; memset(tcam_info, 0, sizeof(struct hinic3_tcam_info)); TAILQ_INIT(&tcam_info->tcam_list); @@ -3944,10 +3972,6 @@ hinic3_func_init(struct rte_eth_dev *eth_dev) nic_dev->tx_ops = NULL; alloc_tx_ops_fail: - rte_free(nic_dev->rx_ops); - nic_dev->rx_ops = NULL; - -alloc_rx_ops_fail: rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; @@ -4043,6 +4067,19 @@ hinic3_nic_common_config_get(struct rte_pci_device *pci_dev, return ret; } +static void hinic3_nic_feature_init(struct hinic3_nic_dev *nic_dev) +{ + if ((HINIC3_SUPPORT_RX_HW_COMPACT_CQE(nic_dev) || + HINIC3_SUPPORT_RX_SW_COMPACT_CQE(nic_dev)) && + nic_dev->config.rx_cqe_compact_en == HINIC3_RX_CQE_COMPACT_EN) { + nic_dev->config.rx_cqe_compact_en = HINIC3_RX_CQE_COMPACT_EN; + PMD_DRV_LOG(INFO, "nic compact_cqe is on."); + } else { + nic_dev->config.rx_cqe_compact_en = 0; + PMD_DRV_LOG(INFO, "nic compact_cqe is off."); + } +} + static int hinic3_dev_init(struct rte_eth_dev *eth_dev) { @@ -4072,7 +4109,13 @@ hinic3_dev_init(struct rte_eth_dev *eth_dev) return err; } - eth_dev->rx_pkt_burst = hinic3_recv_pkts; + hinic3_nic_feature_init(nic_dev); + + if (nic_dev->config.rx_cqe_compact_en != HINIC3_RX_CQE_COMPACT_EN) + eth_dev->rx_pkt_burst = hinic3_recv_pkts; + else + eth_dev->rx_pkt_burst = hinic3_recv_pkts_compact_cqe; + eth_dev->tx_pkt_burst = hinic3_xmit_pkts; return err; diff --git a/drivers/net/hinic3/hinic3_ethdev.h b/drivers/net/hinic3/hinic3_ethdev.h index 8191564fb8..41f6738645 100644 --- a/drivers/net/hinic3/hinic3_ethdev.h +++ b/drivers/net/hinic3/hinic3_ethdev.h @@ -117,6 +117,11 @@ enum nic_feature_cap { TAILQ_HEAD(hinic3_ethertype_filter_list, rte_flow); TAILQ_HEAD(hinic3_fdir_rule_filter_list, rte_flow); +#define HINIC3_PTYPE_NUM 4096 +struct hinic3_ptype_table { + alignas(RTE_CACHE_LINE_SIZE) uint32_t ptype[HINIC3_PTYPE_NUM]; +}; + struct hinic3_nic_common_dev_config { unsigned int rx_empty_threshold; /**< consecutive empty RX polls; skip RX if exceeded */ unsigned int rx_empty_loop; /**< max empty CQE spin count; 0 = no limit */ @@ -146,6 +151,7 @@ struct hinic3_nic_dev { uint16_t max_sqs; uint16_t max_rqs; + uint16_t rxq_depth; uint16_t rx_buff_len; uint16_t mtu_size; @@ -182,7 +188,7 @@ struct hinic3_nic_dev { struct hinic3_ethertype_filter_list filter_ethertype_list; struct hinic3_fdir_rule_filter_list filter_fdir_rule_list; uint8_t cos_map[HINIC3_COS_NUM_MAX]; - struct hinic3_nic_rx_ops *rx_ops; + struct hinic3_ptype_table *ptype_tbl; struct hinic3_nic_tx_ops *tx_ops; uint32_t fec_mode; /**< Current FEC mode for ethdev. */ enum nic_type nic_type; /**< NIC type. */ diff --git a/drivers/net/hinic3/hinic3_rx.c b/drivers/net/hinic3/hinic3_rx.c index 493855b431..fdf41a62ea 100644 --- a/drivers/net/hinic3/hinic3_rx.c +++ b/drivers/net/hinic3/hinic3_rx.c @@ -1,16 +1,248 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2025 Huawei Technologies Co., Ltd */ +#include <rte_ether.h> +#include <rte_mbuf.h> #include "base/hinic3_compat.h" #include "base/hinic3_hwif.h" #include "base/hinic3_hwdev.h" #include "base/hinic3_wq.h" +#include "base/hinic3_mgmt.h" #include "base/hinic3_nic_cfg.h" #include "hinic3_nic_io.h" #include "hinic3_ethdev.h" +#include "hinic3_tx.h" #include "hinic3_rx.h" +static uint32_t +hinic3_get_l3_ptype(uint32_t ip_type) +{ + uint32_t ptype = 0; + if (ip_type == IPSU_METADATA_L3_TP_IPV4) + ptype |= RTE_PTYPE_L3_IPV4_EXT_UNKNOWN; + else if (ip_type == IPSU_METADATA_L3_TP_IPV6) + ptype |= RTE_PTYPE_L3_IPV6_EXT_UNKNOWN; + return ptype; +} +static uint32_t +hinic3_get_l4_ptype(uint32_t packet_type) +{ + int ptype = 0; + switch (packet_type) { + case IPSU_PKT_TYPE_NULL: + break; + case IPSU_PKT_TYPE_TCP: + ptype |= RTE_PTYPE_L4_TCP; + break; + case IPSU_PKT_TYPE_UDP: + ptype |= RTE_PTYPE_L4_UDP; + break; + case IPSU_PKT_TYPE_IPV4_FRAG: + ptype |= RTE_PTYPE_L4_FRAG; + break; + case IPSU_PKT_TYPE_SCTP: + ptype |= RTE_PTYPE_L4_SCTP; + break; + case IPSU_PKT_TYPE_ICMP: + ptype |= RTE_PTYPE_L4_ICMP; + break; + case IPSU_PKT_TYPE_IGMP: + ptype |= RTE_PTYPE_L4_IGMP; + break; + case IPSU_PKT_TYPE_ESP_OVER_IP: + ptype |= RTE_PTYPE_L4_ESP; + break; + default: + ptype |= RTE_PTYPE_L4_NONFRAG; + } + return ptype; +} + +/** + * Calculate the ptype value of given offload type. + * + * @param[in] offload_type + * The offload of Packet + * @return + * Ptype value + */ +static uint32_t +hinic3_calc_rx_ptype_table(uint32_t offload_type, struct hinic3_nic_dev *nic_dev) +{ + uint32_t packet_type, ip_type, enc_l3_type, pkt_fmt; + uint32_t ptype = RTE_PTYPE_UNKNOWN; + + packet_type = HINIC3_GET_RX_PKT_TYPE(offload_type); + ip_type = HINIC3_GET_RX_IP_TYPE(offload_type); + enc_l3_type = HINIC3_GET_RX_ENC_L3_TYPE(offload_type); + pkt_fmt = HINIC3_GET_RX_PKT_FORMAT(offload_type); + + switch (pkt_fmt) { + case IPSU_METADATA_FMT_NO_ENC: + ptype |= RTE_PTYPE_L2_ETHER; + ptype |= hinic3_get_l3_ptype(ip_type); + ptype |= hinic3_get_l4_ptype(packet_type); + break; + case IPSU_METADATA_FMT_FC: + ptype |= RTE_PTYPE_L2_ETHER_FCOE; + break; + case IPSU_METADATA_FMT_NSH: + ptype |= RTE_PTYPE_L2_ETHER_NSH; + break; + /* IPinIP */ + case IPSU_METADATA_FMT_IPIP: + ptype |= RTE_PTYPE_L2_ETHER; + ptype |= RTE_PTYPE_TUNNEL_IP; + if (!(nic_dev->feature_cap & NIC_F_TX_WQE_COMPACT_TASK)) { + ptype |= hinic3_get_l3_ptype(ip_type); + } else { + ptype |= hinic3_get_l3_ptype(enc_l3_type); + ptype |= hinic3_get_l4_ptype(packet_type) << HINIC3_L4_PYTPE_SHIFT; + if (ip_type == IPSU_METADATA_L3_TP_IPV4) + ptype |= RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN; + else if (ip_type == IPSU_METADATA_L3_TP_IPV6) + ptype |= RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN; + } + break; + default: + /* VXLAN ãNVGRE ãVXLAN_GPE ãGENEVE*/ + ptype |= RTE_PTYPE_L2_ETHER; + ptype |= hinic3_get_l3_ptype(enc_l3_type); + + switch (pkt_fmt) { + case IPSU_METADATA_FMT_VXLAN: + ptype |= RTE_PTYPE_L4_UDP; + ptype |= RTE_PTYPE_TUNNEL_VXLAN; + ptype |= RTE_PTYPE_INNER_L2_ETHER; + break; + case IPSU_METADATA_FMT_NVGRE: + ptype |= RTE_PTYPE_TUNNEL_GRE; + if (!HINIC3_IS_SP560_NIC(nic_dev)) + return ptype; + break; + case IPSU_METADATA_FMT_GPE: + ptype |= RTE_PTYPE_L4_UDP; + ptype |= RTE_PTYPE_TUNNEL_VXLAN_GPE; + break; + case IPSU_METADATA_FMT_GENEVE: + ptype |= RTE_PTYPE_L4_UDP; + ptype |= RTE_PTYPE_TUNNEL_GENEVE; + ptype |= RTE_PTYPE_INNER_L2_ETHER; + break; + default: + ptype |= RTE_PTYPE_L4_NONFRAG; + break; + } + if (ip_type == IPSU_METADATA_L3_TP_IPV4) + ptype |= RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN; + else if (ip_type == IPSU_METADATA_L3_TP_IPV6) + ptype |= RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN; + else + return ptype; + /* shift ptype to inner*/ + ptype |= hinic3_get_l4_ptype(packet_type) << HINIC3_L4_PYTPE_SHIFT; + } + return ptype; +} + +static uint32_t +hinic3_calc_rx_ptype_compact_table(uint32_t offload_type) +{ + uint32_t packet_type, ip_type, pkt_fmt; + uint32_t ptype = RTE_PTYPE_UNKNOWN; + + pkt_fmt = HINIC3_RQ_COMPACT_CQE_STATUS_GET(offload_type << HINIC3_COMPACT_CQE_PTYPE_SHIFT, + PKT_FORMAT); + ip_type = HINIC3_RQ_COMPACT_CQE_STATUS_GET(offload_type << HINIC3_COMPACT_CQE_PTYPE_SHIFT, + IP_TYPE); + packet_type = HINIC3_RQ_COMPACT_CQE_STATUS_GET(offload_type << + HINIC3_COMPACT_CQE_PTYPE_SHIFT, + PKT_TYPE); + + switch (pkt_fmt) { + case IPSU_METADATA_FMT_NO_ENC: + ptype |= RTE_PTYPE_L2_ETHER; + ptype |= hinic3_get_l3_ptype(ip_type); + ptype |= hinic3_get_l4_ptype(packet_type); + break; + case IPSU_METADATA_FMT_FC: + ptype |= RTE_PTYPE_L2_ETHER_FCOE; + break; + case IPSU_METADATA_FMT_NSH: + ptype |= RTE_PTYPE_L2_ETHER_NSH; + break; + default: + /* VXLAN ãNVGRE ãVXLAN_GPE ãGENEVE ãIPinIP */ + ptype |= RTE_PTYPE_L2_ETHER; + + switch (pkt_fmt) { + case IPSU_METADATA_FMT_VXLAN: + ptype |= RTE_PTYPE_L4_UDP; + ptype |= RTE_PTYPE_TUNNEL_VXLAN; + ptype |= RTE_PTYPE_INNER_L2_ETHER; + break; + case IPSU_METADATA_FMT_NVGRE: + ptype |= RTE_PTYPE_TUNNEL_GRE; + return ptype; + case IPSU_METADATA_FMT_GENEVE: + ptype |= RTE_PTYPE_L4_UDP; + ptype |= RTE_PTYPE_TUNNEL_GENEVE; + ptype |= RTE_PTYPE_INNER_L2_ETHER; + break; + + case IPSU_METADATA_FMT_IPIP: + ptype |= RTE_PTYPE_TUNNEL_IP; + break; + default: + ptype |= RTE_PTYPE_L4_NONFRAG; + break; + } + if (ip_type == IPSU_METADATA_L3_TP_IPV4) + ptype |= RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN; + else if (ip_type == IPSU_METADATA_L3_TP_IPV6) + ptype |= RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN; + else + return ptype; + /* shift ptype to inner*/ + ptype |= hinic3_get_l4_ptype(packet_type) << HINIC3_L4_PYTPE_SHIFT; + } + return ptype; +} + +/** + * Get receive queue local ci + * + * @param[in] rxq + * Receive queue + * @return + * Receive queue local ci + */ +static inline uint16_t hinic3_get_rq_local_ci(struct hinic3_rxq *rxq) +{ + return MASKED_QUEUE_IDX(rxq, rxq->cons_idx); +} + +static inline uint16_t hinic3_get_rq_free_wqebb(struct hinic3_rxq *rxq) +{ + return rxq->delta - 1; +} + +/** + * Update receive queue local ci + * + * @param[in] rxq + * Receive queue + * @param[in] wqe_cnt + * Wqebb counters + */ +static inline void hinic3_update_rq_local_ci(struct hinic3_rxq *rxq, + uint16_t wqe_cnt) +{ + rxq->cons_idx += wqe_cnt; + rxq->delta += wqe_cnt; +} + /** * Get wqe from receive queue. * @@ -62,6 +294,13 @@ hinic3_get_rq_local_pi(struct hinic3_rxq *rxq) return MASKED_QUEUE_IDX(rxq, rxq->prod_idx); } +static inline uint16_t hinic3_get_rq_hw_ci(struct hinic3_rxq *rxq) +{ + struct hinic3_rq_ci_wb rq_ci; + rq_ci.dw1.value = hinic3_hw_cpu32(rte_read32(&rxq->rq_ci->dw1.value)); + return rq_ci.dw1.bs.hw_ci; +} + uint16_t hinic3_rx_fill_wqe(struct hinic3_rxq *rxq) { @@ -434,11 +673,11 @@ hinic3_init_rss_type(struct hinic3_nic_dev *nic_dev, rss_type.ipv4 = (rss_hf & (RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4)) ? 1 : 0; rss_type.tcp_ipv4 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) ? 1 : 0; rss_type.ipv6 = (rss_hf & (RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6)) ? 1 : 0; + rss_type.ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_EX) ? 1 : 0; rss_type.tcp_ipv6 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP) ? 1 : 0; + rss_type.tcp_ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_TCP_EX) ? 1 : 0; rss_type.udp_ipv4 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) ? 1 : 0; rss_type.udp_ipv6 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP) ? 1 : 0; - rss_type.ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_EX) ? 1 : 0; - rss_type.tcp_ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_TCP_EX) ? 1 : 0; err = hinic3_set_rss_type(nic_dev->hwdev, rss_type); nic_dev->rss_type = rss_type; @@ -503,6 +742,36 @@ hinic3_update_rss_config(struct rte_eth_dev *dev, return err; } +/** + * Initialize the receive packet type table + * @param[in] dev + * Pointer to ethernet device structure. + */ + +int +hinic3_init_rx_ptype_table(struct rte_eth_dev *dev) +{ + struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); + struct hinic3_ptype_table *tbl = + rte_zmalloc("ptype_tbl", sizeof(struct hinic3_ptype_table), 0); + + if (tbl == NULL) + return -ENOMEM; + + uint32_t *ptype = tbl->ptype; + uint32_t i; + + if (nic_dev->config.rx_cqe_compact_en) { + for (i = 0; i < HINIC3_PTYPE_NUM; i++) + ptype[i] = hinic3_calc_rx_ptype_compact_table(i); + } else { + for (i = 0; i < HINIC3_PTYPE_NUM; i++) + ptype[i] = hinic3_calc_rx_ptype_table(i, nic_dev); + } + nic_dev->ptype_tbl = tbl; + return 0; +} + /** * Search given queue array to find position of given id. * Return queue pos or queue_count if not found. @@ -599,7 +868,7 @@ hinic3_rx_queue_release_mbufs(struct hinic3_rxq *rxq) hinic3_update_rq_local_ci(rxq, nr_released); } -int +static int hinic3_poll_rq_empty(struct hinic3_rxq *rxq) { uint64_t end; @@ -620,29 +889,21 @@ hinic3_poll_rq_empty(struct hinic3_rxq *rxq) return err; } -int +static int hinic3_poll_integrated_cqe_rq_empty(struct hinic3_rxq *rxq) { struct hinic3_rx_info *rx_info; - struct hinic3_rq_ci_wb rq_ci; - uint16_t sw_ci; - uint16_t hw_ci; - uint32_t val; + uint16_t sw_ci, sw_pi, hw_ci; + uint64_t end; sw_ci = hinic3_get_rq_local_ci(rxq); - val = rte_read32(&rxq->rq_ci->dw1.value); - rq_ci.dw1.value = hinic3_hw_cpu32(val); - hw_ci = rq_ci.dw1.bs.hw_ci; + sw_pi = hinic3_get_rq_local_pi(rxq); + hw_ci = hinic3_get_rq_hw_ci(rxq); if (HINIC3_IS_SP560_NIC(rxq->nic_dev)) { - uint16_t sw_pi = hinic3_get_rq_local_pi(rxq); - uint64_t end; - end = cycles + msecs_to_cycles(HINIC3_FLUSH_QUEUE_TIMEOUT); do { - val = rte_read32(&rxq->rq_ci->dw1.value); - rq_ci.dw1.value = hinic3_hw_cpu32(val); - hw_ci = rq_ci.dw1.bs.hw_ci; + hw_ci = hinic3_get_rq_hw_ci(rxq); if (sw_pi == hw_ci) break; @@ -666,22 +927,34 @@ hinic3_poll_integrated_cqe_rq_empty(struct hinic3_rxq *rxq) return 0; } -void -hinic3_dump_cqe_status(struct hinic3_rxq *rxq, uint32_t *cqe_done_cnt, - uint32_t *cqe_hole_cnt, uint32_t *head_ci, uint32_t *head_done) +static void +hinic3_dump_cqe_status(struct hinic3_rxq *rxq) { - uint16_t sw_ci; + volatile struct hinic3_rq_cqe *rx_cqe; + uint16_t sw_ci, sw_pi, hw_ci; + uint32_t head_ci, head_done; uint16_t avail_pkts = 0; uint16_t hit_done = 0; uint16_t cqe_hole = 0; - RTE_ATOMIC(uint32_t)status; - volatile struct hinic3_rq_cqe *rx_cqe; + uint32_t status; + + if (rxq->wqe_type == HINIC3_COMPACT_RQ_WQE) { + sw_ci = hinic3_get_rq_local_ci(rxq); + sw_pi = hinic3_get_rq_local_pi(rxq); + hw_ci = hinic3_get_rq_hw_ci(rxq); + PMD_DRV_LOG(ERR, + "Poll rq empty timeout, eth_dev:%s, queue_idx:%d, mbuf_left:%d, sw_pi:%d, sw_ci:%d, hw_ci:%d", + rxq->nic_dev->dev_name, rxq->q_id, + rxq->q_depth - hinic3_get_rq_free_wqebb(rxq), + sw_pi, sw_ci, hw_ci); + return; + } sw_ci = hinic3_get_rq_local_ci(rxq); rx_cqe = &rxq->rx_cqe[sw_ci]; status = rx_cqe->status; - *head_done = HINIC3_GET_RX_DONE(status); - *head_ci = sw_ci; + head_done = HINIC3_GET_RX_DONE(status); + head_ci = sw_ci; for (sw_ci = 0; sw_ci < rxq->q_depth; sw_ci++) { rx_cqe = &rxq->rx_cqe[sw_ci]; @@ -702,17 +975,17 @@ hinic3_dump_cqe_status(struct hinic3_rxq *rxq, uint32_t *cqe_done_cnt, hit_done = 1; } - *cqe_done_cnt = avail_pkts; - *cqe_hole_cnt = cqe_hole; + PMD_DRV_LOG(ERR, "Poll rq empty timeout, eth_dev:%s, queue_idx:%d, " + "mbuf_left:%d, cqe_done:%d, cqe_hole:%d, cqe[%d].done=%d", + rxq->nic_dev->dev_name, rxq->q_id, + rxq->q_depth - hinic3_get_rq_free_wqebb(rxq), + avail_pkts, cqe_hole, head_ci, head_done); } int hinic3_stop_rq(struct rte_eth_dev *eth_dev, struct hinic3_rxq *rxq) { struct hinic3_nic_dev *nic_dev = rxq->nic_dev; - uint32_t cqe_done_cnt = 0; - uint32_t cqe_hole_cnt = 0; - uint32_t head_ci, head_done; int err; /* Disable rxq intr. */ @@ -759,23 +1032,21 @@ hinic3_stop_rq(struct rte_eth_dev *eth_dev, struct hinic3_rxq *rxq) goto rq_flush_failed; } - err = nic_dev->rx_ops->nic_rx_poll_rq_empty(rxq); + if (nic_dev->config.rx_cqe_compact_en) + err = hinic3_poll_integrated_cqe_rq_empty(rxq); + else + err = hinic3_poll_rq_empty(rxq); + if (err) { - hinic3_dump_cqe_status(rxq, &cqe_done_cnt, &cqe_hole_cnt, - &head_ci, &head_done); - PMD_DRV_LOG(ERR, "Poll rq empty timeout"); - PMD_DRV_LOG(ERR, - "eth_dev:%s, queue_idx:%d, mbuf_left:%d, cqe_done:%d, cqe_hole:%d, cqe[%d].done=%d", - nic_dev->dev_name, rxq->q_id, - rxq->q_depth - hinic3_get_rq_free_wqebb(rxq), - cqe_done_cnt, cqe_hole_cnt, head_ci, head_done); + hinic3_dump_cqe_status(rxq); goto poll_rq_failed; } return 0; poll_rq_failed: - hinic3_set_rq_enable(nic_dev, rxq->q_id, true); + if ((hinic3_get_driver_feature(nic_dev) & NIC_F_HTN_FDIR) != 0) + (void)hinic3_set_rq_enable(nic_dev, rxq->q_id, true); rq_flush_failed: rte_spinlock_lock(&nic_dev->queue_list_lock); set_indir_failed: @@ -947,6 +1218,8 @@ hinic3_start_all_rqs(struct rte_eth_dev *eth_dev) for (i = 0; i < nic_dev->num_rqs; i++) { rxq = eth_dev->data->rx_queues[i]; + if (rxq == NULL) + break; hinic3_add_rq_to_rx_queue_list(nic_dev, rxq->q_id); err = hinic3_rearm_rxq_mbuf(rxq); if (err) { @@ -975,6 +1248,8 @@ hinic3_start_all_rqs(struct rte_eth_dev *eth_dev) out: for (i = 0; i < nic_dev->num_rqs; i++) { rxq = eth_dev->data->rx_queues[i]; + if (rxq == NULL) + continue; hinic3_remove_rq_from_rx_queue_list(nic_dev, rxq->q_id); hinic3_free_rxq_mbufs(rxq); hinic3_dev_rx_queue_intr_disable(eth_dev, rxq->q_id); @@ -982,38 +1257,14 @@ hinic3_start_all_rqs(struct rte_eth_dev *eth_dev) } return err; } - -bool -hinic3_rx_separate_cqe_done(struct hinic3_rxq *rxq, volatile struct hinic3_rq_cqe **rx_cqe) -{ - volatile struct hinic3_rq_cqe *cqe = NULL; - uint16_t sw_ci; - uint32_t status; - - sw_ci = hinic3_get_rq_local_ci(rxq); - *rx_cqe = &rxq->rx_cqe[sw_ci]; - cqe = *rx_cqe; - - status = hinic3_hw_cpu32((uint32_t)(rte_atomic_load_explicit(&cqe->status, - rte_memory_order_acquire))); - if (!HINIC3_GET_RX_DONE(status)) - return false; - - return true; -} - -bool +static bool hinic3_rx_integrated_cqe_done(struct hinic3_rxq *rxq, volatile struct hinic3_rq_cqe **rx_cqe) { - struct hinic3_rq_ci_wb rq_ci; struct rte_mbuf *rxm = NULL; uint16_t sw_ci, hw_ci; - uint32_t val; sw_ci = hinic3_get_rq_local_ci(rxq); - val = rte_read32(&rxq->rq_ci->dw1.value); - rq_ci.dw1.value = hinic3_hw_cpu32(val); - hw_ci = rq_ci.dw1.bs.hw_ci; + hw_ci = hinic3_get_rq_hw_ci(rxq); if (hw_ci == sw_ci) return false; @@ -1025,28 +1276,7 @@ hinic3_rx_integrated_cqe_done(struct hinic3_rxq *rxq, volatile struct hinic3_rq_ return true; } -void -hinic3_rx_get_cqe_info(struct hinic3_rxq *rxq __rte_unused, volatile struct hinic3_rq_cqe *rx_cqe, - struct hinic3_cqe_info *cqe_info) -{ - uint32_t dw0 = hinic3_hw_cpu32(rx_cqe->status); - uint32_t dw1 = hinic3_hw_cpu32(rx_cqe->vlan_len); - uint32_t dw2 = hinic3_hw_cpu32(rx_cqe->offload_type); - uint32_t dw3 = hinic3_hw_cpu32(rx_cqe->hash_val); - - cqe_info->lro_num = RQ_CQE_STATUS_GET(dw0, NUM_LRO); - cqe_info->csum_err = RQ_CQE_STATUS_GET(dw0, CSUM_ERR); - - cqe_info->pkt_len = RQ_CQE_SGE_GET(dw1, LEN); - cqe_info->vlan_tag = RQ_CQE_SGE_GET(dw1, VLAN); - - cqe_info->ptype = HINIC3_GET_RX_PTYPE_OFFLOAD(dw0); - cqe_info->vlan_offload = RQ_CQE_OFFOLAD_TYPE_GET(dw2, VLAN_EN); - cqe_info->rss_type = RQ_CQE_OFFOLAD_TYPE_GET(dw2, RSS_TYPE); - cqe_info->rss_hash_value = dw3; -} - -void +static void hinic3_rx_get_compact_cqe_info(struct hinic3_rxq *rxq, volatile struct hinic3_rq_cqe *rx_cqe, struct hinic3_cqe_info *cqe_info) { @@ -1072,7 +1302,16 @@ hinic3_rx_get_compact_cqe_info(struct hinic3_rxq *rxq, volatile struct hinic3_rq cqe_info->ptype = HINIC3_RQ_COMPACT_CQE_STATUS_GET(dw0, PTYPE); cqe_info->rss_type = (rxq->nic_dev->rss_type.val != 0) ? 1 : 0; cqe_info->rss_hash_value = dw1; - + switch (cqe_info->csum_err) { + case HINIC3_RX_COMPACT_CSUM_OTHER_ERROR: + cqe_info->csum_err = HINIC3_RX_CSUM_IPSU_OTHER_ERR; + break; + case HINIC3_RX_COMPACT_HW_BYPASS_ERROR: + cqe_info->csum_err = HINIC3_RX_CSUM_HW_CHECK_NONE; + break; + default: + break; + } if (cqe_info->cqe_len == HINIC3_RQ_COMPACT_CQE_16BYTE) { cqe_info->lro_num = HINIC3_RQ_COMPACT_CQE_OFFLOAD_GET(dw2, NUM_LRO); cqe_info->vlan_tag = HINIC3_RQ_COMPACT_CQE_OFFLOAD_GET(dw2, VLAN); @@ -1083,12 +1322,12 @@ hinic3_rx_get_compact_cqe_info(struct hinic3_rxq *rxq, volatile struct hinic3_rq (cqe_info->cqe_len == HINIC3_RQ_COMPACT_CQE_16BYTE) ? 16 : 8; } -#define HINIC3_RX_EMPTY_THRESHOLD 3 uint16_t -hinic3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) +hinic3_recv_pkts_compact_cqe(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct hinic3_rxq *rxq = rx_queue; struct hinic3_nic_dev *nic_dev = rxq->nic_dev; + const struct hinic3_ptype_table * const ptype_tbl = nic_dev->ptype_tbl; struct hinic3_rx_info *rx_info = NULL; volatile struct hinic3_rq_cqe *rx_cqe = NULL; struct hinic3_cqe_info cqe_info = {0}; @@ -1102,19 +1341,18 @@ hinic3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) uint64_t t2; #endif if (((rte_get_timer_cycles() - rxq->rxq_stats.tsc) < rxq->wait_time_cycle) && - rxq->rxq_stats.empty >= HINIC3_RX_EMPTY_THRESHOLD) + rxq->rxq_stats.empty >= nic_dev->config.rx_empty_threshold) goto out; sw_ci = hinic3_get_rq_local_ci(rxq); while (pkts < nb_pkts) { - rx_cqe = &rxq->rx_cqe[sw_ci]; - if (!nic_dev->rx_ops->nic_rx_cqe_done(rxq, &rx_cqe)) { + if (!hinic3_rx_integrated_cqe_done(rxq, &rx_cqe)) { rxq->rxq_stats.empty++; break; } - nic_dev->rx_ops->nic_rx_get_cqe_info(rxq, rx_cqe, &cqe_info); + hinic3_rx_get_compact_cqe_info(rxq, rx_cqe, &cqe_info); pkt_len = cqe_info.pkt_len; /* @@ -1160,8 +1398,9 @@ hinic3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) /* 5. Vlan offload. */ rxm->ol_flags |= hinic3_rx_vlan(cqe_info.vlan_offload, cqe_info.vlan_tag, &rxm->vlan_tci); - - /* 6. RSS. */ + /* 6. Packet ptype */ + rxm->packet_type = ptype_tbl->ptype[cqe_info.ptype]; + /* 7. RSS. */ rxm->ol_flags |= hinic3_rx_rss_hash(cqe_info.rss_type, cqe_info.rss_hash_value, &rxm->hash.rss); /* 8. LRO. */ @@ -1201,3 +1440,144 @@ hinic3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) return pkts; } + +uint16_t hinic3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) +{ + struct hinic3_rxq *rxq = rx_queue; + struct hinic3_nic_dev *nic_dev = rxq->nic_dev; + struct hinic3_rx_info *rx_info = NULL; + volatile struct hinic3_rq_cqe *rx_cqe = NULL; + struct rte_mbuf *rxm = NULL; + uint16_t sw_ci, rx_buf_len, wqebb_cnt = 0, pkts = 0; + uint32_t status, pkt_len, vlan_len, offload_type, pkt_type, lro_num; + uint64_t rx_bytes = 0; + uint32_t hash_value = 0; + uint32_t empty_nb = 0; + const struct hinic3_ptype_table * const ptype_tbl = nic_dev->ptype_tbl; + +#ifdef HINIC3_XSTAT_PROF_RX + uint64_t t1 = rte_get_tsc_cycles(); + uint64_t t2; +#endif + if (((rte_get_timer_cycles() - rxq->rxq_stats.tsc) < rxq->wait_time_cycle) && + rxq->rxq_stats.empty >= nic_dev->config.rx_empty_threshold) + goto out; + + sw_ci = hinic3_get_rq_local_ci(rxq); + rx_buf_len = rxq->buf_len; + + while (pkts < nb_pkts) { + rx_cqe = &rxq->rx_cqe[sw_ci]; + status = hinic3_hw_cpu32((uint32_t)(rte_atomic_load_explicit(&rx_cqe->status, + rte_memory_order_acquire))); + if (!HINIC3_GET_RX_DONE(status)) { + rxq->rxq_stats.empty++; + if (empty_nb++ >= rxq->rx_empty_loop) + break; + continue; + } + + vlan_len = hinic3_hw_cpu32(rx_cqe->vlan_len); + + pkt_len = HINIC3_GET_RX_PKT_LEN(vlan_len); + + rx_info = &rxq->rx_info[sw_ci]; + rxm = rx_info->mbuf; + + /* 1. Next ci point and prefetch */ + sw_ci++; + sw_ci &= rxq->q_mask; + + /* 2. Prefetch next mbuf first 64B */ + rte_prefetch0(rxq->rx_info[sw_ci].mbuf); + + /* 3. Jumbo frame process */ + + if (likely(pkt_len <= (uint32_t)rx_buf_len)) { + rxm->data_len = (uint16_t)pkt_len; + rxm->pkt_len = pkt_len; + wqebb_cnt++; + } else { + rxm->data_len = rx_buf_len; + rxm->pkt_len = rx_buf_len; + + /* If receive jumbo, updating ci will be done by + * hinic3_recv_jumbo_pkt function. + */ + hinic3_update_rq_local_ci(rxq, wqebb_cnt + 1); + wqebb_cnt = 0; + hinic3_recv_jumbo_pkt(rxq, rxm, pkt_len - rx_buf_len); + sw_ci = hinic3_get_rq_local_ci(rxq); + } + + + /* + * data_off was already set by rearm to the offset of the DMA + * start address relative to buf (HEADROOM + alignment offset + * when alignment is enabled, HEADROOM when disabled). The packet + * data starts at buf + data_off, so no further adjustment is + * needed. + */ + rxm->port = rxq->port_id; + + /* 4. Rx checksum offload */ + rxm->ol_flags |= hinic3_rx_csum(HINIC3_GET_RX_CSUM_ERR(status), rxq); + + /* 5. Vlan offload */ + offload_type = hinic3_hw_cpu32(rx_cqe->offload_type); + + rxm->ol_flags |= hinic3_rx_vlan(HINIC3_GET_RX_VLAN_OFFLOAD_EN(offload_type), + HINIC3_GET_RX_VLAN_TAG(vlan_len), + &rxm->vlan_tci); + + /* 6. Packet ptype */ + pkt_type = HINIC3_GET_RX_PTYPE_OFFLOAD(offload_type); + rxm->packet_type = ptype_tbl->ptype[pkt_type]; + + /* 7. RSS */ + hash_value = hinic3_hw_cpu32(rx_cqe->hash_val); + rxm->ol_flags |= hinic3_rx_rss_hash(HINIC3_GET_RSS_TYPES(offload_type), + hash_value, + &rxm->hash.rss); + + /* 8. LRO */ + lro_num = HINIC3_GET_RX_NUM_LRO(status); + if (unlikely(lro_num != 0)) { + rxm->ol_flags |= HINIC3_PKT_RX_LRO; + rxm->tso_segsz = pkt_len / lro_num; + } + + rx_cqe->status = 0; + + rx_bytes += pkt_len; + rx_pkts[pkts++] = rxm; + } + + if (pkts) { + /* 9. Update local ci */ + hinic3_update_rq_local_ci(rxq, wqebb_cnt); + + /* Update packet stats */ + rxq->rxq_stats.packets += pkts; + rxq->rxq_stats.bytes += rx_bytes; + rxq->rxq_stats.empty = 0; +#ifdef HINIC3_XSTAT_MBUF_USE + rxq->rxq_stats.free_mbuf += pkts; +#endif + } + rxq->rxq_stats.burst_pkts = pkts; + rxq->rxq_stats.tsc = rte_get_timer_cycles(); +out: + /* 10. Rearm mbuf to rxq */ + hinic3_rearm_rxq_mbuf(rxq); + +#ifdef HINIC3_XSTAT_PROF_RX + /* do profiling stats */ + t2 = rte_get_tsc_cycles(); + rxq->rxq_stats.app_tsc = t1 - rxq->prof_rx_end_tsc; + rxq->prof_rx_end_tsc = t2; + rxq->rxq_stats.pmd_tsc = t2 - t1; +#endif + + return pkts; +} diff --git a/drivers/net/hinic3/hinic3_rx.h b/drivers/net/hinic3/hinic3_rx.h index 129c2b4a59..0cdfcb6e9c 100644 --- a/drivers/net/hinic3/hinic3_rx.h +++ b/drivers/net/hinic3/hinic3_rx.h @@ -5,11 +5,23 @@ #ifndef _HINIC3_RX_H_ #define _HINIC3_RX_H_ +#include "hinic3_wq.h" + #define RQ_CQE_OFFOLAD_TYPE_PTYPE_OFFLOAD_SHIFT 0 +#define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_SHIFT 0 +#define RQ_CQE_OFFOLAD_TYPE_IP_TYPE_SHIFT 5 +#define RQ_CQE_OFFOLAD_TYPE_ENC_L3_TYPE_SHIFT 7 +#define RQ_CQE_OFFOLAD_TYPE_PKT_FORMAT_SHIFT 8 +#define RQ_CQE_OFFOLAD_TYPE_PKT_UMBCAST_SHIFT 19 #define RQ_CQE_OFFOLAD_TYPE_VLAN_EN_SHIFT 21 #define RQ_CQE_OFFOLAD_TYPE_RSS_TYPE_SHIFT 24 #define RQ_CQE_OFFOLAD_TYPE_PTYPE_OFFLOAD_MASK 0xFFFU +#define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_MASK 0x1FU +#define RQ_CQE_OFFOLAD_TYPE_IP_TYPE_MASK 0x3U +#define RQ_CQE_OFFOLAD_TYPE_ENC_L3_TYPE_MASK 0X1U +#define RQ_CQE_OFFOLAD_TYPE_PKT_FORMAT_MASK 0xFU +#define RQ_CQE_OFFOLAD_TYPE_PKT_UMBCAST_MASK 0x3U #define RQ_CQE_OFFOLAD_TYPE_VLAN_EN_MASK 0x1U #define RQ_CQE_OFFOLAD_TYPE_RSS_TYPE_MASK 0xFFU @@ -25,6 +37,15 @@ #define HINIC3_GET_RX_PKT_TYPE(offload_type) \ RQ_CQE_OFFOLAD_TYPE_GET(offload_type, PKT_TYPE) +#define HINIC3_GET_RX_IP_TYPE(offload_type) \ + RQ_CQE_OFFOLAD_TYPE_GET(offload_type, IP_TYPE) + +#define HINIC3_GET_RX_ENC_L3_TYPE(offload_type) \ + RQ_CQE_OFFOLAD_TYPE_GET(offload_type, ENC_L3_TYPE) + +#define HINIC3_GET_RX_PKT_FORMAT(offload_type) \ + RQ_CQE_OFFOLAD_TYPE_GET(offload_type, PKT_FORMAT) + #define HINIC3_GET_RX_PKT_UMBCAST(offload_type) \ RQ_CQE_OFFOLAD_TYPE_GET(offload_type, PKT_UMBCAST) @@ -142,10 +163,10 @@ #define RQ_COMPACT_CQE_STATUS_CQE_TYPE_MASK 0x1U #define RQ_COMPACT_CQE_STATUS_TS_FLAG_MASK 0x1U #define RQ_COMPACT_CQE_STATUS_VLAN_EN_MASK 0x1U -#define RQ_COMPACT_CQE_STATUS_PKT_FORMAT_MASK 0x7U +#define RQ_COMPACT_CQE_STATUS_PKT_FORMAT_MASK 0x7U #define RQ_COMPACT_CQE_STATUS_IP_TYPE_MASK 0x1U #define RQ_COMPACT_CQE_STATUS_CQE_LEN_MASK 0x1U -#define RQ_COMPACT_CQE_STATUS_PKT_MC_MASK 0x1U +#define RQ_COMPACT_CQE_STATUS_PKT_MC_MASK 0x3U #define RQ_COMPACT_CQE_STATUS_CSUM_ERR_MASK 0x3U #define RQ_COMPACT_CQE_STATUS_PKT_TYPE_MASK 0x7U #define RQ_COMPACT_CQE_STATUS_PTYPE_MASK 0xFFFU @@ -182,6 +203,13 @@ #define HINIC3_RX_CSUM_HW_CHECK_NONE RTE_BIT32(7) #define HINIC3_RX_CSUM_IPSU_OTHER_ERR RTE_BIT32(8) +enum hinic3_compact_cqe_csum_err_type { + HINIC3_RX_COMPACT_CSUM_NO_ERROR = 0, + HINIC3_RX_COMPACT_L3_L4_CSUM_ERROR, + HINIC3_RX_COMPACT_CSUM_OTHER_ERROR, + HINIC3_RX_COMPACT_HW_BYPASS_ERROR +}; + #define HINIC3_DEFAULT_RX_CSUM_OFFLOAD 0xFFF #define HINIC3_CQE_LEN 32 @@ -200,6 +228,72 @@ RTE_ETH_RSS_IPV6_TCP_EX | \ RTE_ETH_RSS_IPV6_UDP_EX) +#define HINIC3_L4_PYTPE_SHIFT 16 +#define HINIC3_COMPACT_CQE_PTYPE_SHIFT 16 + +/* keep same with IPSU_METADATA_L3_TP_E */ +enum HINIC3_RX_CQE_PT_L3 { + HINIC3_RX_CQE_L3_IPV4 = 0u, + HINIC3_RX_CQE_L3_IPV6 = 1u, +}; + +/* keep same with IPSU_PKT_TYPE_L45FINAL_E */ +enum HINIC3_RX_CQE_PT_L4 { + HINIC3_RX_CQE_L4_TCP = 3, + HINIC3_RX_CQE_L4_UDP = 4, +}; + +enum IPSU_METADATA_L3_TP_E { + IPSU_METADATA_L3_TP_IPV4 = 0u, + IPSU_METADATA_L3_TP_IPV6 = 1u, +}; + +enum IPSU_PKT_TYPE_L45FINAL_E { + IPSU_PKT_TYPE_NULL = 0, + IPSU_PKT_TYPE_ROCEV2, + IPSU_PKT_TYPE_TCPCOCO, + IPSU_PKT_TYPE_TCP, + IPSU_PKT_TYPE_UDP, + IPSU_PKT_TYPE_ICMP, + IPSU_PKT_TYPE_IGMP, + IPSU_PKT_TYPE_SCTP, + IPSU_PKT_TYPE_DHCP, + IPSU_PKT_TYPE_IPV4_FRAG, + IPSU_PKT_TYPE_IPV6_MC, + IPSU_PKT_TYPE_1588, + IPSU_PKT_TYPE_AH_OVER_IP, + IPSU_PKT_TYPE_ESP_OVER_IP, + IPSU_PKT_TYPE_NATT, + IPSU_PKT_TYPE_AH_OVER_VXLAN_GPE, + IPSU_PKT_TYPE_ESP_OVER_VXLAN_GPE, + IPSU_PKT_TYPE_TSO, + IPSU_PKT_TYPE_UFO, + IPSU_PKT_TYPE_INT, + IPSU_PKT_TYPE_IOAM, + IPSU_PKT_TYPE_VXLAN_GPE, + IPSU_PKT_TYPE_GENEVE, + IPSU_PKT_TYPE_NSH_OVER_GENEVE, + IPSU_PKT_TYPE_NSH_OVER_VXLAN_GPE, + IPSU_PKT_TYPE_ESP_OVER_GENEVE, + IPSU_PKT_TYPE_PPOP_OVER_GENEVE, + IPSU_PKT_TYPE_OSPF, + IPSU_PKT_TYPE_VRRP, + IPSU_PKT_TYPE_BGP, + IPSU_PKT_TYPE_GRE, + IPSU_ERR_RSVD, +}; + +enum IPSU_METADATA_FMT_E { + IPSU_METADATA_FMT_NO_ENC = 0u, + IPSU_METADATA_FMT_VXLAN = 1u, + IPSU_METADATA_FMT_NVGRE = 2u, + IPSU_METADATA_FMT_FC = 3u, + IPSU_METADATA_FMT_GPE = 4u, + IPSU_METADATA_FMT_GENEVE = 5u, + IPSU_METADATA_FMT_NSH = 6u, + IPSU_METADATA_FMT_IPIP = 7U, +}; + struct hinic3_rxq_stats { uint64_t packets; uint64_t bytes; @@ -313,7 +407,6 @@ struct hinic3_rq_ci_wb { uint32_t rsvd[3]; }; - struct __rte_cache_aligned hinic3_rxq { struct hinic3_nic_dev *nic_dev; @@ -323,6 +416,7 @@ struct __rte_cache_aligned hinic3_rxq { uint16_t buf_len; uint32_t rx_buff_shift; + uint32_t rx_empty_loop; uint16_t rx_free_thresh; uint16_t rxinfo_align_end; @@ -370,24 +464,6 @@ struct __rte_cache_aligned hinic3_rxq { #endif }; -/* Rx CQE info get callback function */ -typedef void (*nic_rx_get_cqe_info_t)(struct hinic3_rxq *rxq, - volatile struct hinic3_rq_cqe *rx_cqe, - struct hinic3_cqe_info *cqe_info); - -/* Rx CQE check status callback function */ -typedef bool (*nic_rx_cqe_done_t)(struct hinic3_rxq *rxq, - volatile struct hinic3_rq_cqe **rx_cqe); - -/* Rx CQE empty poll callback function */ -typedef int (*nic_rx_poll_rq_empty_t)(struct hinic3_rxq *rxq); - -struct hinic3_nic_rx_ops { - nic_rx_get_cqe_info_t nic_rx_get_cqe_info; - nic_rx_cqe_done_t nic_rx_cqe_done; - nic_rx_poll_rq_empty_t nic_rx_poll_rq_empty; -}; - uint16_t hinic3_rx_fill_wqe(struct hinic3_rxq *rxq); uint16_t hinic3_rx_fill_buffers(struct hinic3_rxq *rxq); @@ -399,16 +475,14 @@ void hinic3_free_all_rxq_mbufs(struct hinic3_nic_dev *nic_dev); int hinic3_update_rss_config(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); -int hinic3_poll_integrated_cqe_rq_empty(struct hinic3_rxq *rxq); -int hinic3_poll_rq_empty(struct hinic3_rxq *rxq); - -void hinic3_dump_cqe_status(struct hinic3_rxq *rxq, uint32_t *cqe_done_cnt, - uint32_t *cqe_hole_cnt, uint32_t *head_ci, uint32_t *head_done); +int hinic3_init_rx_ptype_table(struct rte_eth_dev *dev); int hinic3_stop_rq(struct rte_eth_dev *eth_dev, struct hinic3_rxq *rxq); int hinic3_start_rq(struct rte_eth_dev *eth_dev, struct hinic3_rxq *rxq); +uint16_t hinic3_recv_pkts_compact_cqe(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); + uint16_t hinic3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); void hinic3_add_rq_to_rx_queue_list(struct hinic3_nic_dev *nic_dev, @@ -426,95 +500,4 @@ int hinic3_start_all_rqs(struct rte_eth_dev *eth_dev); void hinic3_get_stats(struct hinic3_rxq *rxq); #endif -/** - * Get receive queue local ci. - * - * @param[in] rxq - * Pointer to receive queue structure. - * @return - * Receive queue local ci. - */ -static inline uint16_t -hinic3_get_rq_local_ci(struct hinic3_rxq *rxq) -{ - return MASKED_QUEUE_IDX(rxq, rxq->cons_idx); -} - -static inline uint16_t -hinic3_get_rq_free_wqebb(struct hinic3_rxq *rxq) -{ - return rxq->delta - 1; -} - -/** - * Update receive queue local ci. - * - * @param[in] rxq - * Pointer to receive queue structure. - * @param[out] wqe_cnt - * Wqebb counters. - */ -static inline void -hinic3_update_rq_local_ci(struct hinic3_rxq *rxq, uint16_t wqe_cnt) -{ - rxq->cons_idx += wqe_cnt; - rxq->delta += wqe_cnt; -} - -/** - * Get receive cqe information - * - * @param[in] rxq - * Receive queue - * @param[in] rx_cqe - * Receive cqe - * @param[in] cqe_info - * Packet information parsed from cqe - */ -void -hinic3_rx_get_cqe_info(struct hinic3_rxq *rxq, volatile struct hinic3_rq_cqe *rx_cqe, - struct hinic3_cqe_info *cqe_info); - -/** - * Get receive compact cqe information - * - * @param[in] rx_queue - * Receive queue - * @param[in] rx_cqe - * Receive compact cqe - * @param[in] cqe_info - * Packet information parsed from cqe - */ -void -hinic3_rx_get_compact_cqe_info(struct hinic3_rxq *rxq, volatile struct hinic3_rq_cqe *rx_cqe, - struct hinic3_cqe_info *cqe_info); - -/** - * Check whether pkt is received when CQE is separated - * - * @param[in] rxq - * Receive queue - * @param[in] rx_cqe - * The CQE written by hw - * @return - * True: Packet is received - * False: Packet is not received - */ -bool -hinic3_rx_separate_cqe_done(struct hinic3_rxq *rxq, volatile struct hinic3_rq_cqe **rx_cqe); - -/** - * Check whether pkt is received when CQE is integrated - * - * @param[in] rxq - * Receive queue - * @param[in] rx_cqe - * The CQE written by hw - * @return - * True: Packet is received - * False: Packet is not received - */ -bool -hinic3_rx_integrated_cqe_done(struct hinic3_rxq *rxq, volatile struct hinic3_rq_cqe **rx_cqe); - #endif /* _HINIC3_RX_H_ */ -- 2.33.0

