1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2014-2018 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <inttypes.h> 7 8 #include <rte_malloc.h> 9 10 #include "bnxt.h" 11 #include "bnxt_ring.h" 12 #include "bnxt_txq.h" 13 #include "bnxt_txr.h" 14 15 /* 16 * TX Queues 17 */ 18 19 void bnxt_free_txq_stats(struct bnxt_tx_queue *txq) 20 { 21 if (txq && txq->cp_ring && txq->cp_ring->hw_stats) 22 txq->cp_ring->hw_stats = NULL; 23 } 24 25 static void bnxt_tx_queue_release_mbufs(struct bnxt_tx_queue *txq) 26 { 27 struct bnxt_sw_tx_bd *sw_ring; 28 uint16_t i; 29 30 if (!txq) 31 return; 32 33 sw_ring = txq->tx_ring->tx_buf_ring; 34 if (sw_ring) { 35 for (i = 0; i < txq->tx_ring->tx_ring_struct->ring_size; i++) { 36 if (sw_ring[i].mbuf) { 37 rte_pktmbuf_free_seg(sw_ring[i].mbuf); 38 sw_ring[i].mbuf = NULL; 39 } 40 } 41 } 42 } 43 44 void bnxt_free_tx_mbufs(struct bnxt *bp) 45 { 46 struct bnxt_tx_queue *txq; 47 int i; 48 49 for (i = 0; i < (int)bp->tx_nr_rings; i++) { 50 txq = bp->tx_queues[i]; 51 bnxt_tx_queue_release_mbufs(txq); 52 } 53 } 54 55 void bnxt_tx_queue_release_op(void *tx_queue) 56 { 57 struct bnxt_tx_queue *txq = (struct bnxt_tx_queue *)tx_queue; 58 59 if (txq) { 60 if (is_bnxt_in_error(txq->bp)) 61 return; 62 63 /* Free TX ring hardware descriptors */ 64 bnxt_tx_queue_release_mbufs(txq); 65 bnxt_free_ring(txq->tx_ring->tx_ring_struct); 66 67 /* Free TX completion ring hardware descriptors */ 68 bnxt_free_ring(txq->cp_ring->cp_ring_struct); 69 70 bnxt_free_txq_stats(txq); 71 rte_memzone_free(txq->mz); 72 txq->mz = NULL; 73 74 rte_free(txq->free); 75 rte_free(txq); 76 } 77 } 78 79 int bnxt_tx_queue_setup_op(struct rte_eth_dev *eth_dev, 80 uint16_t queue_idx, 81 uint16_t nb_desc, 82 unsigned int socket_id, 83 const struct rte_eth_txconf *tx_conf) 84 { 85 struct bnxt *bp = eth_dev->data->dev_private; 86 struct bnxt_tx_queue *txq; 87 int rc = 0; 88 89 rc = is_bnxt_in_error(bp); 90 if (rc) 91 return rc; 92 93 if (queue_idx >= BNXT_MAX_RINGS(bp)) { 94 PMD_DRV_LOG(ERR, 95 "Cannot create Tx ring %d. Only %d rings available\n", 96 queue_idx, bp->max_tx_rings); 97 return -EINVAL; 98 } 99 100 if (nb_desc < BNXT_MIN_RING_DESC || nb_desc > MAX_TX_DESC_CNT) { 101 PMD_DRV_LOG(ERR, "nb_desc %d is invalid", nb_desc); 102 rc = -EINVAL; 103 goto out; 104 } 105 106 if (eth_dev->data->tx_queues) { 107 txq = eth_dev->data->tx_queues[queue_idx]; 108 if (txq) { 109 bnxt_tx_queue_release_op(txq); 110 txq = NULL; 111 } 112 } 113 txq = rte_zmalloc_socket("bnxt_tx_queue", sizeof(struct bnxt_tx_queue), 114 RTE_CACHE_LINE_SIZE, socket_id); 115 if (!txq) { 116 PMD_DRV_LOG(ERR, "bnxt_tx_queue allocation failed!"); 117 rc = -ENOMEM; 118 goto out; 119 } 120 121 txq->free = rte_zmalloc_socket(NULL, 122 sizeof(struct rte_mbuf *) * nb_desc, 123 RTE_CACHE_LINE_SIZE, socket_id); 124 if (!txq->free) { 125 PMD_DRV_LOG(ERR, "allocation of tx mbuf free array failed!"); 126 rte_free(txq); 127 rc = -ENOMEM; 128 goto out; 129 } 130 txq->bp = bp; 131 txq->nb_tx_desc = nb_desc; 132 txq->tx_free_thresh = 133 RTE_MIN(rte_align32pow2(nb_desc) / 4, RTE_BNXT_MAX_TX_BURST); 134 135 txq->tx_deferred_start = tx_conf->tx_deferred_start; 136 137 rc = bnxt_init_tx_ring_struct(txq, socket_id); 138 if (rc) 139 goto out; 140 141 txq->queue_id = queue_idx; 142 txq->port_id = eth_dev->data->port_id; 143 144 /* Allocate TX ring hardware descriptors */ 145 if (bnxt_alloc_rings(bp, queue_idx, txq, NULL, txq->cp_ring, NULL, 146 "txr")) { 147 PMD_DRV_LOG(ERR, "ring_dma_zone_reserve for tx_ring failed!"); 148 bnxt_tx_queue_release_op(txq); 149 rc = -ENOMEM; 150 goto out; 151 } 152 153 if (bnxt_init_one_tx_ring(txq)) { 154 PMD_DRV_LOG(ERR, "bnxt_init_one_tx_ring failed!"); 155 bnxt_tx_queue_release_op(txq); 156 rc = -ENOMEM; 157 goto out; 158 } 159 160 eth_dev->data->tx_queues[queue_idx] = txq; 161 162 if (txq->tx_deferred_start) 163 txq->tx_started = false; 164 else 165 txq->tx_started = true; 166 out: 167 return rc; 168 } 169