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 <unistd.h>
12 : : #include "sxe2_txrx.h"
13 : : #include "sxe2_txrx_common.h"
14 : : #include "sxe2_txrx_vec.h"
15 : : #include "sxe2_txrx_poll.h"
16 : : #include "sxe2_ethdev.h"
17 : : #include "sxe2_common_log.h"
18 : : #include "sxe2_osal.h"
19 : : #include "sxe2_cmd_chnl.h"
20 : : #if defined(RTE_ARCH_ARM64)
21 : : #include <rte_cpuflags.h>
22 : : #endif
23 : :
24 : : int32_t __rte_cold
25 : 0 : sxe2_tx_simple_batch_support_check(struct rte_eth_dev *dev,
26 : : uint32_t *batch_flags)
27 : : {
28 : 0 : struct sxe2_tx_queue *txq;
29 : 0 : int32_t ret = 0;
30 : 0 : uint16_t i;
31 : :
32 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; ++i) {
33 : 0 : txq = (struct sxe2_tx_queue *)dev->data->tx_queues[i];
34 [ # # ]: 0 : if (txq == NULL) {
35 : 0 : ret = -EINVAL;
36 : 0 : goto l_end;
37 : : }
38 [ # # ]: 0 : if (txq->offloads != (txq->offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) ||
39 [ # # ]: 0 : txq->rs_thresh < SXE2_TX_PKTS_BURST_BATCH_NUM) {
40 : 0 : ret = -ENOTSUP;
41 : 0 : goto l_end;
42 : : }
43 : : }
44 : 0 : *batch_flags = SXE2_TX_MODE_SIMPLE_BATCH;
45 : 0 : l_end:
46 : 0 : return ret;
47 : : }
48 : :
49 : 0 : static int32_t sxe2_tx_descriptor_status(void *tx_queue, uint16_t offset)
50 : : {
51 : 0 : struct sxe2_tx_queue *txq = (struct sxe2_tx_queue *)tx_queue;
52 : 0 : int32_t ret;
53 : 0 : uint16_t desc_idx;
54 : :
55 [ # # ]: 0 : if (unlikely(offset >= txq->ring_depth)) {
56 : 0 : ret = -EINVAL;
57 : 0 : goto l_end;
58 : : }
59 : 0 : desc_idx = txq->next_use + offset;
60 : 0 : desc_idx = SXE2_DIV_ROUND_UP(desc_idx, txq->rs_thresh) * (txq->rs_thresh);
61 [ # # ]: 0 : if (desc_idx >= txq->ring_depth) {
62 : 0 : desc_idx -= txq->ring_depth;
63 [ # # ]: 0 : if (desc_idx >= txq->ring_depth)
64 : 0 : desc_idx -= txq->ring_depth;
65 : : }
66 [ # # ]: 0 : if (desc_idx == 0)
67 : 0 : desc_idx = txq->rs_thresh - 1;
68 : : else
69 : 0 : desc_idx -= 1;
70 : 0 : if (rte_cpu_to_le_64(SXE2_TX_DESC_DTYPE_DESC_DONE) ==
71 [ # # ]: 0 : (txq->desc_ring[desc_idx].wb.dd &
72 : : rte_cpu_to_le_64(SXE2_TX_DESC_DTYPE_DESC_MASK)))
73 : : ret = RTE_ETH_TX_DESC_DONE;
74 : : else
75 : 0 : ret = RTE_ETH_TX_DESC_FULL;
76 : 0 : l_end:
77 : 0 : return ret;
78 : : }
79 : :
80 : : static inline int32_t sxe2_tx_mbuf_empty_check(struct rte_mbuf *mbuf)
81 : : {
82 : : struct rte_mbuf *m_seg = mbuf;
83 [ # # ]: 0 : while (m_seg != NULL) {
84 [ # # ]: 0 : if (m_seg->data_len == 0)
85 : : return -EINVAL;
86 : 0 : m_seg = m_seg->next;
87 : : }
88 : :
89 : : return 0;
90 : : }
91 : :
92 : 0 : uint16_t sxe2_tx_pkts_prepare(void *tx_queue,
93 : : struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
94 : : {
95 : 0 : struct sxe2_tx_queue *txq = tx_queue;
96 : 0 : struct rte_mbuf *mbuf;
97 : 0 : uint64_t ol_flags = 0;
98 : 0 : int32_t ret = 0;
99 : 0 : int32_t i = 0;
100 : :
101 [ # # ]: 0 : for (i = 0; i < nb_pkts; i++) {
102 : 0 : mbuf = tx_pkts[i];
103 [ # # ]: 0 : if (!mbuf)
104 : 0 : continue;
105 : 0 : ol_flags = mbuf->ol_flags;
106 [ # # ]: 0 : if (!(ol_flags & (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_UDP_SEG))) {
107 [ # # ]: 0 : if (mbuf->nb_segs > SXE2_TX_MTU_SEG_MAX ||
108 [ # # ]: 0 : mbuf->pkt_len > SXE2_FRAME_SIZE_MAX) {
109 : 0 : rte_errno = -EINVAL;
110 : 0 : goto l_end;
111 : : }
112 [ # # ]: 0 : } else if ((mbuf->tso_segsz < SXE2_MIN_TSO_MSS) ||
113 : 0 : (mbuf->tso_segsz > SXE2_MAX_TSO_MSS) ||
114 [ # # ]: 0 : (mbuf->nb_segs > txq->ring_depth) ||
115 [ # # ]: 0 : (mbuf->pkt_len > SXE2_TX_TSO_PKTLEN_MAX)) {
116 : 0 : rte_errno = -EINVAL;
117 : 0 : goto l_end;
118 : : }
119 [ # # ]: 0 : if (mbuf->pkt_len < SXE2_TX_MIN_PKT_LEN) {
120 : 0 : rte_errno = -EINVAL;
121 : 0 : goto l_end;
122 : : }
123 : : #ifdef RTE_ETHDEV_DEBUG_TX
124 : : ret = rte_validate_tx_offload(mbuf);
125 : : if (ret != 0) {
126 : : rte_errno = -ret;
127 : : goto l_end;
128 : : }
129 : : #endif
130 : 0 : ret = rte_net_intel_cksum_prepare(mbuf);
131 [ # # ]: 0 : if (ret != 0) {
132 : 0 : rte_errno = -ret;
133 : 0 : goto l_end;
134 : : }
135 : 0 : ret = sxe2_tx_mbuf_empty_check(mbuf);
136 [ # # ]: 0 : if (ret != 0) {
137 : 0 : rte_errno = -ret;
138 : 0 : goto l_end;
139 : : }
140 : : }
141 : 0 : l_end:
142 : 0 : return i;
143 : : }
144 : :
145 : 0 : void sxe2_tx_mode_func_set(struct rte_eth_dev *dev)
146 : : {
147 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
148 : 0 : uint32_t tx_mode_flags;
149 : 0 : int32_t ret;
150 : 0 : uint32_t vec_flags = 0;
151 : 0 : uint32_t batch_flags = 0;
152 : :
153 : 0 : PMD_INIT_FUNC_TRACE();
154 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
155 : 0 : tx_mode_flags = 0;
156 : 0 : ret = sxe2_tx_vec_support_check(dev, &vec_flags);
157 [ # # # # ]: 0 : if (ret == 0 &&
158 : 0 : rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128) {
159 : 0 : tx_mode_flags = vec_flags;
160 [ # # ]: 0 : if (tx_mode_flags & SXE2_TX_MODE_VEC_SET_MASK) {
161 : 0 : ret = sxe2_tx_queues_vec_prepare(dev);
162 [ # # ]: 0 : if (ret != 0)
163 : 0 : tx_mode_flags &= ~SXE2_TX_MODE_VEC_SET_MASK;
164 : : }
165 : : }
166 : 0 : ret = sxe2_tx_simple_batch_support_check(dev, &batch_flags);
167 [ # # # # ]: 0 : if (ret == 0 && batch_flags == SXE2_TX_MODE_SIMPLE_BATCH)
168 : 0 : tx_mode_flags |= SXE2_TX_MODE_SIMPLE_BATCH;
169 : :
170 : 0 : adapter->q_ctxt.tx_mode_flags = tx_mode_flags;
171 : : } else {
172 : 0 : tx_mode_flags = adapter->q_ctxt.tx_mode_flags;
173 : : }
174 : :
175 : : #ifdef RTE_ARCH_X86
176 [ # # ]: 0 : if (tx_mode_flags & SXE2_TX_MODE_VEC_SET_MASK) {
177 [ # # ]: 0 : if (tx_mode_flags & SXE2_TX_MODE_VEC_OFFLOAD) {
178 : 0 : dev->tx_pkt_prepare = sxe2_tx_pkts_prepare;
179 : 0 : dev->tx_pkt_burst = sxe2_tx_pkts_vec_sse;
180 : : } else {
181 : 0 : dev->tx_pkt_prepare = NULL;
182 : 0 : dev->tx_pkt_burst = sxe2_tx_pkts_vec_sse_simple;
183 : : }
184 : : } else {
185 : : #endif
186 [ # # ]: 0 : if (tx_mode_flags & SXE2_TX_MODE_SIMPLE_BATCH) {
187 : 0 : dev->tx_pkt_prepare = NULL;
188 : 0 : dev->tx_pkt_burst = sxe2_tx_pkts_simple;
189 : : } else {
190 : 0 : dev->tx_pkt_prepare = sxe2_tx_pkts_prepare;
191 : 0 : dev->tx_pkt_burst = sxe2_tx_pkts;
192 : : }
193 : : #ifdef RTE_ARCH_X86
194 : : }
195 : : #endif
196 : 0 : }
197 : :
198 : : static const struct {
199 : : eth_tx_burst_t tx_burst;
200 : : const char *info;
201 : : } sxe2_tx_burst_infos[] = {
202 : : { sxe2_tx_pkts, "Scalar" },
203 : : #ifdef RTE_ARCH_X86
204 : : { sxe2_tx_pkts_vec_sse, "Vector SSE" },
205 : : { sxe2_tx_pkts_vec_sse_simple, "Vector SSE Simple" },
206 : : #endif
207 : : };
208 : :
209 : 0 : int32_t sxe2_tx_burst_mode_get(struct rte_eth_dev *dev,
210 : : __rte_unused uint16_t queue_id, struct rte_eth_burst_mode *mode)
211 : : {
212 : 0 : eth_tx_burst_t pkt_burst = dev->tx_pkt_burst;
213 : 0 : int32_t ret = -EINVAL;
214 : 0 : uint32_t i;
215 : 0 : uint32_t size;
216 : :
217 : 0 : size = RTE_DIM(sxe2_tx_burst_infos);
218 [ # # ]: 0 : for (i = 0; i < size; ++i) {
219 [ # # ]: 0 : if (pkt_burst == sxe2_tx_burst_infos[i].tx_burst) {
220 : 0 : snprintf(mode->info, sizeof(mode->info), "%s",
221 : 0 : sxe2_tx_burst_infos[i].info);
222 : 0 : ret = 0;
223 : 0 : break;
224 : : }
225 : : }
226 : 0 : return ret;
227 : : }
228 : :
229 : 0 : static int32_t sxe2_rx_descriptor_status(void *rx_queue, uint16_t offset)
230 : : {
231 : 0 : struct sxe2_rx_queue *rxq = (struct sxe2_rx_queue *)rx_queue;
232 : 0 : volatile union sxe2_rx_desc *desc;
233 : 0 : int32_t ret;
234 : :
235 [ # # ]: 0 : if (unlikely(offset >= rxq->ring_depth)) {
236 : 0 : ret = -EINVAL;
237 : 0 : goto l_end;
238 : : }
239 [ # # ]: 0 : if (offset >= rxq->ring_depth - rxq->hold_num) {
240 : 0 : ret = RTE_ETH_RX_DESC_UNAVAIL;
241 : 0 : goto l_end;
242 : : }
243 [ # # ]: 0 : if (rxq->processing_idx + offset >= rxq->ring_depth)
244 : 0 : desc = &rxq->desc_ring[rxq->processing_idx + offset - rxq->ring_depth];
245 : : else
246 : 0 : desc = &rxq->desc_ring[rxq->processing_idx + offset];
247 [ # # ]: 0 : if (rte_le_to_cpu_64(desc->wb.status_err_ptype_len) & SXE2_RX_DESC_STATUS_DD_MASK)
248 : : ret = RTE_ETH_RX_DESC_DONE;
249 : : else
250 : 0 : ret = RTE_ETH_RX_DESC_AVAIL;
251 : 0 : l_end:
252 : 0 : PMD_LOG_DEBUG(RX, "Rx queue desc[%u] status:%d queue_id:%u port_id:%u",
253 : : offset, ret, rxq->queue_id, rxq->port_id);
254 : 0 : return ret;
255 : : }
256 : :
257 : 0 : static int32_t sxe2_rx_queue_count(void *rx_queue)
258 : : {
259 : 0 : struct sxe2_rx_queue *rxq = (struct sxe2_rx_queue *)rx_queue;
260 : 0 : volatile union sxe2_rx_desc *desc;
261 : 0 : uint16_t done_num = 0;
262 : :
263 : 0 : desc = &rxq->desc_ring[rxq->processing_idx];
264 [ # # ]: 0 : while ((done_num < rxq->ring_depth) &&
265 [ # # ]: 0 : (rte_le_to_cpu_64(desc->wb.status_err_ptype_len) &
266 : : SXE2_RX_DESC_STATUS_DD_MASK)) {
267 : 0 : done_num += SXE2_RX_QUEUE_CHECK_INTERVAL_NUM;
268 [ # # ]: 0 : if (rxq->processing_idx + done_num >= rxq->ring_depth)
269 : 0 : desc = &rxq->desc_ring[rxq->processing_idx + done_num - rxq->ring_depth];
270 : : else
271 : 0 : desc += SXE2_RX_QUEUE_CHECK_INTERVAL_NUM;
272 : : }
273 : 0 : PMD_LOG_DEBUG(RX, "Rx queue done desc count:%u queue_id:%u port_id:%u",
274 : : done_num, rxq->queue_id, rxq->port_id);
275 : 0 : return done_num;
276 : : }
277 : :
278 : 0 : void sxe2_rx_mode_func_set(struct rte_eth_dev *dev)
279 : : {
280 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
281 : 0 : uint32_t rx_mode_flags = 0;
282 : 0 : int32_t ret;
283 : 0 : uint32_t vec_flags = 0;
284 : 0 : PMD_INIT_FUNC_TRACE();
285 : :
286 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
287 : 0 : ret = sxe2_rx_vec_support_check(dev, &vec_flags);
288 [ # # # # ]: 0 : if (ret == 0 &&
289 : 0 : rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128) {
290 : 0 : rx_mode_flags = vec_flags;
291 [ # # ]: 0 : if ((rx_mode_flags & SXE2_RX_MODE_VEC_SET_MASK) != 0) {
292 : 0 : ret = sxe2_rx_queues_vec_prepare(dev);
293 [ # # ]: 0 : if (ret != 0)
294 : 0 : rx_mode_flags &= ~SXE2_RX_MODE_VEC_SET_MASK;
295 : : }
296 : : }
297 : 0 : adapter->q_ctxt.rx_mode_flags = rx_mode_flags;
298 : : } else {
299 : 0 : rx_mode_flags = adapter->q_ctxt.rx_mode_flags;
300 : : }
301 : :
302 : : #ifdef RTE_ARCH_X86
303 [ # # ]: 0 : if (rx_mode_flags & SXE2_RX_MODE_VEC_SET_MASK) {
304 : 0 : dev->rx_pkt_burst = sxe2_rx_pkts_scattered_vec_sse_offload;
305 : 0 : return;
306 : : }
307 : : #endif
308 [ # # ]: 0 : if (sxe2_rx_offload_en_check(dev, RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT))
309 : 0 : dev->rx_pkt_burst = sxe2_rx_pkts_scattered_split;
310 : : else
311 : 0 : dev->rx_pkt_burst = sxe2_rx_pkts_scattered;
312 : : }
313 : :
314 : : static const struct {
315 : : eth_rx_burst_t rx_burst;
316 : : const char *info;
317 : : } sxe2_rx_burst_infos[] = {
318 : : { sxe2_rx_pkts_scattered, "Scalar Scattered" },
319 : : { sxe2_rx_pkts_scattered_split, "Scalar Scattered split" },
320 : : #ifdef RTE_ARCH_X86
321 : : { sxe2_rx_pkts_scattered_vec_sse_offload, "Vector SSE Scattered" },
322 : : #endif
323 : : };
324 : :
325 : 0 : int32_t sxe2_rx_burst_mode_get(struct rte_eth_dev *dev,
326 : : __rte_unused uint16_t queue_id, struct rte_eth_burst_mode *mode)
327 : : {
328 : 0 : eth_rx_burst_t pkt_burst = dev->rx_pkt_burst;
329 : 0 : int32_t ret = -EINVAL;
330 : 0 : uint32_t i, size;
331 : 0 : size = RTE_DIM(sxe2_rx_burst_infos);
332 [ # # ]: 0 : for (i = 0; i < size; ++i) {
333 [ # # ]: 0 : if (pkt_burst == sxe2_rx_burst_infos[i].rx_burst) {
334 : 0 : snprintf(mode->info, sizeof(mode->info), "%s",
335 : 0 : sxe2_rx_burst_infos[i].info);
336 : 0 : ret = 0;
337 : 0 : break;
338 : : }
339 : : }
340 : 0 : return ret;
341 : : }
342 : :
343 : 0 : void sxe2_set_common_function(struct rte_eth_dev *dev)
344 : : {
345 : 0 : PMD_INIT_FUNC_TRACE();
346 : 0 : dev->rx_queue_count = sxe2_rx_queue_count;
347 : 0 : dev->rx_descriptor_status = sxe2_rx_descriptor_status;
348 : :
349 : 0 : dev->tx_descriptor_status = sxe2_tx_descriptor_status;
350 : 0 : dev->tx_pkt_prepare = sxe2_tx_pkts_prepare;
351 : 0 : }
|