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