1fd710bb1SScott Branden /* SPDX-License-Identifier: BSD-3-Clause 26d160d77SRandy Schacher * Copyright(c) 2014-2023 Broadcom 351c87ebaSAjit Khaparde * All rights reserved. 451c87ebaSAjit Khaparde */ 551c87ebaSAjit Khaparde 651c87ebaSAjit Khaparde #include <inttypes.h> 751c87ebaSAjit Khaparde 851c87ebaSAjit Khaparde #include <rte_malloc.h> 951c87ebaSAjit Khaparde 1051c87ebaSAjit Khaparde #include "bnxt.h" 110105ea12SAjit Khaparde #include "bnxt_hwrm.h" 1251c87ebaSAjit Khaparde #include "bnxt_ring.h" 1351c87ebaSAjit Khaparde #include "bnxt_txq.h" 146eb3cc22SAjit Khaparde #include "bnxt_txr.h" 1551c87ebaSAjit Khaparde 1651c87ebaSAjit Khaparde /* 1751c87ebaSAjit Khaparde * TX Queues 1851c87ebaSAjit Khaparde */ 1951c87ebaSAjit Khaparde 2047a956a8SKalesh AP uint64_t bnxt_get_tx_port_offloads(struct bnxt *bp) 2147a956a8SKalesh AP { 2247a956a8SKalesh AP uint64_t tx_offload_capa; 2347a956a8SKalesh AP 2447a956a8SKalesh AP tx_offload_capa = RTE_ETH_TX_OFFLOAD_IPV4_CKSUM | 2547a956a8SKalesh AP RTE_ETH_TX_OFFLOAD_UDP_CKSUM | 2647a956a8SKalesh AP RTE_ETH_TX_OFFLOAD_TCP_CKSUM | 2747a956a8SKalesh AP RTE_ETH_TX_OFFLOAD_TCP_TSO | 2847a956a8SKalesh AP RTE_ETH_TX_OFFLOAD_QINQ_INSERT | 2947a956a8SKalesh AP RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 3047a956a8SKalesh AP 3147a956a8SKalesh AP if (bp->fw_cap & BNXT_FW_CAP_VLAN_TX_INSERT) 3247a956a8SKalesh AP tx_offload_capa |= RTE_ETH_TX_OFFLOAD_VLAN_INSERT; 3347a956a8SKalesh AP 34c0278f6eSKalesh AP if (BNXT_TUNNELED_OFFLOADS_CAP_ALL_EN(bp)) 35c0278f6eSKalesh AP tx_offload_capa |= RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM; 36c0278f6eSKalesh AP 37c0278f6eSKalesh AP if (BNXT_TUNNELED_OFFLOADS_CAP_VXLAN_EN(bp)) 38c0278f6eSKalesh AP tx_offload_capa |= RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO; 39c0278f6eSKalesh AP if (BNXT_TUNNELED_OFFLOADS_CAP_GRE_EN(bp)) 40c0278f6eSKalesh AP tx_offload_capa |= RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO; 41c0278f6eSKalesh AP if (BNXT_TUNNELED_OFFLOADS_CAP_NGE_EN(bp)) 42c0278f6eSKalesh AP tx_offload_capa |= RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO; 43c0278f6eSKalesh AP if (BNXT_TUNNELED_OFFLOADS_CAP_IPINIP_EN(bp)) 44c0278f6eSKalesh AP tx_offload_capa |= RTE_ETH_TX_OFFLOAD_IPIP_TNL_TSO; 4567ae7016SAjit Khaparde if (bp->fw_cap & BNXT_FW_CAP_UDP_GSO) 4667ae7016SAjit Khaparde tx_offload_capa |= RTE_ETH_TX_OFFLOAD_UDP_TSO; 47c0278f6eSKalesh AP 4847a956a8SKalesh AP return tx_offload_capa; 4947a956a8SKalesh AP } 5047a956a8SKalesh AP 5151c87ebaSAjit Khaparde void bnxt_free_txq_stats(struct bnxt_tx_queue *txq) 5251c87ebaSAjit Khaparde { 53f7b36e8fSRahul Gupta if (txq && txq->cp_ring && txq->cp_ring->hw_stats) 54f7b36e8fSRahul Gupta txq->cp_ring->hw_stats = NULL; 5551c87ebaSAjit Khaparde } 5651c87ebaSAjit Khaparde 576eb3cc22SAjit Khaparde static void bnxt_tx_queue_release_mbufs(struct bnxt_tx_queue *txq) 5851c87ebaSAjit Khaparde { 59527b1008SLance Richardson struct rte_mbuf **sw_ring; 606eb3cc22SAjit Khaparde uint16_t i; 616eb3cc22SAjit Khaparde 6297c32717SSomnath Kotur if (!txq || !txq->tx_ring) 63f7b36e8fSRahul Gupta return; 64f7b36e8fSRahul Gupta 656eb3cc22SAjit Khaparde sw_ring = txq->tx_ring->tx_buf_ring; 666eb3cc22SAjit Khaparde if (sw_ring) { 676eb3cc22SAjit Khaparde for (i = 0; i < txq->tx_ring->tx_ring_struct->ring_size; i++) { 68527b1008SLance Richardson if (sw_ring[i]) { 69527b1008SLance Richardson rte_pktmbuf_free_seg(sw_ring[i]); 70527b1008SLance Richardson sw_ring[i] = NULL; 716eb3cc22SAjit Khaparde } 726eb3cc22SAjit Khaparde } 736eb3cc22SAjit Khaparde } 7451c87ebaSAjit Khaparde } 7551c87ebaSAjit Khaparde 7651c87ebaSAjit Khaparde void bnxt_free_tx_mbufs(struct bnxt *bp) 7751c87ebaSAjit Khaparde { 7851c87ebaSAjit Khaparde struct bnxt_tx_queue *txq; 7951c87ebaSAjit Khaparde int i; 8051c87ebaSAjit Khaparde 8151c87ebaSAjit Khaparde for (i = 0; i < (int)bp->tx_nr_rings; i++) { 8251c87ebaSAjit Khaparde txq = bp->tx_queues[i]; 8351c87ebaSAjit Khaparde bnxt_tx_queue_release_mbufs(txq); 8451c87ebaSAjit Khaparde } 8551c87ebaSAjit Khaparde } 8651c87ebaSAjit Khaparde 877483341aSXueming Li void bnxt_tx_queue_release_op(struct rte_eth_dev *dev, uint16_t queue_idx) 8851c87ebaSAjit Khaparde { 897483341aSXueming Li struct bnxt_tx_queue *txq = dev->data->tx_queues[queue_idx]; 9051c87ebaSAjit Khaparde 9151c87ebaSAjit Khaparde if (txq) { 921bf01f51SKalesh AP if (is_bnxt_in_error(txq->bp)) 931bf01f51SKalesh AP return; 941bf01f51SKalesh AP 956eb3cc22SAjit Khaparde /* Free TX ring hardware descriptors */ 960105ea12SAjit Khaparde bnxt_free_hwrm_tx_ring(txq->bp, txq->queue_id); 976eb3cc22SAjit Khaparde bnxt_tx_queue_release_mbufs(txq); 9897c32717SSomnath Kotur if (txq->tx_ring) { 996eb3cc22SAjit Khaparde bnxt_free_ring(txq->tx_ring->tx_ring_struct); 10097c32717SSomnath Kotur rte_free(txq->tx_ring->tx_ring_struct); 101925cd070SSomnath Kotur rte_free(txq->tx_ring->nr_bds); 10297c32717SSomnath Kotur rte_free(txq->tx_ring); 10397c32717SSomnath Kotur } 1046eb3cc22SAjit Khaparde 1056eb3cc22SAjit Khaparde /* Free TX completion ring hardware descriptors */ 10697c32717SSomnath Kotur if (txq->cp_ring) { 107f83823f9SKishore Padmanabha bnxt_free_txq_stats(txq); 1086eb3cc22SAjit Khaparde bnxt_free_ring(txq->cp_ring->cp_ring_struct); 10997c32717SSomnath Kotur rte_free(txq->cp_ring->cp_ring_struct); 11097c32717SSomnath Kotur rte_free(txq->cp_ring); 11197c32717SSomnath Kotur } 1126eb3cc22SAjit Khaparde 11323460b4cSAjit Khaparde rte_memzone_free(txq->mz); 11423460b4cSAjit Khaparde txq->mz = NULL; 1156eb3cc22SAjit Khaparde 1165ef3592cSAjit Khaparde rte_free(txq->free); 117d46406c7SAjit Khaparde pthread_mutex_destroy(&txq->txq_lock); 11851c87ebaSAjit Khaparde rte_free(txq); 1197483341aSXueming Li dev->data->tx_queues[queue_idx] = NULL; 12051c87ebaSAjit Khaparde } 12151c87ebaSAjit Khaparde } 12251c87ebaSAjit Khaparde 12351c87ebaSAjit Khaparde int bnxt_tx_queue_setup_op(struct rte_eth_dev *eth_dev, 12451c87ebaSAjit Khaparde uint16_t queue_idx, 12551c87ebaSAjit Khaparde uint16_t nb_desc, 12651c87ebaSAjit Khaparde unsigned int socket_id, 12751c87ebaSAjit Khaparde const struct rte_eth_txconf *tx_conf) 12851c87ebaSAjit Khaparde { 12978466c95SStephen Hemminger struct bnxt *bp = eth_dev->data->dev_private; 13051c87ebaSAjit Khaparde struct bnxt_tx_queue *txq; 1312bb1d5dbSAjit Khaparde int rc = 0; 13251c87ebaSAjit Khaparde 1331bf01f51SKalesh AP rc = is_bnxt_in_error(bp); 1341bf01f51SKalesh AP if (rc) 1351bf01f51SKalesh AP return rc; 1361bf01f51SKalesh AP 137c72fe7acSSriharsha Basavapatna if (queue_idx >= bnxt_max_rings(bp)) { 138e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, 139e99981afSDavid Marchand "Cannot create Tx ring %d. Only %d rings available", 140f10d5282SAjit Khaparde queue_idx, bp->max_tx_rings); 141a42b152aSJay Ding return -EINVAL; 142f10d5282SAjit Khaparde } 143f10d5282SAjit Khaparde 144cec43bbfSLance Richardson if (nb_desc < BNXT_MIN_RING_DESC || nb_desc > MAX_TX_DESC_CNT) { 145e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "nb_desc %d is invalid", nb_desc); 14697c32717SSomnath Kotur return -EINVAL; 14751c87ebaSAjit Khaparde } 14851c87ebaSAjit Khaparde 14951c87ebaSAjit Khaparde if (eth_dev->data->tx_queues) { 15051c87ebaSAjit Khaparde txq = eth_dev->data->tx_queues[queue_idx]; 1517483341aSXueming Li if (txq) 1527483341aSXueming Li bnxt_tx_queue_release_op(eth_dev, queue_idx); 15351c87ebaSAjit Khaparde } 15451c87ebaSAjit Khaparde txq = rte_zmalloc_socket("bnxt_tx_queue", sizeof(struct bnxt_tx_queue), 15551c87ebaSAjit Khaparde RTE_CACHE_LINE_SIZE, socket_id); 1562bb1d5dbSAjit Khaparde if (!txq) { 157e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "bnxt_tx_queue allocation failed!"); 15897c32717SSomnath Kotur return -ENOMEM; 15951c87ebaSAjit Khaparde } 1605ef3592cSAjit Khaparde 1617483341aSXueming Li txq->bp = bp; 1627483341aSXueming Li eth_dev->data->tx_queues[queue_idx] = txq; 1637483341aSXueming Li 1645ef3592cSAjit Khaparde txq->free = rte_zmalloc_socket(NULL, 1655ef3592cSAjit Khaparde sizeof(struct rte_mbuf *) * nb_desc, 1665ef3592cSAjit Khaparde RTE_CACHE_LINE_SIZE, socket_id); 1675ef3592cSAjit Khaparde if (!txq->free) { 168e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "allocation of tx mbuf free array failed!"); 1695ef3592cSAjit Khaparde rc = -ENOMEM; 17097c32717SSomnath Kotur goto err; 1715ef3592cSAjit Khaparde } 17251c87ebaSAjit Khaparde txq->nb_tx_desc = nb_desc; 173cec43bbfSLance Richardson txq->tx_free_thresh = 174cec43bbfSLance Richardson RTE_MIN(rte_align32pow2(nb_desc) / 4, RTE_BNXT_MAX_TX_BURST); 175369f6077SLance Richardson txq->offloads = eth_dev->data->dev_conf.txmode.offloads | 176369f6077SLance Richardson tx_conf->offloads; 177cec43bbfSLance Richardson 1782171e66fSKalesh AP txq->tx_deferred_start = tx_conf->tx_deferred_start; 17951c87ebaSAjit Khaparde 1802bb1d5dbSAjit Khaparde rc = bnxt_init_tx_ring_struct(txq, socket_id); 1812bb1d5dbSAjit Khaparde if (rc) 18297c32717SSomnath Kotur goto err; 18351c87ebaSAjit Khaparde 18451c87ebaSAjit Khaparde txq->queue_id = queue_idx; 18551c87ebaSAjit Khaparde txq->port_id = eth_dev->data->port_id; 18651c87ebaSAjit Khaparde 1876eb3cc22SAjit Khaparde /* Allocate TX ring hardware descriptors */ 188c6c90a33SLance Richardson if (bnxt_alloc_rings(bp, socket_id, queue_idx, txq, NULL, txq->cp_ring, 189c6c90a33SLance Richardson NULL, "txr")) { 190e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "ring_dma_zone_reserve for tx_ring failed!"); 1912bb1d5dbSAjit Khaparde rc = -ENOMEM; 19297c32717SSomnath Kotur goto err; 1936eb3cc22SAjit Khaparde } 19451c87ebaSAjit Khaparde 1956eb3cc22SAjit Khaparde if (bnxt_init_one_tx_ring(txq)) { 196e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "bnxt_init_one_tx_ring failed!"); 1972bb1d5dbSAjit Khaparde rc = -ENOMEM; 19897c32717SSomnath Kotur goto err; 1996eb3cc22SAjit Khaparde } 20051c87ebaSAjit Khaparde 201*7d32c003SAriel Otilibili return pthread_mutex_init(&txq->txq_lock, NULL); 20297c32717SSomnath Kotur err: 2037483341aSXueming Li bnxt_tx_queue_release_op(eth_dev, queue_idx); 2042bb1d5dbSAjit Khaparde return rc; 20551c87ebaSAjit Khaparde } 206