Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : *
3 : : * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
4 : : * Copyright 2016-2024 NXP
5 : : *
6 : : */
7 : :
8 : : #include <time.h>
9 : : #include <net/if.h>
10 : :
11 : : #include <eal_export.h>
12 : : #include <rte_mbuf.h>
13 : : #include <ethdev_driver.h>
14 : : #include <rte_malloc.h>
15 : : #include <rte_memcpy.h>
16 : : #include <rte_string_fns.h>
17 : : #include <dev_driver.h>
18 : : #include <rte_hexdump.h>
19 : :
20 : : #include <bus_fslmc_driver.h>
21 : : #include <fslmc_vfio.h>
22 : : #include <dpaa2_hw_pvt.h>
23 : : #include <dpaa2_hw_dpio.h>
24 : : #include <dpaa2_hw_mempool.h>
25 : :
26 : : #include "dpaa2_pmd_logs.h"
27 : : #include "dpaa2_ethdev.h"
28 : : #include "base/dpaa2_hw_dpni_annot.h"
29 : : #include "dpaa2_parse_dump.h"
30 : :
31 : : static inline uint32_t __rte_hot
32 : : dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf,
33 : : struct dpaa2_annot_hdr *annotation);
34 : :
35 : : static void enable_tx_tstamp(struct qbman_fd *fd) __rte_unused;
36 : :
37 : : static inline rte_mbuf_timestamp_t *
38 : : dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf)
39 : : {
40 : 0 : return RTE_MBUF_DYNFIELD(mbuf,
41 : : dpaa2_timestamp_dynfield_offset, rte_mbuf_timestamp_t *);
42 : : }
43 : :
44 : : #define DPAA2_MBUF_TO_CONTIG_FD(_mbuf, _fd, _bpid) do { \
45 : : DPAA2_SET_FD_ADDR(_fd, DPAA2_MBUF_VADDR_TO_IOVA(_mbuf)); \
46 : : DPAA2_SET_FD_LEN(_fd, _mbuf->data_len); \
47 : : DPAA2_SET_ONLY_FD_BPID(_fd, _bpid); \
48 : : DPAA2_SET_FD_OFFSET(_fd, _mbuf->data_off); \
49 : : DPAA2_SET_FD_FRC(_fd, 0); \
50 : : DPAA2_RESET_FD_CTRL(_fd); \
51 : : DPAA2_RESET_FD_FLC(_fd); \
52 : : } while (0)
53 : :
54 : : static inline void __rte_hot
55 : 0 : dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd,
56 : : void *hw_annot_addr)
57 : : {
58 : 0 : uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd);
59 : : struct dpaa2_annot_hdr *annotation =
60 : : (struct dpaa2_annot_hdr *)hw_annot_addr;
61 : :
62 [ # # ]: 0 : if (unlikely(dpaa2_print_parser_result))
63 : 0 : dpaa2_print_parse_result(annotation);
64 : :
65 : 0 : m->packet_type = RTE_PTYPE_UNKNOWN;
66 [ # # # # : 0 : switch (frc) {
# # # # #
# # # #
# ]
67 : 0 : case DPAA2_PKT_TYPE_ETHER:
68 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER;
69 : 0 : break;
70 : 0 : case DPAA2_PKT_TYPE_IPV4:
71 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
72 : : RTE_PTYPE_L3_IPV4;
73 : 0 : break;
74 : 0 : case DPAA2_PKT_TYPE_IPV6:
75 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
76 : : RTE_PTYPE_L3_IPV6;
77 : 0 : break;
78 : 0 : case DPAA2_PKT_TYPE_IPV4_EXT:
79 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
80 : : RTE_PTYPE_L3_IPV4_EXT;
81 : 0 : break;
82 : 0 : case DPAA2_PKT_TYPE_IPV6_EXT:
83 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
84 : : RTE_PTYPE_L3_IPV6_EXT;
85 : 0 : break;
86 : 0 : case DPAA2_PKT_TYPE_IPV4_TCP:
87 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
88 : : RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP;
89 : 0 : break;
90 : 0 : case DPAA2_PKT_TYPE_IPV6_TCP:
91 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
92 : : RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP;
93 : 0 : break;
94 : 0 : case DPAA2_PKT_TYPE_IPV4_UDP:
95 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
96 : : RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP;
97 : 0 : break;
98 : 0 : case DPAA2_PKT_TYPE_IPV6_UDP:
99 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
100 : : RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP;
101 : 0 : break;
102 : 0 : case DPAA2_PKT_TYPE_IPV4_SCTP:
103 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
104 : : RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP;
105 : 0 : break;
106 : 0 : case DPAA2_PKT_TYPE_IPV6_SCTP:
107 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
108 : : RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_SCTP;
109 : 0 : break;
110 : 0 : case DPAA2_PKT_TYPE_IPV4_ICMP:
111 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
112 : : RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_ICMP;
113 : 0 : break;
114 : 0 : case DPAA2_PKT_TYPE_IPV6_ICMP:
115 : 0 : m->packet_type = RTE_PTYPE_L2_ETHER |
116 : : RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP;
117 : 0 : break;
118 : 0 : default:
119 : 0 : m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation);
120 : : }
121 : 0 : m->hash.rss = fd->simple.flc_hi;
122 : 0 : m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
123 : :
124 [ # # ]: 0 : if (dpaa2_enable_ts[m->port]) {
125 : 0 : *dpaa2_timestamp_dynfield(m) = annotation->word2;
126 : 0 : m->ol_flags |= dpaa2_timestamp_rx_dynflag;
127 : : DPAA2_PMD_DP_DEBUG("pkt timestamp:0x%" PRIx64 "",
128 : : *dpaa2_timestamp_dynfield(m));
129 : : }
130 : :
131 : : DPAA2_PMD_DP_DEBUG("HW frc = 0x%x\t packet type =0x%x "
132 : : "ol_flags =0x%" PRIx64 "",
133 : : frc, m->packet_type, m->ol_flags);
134 : 0 : }
135 : :
136 : : static inline uint32_t __rte_hot
137 : 0 : dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf,
138 : : struct dpaa2_annot_hdr *annotation)
139 : : {
140 : : uint32_t pkt_type = RTE_PTYPE_UNKNOWN;
141 : : uint16_t *vlan_tci;
142 : :
143 : : DPAA2_PMD_DP_DEBUG("(slow parse)annotation(3)=0x%" PRIx64 "\t"
144 : : "(4)=0x%" PRIx64 "\t",
145 : : annotation->word3, annotation->word4);
146 : :
147 : : #if defined(RTE_LIBRTE_IEEE1588)
148 : : if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_PTP)) {
149 : : mbuf->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP;
150 : : mbuf->ol_flags |= RTE_MBUF_F_RX_IEEE1588_TMST;
151 : : }
152 : : #endif
153 : :
154 [ # # ]: 0 : if (BIT_ISSET_AT_POS(annotation->word3, L2_VLAN_1_PRESENT)) {
155 : 0 : vlan_tci = rte_pktmbuf_mtod_offset(mbuf, uint16_t *,
156 : : (VLAN_TCI_OFFSET_1(annotation->word5) >> 16));
157 [ # # ]: 0 : mbuf->vlan_tci = rte_be_to_cpu_16(*vlan_tci);
158 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_VLAN;
159 : : pkt_type |= RTE_PTYPE_L2_ETHER_VLAN;
160 [ # # ]: 0 : } else if (BIT_ISSET_AT_POS(annotation->word3, L2_VLAN_N_PRESENT)) {
161 : 0 : vlan_tci = rte_pktmbuf_mtod_offset(mbuf, uint16_t *,
162 : : (VLAN_TCI_OFFSET_1(annotation->word5) >> 16));
163 [ # # ]: 0 : mbuf->vlan_tci = rte_be_to_cpu_16(*vlan_tci);
164 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_QINQ;
165 : : pkt_type |= RTE_PTYPE_L2_ETHER_QINQ;
166 : : }
167 : :
168 [ # # ]: 0 : if (BIT_ISSET_AT_POS(annotation->word3, L2_ARP_PRESENT)) {
169 : 0 : pkt_type |= RTE_PTYPE_L2_ETHER_ARP;
170 : 0 : goto parse_done;
171 [ # # ]: 0 : } else if (BIT_ISSET_AT_POS(annotation->word3, L2_ETH_MAC_PRESENT)) {
172 : 0 : pkt_type |= RTE_PTYPE_L2_ETHER;
173 : : } else {
174 : 0 : goto parse_done;
175 : : }
176 : :
177 [ # # ]: 0 : if (BIT_ISSET_AT_POS(annotation->word3, L2_MPLS_1_PRESENT |
178 : : L2_MPLS_N_PRESENT))
179 : 0 : pkt_type |= RTE_PTYPE_L2_ETHER_MPLS;
180 : :
181 [ # # ]: 0 : if (BIT_ISSET_AT_POS(annotation->word4, L3_IPV4_1_PRESENT |
182 : : L3_IPV4_N_PRESENT)) {
183 : 0 : pkt_type |= RTE_PTYPE_L3_IPV4;
184 [ # # ]: 0 : if (BIT_ISSET_AT_POS(annotation->word4, L3_IP_1_OPT_PRESENT |
185 : : L3_IP_N_OPT_PRESENT))
186 : 0 : pkt_type |= RTE_PTYPE_L3_IPV4_EXT;
187 [ # # ]: 0 : if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_IPSEC_ESP_PRESENT |
188 : : L3_PROTO_ESP_PRESENT))
189 : 0 : pkt_type |= RTE_PTYPE_TUNNEL_ESP;
190 : :
191 [ # # ]: 0 : } else if (BIT_ISSET_AT_POS(annotation->word4, L3_IPV6_1_PRESENT |
192 : : L3_IPV6_N_PRESENT)) {
193 : 0 : pkt_type |= RTE_PTYPE_L3_IPV6;
194 [ # # ]: 0 : if (BIT_ISSET_AT_POS(annotation->word4, L3_IP_1_OPT_PRESENT |
195 : : L3_IP_N_OPT_PRESENT))
196 : 0 : pkt_type |= RTE_PTYPE_L3_IPV6_EXT;
197 [ # # ]: 0 : if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_IPSEC_ESP_PRESENT |
198 : : L3_PROTO_ESP_PRESENT))
199 : 0 : pkt_type |= RTE_PTYPE_TUNNEL_ESP;
200 : : } else {
201 : 0 : goto parse_done;
202 : : }
203 : :
204 [ # # ]: 0 : if (BIT_ISSET_AT_POS(annotation->word8, DPAA2_ETH_FAS_L3CE))
205 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
206 : : else
207 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
208 [ # # ]: 0 : if (BIT_ISSET_AT_POS(annotation->word8, DPAA2_ETH_FAS_L4CE))
209 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
210 : : else
211 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
212 : :
213 [ # # ]: 0 : if (BIT_ISSET_AT_POS(annotation->word4, L3_IP_1_FIRST_FRAGMENT |
214 : : L3_IP_1_MORE_FRAGMENT |
215 : : L3_IP_N_FIRST_FRAGMENT |
216 : : L3_IP_N_MORE_FRAGMENT)) {
217 : 0 : pkt_type |= RTE_PTYPE_L4_FRAG;
218 : 0 : goto parse_done;
219 : : } else {
220 : 0 : pkt_type |= RTE_PTYPE_L4_NONFRAG;
221 : : }
222 : :
223 [ # # ]: 0 : if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_UDP_PRESENT))
224 : : pkt_type |= RTE_PTYPE_L4_UDP;
225 : :
226 [ # # ]: 0 : else if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_TCP_PRESENT))
227 : 0 : pkt_type |= RTE_PTYPE_L4_TCP;
228 : :
229 [ # # ]: 0 : else if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_SCTP_PRESENT))
230 : : pkt_type |= RTE_PTYPE_L4_SCTP;
231 : :
232 [ # # ]: 0 : else if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_ICMP_PRESENT))
233 : 0 : pkt_type |= RTE_PTYPE_L4_ICMP;
234 : :
235 : : else if (BIT_ISSET_AT_POS(annotation->word4, L3_IP_UNKNOWN_PROTOCOL))
236 : : pkt_type |= RTE_PTYPE_UNKNOWN;
237 : :
238 : 0 : parse_done:
239 : 0 : return pkt_type;
240 : : }
241 : :
242 : : static inline uint32_t __rte_hot
243 : 0 : dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr)
244 : : {
245 : : struct dpaa2_annot_hdr *annotation =
246 : : (struct dpaa2_annot_hdr *)hw_annot_addr;
247 : :
248 : : DPAA2_PMD_DP_DEBUG("(fast parse) Annotation = 0x%" PRIx64 "\t",
249 : : annotation->word4);
250 : :
251 [ # # ]: 0 : if (BIT_ISSET_AT_POS(annotation->word8, DPAA2_ETH_FAS_L3CE))
252 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
253 : : else
254 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
255 [ # # ]: 0 : if (BIT_ISSET_AT_POS(annotation->word8, DPAA2_ETH_FAS_L4CE))
256 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
257 : : else
258 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
259 : :
260 [ # # ]: 0 : if (unlikely(dpaa2_print_parser_result))
261 : 0 : dpaa2_print_parse_result(annotation);
262 : :
263 [ # # ]: 0 : if (dpaa2_enable_ts[mbuf->port]) {
264 : 0 : *dpaa2_timestamp_dynfield(mbuf) = annotation->word2;
265 : 0 : mbuf->ol_flags |= dpaa2_timestamp_rx_dynflag;
266 : : DPAA2_PMD_DP_DEBUG("pkt timestamp: 0x%" PRIx64 "",
267 : : *dpaa2_timestamp_dynfield(mbuf));
268 : : }
269 : :
270 : : /* Check detailed parsing requirement */
271 [ # # ]: 0 : if (annotation->word3 & 0x7FFFFC3FFFF)
272 : 0 : return dpaa2_dev_rx_parse_slow(mbuf, annotation);
273 : :
274 : : /* Return some common types from parse processing */
275 [ # # # # : 0 : switch (annotation->word4) {
# # # ]
276 : : case DPAA2_L3_IPv4:
277 : : return RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4;
278 : 0 : case DPAA2_L3_IPv6:
279 : 0 : return RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6;
280 : 0 : case DPAA2_L3_IPv4_TCP:
281 : 0 : return RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 |
282 : : RTE_PTYPE_L4_TCP;
283 : 0 : case DPAA2_L3_IPv4_UDP:
284 : 0 : return RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 |
285 : : RTE_PTYPE_L4_UDP;
286 : 0 : case DPAA2_L3_IPv6_TCP:
287 : 0 : return RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 |
288 : : RTE_PTYPE_L4_TCP;
289 : 0 : case DPAA2_L3_IPv6_UDP:
290 : 0 : return RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 |
291 : : RTE_PTYPE_L4_UDP;
292 : : default:
293 : : break;
294 : : }
295 : :
296 : 0 : return dpaa2_dev_rx_parse_slow(mbuf, annotation);
297 : : }
298 : :
299 : : static inline struct rte_mbuf *__rte_hot
300 : 0 : eth_sg_fd_to_mbuf(const struct qbman_fd *fd,
301 : : int port_id)
302 : : {
303 : : struct qbman_sge *sgt, *sge;
304 : : size_t sg_addr, fd_addr;
305 : : int i = 0;
306 : : void *hw_annot_addr;
307 : : struct rte_mbuf *first_seg, *next_seg, *cur_seg, *temp;
308 : :
309 : 0 : fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd));
310 : : hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE);
311 : :
312 : : /* Get Scatter gather table address */
313 : 0 : sgt = (struct qbman_sge *)(fd_addr + DPAA2_GET_FD_OFFSET(fd));
314 : :
315 : : sge = &sgt[i++];
316 : 0 : sg_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge));
317 : :
318 : : /* First Scatter gather entry */
319 : 0 : first_seg = DPAA2_INLINE_MBUF_FROM_BUF(sg_addr,
320 : : rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size);
321 : : /* Prepare all the metadata for first segment */
322 : 0 : first_seg->buf_addr = (uint8_t *)sg_addr;
323 : 0 : first_seg->ol_flags = 0;
324 : 0 : first_seg->data_off = DPAA2_GET_FLE_OFFSET(sge);
325 : 0 : first_seg->data_len = sge->length & 0x1FFFF;
326 : 0 : first_seg->pkt_len = DPAA2_GET_FD_LEN(fd);
327 : 0 : first_seg->nb_segs = 1;
328 : 0 : first_seg->next = NULL;
329 : 0 : first_seg->port = port_id;
330 [ # # ]: 0 : if (dpaa2_svr_family == SVR_LX2160A)
331 : 0 : dpaa2_dev_rx_parse_new(first_seg, fd, hw_annot_addr);
332 : : else
333 : 0 : first_seg->packet_type =
334 : 0 : dpaa2_dev_rx_parse(first_seg, hw_annot_addr);
335 : :
336 : : rte_mbuf_refcnt_set(first_seg, 1);
337 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
338 : : rte_mempool_check_cookies(rte_mempool_from_obj((void *)first_seg),
339 : : (void **)&first_seg, 1, 1);
340 : : #endif
341 : : cur_seg = first_seg;
342 [ # # ]: 0 : while (!DPAA2_SG_IS_FINAL(sge)) {
343 : 0 : sge = &sgt[i++];
344 : 0 : sg_addr = (size_t)DPAA2_IOVA_TO_VADDR(
345 : : DPAA2_GET_FLE_ADDR(sge));
346 : 0 : next_seg = DPAA2_INLINE_MBUF_FROM_BUF(sg_addr,
347 : : rte_dpaa2_bpid_info[DPAA2_GET_FLE_BPID(sge)].meta_data_size);
348 : 0 : next_seg->buf_addr = (uint8_t *)sg_addr;
349 : 0 : next_seg->data_off = DPAA2_GET_FLE_OFFSET(sge);
350 : 0 : next_seg->data_len = sge->length & 0x1FFFF;
351 : 0 : first_seg->nb_segs += 1;
352 : : rte_mbuf_refcnt_set(next_seg, 1);
353 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
354 : : rte_mempool_check_cookies(rte_mempool_from_obj((void *)next_seg),
355 : : (void **)&next_seg, 1, 1);
356 : : #endif
357 : 0 : cur_seg->next = next_seg;
358 : 0 : next_seg->next = NULL;
359 : : cur_seg = next_seg;
360 : : }
361 [ # # ]: 0 : temp = DPAA2_INLINE_MBUF_FROM_BUF(fd_addr,
362 : : rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size);
363 : : rte_mbuf_refcnt_set(temp, 1);
364 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
365 : : rte_mempool_check_cookies(rte_mempool_from_obj((void *)temp),
366 : : (void **)&temp, 1, 1);
367 : : #endif
368 : : rte_pktmbuf_free_seg(temp);
369 : :
370 : 0 : return (void *)first_seg;
371 : : }
372 : :
373 : : static inline struct rte_mbuf *__rte_hot
374 : 0 : eth_fd_to_mbuf(const struct qbman_fd *fd,
375 : : int port_id)
376 : : {
377 : 0 : void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd));
378 : : void *hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE);
379 : 0 : struct rte_mbuf *mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr,
380 : : rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size);
381 : :
382 : : /* need to repopulated some of the fields,
383 : : * as they may have changed in last transmission
384 : : */
385 : 0 : mbuf->nb_segs = 1;
386 : 0 : mbuf->ol_flags = 0;
387 : 0 : mbuf->data_off = DPAA2_GET_FD_OFFSET(fd);
388 : 0 : mbuf->data_len = DPAA2_GET_FD_LEN(fd);
389 : 0 : mbuf->pkt_len = mbuf->data_len;
390 : 0 : mbuf->port = port_id;
391 : 0 : mbuf->next = NULL;
392 [ # # ]: 0 : mbuf->hash.sched.color = DPAA2_GET_FD_DROPP(fd);
393 : : rte_mbuf_refcnt_set(mbuf, 1);
394 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
395 : : rte_mempool_check_cookies(rte_mempool_from_obj((void *)mbuf),
396 : : (void **)&mbuf, 1, 1);
397 : : #endif
398 : :
399 : : /* Parse the packet */
400 : : /* parse results for LX2 are there in FRC field of FD.
401 : : * For other DPAA2 platforms , parse results are after
402 : : * the private - sw annotation area
403 : : */
404 : :
405 [ # # ]: 0 : if (dpaa2_svr_family == SVR_LX2160A)
406 : 0 : dpaa2_dev_rx_parse_new(mbuf, fd, hw_annot_addr);
407 : : else
408 : 0 : mbuf->packet_type = dpaa2_dev_rx_parse(mbuf, hw_annot_addr);
409 : :
410 : : DPAA2_PMD_DP_DEBUG("to mbuf - mbuf =%p, mbuf->buf_addr =%p, off = %d,"
411 : : "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d",
412 : : mbuf, mbuf->buf_addr, mbuf->data_off,
413 : : DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ADDR(fd),
414 : : rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size,
415 : : DPAA2_GET_FD_BPID(fd), DPAA2_GET_FD_LEN(fd));
416 : :
417 : 0 : return mbuf;
418 : : }
419 : :
420 : : static int __rte_noinline __rte_hot
421 : 0 : eth_mbuf_to_sg_fd(struct rte_mbuf *mbuf,
422 : : struct qbman_fd *fd,
423 : : struct sw_buf_free *free_buf,
424 : : uint32_t *free_count,
425 : : uint32_t pkt_id,
426 : : uint16_t bpid)
427 : : {
428 : : struct rte_mbuf *cur_seg = mbuf, *mi, *temp;
429 : : struct qbman_sge *sgt, *sge = NULL;
430 : : int i, offset = 0;
431 : :
432 : : #ifdef RTE_LIBRTE_IEEE1588
433 : : /* annotation area for timestamp in first buffer */
434 : : offset = 0x64;
435 : : #endif
436 [ # # ]: 0 : if (RTE_MBUF_DIRECT(mbuf) &&
437 [ # # ]: 0 : (mbuf->data_off > (mbuf->nb_segs * sizeof(struct qbman_sge)
438 : : + offset))) {
439 : : temp = mbuf;
440 [ # # ]: 0 : if (rte_mbuf_refcnt_read(temp) > 1) {
441 : : /* If refcnt > 1, invalid bpid is set to ensure
442 : : * buffer is not freed by HW
443 : : */
444 : : fd->simple.bpid_offset = 0;
445 : 0 : DPAA2_SET_FD_IVP(fd);
446 : 0 : rte_mbuf_refcnt_update(temp, -1);
447 : : } else {
448 : 0 : DPAA2_SET_ONLY_FD_BPID(fd, bpid);
449 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
450 : : rte_mempool_check_cookies(rte_mempool_from_obj((void *)temp),
451 : : (void **)&temp, 1, 0);
452 : : #endif
453 : : }
454 : 0 : DPAA2_SET_FD_OFFSET(fd, offset);
455 : : } else {
456 : 0 : temp = rte_pktmbuf_alloc(dpaa2_tx_sg_pool);
457 [ # # ]: 0 : if (temp == NULL) {
458 : : DPAA2_PMD_DP_DEBUG("No memory to allocate S/G table");
459 : : return -ENOMEM;
460 : : }
461 : 0 : DPAA2_SET_ONLY_FD_BPID(fd, mempool_to_bpid(dpaa2_tx_sg_pool));
462 : 0 : DPAA2_SET_FD_OFFSET(fd, temp->data_off);
463 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
464 : : rte_mempool_check_cookies(rte_mempool_from_obj((void *)temp),
465 : : (void **)&temp, 1, 0);
466 : : #endif
467 : : }
468 : 0 : DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(temp));
469 : 0 : DPAA2_SET_FD_LEN(fd, mbuf->pkt_len);
470 : 0 : DPAA2_FD_SET_FORMAT(fd, qbman_fd_sg);
471 : 0 : DPAA2_RESET_FD_FRC(fd);
472 : 0 : DPAA2_RESET_FD_CTRL(fd);
473 : 0 : DPAA2_RESET_FD_FLC(fd);
474 : : /*Set Scatter gather table and Scatter gather entries*/
475 : 0 : sgt = (struct qbman_sge *)(
476 : 0 : (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd))
477 : 0 : + DPAA2_GET_FD_OFFSET(fd));
478 : :
479 [ # # ]: 0 : for (i = 0; i < mbuf->nb_segs; i++) {
480 : 0 : sge = &sgt[i];
481 : : /*Resetting the buffer pool id and offset field*/
482 [ # # ]: 0 : sge->fin_bpid_offset = 0;
483 : 0 : DPAA2_SET_FLE_ADDR(sge, rte_pktmbuf_iova(cur_seg));
484 : 0 : sge->length = cur_seg->data_len;
485 [ # # ]: 0 : if (RTE_MBUF_DIRECT(cur_seg)) {
486 : : /* if we are using inline SGT in same buffers
487 : : * set the FLE FMT as Frame Data Section
488 : : */
489 [ # # ]: 0 : if (temp == cur_seg) {
490 : : DPAA2_SG_SET_FORMAT(sge, qbman_fd_list);
491 : 0 : DPAA2_SET_FLE_IVP(sge);
492 : : } else {
493 [ # # ]: 0 : if (rte_mbuf_refcnt_read(cur_seg) > 1) {
494 : : /* If refcnt > 1, invalid bpid is set to ensure
495 : : * buffer is not freed by HW
496 : : */
497 : 0 : DPAA2_SET_FLE_IVP(sge);
498 : 0 : rte_mbuf_refcnt_update(cur_seg, -1);
499 : : } else {
500 : 0 : DPAA2_SET_FLE_BPID(sge,
501 : : mempool_to_bpid(cur_seg->pool));
502 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
503 : : rte_mempool_check_cookies(rte_mempool_from_obj((void *)cur_seg),
504 : : (void **)&cur_seg, 1, 0);
505 : : #endif
506 : : }
507 : : }
508 [ # # ]: 0 : } else if (RTE_MBUF_HAS_EXTBUF(cur_seg)) {
509 : 0 : free_buf[*free_count].seg = cur_seg;
510 : 0 : free_buf[*free_count].pkt_id = pkt_id;
511 : 0 : ++*free_count;
512 : 0 : DPAA2_SET_FLE_IVP(sge);
513 : : } else {
514 : : /* Get owner MBUF from indirect buffer */
515 : : mi = rte_mbuf_from_indirect(cur_seg);
516 [ # # ]: 0 : if (rte_mbuf_refcnt_read(mi) > 1) {
517 : : /* If refcnt > 1, invalid bpid is set to ensure
518 : : * owner buffer is not freed by HW
519 : : */
520 : 0 : DPAA2_SET_FLE_IVP(sge);
521 : : } else {
522 : 0 : DPAA2_SET_FLE_BPID(sge,
523 : : mempool_to_bpid(mi->pool));
524 : 0 : rte_mbuf_refcnt_update(mi, 1);
525 : : }
526 : 0 : free_buf[*free_count].seg = cur_seg;
527 : 0 : free_buf[*free_count].pkt_id = pkt_id;
528 : 0 : ++*free_count;
529 : : }
530 : 0 : cur_seg = cur_seg->next;
531 : : }
532 : 0 : DPAA2_SG_SET_FINAL(sge, true);
533 : 0 : return 0;
534 : : }
535 : :
536 : : static void
537 : : eth_mbuf_to_fd(struct rte_mbuf *mbuf,
538 : : struct qbman_fd *fd,
539 : : struct sw_buf_free *buf_to_free,
540 : : uint32_t *free_count,
541 : : uint32_t pkt_id,
542 : : uint16_t bpid) __rte_unused;
543 : :
544 : : static void __rte_noinline __rte_hot
545 : 0 : eth_mbuf_to_fd(struct rte_mbuf *mbuf,
546 : : struct qbman_fd *fd,
547 : : struct sw_buf_free *buf_to_free,
548 : : uint32_t *free_count,
549 : : uint32_t pkt_id,
550 : : uint16_t bpid)
551 : : {
552 : 0 : DPAA2_MBUF_TO_CONTIG_FD(mbuf, fd, bpid);
553 : :
554 : : DPAA2_PMD_DP_DEBUG("mbuf =%p, mbuf->buf_addr =%p, off = %d,"
555 : : "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d",
556 : : mbuf, mbuf->buf_addr, mbuf->data_off,
557 : : DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ADDR(fd),
558 : : rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size,
559 : : DPAA2_GET_FD_BPID(fd), DPAA2_GET_FD_LEN(fd));
560 [ # # ]: 0 : if (RTE_MBUF_DIRECT(mbuf)) {
561 [ # # ]: 0 : if (rte_mbuf_refcnt_read(mbuf) > 1) {
562 : 0 : DPAA2_SET_FD_IVP(fd);
563 : 0 : rte_mbuf_refcnt_update(mbuf, -1);
564 : : }
565 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
566 : : else
567 : : rte_mempool_check_cookies(rte_mempool_from_obj((void *)mbuf),
568 : : (void **)&mbuf, 1, 0);
569 : : #endif
570 [ # # ]: 0 : } else if (RTE_MBUF_HAS_EXTBUF(mbuf)) {
571 : 0 : buf_to_free[*free_count].seg = mbuf;
572 : 0 : buf_to_free[*free_count].pkt_id = pkt_id;
573 : 0 : ++*free_count;
574 : 0 : DPAA2_SET_FD_IVP(fd);
575 : : } else {
576 : : struct rte_mbuf *mi;
577 : :
578 : : mi = rte_mbuf_from_indirect(mbuf);
579 [ # # ]: 0 : if (rte_mbuf_refcnt_read(mi) > 1)
580 : 0 : DPAA2_SET_FD_IVP(fd);
581 : : else
582 : 0 : rte_mbuf_refcnt_update(mi, 1);
583 : :
584 : 0 : buf_to_free[*free_count].seg = mbuf;
585 : 0 : buf_to_free[*free_count].pkt_id = pkt_id;
586 : 0 : ++*free_count;
587 : : }
588 : 0 : }
589 : :
590 : : static inline int __rte_hot
591 : 0 : eth_copy_mbuf_to_fd(struct rte_mbuf *mbuf,
592 : : struct qbman_fd *fd, uint16_t bpid)
593 : : {
594 : : struct rte_mbuf *m;
595 : 0 : void *mb = NULL;
596 : :
597 [ # # ]: 0 : if (rte_dpaa2_mbuf_alloc_bulk(
598 : 0 : rte_dpaa2_bpid_info[bpid].bp_list->mp, &mb, 1)) {
599 : : DPAA2_PMD_DP_DEBUG("Unable to allocated DPAA2 buffer");
600 : : return -1;
601 : : }
602 : 0 : m = (struct rte_mbuf *)mb;
603 : 0 : memcpy((char *)m->buf_addr + mbuf->data_off,
604 : 0 : (void *)((char *)mbuf->buf_addr + mbuf->data_off),
605 : 0 : mbuf->pkt_len);
606 : :
607 : : /* Copy required fields */
608 : 0 : m->data_off = mbuf->data_off;
609 : 0 : m->ol_flags = mbuf->ol_flags;
610 : 0 : m->packet_type = mbuf->packet_type;
611 : 0 : m->tx_offload = mbuf->tx_offload;
612 : :
613 : 0 : DPAA2_MBUF_TO_CONTIG_FD(m, fd, bpid);
614 : :
615 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
616 : : rte_mempool_check_cookies(rte_mempool_from_obj((void *)m),
617 : : (void **)&m, 1, 0);
618 : : #endif
619 : : DPAA2_PMD_DP_DEBUG(
620 : : "mbuf: %p, BMAN buf addr: %p, fdaddr: %" PRIx64 ", bpid: %d,"
621 : : " meta: %d, off: %d, len: %d",
622 : : (void *)mbuf,
623 : : mbuf->buf_addr,
624 : : DPAA2_GET_FD_ADDR(fd),
625 : : DPAA2_GET_FD_BPID(fd),
626 : : rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size,
627 : : DPAA2_GET_FD_OFFSET(fd),
628 : : DPAA2_GET_FD_LEN(fd));
629 : :
630 : 0 : return 0;
631 : : }
632 : :
633 : : static void
634 : 0 : dump_err_pkts(struct dpaa2_queue *dpaa2_q)
635 : : {
636 : : /* Function receive frames for a given device and VQ */
637 : : struct qbman_result *dq_storage;
638 : 0 : uint32_t fqid = dpaa2_q->fqid;
639 : : int ret, num_rx = 0;
640 : : uint8_t pending, status;
641 : : struct qbman_swp *swp;
642 : : const struct qbman_fd *fd;
643 : : struct qbman_pull_desc pulldesc;
644 [ # # ]: 0 : struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data;
645 : : uint32_t lcore_id = rte_lcore_id();
646 : : void *v_addr, *hw_annot_addr;
647 : : struct dpaa2_fas *fas;
648 : :
649 [ # # ]: 0 : if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
650 : 0 : ret = dpaa2_affine_qbman_swp();
651 [ # # ]: 0 : if (ret) {
652 : 0 : DPAA2_PMD_ERR("Failed to allocate IO portal, tid: %d",
653 : : rte_gettid());
654 : 0 : return;
655 : : }
656 : : }
657 : 0 : swp = DPAA2_PER_LCORE_PORTAL;
658 : :
659 : 0 : dq_storage = dpaa2_q->q_storage[lcore_id]->dq_storage[0];
660 : 0 : qbman_pull_desc_clear(&pulldesc);
661 : 0 : qbman_pull_desc_set_fq(&pulldesc, fqid);
662 : 0 : qbman_pull_desc_set_storage(&pulldesc, dq_storage,
663 : : (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1);
664 : 0 : qbman_pull_desc_set_numframes(&pulldesc, dpaa2_dqrr_size);
665 : :
666 : : while (1) {
667 [ # # ]: 0 : if (qbman_swp_pull(swp, &pulldesc)) {
668 : : DPAA2_PMD_DP_DEBUG("VDQ command is not issued.QBMAN is busy");
669 : : /* Portal was busy, try again */
670 : : continue;
671 : : }
672 : : break;
673 : : }
674 : :
675 : : /* Check if the previous issued command is completed. */
676 [ # # ]: 0 : while (!qbman_check_command_complete(dq_storage))
677 : : ;
678 : :
679 : : pending = 1;
680 : : do {
681 : : /* Loop until the dq_storage is updated with
682 : : * new token by QBMAN
683 : : */
684 [ # # ]: 0 : while (!qbman_check_new_result(dq_storage))
685 : : ;
686 : :
687 : : /* Check whether Last Pull command is Expired and
688 : : * setting Condition for Loop termination
689 : : */
690 [ # # ]: 0 : if (qbman_result_DQ_is_pull_complete(dq_storage)) {
691 : : pending = 0;
692 : : /* Check for valid frame. */
693 : 0 : status = qbman_result_DQ_flags(dq_storage);
694 [ # # ]: 0 : if (unlikely((status &
695 : : QBMAN_DQ_STAT_VALIDFRAME) == 0))
696 : 0 : continue;
697 : : }
698 : 0 : fd = qbman_result_DQ_fd(dq_storage);
699 : 0 : v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd));
700 : : hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE);
701 : : fas = hw_annot_addr;
702 : :
703 : 0 : DPAA2_PMD_ERR("[%d] error packet on port[%d]:"
704 : : " fd_off: %d, fd_err: %x, fas_status: %x",
705 : : rte_lcore_id(), eth_data->port_id,
706 : : DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ERR(fd),
707 : : fas->status);
708 : 0 : rte_hexdump(stderr, "Error packet", v_addr,
709 : 0 : DPAA2_GET_FD_OFFSET(fd) + DPAA2_GET_FD_LEN(fd));
710 : :
711 : 0 : dq_storage++;
712 : 0 : num_rx++;
713 [ # # ]: 0 : } while (pending);
714 : :
715 : 0 : dpaa2_q->err_pkts += num_rx;
716 : : }
717 : :
718 : : /* This function assumes that caller will be keep the same value for nb_pkts
719 : : * across calls per queue, if that is not the case, better use non-prefetch
720 : : * version of rx call.
721 : : * It will return the packets as requested in previous call without honoring
722 : : * the current nb_pkts or bufs space.
723 : : */
724 : : uint16_t
725 : 0 : dpaa2_dev_prefetch_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
726 : : {
727 : : /* Function receive frames for a given device and VQ*/
728 : : struct dpaa2_queue *dpaa2_q = queue;
729 : : struct qbman_result *dq_storage, *dq_storage1 = NULL;
730 : 0 : uint32_t fqid = dpaa2_q->fqid;
731 : : int ret, num_rx = 0, pull_size;
732 : : uint8_t pending, status;
733 : : struct qbman_swp *swp;
734 : : const struct qbman_fd *fd;
735 : : struct qbman_pull_desc pulldesc;
736 : : struct queue_storage_info_t *q_storage;
737 : 0 : struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data;
738 [ # # ]: 0 : struct dpaa2_dev_priv *priv = eth_data->dev_private;
739 : :
740 : 0 : q_storage = dpaa2_q->q_storage[rte_lcore_id()];
741 : :
742 [ # # ]: 0 : if (unlikely(dpaa2_enable_err_queue))
743 : 0 : dump_err_pkts(priv->rx_err_vq);
744 : :
745 [ # # ]: 0 : if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) {
746 : 0 : ret = dpaa2_affine_qbman_ethrx_swp();
747 [ # # ]: 0 : if (ret) {
748 : 0 : DPAA2_PMD_ERR("Failure in affining portal");
749 : 0 : return 0;
750 : : }
751 : : }
752 : :
753 [ # # # # ]: 0 : if (unlikely(!rte_dpaa2_bpid_info &&
754 : : rte_eal_process_type() == RTE_PROC_SECONDARY))
755 : 0 : rte_dpaa2_bpid_info = dpaa2_q->bp_array;
756 : :
757 : 0 : swp = DPAA2_PER_LCORE_ETHRX_PORTAL;
758 [ # # ]: 0 : pull_size = (nb_pkts > dpaa2_dqrr_size) ? dpaa2_dqrr_size : nb_pkts;
759 [ # # ]: 0 : if (unlikely(!q_storage->active_dqs)) {
760 : 0 : q_storage->toggle = 0;
761 : 0 : dq_storage = q_storage->dq_storage[q_storage->toggle];
762 : 0 : q_storage->last_num_pkts = pull_size;
763 : 0 : qbman_pull_desc_clear(&pulldesc);
764 : 0 : qbman_pull_desc_set_numframes(&pulldesc,
765 : 0 : q_storage->last_num_pkts);
766 : 0 : qbman_pull_desc_set_fq(&pulldesc, fqid);
767 : 0 : qbman_pull_desc_set_storage(&pulldesc, dq_storage,
768 : : (uint64_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1);
769 [ # # ]: 0 : if (check_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index)) {
770 [ # # ]: 0 : while (!qbman_check_command_complete(
771 : : get_swp_active_dqs(
772 : 0 : DPAA2_PER_LCORE_ETHRX_DPIO->index)))
773 : : ;
774 : 0 : clear_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index);
775 : : }
776 : : while (1) {
777 [ # # ]: 0 : if (qbman_swp_pull(swp, &pulldesc)) {
778 : : DPAA2_PMD_DP_DEBUG("VDQ command is not issued."
779 : : " QBMAN is busy (1)");
780 : : /* Portal was busy, try again */
781 : : continue;
782 : : }
783 : : break;
784 : : }
785 : 0 : q_storage->active_dqs = dq_storage;
786 : 0 : q_storage->active_dpio_id = DPAA2_PER_LCORE_ETHRX_DPIO->index;
787 : 0 : set_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index,
788 : : dq_storage);
789 : : }
790 : :
791 : 0 : dq_storage = q_storage->active_dqs;
792 : : rte_prefetch0((void *)(size_t)(dq_storage));
793 : 0 : rte_prefetch0((void *)(size_t)(dq_storage + 1));
794 : :
795 : : /* Prepare next pull descriptor. This will give space for the
796 : : * prefetching done on DQRR entries
797 : : */
798 : 0 : q_storage->toggle ^= 1;
799 : 0 : dq_storage1 = q_storage->dq_storage[q_storage->toggle];
800 : 0 : qbman_pull_desc_clear(&pulldesc);
801 : 0 : qbman_pull_desc_set_numframes(&pulldesc, pull_size);
802 : 0 : qbman_pull_desc_set_fq(&pulldesc, fqid);
803 : 0 : qbman_pull_desc_set_storage(&pulldesc, dq_storage1,
804 : : (uint64_t)(DPAA2_VADDR_TO_IOVA(dq_storage1)), 1);
805 : :
806 : : /* Check if the previous issued command is completed.
807 : : * Also seems like the SWP is shared between the Ethernet Driver
808 : : * and the SEC driver.
809 : : */
810 [ # # ]: 0 : while (!qbman_check_command_complete(dq_storage))
811 : : ;
812 [ # # ]: 0 : if (dq_storage == get_swp_active_dqs(q_storage->active_dpio_id))
813 : : clear_swp_active_dqs(q_storage->active_dpio_id);
814 : :
815 : : pending = 1;
816 : :
817 : : do {
818 : : /* Loop until the dq_storage is updated with
819 : : * new token by QBMAN
820 : : */
821 [ # # ]: 0 : while (!qbman_check_new_result(dq_storage))
822 : : ;
823 : 0 : rte_prefetch0((void *)((size_t)(dq_storage + 2)));
824 : : /* Check whether Last Pull command is Expired and
825 : : * setting Condition for Loop termination
826 : : */
827 [ # # ]: 0 : if (qbman_result_DQ_is_pull_complete(dq_storage)) {
828 : : pending = 0;
829 : : /* Check for valid frame. */
830 : 0 : status = qbman_result_DQ_flags(dq_storage);
831 [ # # ]: 0 : if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0))
832 : 0 : continue;
833 : : }
834 : 0 : fd = qbman_result_DQ_fd(dq_storage);
835 : :
836 : : #ifndef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA
837 : : if (dpaa2_svr_family != SVR_LX2160A) {
838 : : const struct qbman_fd *next_fd =
839 : : qbman_result_DQ_fd(dq_storage + 1);
840 : : /* Prefetch Annotation address for the parse results */
841 : : rte_prefetch0(DPAA2_IOVA_TO_VADDR((DPAA2_GET_FD_ADDR(
842 : : next_fd) + DPAA2_FD_PTA_SIZE + 16)));
843 : : }
844 : : #endif
845 : :
846 [ # # ]: 0 : if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg))
847 : 0 : bufs[num_rx] = eth_sg_fd_to_mbuf(fd, eth_data->port_id);
848 : : else
849 : 0 : bufs[num_rx] = eth_fd_to_mbuf(fd, eth_data->port_id);
850 : : #if defined(RTE_LIBRTE_IEEE1588)
851 : : if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) {
852 : : priv->rx_timestamp =
853 : : *dpaa2_timestamp_dynfield(bufs[num_rx]);
854 : : }
855 : : #endif
856 : :
857 [ # # ]: 0 : if (eth_data->dev_conf.rxmode.offloads &
858 : : RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
859 : 0 : rte_vlan_strip(bufs[num_rx]);
860 : :
861 : 0 : dq_storage++;
862 : 0 : num_rx++;
863 [ # # ]: 0 : } while (pending);
864 : :
865 [ # # ]: 0 : if (check_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index)) {
866 [ # # ]: 0 : while (!qbman_check_command_complete(
867 : 0 : get_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index)))
868 : : ;
869 : 0 : clear_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index);
870 : : }
871 : : /* issue a volatile dequeue command for next pull */
872 : : while (1) {
873 [ # # ]: 0 : if (qbman_swp_pull(swp, &pulldesc)) {
874 : : DPAA2_PMD_DP_DEBUG("VDQ command is not issued."
875 : : "QBMAN is busy (2)");
876 : : continue;
877 : : }
878 : : break;
879 : : }
880 : 0 : q_storage->active_dqs = dq_storage1;
881 : 0 : q_storage->active_dpio_id = DPAA2_PER_LCORE_ETHRX_DPIO->index;
882 : 0 : set_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index, dq_storage1);
883 : :
884 : 0 : dpaa2_q->rx_pkts += num_rx;
885 : :
886 : 0 : return num_rx;
887 : : }
888 : :
889 : : void __rte_hot
890 : 0 : dpaa2_dev_process_parallel_event(struct qbman_swp *swp,
891 : : const struct qbman_fd *fd,
892 : : const struct qbman_result *dq,
893 : : struct dpaa2_queue *rxq,
894 : : struct rte_event *ev)
895 : : {
896 : 0 : rte_prefetch0((void *)(size_t)(DPAA2_GET_FD_ADDR(fd) +
897 : : DPAA2_FD_PTA_SIZE + 16));
898 : :
899 : 0 : ev->flow_id = rxq->ev.flow_id;
900 : 0 : ev->sub_event_type = rxq->ev.sub_event_type;
901 : 0 : ev->event_type = RTE_EVENT_TYPE_ETHDEV;
902 : 0 : ev->op = RTE_EVENT_OP_NEW;
903 : 0 : ev->sched_type = rxq->ev.sched_type;
904 : 0 : ev->queue_id = rxq->ev.queue_id;
905 : 0 : ev->priority = rxq->ev.priority;
906 : :
907 : 0 : ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id);
908 : :
909 : 0 : qbman_swp_dqrr_consume(swp, dq);
910 : 0 : }
911 : :
912 : : void __rte_hot
913 : 0 : dpaa2_dev_process_atomic_event(struct qbman_swp *swp __rte_unused,
914 : : const struct qbman_fd *fd,
915 : : const struct qbman_result *dq,
916 : : struct dpaa2_queue *rxq,
917 : : struct rte_event *ev)
918 : : {
919 : : uint8_t dqrr_index;
920 : :
921 : 0 : rte_prefetch0((void *)(size_t)(DPAA2_GET_FD_ADDR(fd) +
922 : : DPAA2_FD_PTA_SIZE + 16));
923 : :
924 : 0 : ev->flow_id = rxq->ev.flow_id;
925 : 0 : ev->sub_event_type = rxq->ev.sub_event_type;
926 : 0 : ev->event_type = RTE_EVENT_TYPE_ETHDEV;
927 : 0 : ev->op = RTE_EVENT_OP_NEW;
928 : 0 : ev->sched_type = rxq->ev.sched_type;
929 : 0 : ev->queue_id = rxq->ev.queue_id;
930 : 0 : ev->priority = rxq->ev.priority;
931 : :
932 : 0 : ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id);
933 : :
934 : 0 : dqrr_index = qbman_get_dqrr_idx(dq);
935 : 0 : *dpaa2_seqn(ev->mbuf) = dqrr_index + 1;
936 : 0 : DPAA2_PER_LCORE_DQRR_SIZE++;
937 : 0 : DPAA2_PER_LCORE_DQRR_HELD |= UINT64_C(1) << dqrr_index;
938 : 0 : DPAA2_PER_LCORE_DQRR_MBUF(dqrr_index) = ev->mbuf;
939 : 0 : }
940 : :
941 : : void __rte_hot
942 : 0 : dpaa2_dev_process_ordered_event(struct qbman_swp *swp,
943 : : const struct qbman_fd *fd,
944 : : const struct qbman_result *dq,
945 : : struct dpaa2_queue *rxq,
946 : : struct rte_event *ev)
947 : : {
948 : 0 : rte_prefetch0((void *)(size_t)(DPAA2_GET_FD_ADDR(fd) +
949 : : DPAA2_FD_PTA_SIZE + 16));
950 : :
951 : 0 : ev->flow_id = rxq->ev.flow_id;
952 : 0 : ev->sub_event_type = rxq->ev.sub_event_type;
953 : 0 : ev->event_type = RTE_EVENT_TYPE_ETHDEV;
954 : 0 : ev->op = RTE_EVENT_OP_NEW;
955 : 0 : ev->sched_type = rxq->ev.sched_type;
956 : 0 : ev->queue_id = rxq->ev.queue_id;
957 : 0 : ev->priority = rxq->ev.priority;
958 : :
959 : 0 : ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id);
960 : :
961 : 0 : *dpaa2_seqn(ev->mbuf) = DPAA2_ENQUEUE_FLAG_ORP;
962 : 0 : *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_odpid(dq) << DPAA2_EQCR_OPRID_SHIFT;
963 : 0 : *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_seqnum(dq) << DPAA2_EQCR_SEQNUM_SHIFT;
964 : :
965 : 0 : qbman_swp_dqrr_consume(swp, dq);
966 : 0 : }
967 : :
968 : : uint16_t
969 : 0 : dpaa2_dev_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
970 : : {
971 : : /* Function receive frames for a given device and VQ */
972 : : struct dpaa2_queue *dpaa2_q = queue;
973 : : struct qbman_result *dq_storage;
974 : 0 : uint32_t fqid = dpaa2_q->fqid;
975 : 0 : int ret, num_rx = 0, next_pull = nb_pkts, num_pulled;
976 : : uint8_t pending, status;
977 : : struct qbman_swp *swp;
978 : : const struct qbman_fd *fd;
979 : : struct qbman_pull_desc pulldesc;
980 : 0 : struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data;
981 : 0 : struct dpaa2_dev_priv *priv = eth_data->dev_private;
982 : :
983 [ # # ]: 0 : if (unlikely(dpaa2_enable_err_queue))
984 : 0 : dump_err_pkts(priv->rx_err_vq);
985 : :
986 [ # # ]: 0 : if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
987 : 0 : ret = dpaa2_affine_qbman_swp();
988 [ # # ]: 0 : if (ret) {
989 : 0 : DPAA2_PMD_ERR(
990 : : "Failed to allocate IO portal, tid: %d",
991 : : rte_gettid());
992 : 0 : return 0;
993 : : }
994 : : }
995 : 0 : swp = DPAA2_PER_LCORE_PORTAL;
996 : :
997 : : do {
998 : 0 : dq_storage = dpaa2_q->q_storage[0]->dq_storage[0];
999 : 0 : qbman_pull_desc_clear(&pulldesc);
1000 : 0 : qbman_pull_desc_set_fq(&pulldesc, fqid);
1001 : 0 : qbman_pull_desc_set_storage(&pulldesc, dq_storage,
1002 : : (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1);
1003 : :
1004 [ # # ]: 0 : if (next_pull > dpaa2_dqrr_size) {
1005 : 0 : qbman_pull_desc_set_numframes(&pulldesc,
1006 : : dpaa2_dqrr_size);
1007 : 0 : next_pull -= dpaa2_dqrr_size;
1008 : : } else {
1009 : 0 : qbman_pull_desc_set_numframes(&pulldesc, next_pull);
1010 : : next_pull = 0;
1011 : : }
1012 : :
1013 : : while (1) {
1014 [ # # ]: 0 : if (qbman_swp_pull(swp, &pulldesc)) {
1015 : : DPAA2_PMD_DP_DEBUG(
1016 : : "VDQ command is not issued.QBMAN is busy");
1017 : : /* Portal was busy, try again */
1018 : : continue;
1019 : : }
1020 : : break;
1021 : : }
1022 : :
1023 : 0 : rte_prefetch0((void *)((size_t)(dq_storage + 1)));
1024 : : /* Check if the previous issued command is completed. */
1025 [ # # ]: 0 : while (!qbman_check_command_complete(dq_storage))
1026 : : ;
1027 : :
1028 : : num_pulled = 0;
1029 : : pending = 1;
1030 : : do {
1031 : : /* Loop until the dq_storage is updated with
1032 : : * new token by QBMAN
1033 : : */
1034 [ # # ]: 0 : while (!qbman_check_new_result(dq_storage))
1035 : : ;
1036 : 0 : rte_prefetch0((void *)((size_t)(dq_storage + 2)));
1037 : : /* Check whether Last Pull command is Expired and
1038 : : * setting Condition for Loop termination
1039 : : */
1040 [ # # ]: 0 : if (qbman_result_DQ_is_pull_complete(dq_storage)) {
1041 : : pending = 0;
1042 : : /* Check for valid frame. */
1043 : 0 : status = qbman_result_DQ_flags(dq_storage);
1044 [ # # ]: 0 : if (unlikely((status &
1045 : : QBMAN_DQ_STAT_VALIDFRAME) == 0))
1046 : 0 : continue;
1047 : : }
1048 : 0 : fd = qbman_result_DQ_fd(dq_storage);
1049 : :
1050 : : #ifndef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA
1051 : : if (dpaa2_svr_family != SVR_LX2160A) {
1052 : : const struct qbman_fd *next_fd =
1053 : : qbman_result_DQ_fd(dq_storage + 1);
1054 : :
1055 : : /* Prefetch Annotation address for the parse
1056 : : * results.
1057 : : */
1058 : : rte_prefetch0((DPAA2_IOVA_TO_VADDR(
1059 : : DPAA2_GET_FD_ADDR(next_fd) +
1060 : : DPAA2_FD_PTA_SIZE + 16)));
1061 : : }
1062 : : #endif
1063 : :
1064 [ # # ]: 0 : if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg))
1065 : 0 : bufs[num_rx] = eth_sg_fd_to_mbuf(fd,
1066 : 0 : eth_data->port_id);
1067 : : else
1068 : 0 : bufs[num_rx] = eth_fd_to_mbuf(fd,
1069 : 0 : eth_data->port_id);
1070 : :
1071 : : #if defined(RTE_LIBRTE_IEEE1588)
1072 : : if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) {
1073 : : priv->rx_timestamp =
1074 : : *dpaa2_timestamp_dynfield(bufs[num_rx]);
1075 : : }
1076 : : #endif
1077 : :
1078 [ # # ]: 0 : if (eth_data->dev_conf.rxmode.offloads &
1079 : : RTE_ETH_RX_OFFLOAD_VLAN_STRIP) {
1080 : 0 : rte_vlan_strip(bufs[num_rx]);
1081 : : }
1082 : :
1083 : 0 : dq_storage++;
1084 : 0 : num_rx++;
1085 : 0 : num_pulled++;
1086 [ # # ]: 0 : } while (pending);
1087 : : /* Last VDQ provided all packets and more packets are requested */
1088 [ # # # # ]: 0 : } while (next_pull && num_pulled == dpaa2_dqrr_size);
1089 : :
1090 : 0 : dpaa2_q->rx_pkts += num_rx;
1091 : :
1092 : 0 : return num_rx;
1093 : : }
1094 : :
1095 : 0 : uint16_t dpaa2_dev_tx_conf(void *queue)
1096 : : {
1097 : : /* Function receive frames for a given device and VQ */
1098 : : struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue;
1099 : : struct qbman_result *dq_storage;
1100 : 0 : uint32_t fqid = dpaa2_q->fqid;
1101 : : int ret, num_tx_conf = 0, num_pulled;
1102 : : uint8_t pending, status;
1103 : : struct qbman_swp *swp;
1104 : : const struct qbman_fd *fd, *next_fd;
1105 : : struct qbman_pull_desc pulldesc;
1106 : : struct qbman_release_desc releasedesc;
1107 : : uint32_t bpid;
1108 : : uint64_t buf;
1109 : : #if defined(RTE_LIBRTE_IEEE1588)
1110 : : struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data;
1111 : : struct dpaa2_dev_priv *priv = eth_data->dev_private;
1112 : : struct dpaa2_annot_hdr *annotation;
1113 : : void *v_addr;
1114 : : struct rte_mbuf *mbuf;
1115 : : #endif
1116 : :
1117 [ # # ]: 0 : if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
1118 : 0 : ret = dpaa2_affine_qbman_swp();
1119 [ # # ]: 0 : if (ret) {
1120 : 0 : DPAA2_PMD_ERR(
1121 : : "Failed to allocate IO portal, tid: %d",
1122 : : rte_gettid());
1123 : 0 : return 0;
1124 : : }
1125 : : }
1126 : 0 : swp = DPAA2_PER_LCORE_PORTAL;
1127 : :
1128 : : do {
1129 : 0 : dq_storage = dpaa2_q->q_storage[0]->dq_storage[0];
1130 : 0 : qbman_pull_desc_clear(&pulldesc);
1131 : 0 : qbman_pull_desc_set_fq(&pulldesc, fqid);
1132 : 0 : qbman_pull_desc_set_storage(&pulldesc, dq_storage,
1133 : : (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1);
1134 : :
1135 : 0 : qbman_pull_desc_set_numframes(&pulldesc, dpaa2_dqrr_size);
1136 : :
1137 : : while (1) {
1138 [ # # ]: 0 : if (qbman_swp_pull(swp, &pulldesc)) {
1139 : : DPAA2_PMD_DP_DEBUG("VDQ command is not issued."
1140 : : "QBMAN is busy");
1141 : : /* Portal was busy, try again */
1142 : : continue;
1143 : : }
1144 : : break;
1145 : : }
1146 : :
1147 : 0 : rte_prefetch0((void *)((size_t)(dq_storage + 1)));
1148 : : /* Check if the previous issued command is completed. */
1149 [ # # ]: 0 : while (!qbman_check_command_complete(dq_storage))
1150 : : ;
1151 : :
1152 : : num_pulled = 0;
1153 : : pending = 1;
1154 : : do {
1155 : : /* Loop until the dq_storage is updated with
1156 : : * new token by QBMAN
1157 : : */
1158 [ # # ]: 0 : while (!qbman_check_new_result(dq_storage))
1159 : : ;
1160 : 0 : rte_prefetch0((void *)((size_t)(dq_storage + 2)));
1161 : : /* Check whether Last Pull command is Expired and
1162 : : * setting Condition for Loop termination
1163 : : */
1164 [ # # ]: 0 : if (qbman_result_DQ_is_pull_complete(dq_storage)) {
1165 : : pending = 0;
1166 : : /* Check for valid frame. */
1167 : 0 : status = qbman_result_DQ_flags(dq_storage);
1168 [ # # ]: 0 : if (unlikely((status &
1169 : : QBMAN_DQ_STAT_VALIDFRAME) == 0))
1170 : 0 : continue;
1171 : : }
1172 : 0 : fd = qbman_result_DQ_fd(dq_storage);
1173 : :
1174 : 0 : next_fd = qbman_result_DQ_fd(dq_storage + 1);
1175 : : /* Prefetch Annotation address for the parse results */
1176 : 0 : rte_prefetch0((void *)(size_t)
1177 : 0 : (DPAA2_GET_FD_ADDR(next_fd) +
1178 : : DPAA2_FD_PTA_SIZE + 16));
1179 : :
1180 : 0 : bpid = DPAA2_GET_FD_BPID(fd);
1181 : :
1182 : : /* Create a release descriptor required for releasing
1183 : : * buffers into QBMAN
1184 : : */
1185 : 0 : qbman_release_desc_clear(&releasedesc);
1186 : 0 : qbman_release_desc_set_bpid(&releasedesc, bpid);
1187 : :
1188 : 0 : buf = DPAA2_GET_FD_ADDR(fd);
1189 : : /* feed them to bman */
1190 : : do {
1191 : 0 : ret = qbman_swp_release(swp, &releasedesc,
1192 : : &buf, 1);
1193 [ # # ]: 0 : } while (ret == -EBUSY);
1194 : :
1195 : : dq_storage++;
1196 : 0 : num_tx_conf++;
1197 : 0 : num_pulled++;
1198 : : #if defined(RTE_LIBRTE_IEEE1588)
1199 : : v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd));
1200 : : mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr,
1201 : : rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size);
1202 : :
1203 : : if (mbuf->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) {
1204 : : annotation = (struct dpaa2_annot_hdr *)((size_t)
1205 : : DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) +
1206 : : DPAA2_FD_PTA_SIZE);
1207 : : priv->tx_timestamp = annotation->word2;
1208 : : }
1209 : : #endif
1210 [ # # ]: 0 : } while (pending);
1211 : :
1212 : : /* Last VDQ provided all packets and more packets are requested */
1213 [ # # ]: 0 : } while (num_pulled == dpaa2_dqrr_size);
1214 : :
1215 : 0 : dpaa2_q->rx_pkts += num_tx_conf;
1216 : :
1217 : 0 : return num_tx_conf;
1218 : : }
1219 : :
1220 : : /* Configure the egress frame annotation for timestamp update */
1221 : : static void enable_tx_tstamp(struct qbman_fd *fd)
1222 : : {
1223 : : struct dpaa2_faead *fd_faead;
1224 : :
1225 : : /* Set frame annotation status field as valid */
1226 : : (fd)->simple.frc |= DPAA2_FD_FRC_FASV;
1227 : :
1228 : : /* Set frame annotation egress action descriptor as valid */
1229 : : (fd)->simple.frc |= DPAA2_FD_FRC_FAEADV;
1230 : :
1231 : : /* Set Annotation Length as 128B */
1232 : : (fd)->simple.ctrl |= DPAA2_FD_CTRL_ASAL;
1233 : :
1234 : : /* enable update of confirmation frame annotation */
1235 : : fd_faead = (struct dpaa2_faead *)((size_t)
1236 : : DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) +
1237 : : DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET);
1238 : : fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV |
1239 : : DPAA2_ANNOT_FAEAD_UPD;
1240 : : }
1241 : :
1242 : : /*
1243 : : * Callback to handle sending packets through WRIOP based interface
1244 : : */
1245 : : uint16_t
1246 : 0 : dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
1247 : 0 : {
1248 : : /* Function to transmit the frames to given device and VQ*/
1249 : : uint32_t loop, retry_count;
1250 : : int32_t ret;
1251 : : struct qbman_fd fd_arr[MAX_TX_RING_SLOTS];
1252 : : struct rte_mbuf *mi;
1253 : : uint32_t frames_to_send;
1254 : : struct rte_mempool *mp;
1255 : : struct qbman_eq_desc eqdesc;
1256 : : struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue;
1257 : : struct qbman_swp *swp;
1258 : : uint16_t num_tx = 0;
1259 : : uint16_t bpid;
1260 : 0 : struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data;
1261 : 0 : struct dpaa2_dev_priv *priv = eth_data->dev_private;
1262 : 0 : uint32_t flags[MAX_TX_RING_SLOTS] = {0};
1263 : 0 : struct sw_buf_free buf_to_free[DPAA2_MAX_SGS * dpaa2_dqrr_size];
1264 : 0 : uint32_t free_count = 0;
1265 : :
1266 [ # # ]: 0 : if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
1267 : 0 : ret = dpaa2_affine_qbman_swp();
1268 [ # # ]: 0 : if (ret) {
1269 : 0 : DPAA2_PMD_ERR(
1270 : : "Failed to allocate IO portal, tid: %d",
1271 : : rte_gettid());
1272 : 0 : return 0;
1273 : : }
1274 : : }
1275 : 0 : swp = DPAA2_PER_LCORE_PORTAL;
1276 : :
1277 : : DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d",
1278 : : eth_data, dpaa2_q->fqid);
1279 : :
1280 : : #ifdef RTE_LIBRTE_IEEE1588
1281 : : /* IEEE1588 driver need pointer to tx confirmation queue
1282 : : * corresponding to last packet transmitted for reading
1283 : : * the timestamp
1284 : : */
1285 : : if ((*bufs)->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) {
1286 : : priv->next_tx_conf_queue = dpaa2_q->tx_conf_queue;
1287 : : dpaa2_dev_tx_conf(dpaa2_q->tx_conf_queue);
1288 : : priv->tx_timestamp = 0;
1289 : : }
1290 : : #endif
1291 : :
1292 : : /*Prepare enqueue descriptor*/
1293 : 0 : qbman_eq_desc_clear(&eqdesc);
1294 : 0 : qbman_eq_desc_set_no_orp(&eqdesc, DPAA2_EQ_RESP_ERR_FQ);
1295 : 0 : qbman_eq_desc_set_fq(&eqdesc, dpaa2_q->fqid);
1296 : :
1297 : : /*Clear the unused FD fields before sending*/
1298 [ # # ]: 0 : while (nb_pkts) {
1299 : : /*Check if the queue is congested*/
1300 : : retry_count = 0;
1301 [ # # ]: 0 : while (qbman_result_SCN_state(dpaa2_q->cscn)) {
1302 : 0 : retry_count++;
1303 : : /* Retry for some time before giving up */
1304 [ # # ]: 0 : if (retry_count > CONG_RETRY_COUNT) {
1305 [ # # ]: 0 : if (dpaa2_q->tm_sw_td)
1306 : 0 : goto sw_td;
1307 : 0 : goto skip_tx;
1308 : : }
1309 : : }
1310 : :
1311 : 0 : frames_to_send = (nb_pkts > dpaa2_eqcr_size) ?
1312 [ # # ]: 0 : dpaa2_eqcr_size : nb_pkts;
1313 : :
1314 [ # # ]: 0 : for (loop = 0; loop < frames_to_send; loop++) {
1315 [ # # ]: 0 : if (*dpaa2_seqn(*bufs)) {
1316 : 0 : uint8_t dqrr_index = *dpaa2_seqn(*bufs) - 1;
1317 : :
1318 : 0 : flags[loop] = QBMAN_ENQUEUE_FLAG_DCA |
1319 : : dqrr_index;
1320 : 0 : DPAA2_PER_LCORE_DQRR_SIZE--;
1321 : 0 : DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dqrr_index);
1322 : 0 : *dpaa2_seqn(*bufs) = DPAA2_INVALID_MBUF_SEQN;
1323 : : }
1324 : :
1325 [ # # ]: 0 : if (likely(RTE_MBUF_DIRECT(*bufs))) {
1326 : 0 : mp = (*bufs)->pool;
1327 : : /* Check the basic scenario and set
1328 : : * the FD appropriately here itself.
1329 : : */
1330 [ # # # # : 0 : if (likely(mp && mp->ops_index ==
# # # # ]
1331 : : priv->bp_list->dpaa2_ops_index &&
1332 : : (*bufs)->nb_segs == 1 &&
1333 : : rte_mbuf_refcnt_read((*bufs)) == 1)) {
1334 [ # # # # ]: 0 : if (unlikely(((*bufs)->ol_flags
1335 : : & RTE_MBUF_F_TX_VLAN) ||
1336 : : (eth_data->dev_conf.txmode.offloads
1337 : : & RTE_ETH_TX_OFFLOAD_VLAN_INSERT))) {
1338 : 0 : ret = rte_vlan_insert(bufs);
1339 [ # # ]: 0 : if (ret)
1340 : 0 : goto send_n_return;
1341 : : }
1342 : 0 : DPAA2_MBUF_TO_CONTIG_FD((*bufs),
1343 : : &fd_arr[loop], mempool_to_bpid(mp));
1344 : : #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
1345 : : rte_mempool_check_cookies
1346 : : (rte_mempool_from_obj((void *)*bufs),
1347 : : (void **)bufs, 1, 0);
1348 : : #endif
1349 : 0 : bufs++;
1350 : : #ifdef RTE_LIBRTE_IEEE1588
1351 : : enable_tx_tstamp(&fd_arr[loop]);
1352 : : #endif
1353 : 0 : continue;
1354 : : }
1355 : : } else {
1356 : : mi = rte_mbuf_from_indirect(*bufs);
1357 : 0 : mp = mi->pool;
1358 : : }
1359 : :
1360 [ # # ]: 0 : if (unlikely(RTE_MBUF_HAS_EXTBUF(*bufs))) {
1361 [ # # ]: 0 : if (unlikely((*bufs)->nb_segs > 1)) {
1362 : 0 : mp = (*bufs)->pool;
1363 [ # # ]: 0 : if (eth_mbuf_to_sg_fd(*bufs,
1364 : : &fd_arr[loop],
1365 : : buf_to_free,
1366 : : &free_count,
1367 : : loop,
1368 : 0 : mempool_to_bpid(mp)))
1369 : 0 : goto send_n_return;
1370 : : } else {
1371 : 0 : eth_mbuf_to_fd(*bufs,
1372 : : &fd_arr[loop],
1373 : : buf_to_free,
1374 : : &free_count,
1375 : : loop, 0);
1376 : : }
1377 : 0 : bufs++;
1378 : : #ifdef RTE_LIBRTE_IEEE1588
1379 : : enable_tx_tstamp(&fd_arr[loop]);
1380 : : #endif
1381 : 0 : continue;
1382 : : }
1383 : :
1384 : : /* Not a hw_pkt pool allocated frame */
1385 [ # # # # ]: 0 : if (unlikely(!mp || !priv->bp_list)) {
1386 : 0 : DPAA2_PMD_ERR("Err: No buffer pool attached");
1387 : 0 : goto send_n_return;
1388 : : }
1389 : :
1390 [ # # # # ]: 0 : if (unlikely(((*bufs)->ol_flags & RTE_MBUF_F_TX_VLAN) ||
1391 : : (eth_data->dev_conf.txmode.offloads
1392 : : & RTE_ETH_TX_OFFLOAD_VLAN_INSERT))) {
1393 : 0 : int ret = rte_vlan_insert(bufs);
1394 [ # # ]: 0 : if (ret)
1395 : 0 : goto send_n_return;
1396 : : }
1397 [ # # ]: 0 : if (mp->ops_index != priv->bp_list->dpaa2_ops_index) {
1398 : 0 : DPAA2_PMD_WARN("Non DPAA2 buffer pool");
1399 : : /* alloc should be from the default buffer pool
1400 : : * attached to this interface
1401 : : */
1402 : 0 : bpid = priv->bp_list->buf_pool.bpid;
1403 : :
1404 [ # # ]: 0 : if (unlikely((*bufs)->nb_segs > 1)) {
1405 : 0 : DPAA2_PMD_ERR("S/G support not added"
1406 : : " for non hw offload buffer");
1407 : 0 : goto send_n_return;
1408 : : }
1409 [ # # ]: 0 : if (eth_copy_mbuf_to_fd(*bufs,
1410 : : &fd_arr[loop], bpid)) {
1411 : 0 : goto send_n_return;
1412 : : }
1413 : : /* free the original packet */
1414 : 0 : rte_pktmbuf_free(*bufs);
1415 : : } else {
1416 : 0 : bpid = mempool_to_bpid(mp);
1417 [ # # ]: 0 : if (unlikely((*bufs)->nb_segs > 1)) {
1418 [ # # ]: 0 : if (eth_mbuf_to_sg_fd(*bufs,
1419 : : &fd_arr[loop],
1420 : : buf_to_free,
1421 : : &free_count,
1422 : : loop,
1423 : : bpid))
1424 : 0 : goto send_n_return;
1425 : : } else {
1426 : 0 : eth_mbuf_to_fd(*bufs,
1427 : : &fd_arr[loop],
1428 : : buf_to_free,
1429 : : &free_count,
1430 : : loop, bpid);
1431 : : }
1432 : : }
1433 : : #ifdef RTE_LIBRTE_IEEE1588
1434 : : enable_tx_tstamp(&fd_arr[loop]);
1435 : : #endif
1436 : 0 : bufs++;
1437 : : }
1438 : :
1439 : : loop = 0;
1440 : : retry_count = 0;
1441 [ # # ]: 0 : while (loop < frames_to_send) {
1442 : 0 : ret = qbman_swp_enqueue_multiple(swp, &eqdesc,
1443 : 0 : &fd_arr[loop], &flags[loop],
1444 : 0 : frames_to_send - loop);
1445 [ # # ]: 0 : if (unlikely(ret < 0)) {
1446 : 0 : retry_count++;
1447 [ # # ]: 0 : if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) {
1448 : 0 : num_tx += loop;
1449 : : nb_pkts -= loop;
1450 : 0 : goto send_n_return;
1451 : : }
1452 : : } else {
1453 : 0 : loop += ret;
1454 : : retry_count = 0;
1455 : : }
1456 : : }
1457 : :
1458 : 0 : num_tx += loop;
1459 : 0 : nb_pkts -= loop;
1460 : : }
1461 : 0 : dpaa2_q->tx_pkts += num_tx;
1462 : :
1463 [ # # ]: 0 : for (loop = 0; loop < free_count; loop++) {
1464 [ # # ]: 0 : if (buf_to_free[loop].pkt_id < num_tx)
1465 [ # # ]: 0 : rte_pktmbuf_free_seg(buf_to_free[loop].seg);
1466 : : }
1467 : :
1468 : : return num_tx;
1469 : :
1470 : 0 : send_n_return:
1471 : : /* send any already prepared fd */
1472 [ # # ]: 0 : if (loop) {
1473 : : unsigned int i = 0;
1474 : :
1475 : : retry_count = 0;
1476 [ # # ]: 0 : while (i < loop) {
1477 : 0 : ret = qbman_swp_enqueue_multiple(swp, &eqdesc,
1478 : 0 : &fd_arr[i],
1479 : : &flags[i],
1480 : 0 : loop - i);
1481 [ # # ]: 0 : if (unlikely(ret < 0)) {
1482 : 0 : retry_count++;
1483 [ # # ]: 0 : if (retry_count > DPAA2_MAX_TX_RETRY_COUNT)
1484 : : break;
1485 : : } else {
1486 : 0 : i += ret;
1487 : : retry_count = 0;
1488 : : }
1489 : : }
1490 : 0 : num_tx += i;
1491 : : }
1492 : 0 : skip_tx:
1493 : 0 : dpaa2_q->tx_pkts += num_tx;
1494 : :
1495 [ # # ]: 0 : for (loop = 0; loop < free_count; loop++) {
1496 [ # # ]: 0 : if (buf_to_free[loop].pkt_id < num_tx)
1497 [ # # ]: 0 : rte_pktmbuf_free_seg(buf_to_free[loop].seg);
1498 : : }
1499 : :
1500 : : return num_tx;
1501 : : sw_td:
1502 : : loop = 0;
1503 [ # # ]: 0 : while (loop < num_tx) {
1504 [ # # ]: 0 : if (unlikely(RTE_MBUF_HAS_EXTBUF(*bufs)))
1505 : 0 : rte_pktmbuf_free(*bufs);
1506 : 0 : bufs++;
1507 : 0 : loop++;
1508 : : }
1509 : :
1510 : : /* free the pending buffers */
1511 [ # # ]: 0 : while (nb_pkts) {
1512 : 0 : rte_pktmbuf_free(*bufs);
1513 : 0 : bufs++;
1514 : 0 : nb_pkts--;
1515 : 0 : num_tx++;
1516 : : }
1517 : 0 : dpaa2_q->tx_pkts += num_tx;
1518 : :
1519 : 0 : return num_tx;
1520 : : }
1521 : :
1522 : : void
1523 : 0 : dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci,
1524 : : __rte_unused struct dpaa2_queue *dpaa2_q)
1525 : : {
1526 : 0 : struct dpaa2_dpio_dev *dpio_dev = DPAA2_PER_LCORE_DPIO;
1527 : : struct qbman_fd *fd;
1528 : : struct rte_mbuf *m;
1529 : :
1530 : 0 : fd = qbman_result_eqresp_fd(&dpio_dev->eqresp[eqresp_ci]);
1531 : :
1532 : : /* Setting port id does not matter as we are to free the mbuf */
1533 : 0 : m = eth_fd_to_mbuf(fd, 0);
1534 : 0 : rte_pktmbuf_free(m);
1535 : 0 : }
1536 : :
1537 : : static void
1538 : 0 : dpaa2_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q,
1539 : : struct rte_mbuf *m,
1540 : : struct qbman_eq_desc *eqdesc)
1541 : : {
1542 : 0 : struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data;
1543 : 0 : struct dpaa2_dev_priv *priv = eth_data->dev_private;
1544 : 0 : struct dpaa2_dpio_dev *dpio_dev = DPAA2_PER_LCORE_DPIO;
1545 : : struct eqresp_metadata *eqresp_meta;
1546 : : uint16_t orpid, seqnum;
1547 : : uint8_t dq_idx;
1548 : :
1549 : 0 : qbman_eq_desc_set_fq(eqdesc, dpaa2_q->fqid);
1550 : :
1551 [ # # ]: 0 : if (*dpaa2_seqn(m) & DPAA2_ENQUEUE_FLAG_ORP) {
1552 : 0 : orpid = (*dpaa2_seqn(m) & DPAA2_EQCR_OPRID_MASK) >>
1553 : : DPAA2_EQCR_OPRID_SHIFT;
1554 : : seqnum = (*dpaa2_seqn(m) & DPAA2_EQCR_SEQNUM_MASK) >>
1555 : : DPAA2_EQCR_SEQNUM_SHIFT;
1556 : :
1557 [ # # ]: 0 : if (!priv->en_loose_ordered) {
1558 : 0 : qbman_eq_desc_set_orp(eqdesc, 1, orpid, seqnum, 0);
1559 : 0 : qbman_eq_desc_set_response(eqdesc, (uint64_t)
1560 : 0 : DPAA2_VADDR_TO_IOVA(&dpio_dev->eqresp[
1561 : : dpio_dev->eqresp_pi]), 1);
1562 : 0 : qbman_eq_desc_set_token(eqdesc, 1);
1563 : :
1564 : 0 : eqresp_meta = &dpio_dev->eqresp_meta[
1565 : 0 : dpio_dev->eqresp_pi];
1566 : 0 : eqresp_meta->dpaa2_q = dpaa2_q;
1567 : 0 : eqresp_meta->mp = m->pool;
1568 : :
1569 : : dpio_dev->eqresp_pi + 1 < MAX_EQ_RESP_ENTRIES ?
1570 [ # # ]: 0 : dpio_dev->eqresp_pi++ :
1571 : 0 : (dpio_dev->eqresp_pi = 0);
1572 : : } else {
1573 : 0 : qbman_eq_desc_set_orp(eqdesc, 0, orpid, seqnum, 0);
1574 : : }
1575 : : } else {
1576 : 0 : dq_idx = *dpaa2_seqn(m) - 1;
1577 : 0 : qbman_eq_desc_set_dca(eqdesc, 1, dq_idx, 0);
1578 : 0 : DPAA2_PER_LCORE_DQRR_SIZE--;
1579 : 0 : DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dq_idx);
1580 : : }
1581 : 0 : *dpaa2_seqn(m) = DPAA2_INVALID_MBUF_SEQN;
1582 : 0 : }
1583 : :
1584 : : RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dev_tx_multi_txq_ordered)
1585 : : uint16_t
1586 : 0 : dpaa2_dev_tx_multi_txq_ordered(void **queue,
1587 : : struct rte_mbuf **bufs, uint16_t nb_pkts)
1588 : 0 : {
1589 : : /* Function to transmit the frames to multiple queues respectively.*/
1590 : : uint32_t loop, i, retry_count;
1591 : : int32_t ret;
1592 : : struct qbman_fd fd_arr[MAX_TX_RING_SLOTS];
1593 : : uint32_t frames_to_send, num_free_eq_desc = 0;
1594 : : struct rte_mempool *mp;
1595 : : struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS];
1596 : : struct dpaa2_queue *dpaa2_q[MAX_TX_RING_SLOTS];
1597 : : struct qbman_swp *swp;
1598 : : uint16_t bpid;
1599 : : struct rte_mbuf *mi;
1600 : : struct rte_eth_dev_data *eth_data;
1601 : : struct dpaa2_dev_priv *priv;
1602 : : struct dpaa2_queue *order_sendq;
1603 : 0 : struct sw_buf_free buf_to_free[DPAA2_MAX_SGS * dpaa2_dqrr_size];
1604 : 0 : uint32_t free_count = 0;
1605 : :
1606 [ # # ]: 0 : if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
1607 : 0 : ret = dpaa2_affine_qbman_swp();
1608 [ # # ]: 0 : if (ret) {
1609 : 0 : DPAA2_PMD_ERR(
1610 : : "Failed to allocate IO portal, tid: %d",
1611 : : rte_gettid());
1612 : 0 : return 0;
1613 : : }
1614 : : }
1615 : 0 : swp = DPAA2_PER_LCORE_PORTAL;
1616 : :
1617 : 0 : frames_to_send = (nb_pkts > dpaa2_eqcr_size) ?
1618 [ # # ]: 0 : dpaa2_eqcr_size : nb_pkts;
1619 : :
1620 [ # # ]: 0 : for (loop = 0; loop < frames_to_send; loop++) {
1621 : 0 : dpaa2_q[loop] = (struct dpaa2_queue *)queue[loop];
1622 : 0 : eth_data = dpaa2_q[loop]->eth_data;
1623 : 0 : priv = eth_data->dev_private;
1624 [ # # ]: 0 : if (!priv->en_loose_ordered) {
1625 [ # # ]: 0 : if (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP) {
1626 [ # # ]: 0 : if (!num_free_eq_desc) {
1627 : 0 : num_free_eq_desc = dpaa2_free_eq_descriptors();
1628 [ # # ]: 0 : if (!num_free_eq_desc)
1629 : 0 : goto send_frames;
1630 : : }
1631 : 0 : num_free_eq_desc--;
1632 : : }
1633 : : }
1634 : :
1635 : : DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d",
1636 : : eth_data, dpaa2_q[loop]->fqid);
1637 : :
1638 : : /* Check if the queue is congested */
1639 : : retry_count = 0;
1640 [ # # ]: 0 : while (qbman_result_SCN_state(dpaa2_q[loop]->cscn)) {
1641 : 0 : retry_count++;
1642 : : /* Retry for some time before giving up */
1643 [ # # ]: 0 : if (retry_count > CONG_RETRY_COUNT)
1644 : 0 : goto send_frames;
1645 : : }
1646 : :
1647 : : /* Prepare enqueue descriptor */
1648 : 0 : qbman_eq_desc_clear(&eqdesc[loop]);
1649 : :
1650 [ # # # # ]: 0 : if (*dpaa2_seqn(*bufs) && priv->en_ordered) {
1651 : 0 : order_sendq = (struct dpaa2_queue *)priv->tx_vq[0];
1652 : 0 : dpaa2_set_enqueue_descriptor(order_sendq,
1653 : : (*bufs),
1654 : : &eqdesc[loop]);
1655 : : } else {
1656 : 0 : qbman_eq_desc_set_no_orp(&eqdesc[loop],
1657 : : DPAA2_EQ_RESP_ERR_FQ);
1658 : 0 : qbman_eq_desc_set_fq(&eqdesc[loop],
1659 : : dpaa2_q[loop]->fqid);
1660 : : }
1661 : :
1662 [ # # ]: 0 : if (likely(RTE_MBUF_DIRECT(*bufs))) {
1663 : 0 : mp = (*bufs)->pool;
1664 : : /* Check the basic scenario and set
1665 : : * the FD appropriately here itself.
1666 : : */
1667 [ # # # # : 0 : if (likely(mp && mp->ops_index ==
# # # # ]
1668 : : priv->bp_list->dpaa2_ops_index &&
1669 : : (*bufs)->nb_segs == 1 &&
1670 : : rte_mbuf_refcnt_read((*bufs)) == 1)) {
1671 [ # # ]: 0 : if (unlikely((*bufs)->ol_flags
1672 : : & RTE_MBUF_F_TX_VLAN)) {
1673 : 0 : ret = rte_vlan_insert(bufs);
1674 [ # # ]: 0 : if (ret)
1675 : 0 : goto send_frames;
1676 : : }
1677 : 0 : DPAA2_MBUF_TO_CONTIG_FD((*bufs),
1678 : : &fd_arr[loop],
1679 : : mempool_to_bpid(mp));
1680 : 0 : bufs++;
1681 : 0 : continue;
1682 : : }
1683 : : } else {
1684 : : mi = rte_mbuf_from_indirect(*bufs);
1685 : 0 : mp = mi->pool;
1686 : : }
1687 : : /* Not a hw_pkt pool allocated frame */
1688 [ # # # # ]: 0 : if (unlikely(!mp || !priv->bp_list)) {
1689 : 0 : DPAA2_PMD_ERR("Err: No buffer pool attached");
1690 : 0 : goto send_frames;
1691 : : }
1692 : :
1693 [ # # ]: 0 : if (mp->ops_index != priv->bp_list->dpaa2_ops_index) {
1694 : 0 : DPAA2_PMD_WARN("Non DPAA2 buffer pool");
1695 : : /* alloc should be from the default buffer pool
1696 : : * attached to this interface
1697 : : */
1698 : 0 : bpid = priv->bp_list->buf_pool.bpid;
1699 : :
1700 [ # # ]: 0 : if (unlikely((*bufs)->nb_segs > 1)) {
1701 : 0 : DPAA2_PMD_ERR(
1702 : : "S/G not supp for non hw offload buffer");
1703 : 0 : goto send_frames;
1704 : : }
1705 [ # # ]: 0 : if (eth_copy_mbuf_to_fd(*bufs,
1706 : : &fd_arr[loop], bpid)) {
1707 : 0 : goto send_frames;
1708 : : }
1709 : : /* free the original packet */
1710 : 0 : rte_pktmbuf_free(*bufs);
1711 : : } else {
1712 : 0 : bpid = mempool_to_bpid(mp);
1713 [ # # ]: 0 : if (unlikely((*bufs)->nb_segs > 1)) {
1714 [ # # ]: 0 : if (eth_mbuf_to_sg_fd(*bufs,
1715 : : &fd_arr[loop],
1716 : : buf_to_free,
1717 : : &free_count,
1718 : : loop,
1719 : : bpid))
1720 : 0 : goto send_frames;
1721 : : } else {
1722 : 0 : eth_mbuf_to_fd(*bufs,
1723 : : &fd_arr[loop],
1724 : : buf_to_free,
1725 : : &free_count,
1726 : : loop, bpid);
1727 : : }
1728 : : }
1729 : :
1730 : 0 : bufs++;
1731 : : }
1732 : :
1733 : 0 : send_frames:
1734 : : frames_to_send = loop;
1735 : : loop = 0;
1736 : : retry_count = 0;
1737 [ # # ]: 0 : while (loop < frames_to_send) {
1738 : 0 : ret = qbman_swp_enqueue_multiple_desc(swp, &eqdesc[loop],
1739 : 0 : &fd_arr[loop],
1740 : 0 : frames_to_send - loop);
1741 [ # # ]: 0 : if (likely(ret > 0)) {
1742 : 0 : loop += ret;
1743 : : retry_count = 0;
1744 : : } else {
1745 : 0 : retry_count++;
1746 [ # # ]: 0 : if (retry_count > DPAA2_MAX_TX_RETRY_COUNT)
1747 : : break;
1748 : : }
1749 : : }
1750 : :
1751 [ # # ]: 0 : for (i = 0; i < free_count; i++) {
1752 [ # # ]: 0 : if (buf_to_free[i].pkt_id < loop)
1753 [ # # ]: 0 : rte_pktmbuf_free_seg(buf_to_free[i].seg);
1754 : : }
1755 : 0 : return loop;
1756 : : }
1757 : :
1758 : : /* Callback to handle sending ordered packets through WRIOP based interface */
1759 : : uint16_t
1760 : 0 : dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
1761 : 0 : {
1762 : : /* Function to transmit the frames to given device and VQ*/
1763 : : struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue;
1764 : 0 : struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data;
1765 : 0 : struct dpaa2_dev_priv *priv = eth_data->dev_private;
1766 : 0 : struct dpaa2_queue *order_sendq = (struct dpaa2_queue *)priv->tx_vq[0];
1767 : : struct qbman_fd fd_arr[MAX_TX_RING_SLOTS];
1768 : : struct rte_mbuf *mi;
1769 : : struct rte_mempool *mp;
1770 : : struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS];
1771 : : struct qbman_swp *swp;
1772 : : uint32_t frames_to_send, num_free_eq_desc;
1773 : : uint32_t loop, retry_count;
1774 : : int32_t ret;
1775 : : uint16_t num_tx = 0;
1776 : : uint16_t bpid;
1777 : 0 : struct sw_buf_free buf_to_free[DPAA2_MAX_SGS * dpaa2_dqrr_size];
1778 : 0 : uint32_t free_count = 0;
1779 : :
1780 [ # # ]: 0 : if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
1781 : 0 : ret = dpaa2_affine_qbman_swp();
1782 [ # # ]: 0 : if (ret) {
1783 : 0 : DPAA2_PMD_ERR(
1784 : : "Failed to allocate IO portal, tid: %d",
1785 : : rte_gettid());
1786 : 0 : return 0;
1787 : : }
1788 : : }
1789 : 0 : swp = DPAA2_PER_LCORE_PORTAL;
1790 : :
1791 : : DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d",
1792 : : eth_data, dpaa2_q->fqid);
1793 : :
1794 : : /* This would also handle normal and atomic queues as any type
1795 : : * of packet can be enqueued when ordered queues are being used.
1796 : : */
1797 [ # # ]: 0 : while (nb_pkts) {
1798 : : /*Check if the queue is congested*/
1799 : : retry_count = 0;
1800 [ # # ]: 0 : while (qbman_result_SCN_state(dpaa2_q->cscn)) {
1801 : 0 : retry_count++;
1802 : : /* Retry for some time before giving up */
1803 [ # # ]: 0 : if (retry_count > CONG_RETRY_COUNT)
1804 : 0 : goto skip_tx;
1805 : : }
1806 : :
1807 : 0 : frames_to_send = (nb_pkts > dpaa2_eqcr_size) ?
1808 [ # # ]: 0 : dpaa2_eqcr_size : nb_pkts;
1809 : :
1810 [ # # ]: 0 : if (!priv->en_loose_ordered) {
1811 [ # # ]: 0 : if (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP) {
1812 : 0 : num_free_eq_desc = dpaa2_free_eq_descriptors();
1813 : : if (num_free_eq_desc < frames_to_send)
1814 : : frames_to_send = num_free_eq_desc;
1815 : : }
1816 : : }
1817 : :
1818 [ # # ]: 0 : for (loop = 0; loop < frames_to_send; loop++) {
1819 : : /*Prepare enqueue descriptor*/
1820 : 0 : qbman_eq_desc_clear(&eqdesc[loop]);
1821 : :
1822 [ # # ]: 0 : if (*dpaa2_seqn(*bufs)) {
1823 : : /* Use only queue 0 for Tx in case of atomic/
1824 : : * ordered packets as packets can get unordered
1825 : : * when being transmitted out from the interface
1826 : : */
1827 : 0 : dpaa2_set_enqueue_descriptor(order_sendq,
1828 : : (*bufs),
1829 : : &eqdesc[loop]);
1830 : : } else {
1831 : 0 : qbman_eq_desc_set_no_orp(&eqdesc[loop],
1832 : : DPAA2_EQ_RESP_ERR_FQ);
1833 : 0 : qbman_eq_desc_set_fq(&eqdesc[loop],
1834 : : dpaa2_q->fqid);
1835 : : }
1836 : :
1837 [ # # ]: 0 : if (likely(RTE_MBUF_DIRECT(*bufs))) {
1838 : 0 : mp = (*bufs)->pool;
1839 : : /* Check the basic scenario and set
1840 : : * the FD appropriately here itself.
1841 : : */
1842 [ # # # # : 0 : if (likely(mp && mp->ops_index ==
# # # # ]
1843 : : priv->bp_list->dpaa2_ops_index &&
1844 : : (*bufs)->nb_segs == 1 &&
1845 : : rte_mbuf_refcnt_read((*bufs)) == 1)) {
1846 [ # # ]: 0 : if (unlikely((*bufs)->ol_flags
1847 : : & RTE_MBUF_F_TX_VLAN)) {
1848 : 0 : ret = rte_vlan_insert(bufs);
1849 [ # # ]: 0 : if (ret)
1850 : 0 : goto send_n_return;
1851 : : }
1852 : 0 : DPAA2_MBUF_TO_CONTIG_FD((*bufs),
1853 : : &fd_arr[loop],
1854 : : mempool_to_bpid(mp));
1855 : 0 : bufs++;
1856 : 0 : continue;
1857 : : }
1858 : : } else {
1859 : : mi = rte_mbuf_from_indirect(*bufs);
1860 : 0 : mp = mi->pool;
1861 : : }
1862 : : /* Not a hw_pkt pool allocated frame */
1863 [ # # # # ]: 0 : if (unlikely(!mp || !priv->bp_list)) {
1864 : 0 : DPAA2_PMD_ERR("Err: No buffer pool attached");
1865 : 0 : goto send_n_return;
1866 : : }
1867 : :
1868 [ # # ]: 0 : if (mp->ops_index != priv->bp_list->dpaa2_ops_index) {
1869 : 0 : DPAA2_PMD_WARN("Non DPAA2 buffer pool");
1870 : : /* alloc should be from the default buffer pool
1871 : : * attached to this interface
1872 : : */
1873 : 0 : bpid = priv->bp_list->buf_pool.bpid;
1874 : :
1875 [ # # ]: 0 : if (unlikely((*bufs)->nb_segs > 1)) {
1876 : 0 : DPAA2_PMD_ERR(
1877 : : "S/G not supp for non hw offload buffer");
1878 : 0 : goto send_n_return;
1879 : : }
1880 [ # # ]: 0 : if (eth_copy_mbuf_to_fd(*bufs,
1881 : : &fd_arr[loop], bpid)) {
1882 : 0 : goto send_n_return;
1883 : : }
1884 : : /* free the original packet */
1885 : 0 : rte_pktmbuf_free(*bufs);
1886 : : } else {
1887 : 0 : bpid = mempool_to_bpid(mp);
1888 [ # # ]: 0 : if (unlikely((*bufs)->nb_segs > 1)) {
1889 [ # # ]: 0 : if (eth_mbuf_to_sg_fd(*bufs,
1890 : : &fd_arr[loop],
1891 : : buf_to_free,
1892 : : &free_count,
1893 : : loop,
1894 : : bpid))
1895 : 0 : goto send_n_return;
1896 : : } else {
1897 : 0 : eth_mbuf_to_fd(*bufs,
1898 : : &fd_arr[loop],
1899 : : buf_to_free,
1900 : : &free_count,
1901 : : loop, bpid);
1902 : : }
1903 : : }
1904 : 0 : bufs++;
1905 : : }
1906 : :
1907 : : loop = 0;
1908 : : retry_count = 0;
1909 [ # # ]: 0 : while (loop < frames_to_send) {
1910 : 0 : ret = qbman_swp_enqueue_multiple_desc(swp,
1911 : 0 : &eqdesc[loop], &fd_arr[loop],
1912 : 0 : frames_to_send - loop);
1913 [ # # ]: 0 : if (unlikely(ret < 0)) {
1914 : 0 : retry_count++;
1915 [ # # ]: 0 : if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) {
1916 : 0 : num_tx += loop;
1917 : : nb_pkts -= loop;
1918 : 0 : goto send_n_return;
1919 : : }
1920 : : } else {
1921 : 0 : loop += ret;
1922 : : retry_count = 0;
1923 : : }
1924 : : }
1925 : :
1926 : 0 : num_tx += loop;
1927 : 0 : nb_pkts -= loop;
1928 : : }
1929 : 0 : dpaa2_q->tx_pkts += num_tx;
1930 [ # # ]: 0 : for (loop = 0; loop < free_count; loop++) {
1931 [ # # ]: 0 : if (buf_to_free[loop].pkt_id < num_tx)
1932 [ # # ]: 0 : rte_pktmbuf_free_seg(buf_to_free[loop].seg);
1933 : : }
1934 : :
1935 : : return num_tx;
1936 : :
1937 : 0 : send_n_return:
1938 : : /* send any already prepared fd */
1939 [ # # ]: 0 : if (loop) {
1940 : : unsigned int i = 0;
1941 : :
1942 : : retry_count = 0;
1943 [ # # ]: 0 : while (i < loop) {
1944 : 0 : ret = qbman_swp_enqueue_multiple_desc(swp,
1945 : 0 : &eqdesc[i], &fd_arr[i], loop - i);
1946 [ # # ]: 0 : if (unlikely(ret < 0)) {
1947 : 0 : retry_count++;
1948 [ # # ]: 0 : if (retry_count > DPAA2_MAX_TX_RETRY_COUNT)
1949 : : break;
1950 : : } else {
1951 : 0 : i += ret;
1952 : : retry_count = 0;
1953 : : }
1954 : : }
1955 : 0 : num_tx += i;
1956 : : }
1957 : 0 : skip_tx:
1958 : 0 : dpaa2_q->tx_pkts += num_tx;
1959 [ # # ]: 0 : for (loop = 0; loop < free_count; loop++) {
1960 [ # # ]: 0 : if (buf_to_free[loop].pkt_id < num_tx)
1961 [ # # ]: 0 : rte_pktmbuf_free_seg(buf_to_free[loop].seg);
1962 : : }
1963 : :
1964 : : return num_tx;
1965 : : }
1966 : :
1967 : : /* This function loopbacks all the received packets.*/
1968 : : uint16_t
1969 : 0 : dpaa2_dev_loopback_rx(void *queue,
1970 : : struct rte_mbuf **bufs __rte_unused,
1971 : : uint16_t nb_pkts)
1972 : : {
1973 : : /* Function receive frames for a given device and VQ*/
1974 : : struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue;
1975 : : struct qbman_result *dq_storage, *dq_storage1 = NULL;
1976 : 0 : uint32_t fqid = dpaa2_q->fqid;
1977 : : int ret, num_rx = 0, num_tx = 0, pull_size;
1978 : : uint8_t pending, status;
1979 : : struct qbman_swp *swp;
1980 : : struct qbman_fd *fd[DPAA2_LX2_DQRR_RING_SIZE];
1981 : : struct qbman_pull_desc pulldesc;
1982 : : struct qbman_eq_desc eqdesc;
1983 : : struct queue_storage_info_t *q_storage;
1984 : 0 : struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data;
1985 : 0 : struct dpaa2_dev_priv *priv = eth_data->dev_private;
1986 [ # # ]: 0 : struct dpaa2_queue *tx_q = priv->tx_vq[0];
1987 : : /* todo - currently we are using 1st TX queue only for loopback*/
1988 : :
1989 : 0 : q_storage = dpaa2_q->q_storage[rte_lcore_id()];
1990 [ # # ]: 0 : if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) {
1991 : 0 : ret = dpaa2_affine_qbman_ethrx_swp();
1992 [ # # ]: 0 : if (ret) {
1993 : 0 : DPAA2_PMD_ERR("Failure in affining portal");
1994 : 0 : return 0;
1995 : : }
1996 : : }
1997 : 0 : swp = DPAA2_PER_LCORE_ETHRX_PORTAL;
1998 [ # # ]: 0 : pull_size = (nb_pkts > dpaa2_dqrr_size) ? dpaa2_dqrr_size : nb_pkts;
1999 [ # # ]: 0 : if (unlikely(!q_storage->active_dqs)) {
2000 : 0 : q_storage->toggle = 0;
2001 : 0 : dq_storage = q_storage->dq_storage[q_storage->toggle];
2002 : 0 : q_storage->last_num_pkts = pull_size;
2003 : 0 : qbman_pull_desc_clear(&pulldesc);
2004 : 0 : qbman_pull_desc_set_numframes(&pulldesc,
2005 : 0 : q_storage->last_num_pkts);
2006 : 0 : qbman_pull_desc_set_fq(&pulldesc, fqid);
2007 : 0 : qbman_pull_desc_set_storage(&pulldesc, dq_storage,
2008 : : (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1);
2009 [ # # ]: 0 : if (check_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index)) {
2010 [ # # ]: 0 : while (!qbman_check_command_complete(
2011 : : get_swp_active_dqs(
2012 : 0 : DPAA2_PER_LCORE_ETHRX_DPIO->index)))
2013 : : ;
2014 : 0 : clear_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index);
2015 : : }
2016 : : while (1) {
2017 [ # # ]: 0 : if (qbman_swp_pull(swp, &pulldesc)) {
2018 : : DPAA2_PMD_DP_DEBUG(
2019 : : "VDQ command not issued.QBMAN busy");
2020 : : /* Portal was busy, try again */
2021 : : continue;
2022 : : }
2023 : : break;
2024 : : }
2025 : 0 : q_storage->active_dqs = dq_storage;
2026 : 0 : q_storage->active_dpio_id = DPAA2_PER_LCORE_ETHRX_DPIO->index;
2027 : 0 : set_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index,
2028 : : dq_storage);
2029 : : }
2030 : :
2031 : 0 : dq_storage = q_storage->active_dqs;
2032 : : rte_prefetch0((void *)(size_t)(dq_storage));
2033 : 0 : rte_prefetch0((void *)(size_t)(dq_storage + 1));
2034 : :
2035 : : /* Prepare next pull descriptor. This will give space for the
2036 : : * prefetching done on DQRR entries
2037 : : */
2038 : 0 : q_storage->toggle ^= 1;
2039 : 0 : dq_storage1 = q_storage->dq_storage[q_storage->toggle];
2040 : 0 : qbman_pull_desc_clear(&pulldesc);
2041 : 0 : qbman_pull_desc_set_numframes(&pulldesc, pull_size);
2042 : 0 : qbman_pull_desc_set_fq(&pulldesc, fqid);
2043 : 0 : qbman_pull_desc_set_storage(&pulldesc, dq_storage1,
2044 : : (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage1)), 1);
2045 : :
2046 : : /*Prepare enqueue descriptor*/
2047 : 0 : qbman_eq_desc_clear(&eqdesc);
2048 : 0 : qbman_eq_desc_set_no_orp(&eqdesc, DPAA2_EQ_RESP_ERR_FQ);
2049 : 0 : qbman_eq_desc_set_response(&eqdesc, 0, 0);
2050 : 0 : qbman_eq_desc_set_fq(&eqdesc, tx_q->fqid);
2051 : :
2052 : : /* Check if the previous issued command is completed.
2053 : : * Also seems like the SWP is shared between the Ethernet Driver
2054 : : * and the SEC driver.
2055 : : */
2056 [ # # ]: 0 : while (!qbman_check_command_complete(dq_storage))
2057 : : ;
2058 [ # # ]: 0 : if (dq_storage == get_swp_active_dqs(q_storage->active_dpio_id))
2059 : : clear_swp_active_dqs(q_storage->active_dpio_id);
2060 : :
2061 : : pending = 1;
2062 : :
2063 : : do {
2064 : : /* Loop until the dq_storage is updated with
2065 : : * new token by QBMAN
2066 : : */
2067 [ # # ]: 0 : while (!qbman_check_new_result(dq_storage))
2068 : : ;
2069 : 0 : rte_prefetch0((void *)((size_t)(dq_storage + 2)));
2070 : : /* Check whether Last Pull command is Expired and
2071 : : * setting Condition for Loop termination
2072 : : */
2073 [ # # ]: 0 : if (qbman_result_DQ_is_pull_complete(dq_storage)) {
2074 : : pending = 0;
2075 : : /* Check for valid frame. */
2076 : 0 : status = qbman_result_DQ_flags(dq_storage);
2077 [ # # ]: 0 : if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0))
2078 : 0 : continue;
2079 : : }
2080 : 0 : fd[num_rx] = RTE_PTR_UNQUAL(qbman_result_DQ_fd(dq_storage));
2081 : :
2082 : 0 : dq_storage++;
2083 : 0 : num_rx++;
2084 [ # # ]: 0 : } while (pending);
2085 : :
2086 [ # # ]: 0 : while (num_tx < num_rx) {
2087 : 0 : num_tx += qbman_swp_enqueue_multiple_fd(swp, &eqdesc,
2088 : : &fd[num_tx], 0, num_rx - num_tx);
2089 : : }
2090 : :
2091 [ # # ]: 0 : if (check_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index)) {
2092 [ # # ]: 0 : while (!qbman_check_command_complete(
2093 : 0 : get_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index)))
2094 : : ;
2095 : 0 : clear_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index);
2096 : : }
2097 : : /* issue a volatile dequeue command for next pull */
2098 : : while (1) {
2099 [ # # ]: 0 : if (qbman_swp_pull(swp, &pulldesc)) {
2100 : : DPAA2_PMD_DP_DEBUG("VDQ command is not issued."
2101 : : "QBMAN is busy (2)");
2102 : : continue;
2103 : : }
2104 : : break;
2105 : : }
2106 : 0 : q_storage->active_dqs = dq_storage1;
2107 : 0 : q_storage->active_dpio_id = DPAA2_PER_LCORE_ETHRX_DPIO->index;
2108 : 0 : set_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index, dq_storage1);
2109 : :
2110 : 0 : dpaa2_q->rx_pkts += num_rx;
2111 : 0 : dpaa2_q->tx_pkts += num_tx;
2112 : :
2113 : 0 : return 0;
2114 : : }
|