Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
3 : : */
4 : :
5 : : #include <rte_common.h>
6 : : #include <rte_net.h>
7 : : #include <rte_vect.h>
8 : : #include <rte_malloc.h>
9 : : #include <rte_memzone.h>
10 : : #include <ethdev_driver.h>
11 : : #include "sxe2_tx.h"
12 : : #include "sxe2_ethdev.h"
13 : : #include "sxe2_common_log.h"
14 : : #include "sxe2_cmd_chnl.h"
15 : :
16 : 0 : static void *sxe2_tx_doorbell_addr_get(struct sxe2_adapter *adapter, uint16_t queue_id)
17 : : {
18 : 0 : return sxe2_pci_map_addr_get(adapter, SXE2_PCI_MAP_RES_DOORBELL_TX,
19 : : queue_id);
20 : : }
21 : :
22 : 0 : static void sxe2_tx_tail_init(struct sxe2_adapter *adapter, struct sxe2_tx_queue *txq)
23 : : {
24 : 0 : txq->tdt_reg_addr = sxe2_tx_doorbell_addr_get(adapter, txq->queue_id);
25 : 0 : SXE2_PCI_REG_WRITE_WC(txq->tdt_reg_addr, 0);
26 : 0 : }
27 : :
28 : 0 : void __rte_cold sxe2_tx_queue_reset(struct sxe2_tx_queue *txq)
29 : : {
30 : 0 : uint16_t prev, i;
31 : 0 : volatile union sxe2_tx_data_desc *txd;
32 : 0 : static const union sxe2_tx_data_desc zeroed_desc = {{0}};
33 : 0 : struct sxe2_tx_buffer *tx_buffer = txq->buffer_ring;
34 : :
35 [ # # ]: 0 : for (i = 0; i < txq->ring_depth; i++)
36 : 0 : txq->desc_ring[i] = zeroed_desc;
37 : :
38 : 0 : prev = txq->ring_depth - 1;
39 [ # # ]: 0 : for (i = 0; i < txq->ring_depth; i++) {
40 : 0 : txd = &txq->desc_ring[i];
41 [ # # ]: 0 : if (txd == NULL)
42 : 0 : continue;
43 : :
44 : 0 : txd->wb.dd = rte_cpu_to_le_64(SXE2_TX_DESC_DTYPE_DESC_DONE);
45 : 0 : tx_buffer[i].mbuf = NULL;
46 : 0 : tx_buffer[i].last_id = i;
47 : 0 : tx_buffer[prev].next_id = i;
48 : 0 : prev = i;
49 : : }
50 : :
51 : 0 : txq->desc_used_num = 0;
52 : 0 : txq->desc_free_num = txq->ring_depth - 1;
53 : 0 : txq->next_use = 0;
54 : 0 : txq->next_clean = txq->ring_depth - 1;
55 : 0 : txq->next_dd = txq->rs_thresh - 1;
56 : 0 : txq->next_rs = txq->rs_thresh - 1;
57 : 0 : }
58 : :
59 : 0 : void __rte_cold sxe2_tx_queue_mbufs_release(struct sxe2_tx_queue *txq)
60 : : {
61 : 0 : uint32_t i;
62 : :
63 [ # # # # ]: 0 : if (txq != NULL && txq->buffer_ring != NULL) {
64 [ # # ]: 0 : for (i = 0; i < txq->ring_depth; i++) {
65 [ # # ]: 0 : if (txq->buffer_ring[i].mbuf != NULL) {
66 : 0 : rte_pktmbuf_free_seg(txq->buffer_ring[i].mbuf);
67 : 0 : txq->buffer_ring[i].mbuf = NULL;
68 : : }
69 : : }
70 : : }
71 : 0 : }
72 : :
73 : 0 : static void sxe2_tx_buffer_ring_free(struct sxe2_tx_queue *txq)
74 : : {
75 [ # # # # ]: 0 : if (txq != NULL && txq->buffer_ring != NULL)
76 : 0 : rte_free(txq->buffer_ring);
77 : 0 : }
78 : :
79 : : const struct sxe2_txq_ops sxe2_default_txq_ops = {
80 : : .queue_reset = sxe2_tx_queue_reset,
81 : : .mbufs_release = sxe2_tx_queue_mbufs_release,
82 : : .buffer_ring_free = sxe2_tx_buffer_ring_free,
83 : : };
84 : :
85 : 0 : static struct sxe2_txq_ops sxe2_tx_default_ops_get(void)
86 : : {
87 : 0 : return sxe2_default_txq_ops;
88 : : }
89 : :
90 : 0 : static int32_t sxe2_txq_arg_validate(struct rte_eth_dev *dev, uint16_t ring_depth,
91 : : uint16_t *rs_thresh, uint16_t *free_thresh, const struct rte_eth_txconf *tx_conf)
92 : : {
93 : 0 : int32_t ret = 0;
94 : :
95 [ # # ]: 0 : if ((ring_depth % SXE2_TX_DESC_RING_ALIGN) != 0 ||
96 [ # # ]: 0 : ring_depth > SXE2_MAX_RING_DESC ||
97 : : ring_depth < SXE2_MIN_RING_DESC) {
98 : 0 : PMD_LOG_ERR(TX, "number:%u of receive descriptors is invalid", ring_depth);
99 : 0 : ret = -EINVAL;
100 : 0 : goto l_end;
101 : : }
102 : :
103 [ # # ]: 0 : *free_thresh = (uint16_t)((tx_conf->tx_free_thresh) ?
104 : : tx_conf->tx_free_thresh : DEFAULT_TX_FREE_THRESH);
105 [ # # ]: 0 : *rs_thresh = (uint16_t)((tx_conf->tx_rs_thresh) ?
106 : : tx_conf->tx_rs_thresh : DEFAULT_TX_RS_THRESH);
107 : :
108 [ # # ]: 0 : if (*rs_thresh >= (ring_depth - 2)) {
109 : 0 : PMD_LOG_ERR(TX, "tx_rs_thresh must be less than the number "
110 : : "of tx descriptors minus 2. (tx_rs_thresh:%u port:%u)",
111 : : *rs_thresh, dev->data->port_id);
112 : 0 : ret = -EINVAL;
113 : 0 : goto l_end;
114 : : }
115 : :
116 [ # # ]: 0 : if (*free_thresh >= (ring_depth - 3)) {
117 : 0 : PMD_LOG_ERR(TX, "tx_free_thresh must be less than the number "
118 : : "of tx descriptors minus 3. (tx_free_thresh:%u port:%u)",
119 : : *free_thresh, dev->data->port_id);
120 : 0 : ret = -EINVAL;
121 : 0 : goto l_end;
122 : : }
123 : :
124 [ # # ]: 0 : if (*rs_thresh > *free_thresh) {
125 : 0 : PMD_LOG_ERR(TX, "tx_rs_thresh must be less than or equal to "
126 : : "tx_free_thresh. (tx_free_thresh:%u tx_rs_thresh:%u port:%u)",
127 : : *free_thresh, *rs_thresh, dev->data->port_id);
128 : 0 : ret = -EINVAL;
129 : 0 : goto l_end;
130 : : }
131 : :
132 [ # # ]: 0 : if ((ring_depth % *rs_thresh) != 0) {
133 : 0 : PMD_LOG_ERR(TX, "tx_rs_thresh must be a divisor of the "
134 : : "number of tx descriptors. (tx_rs_thresh:%u port:%d ring_depth:%u)",
135 : : *rs_thresh, dev->data->port_id, ring_depth);
136 : 0 : ret = -EINVAL;
137 : 0 : goto l_end;
138 : : }
139 : :
140 : : ret = 0;
141 : :
142 : 0 : l_end:
143 : 0 : return ret;
144 : : }
145 : :
146 : 0 : void __rte_cold sxe2_tx_queue_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
147 : : struct rte_eth_txq_info *qinfo)
148 : : {
149 : 0 : struct sxe2_tx_queue *txq = NULL;
150 : :
151 : 0 : txq = dev->data->tx_queues[queue_id];
152 [ # # ]: 0 : if (txq == NULL) {
153 : 0 : PMD_LOG_WARN(TX, "tx queue:%u is NULL", queue_id);
154 : 0 : goto end;
155 : : }
156 : :
157 : 0 : qinfo->nb_desc = txq->ring_depth;
158 : :
159 : 0 : qinfo->conf.tx_thresh.pthresh = txq->pthresh;
160 : 0 : qinfo->conf.tx_thresh.hthresh = txq->hthresh;
161 : 0 : qinfo->conf.tx_thresh.wthresh = txq->wthresh;
162 : 0 : qinfo->conf.tx_free_thresh = txq->free_thresh;
163 : 0 : qinfo->conf.tx_rs_thresh = txq->rs_thresh;
164 : 0 : qinfo->conf.offloads = txq->offloads;
165 : 0 : qinfo->conf.tx_deferred_start = txq->tx_deferred_start;
166 : :
167 : 0 : end:
168 : 0 : return;
169 : : }
170 : :
171 : 0 : int32_t __rte_cold sxe2_tx_queue_stop(struct rte_eth_dev *dev, uint16_t queue_id)
172 : : {
173 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
174 : 0 : struct sxe2_tx_queue *txq;
175 : 0 : int32_t ret;
176 : 0 : PMD_INIT_FUNC_TRACE();
177 : :
178 [ # # ]: 0 : if (dev->data->tx_queue_state[queue_id] ==
179 : : RTE_ETH_QUEUE_STATE_STOPPED) {
180 : 0 : ret = 0;
181 : 0 : goto l_end;
182 : : }
183 : :
184 : 0 : txq = dev->data->tx_queues[queue_id];
185 [ # # ]: 0 : if (txq == NULL) {
186 : 0 : ret = 0;
187 : 0 : goto l_end;
188 : : }
189 : :
190 : 0 : ret = sxe2_drv_txq_switch(adapter, txq, false);
191 [ # # ]: 0 : if (ret) {
192 : 0 : PMD_LOG_ERR(TX, "Failed to switch tx queue %u off",
193 : : queue_id);
194 : 0 : goto l_end;
195 : : }
196 : :
197 : 0 : txq->ops.mbufs_release(txq);
198 : 0 : txq->ops.queue_reset(txq);
199 : 0 : dev->data->tx_queue_state[queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
200 : 0 : ret = 0;
201 : :
202 : 0 : l_end:
203 : 0 : return ret;
204 : : }
205 : :
206 : 0 : static void __rte_cold sxe2_tx_queue_free(struct sxe2_tx_queue *txq)
207 : : {
208 [ # # ]: 0 : if (txq != NULL) {
209 : 0 : txq->ops.mbufs_release(txq);
210 : 0 : txq->ops.buffer_ring_free(txq);
211 : :
212 : 0 : rte_memzone_free(txq->mz);
213 : 0 : rte_free(txq);
214 : : }
215 : 0 : }
216 : :
217 : 0 : void __rte_cold sxe2_tx_queue_release(struct rte_eth_dev *dev, uint16_t queue_idx)
218 : : {
219 : 0 : (void)sxe2_tx_queue_stop(dev, queue_idx);
220 : 0 : sxe2_tx_queue_free(dev->data->tx_queues[queue_idx]);
221 : 0 : dev->data->tx_queues[queue_idx] = NULL;
222 : 0 : }
223 : :
224 : 0 : void __rte_cold sxe2_all_txqs_release(struct rte_eth_dev *dev)
225 : : {
226 : 0 : struct rte_eth_dev_data *data = dev->data;
227 : 0 : uint16_t nb_txq;
228 : :
229 [ # # ]: 0 : for (nb_txq = 0; nb_txq < data->nb_tx_queues; nb_txq++) {
230 [ # # ]: 0 : if (data->tx_queues[nb_txq] == NULL)
231 : 0 : continue;
232 : :
233 : 0 : sxe2_tx_queue_release(dev, nb_txq);
234 : 0 : data->tx_queues[nb_txq] = NULL;
235 : : }
236 : 0 : data->nb_tx_queues = 0;
237 : 0 : }
238 : :
239 : : static struct sxe2_tx_queue
240 : 0 : *sxe2_tx_queue_alloc(struct rte_eth_dev *dev, uint16_t queue_idx,
241 : : uint16_t ring_depth, uint32_t socket_id)
242 : : {
243 : 0 : struct sxe2_tx_queue *txq;
244 : 0 : const struct rte_memzone *tz;
245 : :
246 [ # # ]: 0 : if (dev->data->tx_queues[queue_idx]) {
247 : 0 : sxe2_tx_queue_release(dev, queue_idx);
248 : 0 : dev->data->tx_queues[queue_idx] = NULL;
249 : : }
250 : :
251 : 0 : txq = rte_zmalloc_socket("tx_queue", sizeof(struct sxe2_tx_queue),
252 : : RTE_CACHE_LINE_SIZE, socket_id);
253 [ # # ]: 0 : if (txq == NULL) {
254 : 0 : PMD_LOG_ERR(TX, "tx queue:%d alloc failed", queue_idx);
255 : 0 : goto l_end;
256 : : }
257 : :
258 : 0 : tz = rte_eth_dma_zone_reserve(dev, "tx_dma", queue_idx,
259 : : sizeof(union sxe2_tx_data_desc) * SXE2_MAX_RING_DESC,
260 : : SXE2_DESC_ADDR_ALIGN, socket_id);
261 [ # # ]: 0 : if (tz == NULL) {
262 : 0 : PMD_LOG_ERR(TX, "tx desc ring alloc failed, queue_id:%d", queue_idx);
263 : 0 : rte_free(txq);
264 : 0 : txq = NULL;
265 : 0 : goto l_end;
266 : : }
267 : :
268 : 0 : txq->buffer_ring = rte_zmalloc_socket("tx_buffer_ring",
269 : : sizeof(struct sxe2_tx_buffer) * ring_depth,
270 : : RTE_CACHE_LINE_SIZE, socket_id);
271 [ # # ]: 0 : if (txq->buffer_ring == NULL) {
272 : 0 : PMD_LOG_ERR(TX, "tx buffer alloc failed, queue_id:%d", queue_idx);
273 : 0 : rte_memzone_free(tz);
274 : 0 : rte_free(txq);
275 : 0 : txq = NULL;
276 : 0 : goto l_end;
277 : : }
278 : :
279 : 0 : txq->mz = tz;
280 : 0 : txq->base_addr = tz->iova;
281 : 0 : txq->desc_ring = (volatile union sxe2_tx_data_desc *)tz->addr;
282 : :
283 : 0 : l_end:
284 : 0 : return txq;
285 : : }
286 : :
287 : 0 : int32_t __rte_cold sxe2_tx_queue_setup(struct rte_eth_dev *dev,
288 : : uint16_t queue_idx, uint16_t nb_desc, uint32_t socket_id,
289 : : const struct rte_eth_txconf *tx_conf)
290 : : {
291 : 0 : int32_t ret = 0;
292 : 0 : uint16_t tx_rs_thresh;
293 : 0 : uint16_t tx_free_thresh;
294 : 0 : struct sxe2_tx_queue *txq;
295 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
296 : 0 : struct sxe2_vsi *vsi = adapter->vsi_ctxt.main_vsi;
297 : 0 : uint64_t offloads;
298 : 0 : PMD_INIT_FUNC_TRACE();
299 : :
300 : 0 : ret = sxe2_txq_arg_validate(dev, nb_desc, &tx_rs_thresh, &tx_free_thresh, tx_conf);
301 [ # # ]: 0 : if (ret) {
302 : 0 : PMD_LOG_ERR(TX, "tx queue:%u arg validate failed", queue_idx);
303 : 0 : goto end;
304 : : }
305 : :
306 : 0 : offloads = tx_conf->offloads | dev->data->dev_conf.txmode.offloads;
307 : :
308 : 0 : txq = sxe2_tx_queue_alloc(dev, queue_idx, nb_desc, socket_id);
309 [ # # ]: 0 : if (txq == NULL) {
310 : 0 : PMD_LOG_ERR(TX, "failed to alloc sxe2vf tx queue:%u resource", queue_idx);
311 : 0 : ret = -ENOMEM;
312 : 0 : goto end;
313 : : }
314 : :
315 : 0 : txq->vlan_flag = SXE2_TX_FLAGS_VLAN_TAG_LOC_L2TAG1;
316 : 0 : txq->ring_depth = nb_desc;
317 : 0 : txq->rs_thresh = tx_rs_thresh;
318 : 0 : txq->free_thresh = tx_free_thresh;
319 : 0 : txq->pthresh = tx_conf->tx_thresh.pthresh;
320 : 0 : txq->hthresh = tx_conf->tx_thresh.hthresh;
321 : 0 : txq->wthresh = tx_conf->tx_thresh.wthresh;
322 : 0 : txq->queue_id = queue_idx;
323 : 0 : txq->idx_in_func = vsi->txqs.base_idx_in_func + queue_idx;
324 : 0 : txq->port_id = dev->data->port_id;
325 : 0 : txq->offloads = offloads;
326 : 0 : txq->tx_deferred_start = tx_conf->tx_deferred_start;
327 : 0 : txq->vsi = vsi;
328 : 0 : txq->ops = sxe2_tx_default_ops_get();
329 : 0 : txq->ops.queue_reset(txq);
330 : :
331 : 0 : dev->data->tx_queues[queue_idx] = txq;
332 : 0 : ret = 0;
333 : :
334 : 0 : end:
335 : 0 : return ret;
336 : : }
337 : :
338 : 0 : int32_t __rte_cold sxe2_tx_queue_start(struct rte_eth_dev *dev, uint16_t queue_id)
339 : : {
340 : 0 : int32_t ret = 0;
341 : 0 : struct sxe2_tx_queue *txq;
342 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
343 : 0 : PMD_INIT_FUNC_TRACE();
344 : :
345 [ # # ]: 0 : if (dev->data->tx_queue_state[queue_id] == RTE_ETH_QUEUE_STATE_STARTED) {
346 : 0 : ret = 0;
347 : 0 : goto l_end;
348 : : }
349 : :
350 : 0 : txq = dev->data->tx_queues[queue_id];
351 [ # # ]: 0 : if (txq == NULL) {
352 : 0 : PMD_LOG_ERR(TX, "tx queue:%u is not available or setup", queue_id);
353 : 0 : ret = -EINVAL;
354 : 0 : goto l_end;
355 : : }
356 : :
357 : 0 : ret = sxe2_drv_txq_ctxt_cfg(adapter, txq, 1);
358 [ # # ]: 0 : if (ret) {
359 : 0 : PMD_LOG_ERR(TX, "tx queue:%u config ctxt fail", queue_id);
360 : :
361 : 0 : (void)sxe2_drv_txq_switch(adapter, txq, false);
362 : 0 : txq->ops.mbufs_release(txq);
363 : 0 : txq->ops.queue_reset(txq);
364 : 0 : goto l_end;
365 : : }
366 : :
367 : 0 : sxe2_tx_tail_init(adapter, txq);
368 : :
369 : 0 : dev->data->tx_queue_state[queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
370 : 0 : ret = 0;
371 : :
372 : 0 : l_end:
373 : 0 : return ret;
374 : : }
375 : :
376 : 0 : int32_t __rte_cold sxe2_txqs_all_start(struct rte_eth_dev *dev)
377 : : {
378 : 0 : struct rte_eth_dev_data *data = dev->data;
379 : 0 : struct sxe2_tx_queue *txq;
380 : 0 : uint16_t nb_txq;
381 : 0 : uint16_t nb_started_txq;
382 : 0 : int32_t ret;
383 : 0 : PMD_INIT_FUNC_TRACE();
384 : :
385 [ # # ]: 0 : for (nb_txq = 0; nb_txq < data->nb_tx_queues; nb_txq++) {
386 : 0 : txq = dev->data->tx_queues[nb_txq];
387 [ # # # # ]: 0 : if (!txq || txq->tx_deferred_start)
388 : 0 : continue;
389 : :
390 : 0 : ret = sxe2_tx_queue_start(dev, nb_txq);
391 [ # # ]: 0 : if (ret) {
392 : 0 : PMD_LOG_ERR(TX, "Fail to start tx queue %u", nb_txq);
393 : 0 : goto l_free_started_queue;
394 : : }
395 : : }
396 : 0 : ret = 0;
397 : 0 : goto l_end;
398 : :
399 : 0 : l_free_started_queue:
400 [ # # ]: 0 : for (nb_started_txq = 0; nb_started_txq <= nb_txq; nb_started_txq++)
401 : 0 : (void)sxe2_tx_queue_stop(dev, nb_started_txq);
402 : :
403 : 0 : l_end:
404 : 0 : return ret;
405 : : }
406 : :
407 : 0 : void __rte_cold sxe2_txqs_all_stop(struct rte_eth_dev *dev)
408 : : {
409 : 0 : struct rte_eth_dev_data *data = dev->data;
410 : 0 : uint16_t nb_txq;
411 : 0 : int32_t ret;
412 : :
413 [ # # ]: 0 : for (nb_txq = 0; nb_txq < data->nb_tx_queues; nb_txq++) {
414 : 0 : ret = sxe2_tx_queue_stop(dev, nb_txq);
415 [ # # ]: 0 : if (ret) {
416 : 0 : PMD_LOG_WARN(TX, "Fail to stop tx queue %u", nb_txq);
417 : 0 : continue;
418 : : }
419 : : }
420 : 0 : }
|