Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2008-2017 Cisco Systems, Inc. All rights reserved.
3 : : * Copyright 2007 Nuova Systems, Inc. All rights reserved.
4 : : */
5 : :
6 : : #include <rte_mbuf.h>
7 : : #include <ethdev_driver.h>
8 : : #include <rte_net.h>
9 : : #include <rte_prefetch.h>
10 : :
11 : : #include "enic_compat.h"
12 : : #include "rq_enet_desc.h"
13 : : #include "enic.h"
14 : : #include "enic_rxtx_common.h"
15 : : #include <rte_ether.h>
16 : : #include <rte_ip.h>
17 : : #include <rte_tcp.h>
18 : :
19 : : #define RTE_PMD_USE_PREFETCH
20 : :
21 : : #ifdef RTE_PMD_USE_PREFETCH
22 : : /*Prefetch a cache line into all cache levels. */
23 : : #define rte_enic_prefetch(p) rte_prefetch0(p)
24 : : #else
25 : : #define rte_enic_prefetch(p) do {} while (0)
26 : : #endif
27 : :
28 : : #ifdef RTE_PMD_PACKET_PREFETCH
29 : : #define rte_packet_prefetch(p) rte_prefetch1(p)
30 : : #else
31 : : #define rte_packet_prefetch(p) do {} while (0)
32 : : #endif
33 : :
34 : : static inline uint16_t
35 : 0 : enic_recv_pkts_common(void *rx_queue, struct rte_mbuf **rx_pkts,
36 : : uint16_t nb_pkts, const bool use_64b_desc)
37 : : {
38 : : struct vnic_rq *sop_rq = rx_queue;
39 : : struct vnic_rq *data_rq;
40 : : struct vnic_rq *rq;
41 : 0 : struct enic *enic = vnic_dev_priv(sop_rq->vdev);
42 : : uint16_t cq_idx;
43 : : uint16_t rq_idx, max_rx;
44 : : uint16_t rq_num;
45 : : struct rte_mbuf *nmb, *rxmb;
46 : : uint16_t nb_rx = 0;
47 : : struct vnic_cq *cq;
48 : : volatile struct cq_desc *cqd_ptr;
49 : : uint8_t color;
50 : : uint8_t tnl;
51 : : uint16_t seg_length;
52 : 0 : struct rte_mbuf *first_seg = sop_rq->pkt_first_seg;
53 : 0 : struct rte_mbuf *last_seg = sop_rq->pkt_last_seg;
54 [ # # ]: 0 : const int desc_size = use_64b_desc ?
55 : : sizeof(struct cq_enet_rq_desc_64) :
56 : : sizeof(struct cq_enet_rq_desc);
57 : : RTE_BUILD_BUG_ON(sizeof(struct cq_enet_rq_desc_64) != 64);
58 : :
59 : 0 : cq = &enic->cq[enic_cq_rq(enic, sop_rq->index)];
60 : 0 : cq_idx = cq->to_clean; /* index of cqd, rqd, mbuf_table */
61 : 0 : cqd_ptr = (struct cq_desc *)((uintptr_t)(cq->ring.descs) +
62 : 0 : (uintptr_t)cq_idx * desc_size);
63 : 0 : color = cq->last_color;
64 : :
65 : 0 : data_rq = &enic->rq[sop_rq->data_queue_idx];
66 : :
67 : : /* Receive until the end of the ring, at most. */
68 : 0 : max_rx = RTE_MIN(nb_pkts, cq->ring.desc_count - cq_idx);
69 : :
70 [ # # ]: 0 : while (max_rx) {
71 : : volatile struct rq_enet_desc *rqd_ptr;
72 : : struct cq_desc cqd;
73 : : uint8_t packet_error;
74 : : uint16_t ciflags;
75 : : uint8_t tc;
76 : : uint16_t rq_idx_msbs = 0;
77 : :
78 : 0 : max_rx--;
79 : :
80 : 0 : tc = *(volatile uint8_t *)((uintptr_t)cqd_ptr + desc_size - 1);
81 : : /* Check for pkts available */
82 [ # # ]: 0 : if ((tc & CQ_DESC_COLOR_MASK_NOSHIFT) == color)
83 : : break;
84 : :
85 : : /* Get the cq descriptor and extract rq info from it */
86 : 0 : cqd = *cqd_ptr;
87 : :
88 : : /*
89 : : * The first 16B of a 64B descriptor is identical to a 16B
90 : : * descriptor except for the type_color and fetch index. Extract
91 : : * fetch index and copy the type_color from the 64B to where it
92 : : * would be in a 16B descriptor so sebwequent code can run
93 : : * without further conditionals.
94 : : */
95 [ # # ]: 0 : if (use_64b_desc) {
96 : 0 : rq_idx_msbs = (((volatile struct cq_enet_rq_desc_64 *)
97 : 0 : cqd_ptr)->fetch_idx_flags
98 : : & CQ_ENET_RQ_DESC_FETCH_IDX_MASK)
99 : 0 : << CQ_DESC_COMP_NDX_BITS;
100 : 0 : cqd.type_color = tc;
101 : : }
102 : 0 : rq_num = cqd.q_number & CQ_DESC_Q_NUM_MASK;
103 : 0 : rq_idx = rq_idx_msbs +
104 : 0 : (cqd.completed_index & CQ_DESC_COMP_NDX_MASK);
105 : :
106 : 0 : rq = &enic->rq[rq_num];
107 : 0 : rqd_ptr = ((struct rq_enet_desc *)rq->ring.descs) + rq_idx;
108 : :
109 : : /* allocate a new mbuf */
110 : 0 : nmb = rte_mbuf_raw_alloc(rq->mp);
111 [ # # ]: 0 : if (nmb == NULL) {
112 : 0 : rte_atomic64_inc(&enic->soft_stats.rx_nombuf);
113 : : break;
114 : : }
115 : :
116 : : /* A packet error means descriptor and data are untrusted */
117 : : packet_error = enic_cq_rx_check_err(&cqd);
118 : :
119 : : /* Get the mbuf to return and replace with one just allocated */
120 : 0 : rxmb = rq->mbuf_ring[rq_idx];
121 : 0 : rq->mbuf_ring[rq_idx] = nmb;
122 : 0 : cq_idx++;
123 : :
124 : : /* Prefetch next mbuf & desc while processing current one */
125 : 0 : cqd_ptr = (struct cq_desc *)((uintptr_t)(cq->ring.descs) +
126 : 0 : (uintptr_t)cq_idx * desc_size);
127 : : rte_enic_prefetch(cqd_ptr);
128 : :
129 : : ciflags = enic_cq_rx_desc_ciflags(
130 : : (struct cq_enet_rq_desc *)&cqd);
131 : :
132 : : /* Push descriptor for newly allocated mbuf */
133 : 0 : nmb->data_off = RTE_PKTMBUF_HEADROOM;
134 : : /*
135 : : * Only the address needs to be refilled. length_type of the
136 : : * descriptor it set during initialization
137 : : * (enic_alloc_rx_queue_mbufs) and does not change.
138 : : */
139 [ # # ]: 0 : rqd_ptr->address = rte_cpu_to_le_64(nmb->buf_iova +
140 : : RTE_PKTMBUF_HEADROOM);
141 : :
142 : : /* Fill in the rest of the mbuf */
143 : : seg_length = enic_cq_rx_desc_n_bytes(&cqd);
144 : :
145 [ # # ]: 0 : if (rq->is_sop) {
146 : : first_seg = rxmb;
147 : 0 : first_seg->pkt_len = seg_length;
148 : : } else {
149 : 0 : first_seg->pkt_len = (uint16_t)(first_seg->pkt_len
150 : : + seg_length);
151 : 0 : first_seg->nb_segs++;
152 : 0 : last_seg->next = rxmb;
153 : : }
154 : :
155 : 0 : rxmb->port = enic->port_id;
156 : 0 : rxmb->data_len = seg_length;
157 : :
158 : 0 : rq->rx_nb_hold++;
159 : :
160 [ # # ]: 0 : if (!(enic_cq_rx_desc_eop(ciflags))) {
161 : : last_seg = rxmb;
162 : 0 : continue;
163 : : }
164 : :
165 : : /*
166 : : * When overlay offload is enabled, CQ.fcoe indicates the
167 : : * packet is tunnelled.
168 : : */
169 [ # # # # ]: 0 : tnl = enic->overlay_offload &&
170 : : (ciflags & CQ_ENET_RQ_DESC_FLAGS_FCOE) != 0;
171 : : /* cq rx flags are only valid if eop bit is set */
172 : 0 : first_seg->packet_type =
173 : : enic_cq_rx_flags_to_pkt_type(&cqd, tnl);
174 : 0 : enic_cq_rx_to_pkt_flags(&cqd, first_seg);
175 : :
176 : : /* Wipe the outer types set by enic_cq_rx_flags_to_pkt_type() */
177 [ # # ]: 0 : if (tnl) {
178 : 0 : first_seg->packet_type &= ~(RTE_PTYPE_L3_MASK |
179 : : RTE_PTYPE_L4_MASK);
180 : : }
181 [ # # ]: 0 : if (unlikely(packet_error)) {
182 : 0 : rte_pktmbuf_free(first_seg);
183 : 0 : rte_atomic64_inc(&enic->soft_stats.rx_packet_errors);
184 : 0 : continue;
185 : : }
186 : :
187 : :
188 : : /* prefetch mbuf data for caller */
189 : 0 : rte_packet_prefetch(RTE_PTR_ADD(first_seg->buf_addr,
190 : : RTE_PKTMBUF_HEADROOM));
191 : :
192 : : /* store the mbuf address into the next entry of the array */
193 : 0 : rx_pkts[nb_rx++] = first_seg;
194 : : }
195 [ # # ]: 0 : if (unlikely(cq_idx == cq->ring.desc_count)) {
196 : : cq_idx = 0;
197 : 0 : cq->last_color ^= CQ_DESC_COLOR_MASK_NOSHIFT;
198 : : }
199 : :
200 : 0 : sop_rq->pkt_first_seg = first_seg;
201 : 0 : sop_rq->pkt_last_seg = last_seg;
202 : :
203 : 0 : cq->to_clean = cq_idx;
204 : :
205 : 0 : if ((sop_rq->rx_nb_hold + data_rq->rx_nb_hold) >
206 [ # # ]: 0 : sop_rq->rx_free_thresh) {
207 [ # # ]: 0 : if (data_rq->in_use) {
208 : 0 : data_rq->posted_index =
209 [ # # ]: 0 : enic_ring_add(data_rq->ring.desc_count,
210 : : data_rq->posted_index,
211 : : data_rq->rx_nb_hold);
212 : 0 : data_rq->rx_nb_hold = 0;
213 : : }
214 : 0 : sop_rq->posted_index = enic_ring_add(sop_rq->ring.desc_count,
215 : : sop_rq->posted_index,
216 [ # # ]: 0 : sop_rq->rx_nb_hold);
217 : 0 : sop_rq->rx_nb_hold = 0;
218 : :
219 : : rte_mb();
220 [ # # ]: 0 : if (data_rq->in_use)
221 : 0 : iowrite32_relaxed(data_rq->posted_index,
222 : 0 : &data_rq->ctrl->posted_index);
223 : 0 : rte_compiler_barrier();
224 : 0 : iowrite32_relaxed(sop_rq->posted_index,
225 : 0 : &sop_rq->ctrl->posted_index);
226 : : }
227 : :
228 : :
229 : 0 : return nb_rx;
230 : : }
231 : :
232 : : uint16_t
233 : 0 : enic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
234 : : {
235 : 0 : return enic_recv_pkts_common(rx_queue, rx_pkts, nb_pkts, false);
236 : : }
237 : :
238 : : uint16_t
239 : 0 : enic_recv_pkts_64(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
240 : : {
241 : 0 : return enic_recv_pkts_common(rx_queue, rx_pkts, nb_pkts, true);
242 : : }
243 : :
244 : : uint16_t
245 : 0 : enic_noscatter_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
246 : : uint16_t nb_pkts)
247 : : {
248 : : struct rte_mbuf *mb, **rx, **rxmb;
249 : : uint16_t cq_idx, nb_rx, max_rx;
250 : : struct cq_enet_rq_desc *cqd;
251 : : struct rq_enet_desc *rqd;
252 : : unsigned int port_id;
253 : : struct vnic_cq *cq;
254 : : struct vnic_rq *rq;
255 : : struct enic *enic;
256 : : uint8_t color;
257 : : bool overlay;
258 : : bool tnl;
259 : :
260 : : rq = rx_queue;
261 : 0 : enic = vnic_dev_priv(rq->vdev);
262 : 0 : cq = &enic->cq[enic_cq_rq(enic, rq->index)];
263 : 0 : cq_idx = cq->to_clean;
264 : :
265 : : /*
266 : : * Fill up the reserve of free mbufs. Below, we restock the receive
267 : : * ring with these mbufs to avoid allocation failures.
268 : : */
269 [ # # ]: 0 : if (rq->num_free_mbufs == 0) {
270 [ # # # # ]: 0 : if (rte_mempool_get_bulk(rq->mp, (void **)rq->free_mbufs,
271 : : ENIC_RX_BURST_MAX))
272 : : return 0;
273 : 0 : rq->num_free_mbufs = ENIC_RX_BURST_MAX;
274 : : }
275 : :
276 : : /* Receive until the end of the ring, at most. */
277 : 0 : max_rx = RTE_MIN(nb_pkts, rq->num_free_mbufs);
278 : 0 : max_rx = RTE_MIN(max_rx, cq->ring.desc_count - cq_idx);
279 : :
280 : 0 : cqd = (struct cq_enet_rq_desc *)(cq->ring.descs) + cq_idx;
281 : 0 : color = cq->last_color;
282 : 0 : rxmb = rq->mbuf_ring + cq_idx;
283 : 0 : port_id = enic->port_id;
284 : 0 : overlay = enic->overlay_offload;
285 : :
286 : : rx = rx_pkts;
287 [ # # ]: 0 : while (max_rx) {
288 : 0 : max_rx--;
289 [ # # ]: 0 : if ((cqd->type_color & CQ_DESC_COLOR_MASK_NOSHIFT) == color)
290 : : break;
291 [ # # ]: 0 : if (unlikely(cqd->bytes_written_flags &
292 : : CQ_ENET_RQ_DESC_FLAGS_TRUNCATED)) {
293 : 0 : rte_pktmbuf_free(*rxmb++);
294 : 0 : rte_atomic64_inc(&enic->soft_stats.rx_packet_errors);
295 : 0 : cqd++;
296 : 0 : continue;
297 : : }
298 : :
299 : 0 : mb = *rxmb++;
300 : : /* prefetch mbuf data for caller */
301 : 0 : rte_packet_prefetch(RTE_PTR_ADD(mb->buf_addr,
302 : : RTE_PKTMBUF_HEADROOM));
303 : 0 : mb->data_len = cqd->bytes_written_flags &
304 : : CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK;
305 : 0 : mb->pkt_len = mb->data_len;
306 : 0 : mb->port = port_id;
307 [ # # # # ]: 0 : tnl = overlay && (cqd->completed_index_flags &
308 : : CQ_ENET_RQ_DESC_FLAGS_FCOE) != 0;
309 : 0 : mb->packet_type =
310 : : enic_cq_rx_flags_to_pkt_type((struct cq_desc *)cqd,
311 : : tnl);
312 : 0 : enic_cq_rx_to_pkt_flags((struct cq_desc *)cqd, mb);
313 : : /* Wipe the outer types set by enic_cq_rx_flags_to_pkt_type() */
314 [ # # ]: 0 : if (tnl) {
315 : 0 : mb->packet_type &= ~(RTE_PTYPE_L3_MASK |
316 : : RTE_PTYPE_L4_MASK);
317 : : }
318 : 0 : cqd++;
319 : 0 : *rx++ = mb;
320 : : }
321 : : /* Number of descriptors visited */
322 : 0 : nb_rx = cqd - (struct cq_enet_rq_desc *)(cq->ring.descs) - cq_idx;
323 [ # # ]: 0 : if (nb_rx == 0)
324 : : return 0;
325 : 0 : rqd = ((struct rq_enet_desc *)rq->ring.descs) + cq_idx;
326 : 0 : rxmb = rq->mbuf_ring + cq_idx;
327 : : cq_idx += nb_rx;
328 : 0 : rq->rx_nb_hold += nb_rx;
329 [ # # ]: 0 : if (unlikely(cq_idx == cq->ring.desc_count)) {
330 : : cq_idx = 0;
331 : 0 : cq->last_color ^= CQ_DESC_COLOR_MASK_NOSHIFT;
332 : : }
333 : 0 : cq->to_clean = cq_idx;
334 : :
335 : 0 : memcpy(rxmb, rq->free_mbufs + ENIC_RX_BURST_MAX - rq->num_free_mbufs,
336 : : sizeof(struct rte_mbuf *) * nb_rx);
337 : 0 : rq->num_free_mbufs -= nb_rx;
338 [ # # ]: 0 : while (nb_rx) {
339 : 0 : nb_rx--;
340 : 0 : mb = *rxmb++;
341 : 0 : mb->data_off = RTE_PKTMBUF_HEADROOM;
342 : 0 : rqd->address = mb->buf_iova + RTE_PKTMBUF_HEADROOM;
343 : 0 : rqd++;
344 : : }
345 [ # # ]: 0 : if (rq->rx_nb_hold > rq->rx_free_thresh) {
346 [ # # ]: 0 : rq->posted_index = enic_ring_add(rq->ring.desc_count,
347 : : rq->posted_index,
348 : : rq->rx_nb_hold);
349 : 0 : rq->rx_nb_hold = 0;
350 : : rte_wmb();
351 : 0 : iowrite32_relaxed(rq->posted_index,
352 : 0 : &rq->ctrl->posted_index);
353 : : }
354 : :
355 : 0 : return rx - rx_pkts;
356 : : }
357 : :
358 : 0 : static inline void enic_free_wq_bufs(struct vnic_wq *wq,
359 : : uint16_t completed_index)
360 : : {
361 : : struct rte_mbuf *buf;
362 : : struct rte_mbuf *m, *free[ENIC_LEGACY_MAX_WQ_DESCS];
363 : : unsigned int nb_to_free, nb_free = 0, i;
364 : : struct rte_mempool *pool;
365 : : unsigned int tail_idx;
366 : 0 : unsigned int desc_count = wq->ring.desc_count;
367 : :
368 : : /*
369 : : * On 1500 Series VIC and beyond, greater than ENIC_LEGACY_MAX_WQ_DESCS
370 : : * may be attempted to be freed. Cap it at ENIC_LEGACY_MAX_WQ_DESCS.
371 : : */
372 [ # # ]: 0 : nb_to_free = RTE_MIN(enic_ring_sub(desc_count, wq->tail_idx,
373 : : completed_index) + 1,
374 : : (uint32_t)ENIC_LEGACY_MAX_WQ_DESCS);
375 : : tail_idx = wq->tail_idx;
376 : 0 : pool = wq->bufs[tail_idx]->pool;
377 [ # # ]: 0 : for (i = 0; i < nb_to_free; i++) {
378 : 0 : buf = wq->bufs[tail_idx];
379 : : m = rte_pktmbuf_prefree_seg(buf);
380 [ # # ]: 0 : if (unlikely(m == NULL)) {
381 : : tail_idx = enic_ring_incr(desc_count, tail_idx);
382 : 0 : continue;
383 : : }
384 : :
385 [ # # ]: 0 : if (likely(m->pool == pool)) {
386 : : RTE_ASSERT(nb_free < ENIC_LEGACY_MAX_WQ_DESCS);
387 : 0 : free[nb_free++] = m;
388 : : } else {
389 : : rte_mempool_put_bulk(pool, (void *)free, nb_free);
390 : 0 : free[0] = m;
391 : : nb_free = 1;
392 : 0 : pool = m->pool;
393 : : }
394 : : tail_idx = enic_ring_incr(desc_count, tail_idx);
395 : : }
396 : :
397 [ # # ]: 0 : if (nb_free > 0)
398 : : rte_mempool_put_bulk(pool, (void **)free, nb_free);
399 : :
400 : 0 : wq->tail_idx = tail_idx;
401 : 0 : wq->ring.desc_avail += nb_to_free;
402 : 0 : }
403 : :
404 : 0 : unsigned int enic_cleanup_wq(__rte_unused struct enic *enic, struct vnic_wq *wq)
405 : : {
406 : : uint16_t completed_index;
407 : :
408 : 0 : completed_index = *((uint32_t *)wq->cqmsg_rz->addr) & 0xffff;
409 : :
410 [ # # ]: 0 : if (wq->last_completed_index != completed_index) {
411 : 0 : enic_free_wq_bufs(wq, completed_index);
412 : 0 : wq->last_completed_index = completed_index;
413 : : }
414 : 0 : return 0;
415 : : }
416 : :
417 : 0 : uint16_t enic_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
418 : : uint16_t nb_pkts)
419 : : {
420 : : struct vnic_wq *wq = (struct vnic_wq *)tx_queue;
421 : : int32_t ret;
422 : : uint16_t i;
423 : : uint64_t ol_flags;
424 : : struct rte_mbuf *m;
425 : :
426 [ # # ]: 0 : for (i = 0; i != nb_pkts; i++) {
427 : 0 : m = tx_pkts[i];
428 : 0 : ol_flags = m->ol_flags;
429 [ # # ]: 0 : if (!(ol_flags & RTE_MBUF_F_TX_TCP_SEG)) {
430 [ # # ]: 0 : if (unlikely(m->pkt_len > ENIC_TX_MAX_PKT_SIZE)) {
431 : 0 : rte_errno = EINVAL;
432 : 0 : return i;
433 : : }
434 : : } else {
435 : : uint16_t header_len;
436 : :
437 : 0 : header_len = m->l2_len + m->l3_len + m->l4_len;
438 [ # # ]: 0 : if (m->tso_segsz + header_len > ENIC_TX_MAX_PKT_SIZE) {
439 : 0 : rte_errno = EINVAL;
440 : 0 : return i;
441 : : }
442 : : }
443 : :
444 [ # # ]: 0 : if (ol_flags & wq->tx_offload_notsup_mask) {
445 : 0 : rte_errno = ENOTSUP;
446 : 0 : return i;
447 : : }
448 : : #ifdef RTE_LIBRTE_ETHDEV_DEBUG
449 : : ret = rte_validate_tx_offload(m);
450 : : if (ret != 0) {
451 : : rte_errno = -ret;
452 : : return i;
453 : : }
454 : : #endif
455 : : ret = rte_net_intel_cksum_prepare(m);
456 [ # # ]: 0 : if (ret != 0) {
457 : 0 : rte_errno = -ret;
458 : 0 : return i;
459 : : }
460 : : }
461 : :
462 : : return i;
463 : : }
464 : :
465 : 0 : uint16_t enic_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
466 : : uint16_t nb_pkts)
467 : : {
468 : : uint16_t index;
469 : : unsigned int pkt_len, data_len;
470 : : unsigned int nb_segs;
471 : : struct rte_mbuf *tx_pkt;
472 : : struct vnic_wq *wq = (struct vnic_wq *)tx_queue;
473 : 0 : struct enic *enic = vnic_dev_priv(wq->vdev);
474 : : unsigned short vlan_id;
475 : : uint64_t ol_flags;
476 : : uint64_t ol_flags_mask;
477 : : unsigned int wq_desc_avail;
478 : : int head_idx;
479 : : unsigned int desc_count;
480 : : struct wq_enet_desc *descs, *desc_p, desc_tmp;
481 : : uint16_t mss;
482 : : uint8_t vlan_tag_insert;
483 : : uint8_t eop, cq;
484 : : uint64_t bus_addr;
485 : : uint8_t offload_mode;
486 : : uint16_t header_len;
487 : : uint64_t tso;
488 : : rte_atomic64_t *tx_oversized;
489 : :
490 : 0 : enic_cleanup_wq(enic, wq);
491 : : wq_desc_avail = vnic_wq_desc_avail(wq);
492 : 0 : head_idx = wq->head_idx;
493 : 0 : desc_count = wq->ring.desc_count;
494 : : ol_flags_mask = RTE_MBUF_F_TX_VLAN | RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_L4_MASK;
495 : 0 : tx_oversized = &enic->soft_stats.tx_oversized;
496 : :
497 : 0 : nb_pkts = RTE_MIN(nb_pkts, ENIC_TX_XMIT_MAX);
498 : :
499 [ # # ]: 0 : for (index = 0; index < nb_pkts; index++) {
500 : 0 : tx_pkt = *tx_pkts++;
501 : 0 : pkt_len = tx_pkt->pkt_len;
502 : 0 : data_len = tx_pkt->data_len;
503 : 0 : ol_flags = tx_pkt->ol_flags;
504 : 0 : nb_segs = tx_pkt->nb_segs;
505 : 0 : tso = ol_flags & RTE_MBUF_F_TX_TCP_SEG;
506 : :
507 : : /* drop packet if it's too big to send */
508 [ # # ]: 0 : if (unlikely(!tso && pkt_len > ENIC_TX_MAX_PKT_SIZE)) {
509 : 0 : rte_pktmbuf_free(tx_pkt);
510 : : rte_atomic64_inc(tx_oversized);
511 : 0 : continue;
512 : : }
513 : :
514 [ # # ]: 0 : if (nb_segs > wq_desc_avail) {
515 [ # # ]: 0 : if (index > 0)
516 : 0 : goto post;
517 : 0 : goto done;
518 : : }
519 : :
520 : : mss = 0;
521 : 0 : vlan_id = tx_pkt->vlan_tci;
522 : 0 : vlan_tag_insert = !!(ol_flags & RTE_MBUF_F_TX_VLAN);
523 : 0 : bus_addr = (dma_addr_t)
524 : 0 : (tx_pkt->buf_iova + tx_pkt->data_off);
525 : :
526 : 0 : descs = (struct wq_enet_desc *)wq->ring.descs;
527 : 0 : desc_p = descs + head_idx;
528 : :
529 : 0 : eop = (data_len == pkt_len);
530 : : offload_mode = WQ_ENET_OFFLOAD_MODE_CSUM;
531 : : header_len = 0;
532 : :
533 [ # # ]: 0 : if (tso) {
534 : 0 : header_len = tx_pkt->l2_len + tx_pkt->l3_len +
535 : 0 : tx_pkt->l4_len;
536 : :
537 : : /* Drop if non-TCP packet or TSO seg size is too big */
538 [ # # # # ]: 0 : if (unlikely(header_len == 0 || ((tx_pkt->tso_segsz +
539 : : header_len) > ENIC_TX_MAX_PKT_SIZE))) {
540 : 0 : rte_pktmbuf_free(tx_pkt);
541 : : rte_atomic64_inc(tx_oversized);
542 : 0 : continue;
543 : : }
544 : :
545 : : offload_mode = WQ_ENET_OFFLOAD_MODE_TSO;
546 : : mss = tx_pkt->tso_segsz;
547 : : /* For tunnel, need the size of outer+inner headers */
548 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
549 : 0 : header_len += tx_pkt->outer_l2_len +
550 : 0 : tx_pkt->outer_l3_len;
551 : : }
552 : : }
553 : :
554 [ # # # # ]: 0 : if ((ol_flags & ol_flags_mask) && (header_len == 0)) {
555 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
556 : 0 : mss |= ENIC_CALC_IP_CKSUM;
557 : :
558 : : /* Nic uses just 1 bit for UDP and TCP */
559 [ # # ]: 0 : switch (ol_flags & RTE_MBUF_F_TX_L4_MASK) {
560 : 0 : case RTE_MBUF_F_TX_TCP_CKSUM:
561 : : case RTE_MBUF_F_TX_UDP_CKSUM:
562 : 0 : mss |= ENIC_CALC_TCP_UDP_CKSUM;
563 : 0 : break;
564 : : }
565 : : }
566 : 0 : wq->cq_pend++;
567 : : cq = 0;
568 [ # # # # ]: 0 : if (eop && wq->cq_pend >= ENIC_WQ_CQ_THRESH) {
569 : : cq = 1;
570 : 0 : wq->cq_pend = 0;
571 : : }
572 [ # # ]: 0 : wq_enet_desc_enc(&desc_tmp, bus_addr, data_len, mss, header_len,
573 : : offload_mode, eop, cq, 0, vlan_tag_insert,
574 : : vlan_id, 0);
575 : :
576 : 0 : *desc_p = desc_tmp;
577 : 0 : wq->bufs[head_idx] = tx_pkt;
578 [ # # ]: 0 : head_idx = enic_ring_incr(desc_count, head_idx);
579 : 0 : wq_desc_avail--;
580 : :
581 [ # # ]: 0 : if (!eop) {
582 [ # # ]: 0 : for (tx_pkt = tx_pkt->next; tx_pkt; tx_pkt =
583 : : tx_pkt->next) {
584 : 0 : data_len = tx_pkt->data_len;
585 : :
586 : 0 : wq->cq_pend++;
587 : : cq = 0;
588 [ # # ]: 0 : if (tx_pkt->next == NULL) {
589 : : eop = 1;
590 [ # # ]: 0 : if (wq->cq_pend >= ENIC_WQ_CQ_THRESH) {
591 : : cq = 1;
592 : 0 : wq->cq_pend = 0;
593 : : }
594 : : }
595 : 0 : desc_p = descs + head_idx;
596 : 0 : bus_addr = (dma_addr_t)(tx_pkt->buf_iova
597 : 0 : + tx_pkt->data_off);
598 [ # # ]: 0 : wq_enet_desc_enc((struct wq_enet_desc *)
599 : : &desc_tmp, bus_addr, data_len,
600 : : mss, 0, offload_mode, eop, cq,
601 : : 0, vlan_tag_insert, vlan_id,
602 : : 0);
603 : :
604 : 0 : *desc_p = desc_tmp;
605 : 0 : wq->bufs[head_idx] = tx_pkt;
606 [ # # ]: 0 : head_idx = enic_ring_incr(desc_count, head_idx);
607 : 0 : wq_desc_avail--;
608 : : }
609 : : }
610 : : }
611 : 0 : post:
612 : : rte_wmb();
613 : 0 : iowrite32_relaxed(head_idx, &wq->ctrl->posted_index);
614 : 0 : done:
615 : 0 : wq->ring.desc_avail = wq_desc_avail;
616 : 0 : wq->head_idx = head_idx;
617 : :
618 : 0 : return index;
619 : : }
620 : :
621 : 0 : static void enqueue_simple_pkts(struct rte_mbuf **pkts,
622 : : struct wq_enet_desc *desc,
623 : : uint16_t n,
624 : : struct enic *enic)
625 : : {
626 : : struct rte_mbuf *p;
627 : : uint16_t mss;
628 : :
629 [ # # ]: 0 : while (n) {
630 : 0 : n--;
631 : 0 : p = *pkts++;
632 : 0 : desc->address = p->buf_iova + p->data_off;
633 : 0 : desc->length = p->pkt_len;
634 : : /* VLAN insert */
635 : 0 : desc->vlan_tag = p->vlan_tci;
636 : 0 : desc->header_length_flags &=
637 : : ((1 << WQ_ENET_FLAGS_EOP_SHIFT) |
638 : : (1 << WQ_ENET_FLAGS_CQ_ENTRY_SHIFT));
639 [ # # ]: 0 : if (p->ol_flags & RTE_MBUF_F_TX_VLAN) {
640 : 0 : desc->header_length_flags |=
641 : : 1 << WQ_ENET_FLAGS_VLAN_TAG_INSERT_SHIFT;
642 : : }
643 : : /*
644 : : * Checksum offload. We use WQ_ENET_OFFLOAD_MODE_CSUM, which
645 : : * is 0, so no need to set offload_mode.
646 : : */
647 : : mss = 0;
648 [ # # ]: 0 : if (p->ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
649 : : mss |= ENIC_CALC_IP_CKSUM << WQ_ENET_MSS_SHIFT;
650 [ # # ]: 0 : if (p->ol_flags & RTE_MBUF_F_TX_L4_MASK)
651 : 0 : mss |= ENIC_CALC_TCP_UDP_CKSUM << WQ_ENET_MSS_SHIFT;
652 : 0 : desc->mss_loopback = mss;
653 : :
654 : : /*
655 : : * The app should not send oversized
656 : : * packets. tx_pkt_prepare includes a check as
657 : : * well. But some apps ignore the device max size and
658 : : * tx_pkt_prepare. Oversized packets cause WQ errors
659 : : * and the NIC ends up disabling the whole WQ. So
660 : : * truncate packets..
661 : : */
662 [ # # ]: 0 : if (unlikely(p->pkt_len > ENIC_TX_MAX_PKT_SIZE)) {
663 : 0 : desc->length = ENIC_TX_MAX_PKT_SIZE;
664 : 0 : rte_atomic64_inc(&enic->soft_stats.tx_oversized);
665 : : }
666 : 0 : desc++;
667 : : }
668 : 0 : }
669 : :
670 : 0 : uint16_t enic_simple_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
671 : : uint16_t nb_pkts)
672 : : {
673 : : unsigned int head_idx, desc_count;
674 : : struct wq_enet_desc *desc;
675 : : struct vnic_wq *wq;
676 : : struct enic *enic;
677 : : uint16_t rem, n;
678 : :
679 : : wq = (struct vnic_wq *)tx_queue;
680 : 0 : enic = vnic_dev_priv(wq->vdev);
681 : 0 : enic_cleanup_wq(enic, wq);
682 : : /* Will enqueue this many packets in this call */
683 : 0 : nb_pkts = RTE_MIN(nb_pkts, wq->ring.desc_avail);
684 [ # # ]: 0 : if (nb_pkts == 0)
685 : : return 0;
686 : :
687 : 0 : head_idx = wq->head_idx;
688 : 0 : desc_count = wq->ring.desc_count;
689 : :
690 : : /* Descriptors until the end of the ring */
691 : 0 : n = desc_count - head_idx;
692 : 0 : n = RTE_MIN(nb_pkts, n);
693 : :
694 : : /* Save mbuf pointers to free later */
695 : 0 : memcpy(wq->bufs + head_idx, tx_pkts, sizeof(struct rte_mbuf *) * n);
696 : :
697 : : /* Enqueue until the ring end */
698 : 0 : rem = nb_pkts - n;
699 : 0 : desc = ((struct wq_enet_desc *)wq->ring.descs) + head_idx;
700 : 0 : enqueue_simple_pkts(tx_pkts, desc, n, enic);
701 : :
702 : : /* Wrap to the start of the ring */
703 [ # # ]: 0 : if (rem) {
704 : 0 : tx_pkts += n;
705 : 0 : memcpy(wq->bufs, tx_pkts, sizeof(struct rte_mbuf *) * rem);
706 : 0 : desc = (struct wq_enet_desc *)wq->ring.descs;
707 : 0 : enqueue_simple_pkts(tx_pkts, desc, rem, enic);
708 : : }
709 : : rte_wmb();
710 : :
711 : : /* Update head_idx and desc_avail */
712 : 0 : wq->ring.desc_avail -= nb_pkts;
713 : 0 : head_idx += nb_pkts;
714 [ # # ]: 0 : if (head_idx >= desc_count)
715 : 0 : head_idx -= desc_count;
716 : 0 : wq->head_idx = head_idx;
717 : 0 : iowrite32_relaxed(head_idx, &wq->ctrl->posted_index);
718 : 0 : return nb_pkts;
719 : : }
|