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