From: Jie Liu <[email protected]> This patch improves the SXE2 PMD with several key enhancements:
- Enhance device info reporting: * Add NULL check for main VSI in dev_infos_get * Add max_mac_addrs field support * Add RSS_HASH offload capability * Conditionally enable QINQ_STRIP/QINQ_INSERT based on port VLAN check * Fill nb_rx_queues and nb_tx_queues fields * Set no_of_elements in buffer_split_supported_hdr_ptypes_get - Unify PCI register operations: * Move SXE2_PCI_REG_WRITE and SXE2_PCI_REG_READ to common header * Replace write-combined write with regular write in pci_map_write_reg * Add resource type validation in dev_pci_res_seg_map - Improve VF representor matching logic: * Remove kernel_repr_id encoding approach * Match PF number and VF ID directly against representor info * Add proper error handling for mismatched representor types - Support multi-port probing: * Loop through nb_ports in eth_pmd_probe * Handle probe failure with proper cleanup - Update resource cleanup order in dev_close: * Adjust uninit sequence to prevent use-after-free * Add NULL check for dev_ops before calling dev_close - Add device type checks in UDP tunnel operations: * Restrict tunnel operations to PF only * Reject operations on VF representors - Store additional device capabilities: * Save port_idx and pf_idx from device capabilities Signed-off-by: Jie Liu <[email protected]> --- drivers/net/sxe2/sxe2_ethdev.c | 178 +++++++++++++++++++-------------- drivers/net/sxe2/sxe2_ethdev.h | 6 +- drivers/net/sxe2/sxe2_queue.h | 2 - 3 files changed, 107 insertions(+), 79 deletions(-) diff --git a/drivers/net/sxe2/sxe2_ethdev.c b/drivers/net/sxe2/sxe2_ethdev.c index 3c3e78125d..ccf04fe1d9 100644 --- a/drivers/net/sxe2/sxe2_ethdev.c +++ b/drivers/net/sxe2/sxe2_ethdev.c @@ -95,7 +95,7 @@ static struct sxe2_pci_map_addr_info sxe2_net_map_addr_info_pf[SXE2_PCI_MAP_RES_ .reg_width = 4}, [SXE2_PCI_MAP_RES_IRQ_MSIX] = {.addr_base = SXE2_BAR4_MSIX_CTL(0), .bar_idx = 4, - .reg_width = 10}, + .reg_width = 0x10}, }; static struct sxe2_pci_map_addr_info sxe2_net_map_addr_info_vf[SXE2_PCI_MAP_RES_MAX_COUNT] = { @@ -630,6 +630,10 @@ int32_t sxe2_udp_tunnel_port_add_common(struct sxe2_adapter *ad, struct sxe2_udp_tunnel_cfg *tunnel_config; int32_t ret = -1; + if (ad->dev_type != SXE2_DEV_T_PF || ad->is_dev_repr) { + ret = -ENOTSUP; + goto l_end; + } rte_spinlock_lock(&ad->udp_tunnel_ctx.lock); tunnel_config = &ad->udp_tunnel_ctx.tunnel_conf[tunnel_proto]; @@ -659,6 +663,7 @@ int32_t sxe2_udp_tunnel_port_add_common(struct sxe2_adapter *ad, l_unlock_end: rte_spinlock_unlock(&ad->udp_tunnel_ctx.lock); +l_end: return ret; } @@ -782,6 +787,10 @@ static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev, struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev); struct sxe2_vsi *vsi = adapter->vsi_ctxt.main_vsi; + if (unlikely(vsi == NULL)) { + PMD_LOG_ERR(INIT, "main vsi is NULL"); + return -EINVAL; + } dev_info->max_rx_queues = vsi->rxqs.q_cnt; dev_info->max_tx_queues = vsi->txqs.q_cnt; dev_info->min_rx_bufsize = SXE2_MIN_BUF_SIZE; @@ -789,6 +798,7 @@ static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev, dev_info->max_lro_pkt_size = SXE2_FRAME_SIZE_MAX * SXE2_RX_LRO_DESC_MAX_NUM; dev_info->max_mtu = dev_info->max_rx_pktlen - SXE2_ETH_OVERHEAD; dev_info->min_mtu = RTE_ETHER_MIN_MTU; + dev_info->max_mac_addrs = SXE2_NUM_MACADDR_MAX; dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_VLAN_STRIP | @@ -800,11 +810,9 @@ static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev, RTE_ETH_RX_OFFLOAD_SCTP_CKSUM | RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM | RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT | -#ifndef RTE_LIBRTE_SXE2_16BYTE_RX_DESC - RTE_ETH_RX_OFFLOAD_QINQ_STRIP | -#endif RTE_ETH_RX_OFFLOAD_VLAN_EXTEND | - RTE_ETH_RX_OFFLOAD_TCP_LRO; + RTE_ETH_RX_OFFLOAD_TCP_LRO | + RTE_ETH_RX_OFFLOAD_RSS_HASH; dev_info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_VLAN_INSERT | @@ -850,13 +858,20 @@ static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev, RTE_ETH_TX_OFFLOAD_IPIP_TNL_TSO | RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO; + if (sxe2_ipsec_supported(adapter)) { + dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_SECURITY; + dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_SECURITY; + } if (adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_PTP) dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TIMESTAMP; - if (sxe2_ipsec_supported(adapter)) { - dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_SECURITY; - dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_SECURITY; + if (!sxe2_dev_port_vlan_check(dev)) { + dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_QINQ_INSERT; +#ifndef RTE_LIBRTE_SXE2_16BYTE_RX_DESC + dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_QINQ_STRIP; +#endif + dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER; } if (adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_RSS) { @@ -909,7 +924,8 @@ static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev, dev_info->speed_capa = RTE_ETH_LINK_SPEED_10G | RTE_ETH_LINK_SPEED_25G | RTE_ETH_LINK_SPEED_50G | RTE_ETH_LINK_SPEED_100G; - + dev_info->nb_rx_queues = dev->data->nb_rx_queues; + dev_info->nb_tx_queues = dev->data->nb_tx_queues; dev_info->default_rxportconf.burst_size = SXE2_RX_MAX_BURST; dev_info->default_txportconf.burst_size = SXE2_TX_MAX_BURST; dev_info->default_rxportconf.nb_queues = 1; @@ -918,11 +934,8 @@ static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev, dev_info->default_txportconf.ring_size = SXE2_RING_SIZE_MIN; dev_info->rx_seg_capa.max_nseg = SXE2_RX_MAX_NSEG; - dev_info->rx_seg_capa.multi_pools = true; - dev_info->rx_seg_capa.offset_allowed = false; - dev_info->rx_seg_capa.offset_align_log2 = false; return 0; @@ -930,7 +943,7 @@ static int32_t sxe2_dev_infos_get(struct rte_eth_dev *dev, static const uint32_t * sxe2_buffer_split_supported_hdr_ptypes_get(struct rte_eth_dev *dev __rte_unused, - size_t *no_of_elements __rte_unused) + size_t *no_of_elements) { static const uint32_t ptypes[] = { RTE_PTYPE_L2_ETHER, @@ -968,6 +981,7 @@ sxe2_buffer_split_supported_hdr_ptypes_get(struct rte_eth_dev *dev __rte_unused, RTE_PTYPE_UNKNOWN }; + *no_of_elements = RTE_DIM(ptypes); return ptypes; } @@ -1352,6 +1366,8 @@ static int32_t sxe2_func_caps_get(struct sxe2_adapter *adapter) goto l_end; adapter->dev_type = dev_caps.dev_type; + adapter->port_idx = dev_caps.port_idx; + adapter->pf_idx = dev_caps.pf_idx; sxe2_drv_dev_caps_set(adapter, &dev_caps); @@ -1437,7 +1453,7 @@ void sxe2_pci_map_write_reg(struct sxe2_adapter *adapter, goto l_ret; } - SXE2_PCI_REG_WRITE_WC(reg_addr, value); + SXE2_PCI_REG_WRITE(reg_addr, value); l_ret: return; } @@ -1550,6 +1566,12 @@ int32_t sxe2_dev_pci_res_seg_map(struct sxe2_adapter *adapter, struct sxe2_pci_map_addr_info *addr_info = NULL; int32_t ret = 0; + if (unlikely(res_type >= SXE2_PCI_MAP_RES_MAX_COUNT)) { + PMD_DEV_LOG_ERR(adapter, INIT, "Invalid resource type %u", res_type); + ret = -EINVAL; + goto l_end; + } + addr_info = &adapter->map_ctxt.addr_info[res_type]; if (!addr_info || addr_info->bar_idx == SXE2_PCI_MAP_BAR_INVALID) { PMD_DEV_LOG_ERR(adapter, INIT, "Invalid bar index with resource type %d", res_type); @@ -1765,14 +1787,13 @@ void sxe2_dev_pci_map_uinit(struct rte_eth_dev *dev) uint8_t i = 0; PMD_INIT_FUNC_TRACE(); + if (map_ctxt->bar_info != NULL) { + (void)sxe2_dev_pci_seg_unmap(adapter, SXE2_PCI_MAP_RES_DOORBELL_RX_TAIL); + (void)sxe2_dev_pci_seg_unmap(adapter, SXE2_PCI_MAP_RES_DOORBELL_TX); + (void)sxe2_dev_pci_seg_unmap(adapter, SXE2_PCI_MAP_RES_IRQ_DYN); + (void)sxe2_dev_pci_seg_unmap(adapter, SXE2_PCI_MAP_RES_IRQ_ITR); + (void)sxe2_dev_pci_seg_unmap(adapter, SXE2_PCI_MAP_RES_IRQ_MSIX); - (void)sxe2_dev_pci_seg_unmap(adapter, SXE2_PCI_MAP_RES_DOORBELL_RX_TAIL); - (void)sxe2_dev_pci_seg_unmap(adapter, SXE2_PCI_MAP_RES_DOORBELL_TX); - (void)sxe2_dev_pci_seg_unmap(adapter, SXE2_PCI_MAP_RES_IRQ_DYN); - (void)sxe2_dev_pci_seg_unmap(adapter, SXE2_PCI_MAP_RES_IRQ_ITR); - (void)sxe2_dev_pci_seg_unmap(adapter, SXE2_PCI_MAP_RES_IRQ_MSIX); - - if (map_ctxt != NULL && map_ctxt->bar_info != NULL) { for (i = 0; i < map_ctxt->bar_cnt; i++) { bar_info = &map_ctxt->bar_info[i]; if (bar_info != NULL && bar_info->seg_info != NULL) { @@ -1783,7 +1804,6 @@ void sxe2_dev_pci_map_uinit(struct rte_eth_dev *dev) rte_free(map_ctxt->bar_info); map_ctxt->bar_info = NULL; } - adapter->dev_info.dev_data = NULL; } @@ -1936,6 +1956,12 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev, goto init_switchdev_err; } + ret = sxe2_eth_init(dev); + if (ret) { + PMD_LOG_ERR(INIT, "Failed to initialize eth parameters, ret=%d", ret); + goto init_eth_err; + } + ret = sxe2_sw_init(dev); if (ret) { PMD_LOG_ERR(INIT, "Failed to initialize sw parameters, ret=[%d]", ret); @@ -1948,12 +1974,6 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev, goto init_irq_err; } - ret = sxe2_eth_init(dev); - if (ret) { - PMD_LOG_ERR(INIT, "Failed to initialize eth parameters, ret=%d", ret); - goto init_eth_err; - } - ret = sxe2_security_init(dev); if (ret) { PMD_LOG_ERR(INIT, "Failed to initialize security, ret=%d", ret); @@ -2005,15 +2025,15 @@ static int32_t sxe2_dev_init(struct rte_eth_dev *dev, init_fc_state_err: (void)sxe2_flow_uninit(dev); init_flow_err: -init_rss_err: sxe2_security_uinit(dev); +init_rss_err: init_security_err: - sxe2_eth_uinit(dev); -init_eth_err: sxe2_intr_uninit(dev); init_irq_err: sxe2_sw_uninit(dev); init_sw_err: + sxe2_eth_uinit(dev); +init_eth_err: (void)sxe2_switchdev_uninit(dev); init_switchdev_err: init_dev_info_err: @@ -2035,17 +2055,15 @@ static int32_t sxe2_dev_close(struct rte_eth_dev *dev) (void)sxe2_queues_release(dev); sxe2_mp_uninit(dev); (void)sxe2_sched_uinit(dev); - (void)sxe2_rss_disable(dev); (void)sxe2_flow_uninit(dev); + (void)sxe2_rss_disable(dev); (void)sxe2_udp_tunnel_port_clear(dev); - sxe2_vsi_uninit(dev); sxe2_security_uinit(dev); sxe2_intr_uninit(dev); (void)sxe2_switchdev_uninit(dev); sxe2_sw_uninit(dev); - (void)sxe2_switchdev_uninit(dev); - sxe2_dev_pci_map_uinit(dev); sxe2_eth_uinit(dev); + sxe2_vsi_uninit(dev); sxe2_dev_pci_map_uinit(dev); sxe2_free_repr_info(dev); sxe2_fc_state_uinit(dev); @@ -2068,9 +2086,11 @@ static int32_t sxe2_dev_uninit(struct rte_eth_dev *dev) for (i = 0; i < adapter->repr_ctxt.nb_repr_vf; i++) { rep_dev = adapter->repr_ctxt.vf_rep_eth_dev[i]; if (rep_dev) { - ret = rep_dev->dev_ops->dev_close(rep_dev); - if (ret) - goto l_end; + if (rep_dev->dev_ops && rep_dev->dev_ops->dev_close) { + ret = rep_dev->dev_ops->dev_close(rep_dev); + if (ret) + goto l_end; + } if (rep_dev->intr_handle) rte_intr_instance_free(rep_dev->intr_handle); ret = rte_eth_dev_release_port(rep_dev); @@ -2143,42 +2163,25 @@ static int32_t sxe2_fw_version_string_get(struct rte_eth_dev *dev, char *fw_vers return ret; } -static uint16_t sxe2_switchdev_repr_id_encode_get(struct sxe2_switchdev_info *switchdev_info) -{ - enum rte_eth_representor_type type; - uint16_t repr = switchdev_info->vf_num; - uint32_t pf = switchdev_info->pf_num; - - switch (switchdev_info->port_name_type) { - case SXE2_PHYS_PORT_NAME_TYPE_UPLINK: - if (!switchdev_info->representor) - return UINT16_MAX; - type = RTE_ETH_REPRESENTOR_PF; - pf = switchdev_info->mpesw_owner; - break; - case SXE2_PHYS_PORT_NAME_TYPE_PFVF: - default: - type = RTE_ETH_REPRESENTOR_VF; - break; - } - - return SXE2_REPRESENTOR_ID(pf, type, repr); -} - static bool sxe2_switchdev_repr_match(struct sxe2_adapter *adapter, struct rte_eth_devargs *req_eth_da) { - uint32_t port_idx = 0; - uint32_t repr_idx; - uint16_t kernel_repr_id = sxe2_switchdev_repr_id_encode_get(&adapter->switchdev_info); - uint16_t repr_id; + uint16_t port_idx = UINT16_MAX; + uint16_t repr_idx; + uint16_t vf_id; + uint16_t i; switch (req_eth_da->type) { case RTE_ETH_REPRESENTOR_PF: + if (adapter->switchdev_info.port_name_type != + SXE2_PHYS_PORT_NAME_TYPE_UPLINK) { + rte_errno = EBUSY; + return false; + } break; case RTE_ETH_REPRESENTOR_VF: if (adapter->switchdev_info.port_name_type != - SXE2_PHYS_PORT_NAME_TYPE_PFVF) { + SXE2_PHYS_PORT_NAME_TYPE_PFVF) { rte_errno = EBUSY; return false; } @@ -2191,15 +2194,30 @@ static bool sxe2_switchdev_repr_match(struct sxe2_adapter *adapter, return false; } + for (port_idx = 0; port_idx < req_eth_da->nb_ports; ++port_idx) { + if (adapter->switchdev_info.pf_num != req_eth_da->ports[port_idx]) { + PMD_DEV_LOG_DEBUG(adapter, DRV, "switchdev pf %u not match req pf %u", + adapter->switchdev_info.pf_num, req_eth_da->ports[port_idx]); + rte_errno = EBUSY; + return false; + } + } + for (repr_idx = 0; repr_idx < req_eth_da->nb_representor_ports; ++repr_idx) { - repr_id = SXE2_REPRESENTOR_ID(req_eth_da->ports[port_idx], - req_eth_da->type, - req_eth_da->representor_ports[repr_idx]); - if (repr_id == kernel_repr_id) - return true; - } - rte_errno = EBUSY; - return false; + for (i = 0; i < adapter->repr_ctxt.nb_vf; ++i) { + vf_id = rte_le_to_cpu_16(adapter->repr_ctxt.repr_vf_id[i].func_id); + if (vf_id == req_eth_da->representor_ports[repr_idx]) + break; + } + if (i == adapter->repr_ctxt.nb_vf) { + PMD_DEV_LOG_DEBUG(adapter, DRV, "switchdev vf %u not match req vf(cnt:%u)", + req_eth_da->representor_ports[repr_idx], adapter->repr_ctxt.nb_vf); + rte_errno = EBUSY; + return false; + } + } + + return true; } static int32_t sxe2_eth_pmd_probe_pf(struct sxe2_common_device *cdev, @@ -2317,6 +2335,7 @@ static int32_t sxe2_eth_pmd_probe(struct sxe2_common_device *cdev, { struct rte_eth_devargs eth_da = { .nb_ports = 0 }; int32_t ret = 0; + uint16_t port; ret = sxe2_parse_eth_devargs(cdev->dev, ð_da); if (ret != 0) { @@ -2324,7 +2343,18 @@ static int32_t sxe2_eth_pmd_probe(struct sxe2_common_device *cdev, goto l_end; } - ret = sxe2_eth_pmd_probe_pf(cdev, ð_da, 0, kvargs); + if (eth_da.nb_ports > 0) { + for (port = 0; port < eth_da.nb_ports; port++) { + ret = sxe2_eth_pmd_probe_pf(cdev, ð_da, port, kvargs); + if (ret != 0) { + PMD_LOG_ERR(INIT, "sxe2 eth pmd probe failed, ret=%d", ret); + (void)sxe2_eth_pmd_remove(cdev); + goto l_end; + } + } + } else { + ret = sxe2_eth_pmd_probe_pf(cdev, ð_da, 0, kvargs); + } l_end: return ret; diff --git a/drivers/net/sxe2/sxe2_ethdev.h b/drivers/net/sxe2/sxe2_ethdev.h index 7e495e5cb9..cfcb7fcf00 100644 --- a/drivers/net/sxe2/sxe2_ethdev.h +++ b/drivers/net/sxe2/sxe2_ethdev.h @@ -65,9 +65,6 @@ enum sxe2_fnav_tunnel_flag_type { #define upper_32_bits(n) ((uint32_t)(((n) >> 16) >> 16)) #define lower_32_bits(n) ((uint32_t)((n) & 0xffffffff)) -#define SXE2_REPRESENTOR_ID(pf, type, repr) \ - (((pf) << 14) + ((type) << 12) + ((repr) & 0xfff)) - #define SXE2_I2C_EEPROM_DEV_ADDR 0xA0 #define SXE2_I2C_EEPROM_DEV_ADDR2 0xA2 #define SXE2_MODULE_TYPE_SFP 0x03 @@ -356,6 +353,9 @@ struct sxe2_adapter { #define SXE2_DEV_PRIVATE_TO_ADAPTER(dev) \ ((struct sxe2_adapter *)(dev)->data->dev_private) +#define SXE2_PCI_REG_WRITE(reg, value) rte_write32((rte_cpu_to_le_32(value)), (reg)) +#define SXE2_PCI_REG_READ(reg) rte_read32(reg) + void *sxe2_pci_map_addr_get(struct sxe2_adapter *adapter, enum sxe2_pci_map_resource res_type, uint16_t idx_in_func); diff --git a/drivers/net/sxe2/sxe2_queue.h b/drivers/net/sxe2/sxe2_queue.h index a300b66771..10bdaf5b8d 100644 --- a/drivers/net/sxe2/sxe2_queue.h +++ b/drivers/net/sxe2/sxe2_queue.h @@ -12,8 +12,6 @@ #include "sxe2_drv_cmd.h" #include "sxe2_txrx_common.h" -#define SXE2_PCI_REG_READ(reg) \ - rte_read32(reg) #define SXE2_PCI_REG_WRITE_WC(reg, value) \ rte_write32_wc((rte_cpu_to_le_32(value)), reg) #define SXE2_PCI_REG_WRITE_WC_RELAXED(reg, value) \ -- 2.52.0

