1
2
3
4
5#include <sys/queue.h>
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <errno.h>
11#include <stdint.h>
12#include <stdarg.h>
13#include <unistd.h>
14#include <inttypes.h>
15
16#include <rte_byteorder.h>
17#include <rte_common.h>
18#include <rte_cycles.h>
19#include <rte_log.h>
20#include <rte_debug.h>
21#include <rte_interrupts.h>
22#include <rte_pci.h>
23#include <rte_memory.h>
24#include <rte_memzone.h>
25#include <rte_launch.h>
26#include <rte_eal.h>
27#include <rte_per_lcore.h>
28#include <rte_lcore.h>
29#include <rte_atomic.h>
30#include <rte_branch_prediction.h>
31#include <rte_mempool.h>
32#include <rte_malloc.h>
33#include <rte_mbuf.h>
34#include <rte_ether.h>
35#include <ethdev_driver.h>
36#include <rte_prefetch.h>
37#include <rte_ip.h>
38#include <rte_udp.h>
39#include <rte_tcp.h>
40#include <rte_sctp.h>
41#include <rte_string_fns.h>
42#include <rte_errno.h>
43#include <rte_net.h>
44
45#include "base/vmxnet3_defs.h"
46#include "vmxnet3_ring.h"
47
48#include "vmxnet3_logs.h"
49#include "vmxnet3_ethdev.h"
50
51#define VMXNET3_TX_OFFLOAD_MASK ( \
52 PKT_TX_VLAN_PKT | \
53 PKT_TX_IPV6 | \
54 PKT_TX_IPV4 | \
55 PKT_TX_L4_MASK | \
56 PKT_TX_TCP_SEG)
57
58#define VMXNET3_TX_OFFLOAD_NOTSUP_MASK \
59 (PKT_TX_OFFLOAD_MASK ^ VMXNET3_TX_OFFLOAD_MASK)
60
61static const uint32_t rxprod_reg[2] = {VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2};
62
63static int vmxnet3_post_rx_bufs(vmxnet3_rx_queue_t*, uint8_t);
64static void vmxnet3_tq_tx_complete(vmxnet3_tx_queue_t *);
65#ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER_NOT_USED
66static void vmxnet3_rxq_dump(struct vmxnet3_rx_queue *);
67static void vmxnet3_txq_dump(struct vmxnet3_tx_queue *);
68#endif
69
70#ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER_NOT_USED
71static void
72vmxnet3_rxq_dump(struct vmxnet3_rx_queue *rxq)
73{
74 uint32_t avail = 0;
75
76 if (rxq == NULL)
77 return;
78
79 PMD_RX_LOG(DEBUG,
80 "RXQ: cmd0 base : %p cmd1 base : %p comp ring base : %p.",
81 rxq->cmd_ring[0].base, rxq->cmd_ring[1].base, rxq->comp_ring.base);
82 PMD_RX_LOG(DEBUG,
83 "RXQ: cmd0 basePA : 0x%lx cmd1 basePA : 0x%lx comp ring basePA : 0x%lx.",
84 (unsigned long)rxq->cmd_ring[0].basePA,
85 (unsigned long)rxq->cmd_ring[1].basePA,
86 (unsigned long)rxq->comp_ring.basePA);
87
88 avail = vmxnet3_cmd_ring_desc_avail(&rxq->cmd_ring[0]);
89 PMD_RX_LOG(DEBUG,
90 "RXQ:cmd0: size=%u; free=%u; next2proc=%u; queued=%u",
91 (uint32_t)rxq->cmd_ring[0].size, avail,
92 rxq->comp_ring.next2proc,
93 rxq->cmd_ring[0].size - avail);
94
95 avail = vmxnet3_cmd_ring_desc_avail(&rxq->cmd_ring[1]);
96 PMD_RX_LOG(DEBUG, "RXQ:cmd1 size=%u; free=%u; next2proc=%u; queued=%u",
97 (uint32_t)rxq->cmd_ring[1].size, avail, rxq->comp_ring.next2proc,
98 rxq->cmd_ring[1].size - avail);
99
100}
101
102static void
103vmxnet3_txq_dump(struct vmxnet3_tx_queue *txq)
104{
105 uint32_t avail = 0;
106
107 if (txq == NULL)
108 return;
109
110 PMD_TX_LOG(DEBUG, "TXQ: cmd base : %p comp ring base : %p data ring base : %p.",
111 txq->cmd_ring.base, txq->comp_ring.base, txq->data_ring.base);
112 PMD_TX_LOG(DEBUG, "TXQ: cmd basePA : 0x%lx comp ring basePA : 0x%lx data ring basePA : 0x%lx.",
113 (unsigned long)txq->cmd_ring.basePA,
114 (unsigned long)txq->comp_ring.basePA,
115 (unsigned long)txq->data_ring.basePA);
116
117 avail = vmxnet3_cmd_ring_desc_avail(&txq->cmd_ring);
118 PMD_TX_LOG(DEBUG, "TXQ: size=%u; free=%u; next2proc=%u; queued=%u",
119 (uint32_t)txq->cmd_ring.size, avail,
120 txq->comp_ring.next2proc, txq->cmd_ring.size - avail);
121}
122#endif
123
124static void
125vmxnet3_tx_cmd_ring_release_mbufs(vmxnet3_cmd_ring_t *ring)
126{
127 while (ring->next2comp != ring->next2fill) {
128
129 vmxnet3_buf_info_t *buf_info = ring->buf_info + ring->next2comp;
130
131 if (buf_info->m) {
132 rte_pktmbuf_free(buf_info->m);
133 buf_info->m = NULL;
134 buf_info->bufPA = 0;
135 buf_info->len = 0;
136 }
137 vmxnet3_cmd_ring_adv_next2comp(ring);
138 }
139}
140
141static void
142vmxnet3_rx_cmd_ring_release_mbufs(vmxnet3_cmd_ring_t *ring)
143{
144 uint32_t i;
145
146 for (i = 0; i < ring->size; i++) {
147
148 vmxnet3_buf_info_t *buf_info = &ring->buf_info[i];
149
150 if (buf_info->m) {
151 rte_pktmbuf_free_seg(buf_info->m);
152 buf_info->m = NULL;
153 buf_info->bufPA = 0;
154 buf_info->len = 0;
155 }
156 vmxnet3_cmd_ring_adv_next2comp(ring);
157 }
158}
159
160static void
161vmxnet3_cmd_ring_release(vmxnet3_cmd_ring_t *ring)
162{
163 rte_free(ring->buf_info);
164 ring->buf_info = NULL;
165}
166
167void
168vmxnet3_dev_tx_queue_release(void *txq)
169{
170 vmxnet3_tx_queue_t *tq = txq;
171
172 if (tq != NULL) {
173
174 vmxnet3_tx_cmd_ring_release_mbufs(&tq->cmd_ring);
175
176 vmxnet3_cmd_ring_release(&tq->cmd_ring);
177
178 rte_memzone_free(tq->mz);
179
180 rte_free(tq);
181 }
182}
183
184void
185vmxnet3_dev_rx_queue_release(void *rxq)
186{
187 int i;
188 vmxnet3_rx_queue_t *rq = rxq;
189
190 if (rq != NULL) {
191
192 for (i = 0; i < VMXNET3_RX_CMDRING_SIZE; i++)
193 vmxnet3_rx_cmd_ring_release_mbufs(&rq->cmd_ring[i]);
194
195
196 for (i = 0; i < VMXNET3_RX_CMDRING_SIZE; i++)
197 vmxnet3_cmd_ring_release(&rq->cmd_ring[i]);
198
199
200 rte_memzone_free(rq->mz);
201
202
203 rte_free(rq);
204 }
205}
206
207static void
208vmxnet3_dev_tx_queue_reset(void *txq)
209{
210 vmxnet3_tx_queue_t *tq = txq;
211 struct vmxnet3_cmd_ring *ring = &tq->cmd_ring;
212 struct vmxnet3_comp_ring *comp_ring = &tq->comp_ring;
213 struct vmxnet3_data_ring *data_ring = &tq->data_ring;
214 int size;
215
216 if (tq != NULL) {
217
218 vmxnet3_tx_cmd_ring_release_mbufs(&tq->cmd_ring);
219 }
220
221
222 ring->next2fill = 0;
223 ring->next2comp = 0;
224 ring->gen = VMXNET3_INIT_GEN;
225 comp_ring->next2proc = 0;
226 comp_ring->gen = VMXNET3_INIT_GEN;
227
228 size = sizeof(struct Vmxnet3_TxDesc) * ring->size;
229 size += sizeof(struct Vmxnet3_TxCompDesc) * comp_ring->size;
230 size += tq->txdata_desc_size * data_ring->size;
231
232 memset(ring->base, 0, size);
233}
234
235static void
236vmxnet3_dev_rx_queue_reset(void *rxq)
237{
238 int i;
239 vmxnet3_rx_queue_t *rq = rxq;
240 struct vmxnet3_hw *hw = rq->hw;
241 struct vmxnet3_cmd_ring *ring0, *ring1;
242 struct vmxnet3_comp_ring *comp_ring;
243 struct vmxnet3_rx_data_ring *data_ring = &rq->data_ring;
244 int size;
245
246
247 for (i = 0; i < VMXNET3_RX_CMDRING_SIZE; i++)
248 vmxnet3_rx_cmd_ring_release_mbufs(&rq->cmd_ring[i]);
249
250 ring0 = &rq->cmd_ring[0];
251 ring1 = &rq->cmd_ring[1];
252 comp_ring = &rq->comp_ring;
253
254
255 ring0->next2fill = 0;
256 ring1->next2fill = 0;
257 ring0->next2comp = 0;
258 ring1->next2comp = 0;
259 ring0->gen = VMXNET3_INIT_GEN;
260 ring1->gen = VMXNET3_INIT_GEN;
261 comp_ring->next2proc = 0;
262 comp_ring->gen = VMXNET3_INIT_GEN;
263
264 size = sizeof(struct Vmxnet3_RxDesc) * (ring0->size + ring1->size);
265 size += sizeof(struct Vmxnet3_RxCompDesc) * comp_ring->size;
266 if (VMXNET3_VERSION_GE_3(hw) && rq->data_desc_size)
267 size += rq->data_desc_size * data_ring->size;
268
269 memset(ring0->base, 0, size);
270}
271
272void
273vmxnet3_dev_clear_queues(struct rte_eth_dev *dev)
274{
275 unsigned i;
276
277 PMD_INIT_FUNC_TRACE();
278
279 for (i = 0; i < dev->data->nb_tx_queues; i++) {
280 struct vmxnet3_tx_queue *txq = dev->data->tx_queues[i];
281
282 if (txq != NULL) {
283 txq->stopped = TRUE;
284 vmxnet3_dev_tx_queue_reset(txq);
285 }
286 }
287
288 for (i = 0; i < dev->data->nb_rx_queues; i++) {
289 struct vmxnet3_rx_queue *rxq = dev->data->rx_queues[i];
290
291 if (rxq != NULL) {
292 rxq->stopped = TRUE;
293 vmxnet3_dev_rx_queue_reset(rxq);
294 }
295 }
296}
297
298static int
299vmxnet3_unmap_pkt(uint16_t eop_idx, vmxnet3_tx_queue_t *txq)
300{
301 int completed = 0;
302 struct rte_mbuf *mbuf;
303
304
305 RTE_ASSERT(txq->cmd_ring.base[eop_idx].txd.eop == 1);
306
307 mbuf = txq->cmd_ring.buf_info[eop_idx].m;
308 if (mbuf == NULL)
309 rte_panic("EOP desc does not point to a valid mbuf");
310 rte_pktmbuf_free(mbuf);
311
312 txq->cmd_ring.buf_info[eop_idx].m = NULL;
313
314 while (txq->cmd_ring.next2comp != eop_idx) {
315
316 RTE_ASSERT(txq->cmd_ring.base[txq->cmd_ring.next2comp].txd.cq == 0);
317 vmxnet3_cmd_ring_adv_next2comp(&txq->cmd_ring);
318 completed++;
319 }
320
321
322 vmxnet3_cmd_ring_adv_next2comp(&txq->cmd_ring);
323
324 return completed + 1;
325}
326
327static void
328vmxnet3_tq_tx_complete(vmxnet3_tx_queue_t *txq)
329{
330 int completed = 0;
331 vmxnet3_comp_ring_t *comp_ring = &txq->comp_ring;
332 struct Vmxnet3_TxCompDesc *tcd = (struct Vmxnet3_TxCompDesc *)
333 (comp_ring->base + comp_ring->next2proc);
334
335 while (tcd->gen == comp_ring->gen) {
336 completed += vmxnet3_unmap_pkt(tcd->txdIdx, txq);
337
338 vmxnet3_comp_ring_adv_next2proc(comp_ring);
339 tcd = (struct Vmxnet3_TxCompDesc *)(comp_ring->base +
340 comp_ring->next2proc);
341 }
342
343 PMD_TX_LOG(DEBUG, "Processed %d tx comps & command descs.", completed);
344}
345
346uint16_t
347vmxnet3_prep_pkts(__rte_unused void *tx_queue, struct rte_mbuf **tx_pkts,
348 uint16_t nb_pkts)
349{
350 int32_t ret;
351 uint32_t i;
352 uint64_t ol_flags;
353 struct rte_mbuf *m;
354
355 for (i = 0; i != nb_pkts; i++) {
356 m = tx_pkts[i];
357 ol_flags = m->ol_flags;
358
359
360
361
362 if ((ol_flags & PKT_TX_TCP_SEG) == 0 &&
363 m->nb_segs > VMXNET3_MAX_TXD_PER_PKT) {
364 rte_errno = EINVAL;
365 return i;
366 }
367
368
369 if ((ol_flags & VMXNET3_TX_OFFLOAD_NOTSUP_MASK) != 0 ||
370 (ol_flags & PKT_TX_L4_MASK) ==
371 PKT_TX_SCTP_CKSUM) {
372 rte_errno = ENOTSUP;
373 return i;
374 }
375
376#ifdef RTE_LIBRTE_ETHDEV_DEBUG
377 ret = rte_validate_tx_offload(m);
378 if (ret != 0) {
379 rte_errno = -ret;
380 return i;
381 }
382#endif
383 ret = rte_net_intel_cksum_prepare(m);
384 if (ret != 0) {
385 rte_errno = -ret;
386 return i;
387 }
388 }
389
390 return i;
391}
392
393uint16_t
394vmxnet3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
395 uint16_t nb_pkts)
396{
397 uint16_t nb_tx;
398 vmxnet3_tx_queue_t *txq = tx_queue;
399 struct vmxnet3_hw *hw = txq->hw;
400 Vmxnet3_TxQueueCtrl *txq_ctrl = &txq->shared->ctrl;
401 uint32_t deferred = rte_le_to_cpu_32(txq_ctrl->txNumDeferred);
402
403 if (unlikely(txq->stopped)) {
404 PMD_TX_LOG(DEBUG, "Tx queue is stopped.");
405 return 0;
406 }
407
408
409 vmxnet3_tq_tx_complete(txq);
410
411 nb_tx = 0;
412 while (nb_tx < nb_pkts) {
413 Vmxnet3_GenericDesc *gdesc;
414 vmxnet3_buf_info_t *tbi;
415 uint32_t first2fill, avail, dw2;
416 struct rte_mbuf *txm = tx_pkts[nb_tx];
417 struct rte_mbuf *m_seg = txm;
418 int copy_size = 0;
419 bool tso = (txm->ol_flags & PKT_TX_TCP_SEG) != 0;
420
421 unsigned count = txm->nb_segs;
422
423 avail = vmxnet3_cmd_ring_desc_avail(&txq->cmd_ring);
424 if (count > avail) {
425
426 if (unlikely(avail == 0)) {
427 PMD_TX_LOG(DEBUG, "No free ring descriptors");
428 txq->stats.tx_ring_full++;
429 txq->stats.drop_total += (nb_pkts - nb_tx);
430 break;
431 }
432
433
434
435
436
437 PMD_TX_LOG(DEBUG, "Running out of ring descriptors "
438 "(avail %d needed %d)", avail, count);
439 txq->stats.drop_total++;
440 if (tso)
441 txq->stats.drop_tso++;
442 rte_pktmbuf_free(txm);
443 nb_tx++;
444 continue;
445 }
446
447
448 if (unlikely(!tso && count > VMXNET3_MAX_TXD_PER_PKT)) {
449 PMD_TX_LOG(ERR, "Non-TSO packet cannot occupy more than %d tx "
450 "descriptors. Packet dropped.", VMXNET3_MAX_TXD_PER_PKT);
451 txq->stats.drop_too_many_segs++;
452 txq->stats.drop_total++;
453 rte_pktmbuf_free(txm);
454 nb_tx++;
455 continue;
456 }
457
458 if (txm->nb_segs == 1 &&
459 rte_pktmbuf_pkt_len(txm) <= txq->txdata_desc_size) {
460 struct Vmxnet3_TxDataDesc *tdd;
461
462
463 if (unlikely(rte_pktmbuf_pkt_len(txm) == 0)) {
464 txq->stats.drop_total++;
465 rte_pktmbuf_free(txm);
466 nb_tx++;
467 continue;
468 }
469
470 tdd = (struct Vmxnet3_TxDataDesc *)
471 ((uint8 *)txq->data_ring.base +
472 txq->cmd_ring.next2fill *
473 txq->txdata_desc_size);
474 copy_size = rte_pktmbuf_pkt_len(txm);
475 rte_memcpy(tdd->data, rte_pktmbuf_mtod(txm, char *), copy_size);
476 }
477
478
479 dw2 = (txq->cmd_ring.gen ^ 0x1) << VMXNET3_TXD_GEN_SHIFT;
480 first2fill = txq->cmd_ring.next2fill;
481 do {
482
483 tbi = txq->cmd_ring.buf_info + txq->cmd_ring.next2fill;
484
485
486
487
488
489 gdesc = txq->cmd_ring.base + txq->cmd_ring.next2fill;
490
491
492 if (unlikely(m_seg->data_len == 0))
493 continue;
494
495 if (copy_size) {
496 uint64 offset =
497 (uint64)txq->cmd_ring.next2fill *
498 txq->txdata_desc_size;
499 gdesc->txd.addr =
500 rte_cpu_to_le_64(txq->data_ring.basePA +
501 offset);
502 } else {
503 gdesc->txd.addr = rte_mbuf_data_iova(m_seg);
504 }
505
506 gdesc->dword[2] = dw2 | m_seg->data_len;
507 gdesc->dword[3] = 0;
508
509
510 vmxnet3_cmd_ring_adv_next2fill(&txq->cmd_ring);
511
512
513 dw2 = txq->cmd_ring.gen << VMXNET3_TXD_GEN_SHIFT;
514 } while ((m_seg = m_seg->next) != NULL);
515
516
517 tbi->m = txm;
518
519 gdesc->dword[3] |= VMXNET3_TXD_EOP | VMXNET3_TXD_CQ;
520
521
522 gdesc = txq->cmd_ring.base + first2fill;
523 if (txm->ol_flags & PKT_TX_VLAN_PKT) {
524 gdesc->txd.ti = 1;
525 gdesc->txd.tci = txm->vlan_tci;
526 }
527
528 if (tso) {
529 uint16_t mss = txm->tso_segsz;
530
531 RTE_ASSERT(mss > 0);
532
533 gdesc->txd.hlen = txm->l2_len + txm->l3_len + txm->l4_len;
534 gdesc->txd.om = VMXNET3_OM_TSO;
535 gdesc->txd.msscof = mss;
536
537 deferred += (rte_pktmbuf_pkt_len(txm) - gdesc->txd.hlen + mss - 1) / mss;
538 } else if (txm->ol_flags & PKT_TX_L4_MASK) {
539 gdesc->txd.om = VMXNET3_OM_CSUM;
540 gdesc->txd.hlen = txm->l2_len + txm->l3_len;
541
542 switch (txm->ol_flags & PKT_TX_L4_MASK) {
543 case PKT_TX_TCP_CKSUM:
544 gdesc->txd.msscof = gdesc->txd.hlen +
545 offsetof(struct rte_tcp_hdr, cksum);
546 break;
547 case PKT_TX_UDP_CKSUM:
548 gdesc->txd.msscof = gdesc->txd.hlen +
549 offsetof(struct rte_udp_hdr,
550 dgram_cksum);
551 break;
552 default:
553 PMD_TX_LOG(WARNING, "requested cksum offload not supported %#llx",
554 txm->ol_flags & PKT_TX_L4_MASK);
555 abort();
556 }
557 deferred++;
558 } else {
559 gdesc->txd.hlen = 0;
560 gdesc->txd.om = VMXNET3_OM_NONE;
561 gdesc->txd.msscof = 0;
562 deferred++;
563 }
564
565
566 rte_compiler_barrier();
567 gdesc->dword[2] ^= VMXNET3_TXD_GEN;
568
569 txq_ctrl->txNumDeferred = rte_cpu_to_le_32(deferred);
570 nb_tx++;
571 }
572
573 PMD_TX_LOG(DEBUG, "vmxnet3 txThreshold: %u", rte_le_to_cpu_32(txq_ctrl->txThreshold));
574
575 if (deferred >= rte_le_to_cpu_32(txq_ctrl->txThreshold)) {
576 txq_ctrl->txNumDeferred = 0;
577
578 VMXNET3_WRITE_BAR0_REG(hw, (VMXNET3_REG_TXPROD + txq->queue_id * VMXNET3_REG_ALIGN),
579 txq->cmd_ring.next2fill);
580 }
581
582 return nb_tx;
583}
584
585static inline void
586vmxnet3_renew_desc(vmxnet3_rx_queue_t *rxq, uint8_t ring_id,
587 struct rte_mbuf *mbuf)
588{
589 uint32_t val;
590 struct vmxnet3_cmd_ring *ring = &rxq->cmd_ring[ring_id];
591 struct Vmxnet3_RxDesc *rxd =
592 (struct Vmxnet3_RxDesc *)(ring->base + ring->next2fill);
593 vmxnet3_buf_info_t *buf_info = &ring->buf_info[ring->next2fill];
594
595 if (ring_id == 0) {
596
597
598
599
600
601
602 val = VMXNET3_RXD_BTYPE_HEAD;
603 } else {
604
605 val = VMXNET3_RXD_BTYPE_BODY;
606 }
607
608
609
610
611
612 buf_info->m = mbuf;
613 buf_info->len = (uint16_t)(mbuf->buf_len - RTE_PKTMBUF_HEADROOM);
614 buf_info->bufPA = rte_mbuf_data_iova_default(mbuf);
615
616
617 rxd->addr = buf_info->bufPA;
618
619
620 rxd->btype = val;
621 rxd->len = buf_info->len;
622
623 rxd->gen = ring->gen;
624
625 vmxnet3_cmd_ring_adv_next2fill(ring);
626}
627
628
629
630
631
632
633
634
635
636
637static int
638vmxnet3_post_rx_bufs(vmxnet3_rx_queue_t *rxq, uint8_t ring_id)
639{
640 int err = 0;
641 uint32_t i = 0;
642 struct vmxnet3_cmd_ring *ring = &rxq->cmd_ring[ring_id];
643
644 while (vmxnet3_cmd_ring_desc_avail(ring) > 0) {
645 struct rte_mbuf *mbuf;
646
647
648 mbuf = rte_mbuf_raw_alloc(rxq->mp);
649 if (unlikely(mbuf == NULL)) {
650 PMD_RX_LOG(ERR, "Error allocating mbuf");
651 rxq->stats.rx_buf_alloc_failure++;
652 err = ENOMEM;
653 break;
654 }
655
656 vmxnet3_renew_desc(rxq, ring_id, mbuf);
657 i++;
658 }
659
660
661 if (vmxnet3_cmd_ring_desc_avail(ring) >= (ring->size - 1))
662 return -err;
663 else
664 return i;
665}
666
667
668static uint16_t
669vmxnet3_guess_mss(struct vmxnet3_hw *hw, const Vmxnet3_RxCompDesc *rcd,
670 struct rte_mbuf *rxm)
671{
672 uint32_t hlen, slen;
673 struct rte_ipv4_hdr *ipv4_hdr;
674 struct rte_ipv6_hdr *ipv6_hdr;
675 struct rte_tcp_hdr *tcp_hdr;
676 char *ptr;
677 uint8_t segs;
678
679 RTE_ASSERT(rcd->tcp);
680
681 ptr = rte_pktmbuf_mtod(rxm, char *);
682 slen = rte_pktmbuf_data_len(rxm);
683 hlen = sizeof(struct rte_ether_hdr);
684
685 if (rcd->v4) {
686 if (unlikely(slen < hlen + sizeof(struct rte_ipv4_hdr)))
687 return hw->mtu - sizeof(struct rte_ipv4_hdr)
688 - sizeof(struct rte_tcp_hdr);
689
690 ipv4_hdr = (struct rte_ipv4_hdr *)(ptr + hlen);
691 hlen += rte_ipv4_hdr_len(ipv4_hdr);
692 } else if (rcd->v6) {
693 if (unlikely(slen < hlen + sizeof(struct rte_ipv6_hdr)))
694 return hw->mtu - sizeof(struct rte_ipv6_hdr) -
695 sizeof(struct rte_tcp_hdr);
696
697 ipv6_hdr = (struct rte_ipv6_hdr *)(ptr + hlen);
698 hlen += sizeof(struct rte_ipv6_hdr);
699 if (unlikely(ipv6_hdr->proto != IPPROTO_TCP)) {
700 int frag;
701
702 rte_net_skip_ip6_ext(ipv6_hdr->proto, rxm,
703 &hlen, &frag);
704 }
705 }
706
707 if (unlikely(slen < hlen + sizeof(struct rte_tcp_hdr)))
708 return hw->mtu - hlen - sizeof(struct rte_tcp_hdr) +
709 sizeof(struct rte_ether_hdr);
710
711 tcp_hdr = (struct rte_tcp_hdr *)(ptr + hlen);
712 hlen += (tcp_hdr->data_off & 0xf0) >> 2;
713
714 segs = *vmxnet3_segs_dynfield(rxm);
715 if (segs > 1)
716 return (rte_pktmbuf_pkt_len(rxm) - hlen + segs - 1) / segs;
717 else
718 return hw->mtu - hlen + sizeof(struct rte_ether_hdr);
719}
720
721
722static inline void
723vmxnet3_rx_offload(struct vmxnet3_hw *hw, const Vmxnet3_RxCompDesc *rcd,
724 struct rte_mbuf *rxm, const uint8_t sop)
725{
726 uint64_t ol_flags = rxm->ol_flags;
727 uint32_t packet_type = rxm->packet_type;
728
729
730 if (sop) {
731
732 packet_type |= RTE_PTYPE_L2_ETHER;
733
734
735 if (VMXNET3_VERSION_GE_2(hw) &&
736 rcd->type == VMXNET3_CDTYPE_RXCOMP_LRO) {
737 const Vmxnet3_RxCompDescExt *rcde =
738 (const Vmxnet3_RxCompDescExt *)rcd;
739
740 rxm->tso_segsz = rcde->mss;
741 *vmxnet3_segs_dynfield(rxm) = rcde->segCnt;
742 ol_flags |= PKT_RX_LRO;
743 }
744 } else {
745
746 if (rcd->rssType != VMXNET3_RCD_RSS_TYPE_NONE) {
747 ol_flags |= PKT_RX_RSS_HASH;
748 rxm->hash.rss = rcd->rssHash;
749 }
750
751
752 if (rcd->ts) {
753 ol_flags |= (PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED);
754 rxm->vlan_tci = rte_le_to_cpu_16((uint16_t)rcd->tci);
755 }
756
757
758 if (rcd->cnc) {
759 ol_flags |= PKT_RX_L4_CKSUM_UNKNOWN;
760 } else {
761 if (rcd->v4) {
762 packet_type |= RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
763
764 if (rcd->ipc)
765 ol_flags |= PKT_RX_IP_CKSUM_GOOD;
766 else
767 ol_flags |= PKT_RX_IP_CKSUM_BAD;
768
769 if (rcd->tuc) {
770 ol_flags |= PKT_RX_L4_CKSUM_GOOD;
771 if (rcd->tcp)
772 packet_type |= RTE_PTYPE_L4_TCP;
773 else
774 packet_type |= RTE_PTYPE_L4_UDP;
775 } else {
776 if (rcd->tcp) {
777 packet_type |= RTE_PTYPE_L4_TCP;
778 ol_flags |= PKT_RX_L4_CKSUM_BAD;
779 } else if (rcd->udp) {
780 packet_type |= RTE_PTYPE_L4_UDP;
781 ol_flags |= PKT_RX_L4_CKSUM_BAD;
782 }
783 }
784 } else if (rcd->v6) {
785 packet_type |= RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
786
787 if (rcd->tuc) {
788 ol_flags |= PKT_RX_L4_CKSUM_GOOD;
789 if (rcd->tcp)
790 packet_type |= RTE_PTYPE_L4_TCP;
791 else
792 packet_type |= RTE_PTYPE_L4_UDP;
793 } else {
794 if (rcd->tcp) {
795 packet_type |= RTE_PTYPE_L4_TCP;
796 ol_flags |= PKT_RX_L4_CKSUM_BAD;
797 } else if (rcd->udp) {
798 packet_type |= RTE_PTYPE_L4_UDP;
799 ol_flags |= PKT_RX_L4_CKSUM_BAD;
800 }
801 }
802 } else {
803 packet_type |= RTE_PTYPE_UNKNOWN;
804 }
805
806
807 if ((ol_flags & PKT_RX_LRO) && rxm->tso_segsz == 0)
808 rxm->tso_segsz = vmxnet3_guess_mss(hw,
809 rcd, rxm);
810 }
811 }
812
813 rxm->ol_flags = ol_flags;
814 rxm->packet_type = packet_type;
815}
816
817
818
819
820
821uint16_t
822vmxnet3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
823{
824 uint16_t nb_rx;
825 uint32_t nb_rxd, idx;
826 uint8_t ring_idx;
827 vmxnet3_rx_queue_t *rxq;
828 Vmxnet3_RxCompDesc *rcd;
829 vmxnet3_buf_info_t *rbi;
830 Vmxnet3_RxDesc *rxd;
831 struct rte_mbuf *rxm = NULL;
832 struct vmxnet3_hw *hw;
833
834 nb_rx = 0;
835 ring_idx = 0;
836 nb_rxd = 0;
837 idx = 0;
838
839 rxq = rx_queue;
840 hw = rxq->hw;
841
842 rcd = &rxq->comp_ring.base[rxq->comp_ring.next2proc].rcd;
843
844 if (unlikely(rxq->stopped)) {
845 PMD_RX_LOG(DEBUG, "Rx queue is stopped.");
846 return 0;
847 }
848
849 while (rcd->gen == rxq->comp_ring.gen) {
850 struct rte_mbuf *newm;
851
852 if (nb_rx >= nb_pkts)
853 break;
854
855 newm = rte_mbuf_raw_alloc(rxq->mp);
856 if (unlikely(newm == NULL)) {
857 PMD_RX_LOG(ERR, "Error allocating mbuf");
858 rxq->stats.rx_buf_alloc_failure++;
859 break;
860 }
861
862 idx = rcd->rxdIdx;
863 ring_idx = vmxnet3_get_ring_idx(hw, rcd->rqID);
864 rxd = (Vmxnet3_RxDesc *)rxq->cmd_ring[ring_idx].base + idx;
865 RTE_SET_USED(rxd);
866 rbi = rxq->cmd_ring[ring_idx].buf_info + idx;
867
868 PMD_RX_LOG(DEBUG, "rxd idx: %d ring idx: %d.", idx, ring_idx);
869
870 RTE_ASSERT(rcd->len <= rxd->len);
871 RTE_ASSERT(rbi->m);
872
873
874 rxm = rbi->m;
875
876
877 rbi->m = NULL;
878 rbi->bufPA = 0;
879
880
881 rxq->cmd_ring[ring_idx].next2comp = idx;
882
883
884 if (unlikely(rcd->eop && rcd->err)) {
885 rxq->stats.drop_total++;
886 rxq->stats.drop_err++;
887
888 if (!rcd->fcs) {
889 rxq->stats.drop_fcs++;
890 PMD_RX_LOG(ERR, "Recv packet dropped due to frame err.");
891 }
892 PMD_RX_LOG(ERR, "Error in received packet rcd#:%d rxd:%d",
893 (int)(rcd - (struct Vmxnet3_RxCompDesc *)
894 rxq->comp_ring.base), rcd->rxdIdx);
895 rte_pktmbuf_free_seg(rxm);
896 if (rxq->start_seg) {
897 struct rte_mbuf *start = rxq->start_seg;
898
899 rxq->start_seg = NULL;
900 rte_pktmbuf_free(start);
901 }
902 goto rcd_done;
903 }
904
905
906 rxm->port = rxq->port_id;
907 rxm->nb_segs = 1;
908 rxm->next = NULL;
909 rxm->pkt_len = (uint16_t)rcd->len;
910 rxm->data_len = (uint16_t)rcd->len;
911 rxm->data_off = RTE_PKTMBUF_HEADROOM;
912 rxm->ol_flags = 0;
913 rxm->vlan_tci = 0;
914 rxm->packet_type = 0;
915
916
917
918
919
920
921
922
923 if (rcd->sop) {
924 RTE_ASSERT(rxd->btype == VMXNET3_RXD_BTYPE_HEAD);
925
926 if (unlikely(rcd->len == 0)) {
927 RTE_ASSERT(rcd->eop);
928
929 PMD_RX_LOG(DEBUG,
930 "Rx buf was skipped. rxring[%d][%d])",
931 ring_idx, idx);
932 rte_pktmbuf_free_seg(rxm);
933 goto rcd_done;
934 }
935
936 if (vmxnet3_rx_data_ring(hw, rcd->rqID)) {
937 uint8_t *rdd = rxq->data_ring.base +
938 idx * rxq->data_desc_size;
939
940 RTE_ASSERT(VMXNET3_VERSION_GE_3(hw));
941 rte_memcpy(rte_pktmbuf_mtod(rxm, char *),
942 rdd, rcd->len);
943 }
944
945 rxq->start_seg = rxm;
946 rxq->last_seg = rxm;
947 vmxnet3_rx_offload(hw, rcd, rxm, 1);
948 } else {
949 struct rte_mbuf *start = rxq->start_seg;
950
951 RTE_ASSERT(rxd->btype == VMXNET3_RXD_BTYPE_BODY);
952
953 if (likely(start && rxm->data_len > 0)) {
954 start->pkt_len += rxm->data_len;
955 start->nb_segs++;
956
957 rxq->last_seg->next = rxm;
958 rxq->last_seg = rxm;
959 } else {
960 PMD_RX_LOG(ERR, "Error received empty or out of order frame.");
961 rxq->stats.drop_total++;
962 rxq->stats.drop_err++;
963
964 rte_pktmbuf_free_seg(rxm);
965 }
966 }
967
968 if (rcd->eop) {
969 struct rte_mbuf *start = rxq->start_seg;
970
971 vmxnet3_rx_offload(hw, rcd, start, 0);
972 rx_pkts[nb_rx++] = start;
973 rxq->start_seg = NULL;
974 }
975
976rcd_done:
977 rxq->cmd_ring[ring_idx].next2comp = idx;
978 VMXNET3_INC_RING_IDX_ONLY(rxq->cmd_ring[ring_idx].next2comp,
979 rxq->cmd_ring[ring_idx].size);
980
981
982 vmxnet3_renew_desc(rxq, ring_idx, newm);
983 if (unlikely(rxq->shared->ctrl.updateRxProd)) {
984 VMXNET3_WRITE_BAR0_REG(hw, rxprod_reg[ring_idx] + (rxq->queue_id * VMXNET3_REG_ALIGN),
985 rxq->cmd_ring[ring_idx].next2fill);
986 }
987
988
989 vmxnet3_comp_ring_adv_next2proc(&rxq->comp_ring);
990
991 rcd = &rxq->comp_ring.base[rxq->comp_ring.next2proc].rcd;
992 nb_rxd++;
993 if (nb_rxd > rxq->cmd_ring[0].size) {
994 PMD_RX_LOG(ERR, "Used up quota of receiving packets,"
995 " relinquish control.");
996 break;
997 }
998 }
999
1000 if (unlikely(nb_rxd == 0)) {
1001 uint32_t avail;
1002 for (ring_idx = 0; ring_idx < VMXNET3_RX_CMDRING_SIZE; ring_idx++) {
1003 avail = vmxnet3_cmd_ring_desc_avail(&rxq->cmd_ring[ring_idx]);
1004 if (unlikely(avail > 0)) {
1005
1006 vmxnet3_post_rx_bufs(rxq, ring_idx);
1007 }
1008 }
1009 if (unlikely(rxq->shared->ctrl.updateRxProd)) {
1010 for (ring_idx = 0; ring_idx < VMXNET3_RX_CMDRING_SIZE; ring_idx++) {
1011 VMXNET3_WRITE_BAR0_REG(hw, rxprod_reg[ring_idx] + (rxq->queue_id * VMXNET3_REG_ALIGN),
1012 rxq->cmd_ring[ring_idx].next2fill);
1013 }
1014 }
1015 }
1016
1017 return nb_rx;
1018}
1019
1020int
1021vmxnet3_dev_tx_queue_setup(struct rte_eth_dev *dev,
1022 uint16_t queue_idx,
1023 uint16_t nb_desc,
1024 unsigned int socket_id,
1025 const struct rte_eth_txconf *tx_conf __rte_unused)
1026{
1027 struct vmxnet3_hw *hw = dev->data->dev_private;
1028 const struct rte_memzone *mz;
1029 struct vmxnet3_tx_queue *txq;
1030 struct vmxnet3_cmd_ring *ring;
1031 struct vmxnet3_comp_ring *comp_ring;
1032 struct vmxnet3_data_ring *data_ring;
1033 int size;
1034
1035 PMD_INIT_FUNC_TRACE();
1036
1037 txq = rte_zmalloc("ethdev_tx_queue", sizeof(struct vmxnet3_tx_queue),
1038 RTE_CACHE_LINE_SIZE);
1039 if (txq == NULL) {
1040 PMD_INIT_LOG(ERR, "Can not allocate tx queue structure");
1041 return -ENOMEM;
1042 }
1043
1044 txq->queue_id = queue_idx;
1045 txq->port_id = dev->data->port_id;
1046 txq->shared = NULL;
1047 txq->hw = hw;
1048 txq->qid = queue_idx;
1049 txq->stopped = TRUE;
1050 txq->txdata_desc_size = hw->txdata_desc_size;
1051
1052 ring = &txq->cmd_ring;
1053 comp_ring = &txq->comp_ring;
1054 data_ring = &txq->data_ring;
1055
1056
1057 if (nb_desc < VMXNET3_DEF_TX_RING_SIZE) {
1058 PMD_INIT_LOG(ERR, "VMXNET3 Tx Ring Size Min: %u",
1059 VMXNET3_DEF_TX_RING_SIZE);
1060 return -EINVAL;
1061 } else if (nb_desc > VMXNET3_TX_RING_MAX_SIZE) {
1062 PMD_INIT_LOG(ERR, "VMXNET3 Tx Ring Size Max: %u",
1063 VMXNET3_TX_RING_MAX_SIZE);
1064 return -EINVAL;
1065 } else {
1066 ring->size = nb_desc;
1067 ring->size &= ~VMXNET3_RING_SIZE_MASK;
1068 }
1069 comp_ring->size = data_ring->size = ring->size;
1070
1071
1072 ring->next2fill = 0;
1073 ring->next2comp = 0;
1074 ring->gen = VMXNET3_INIT_GEN;
1075 comp_ring->next2proc = 0;
1076 comp_ring->gen = VMXNET3_INIT_GEN;
1077
1078 size = sizeof(struct Vmxnet3_TxDesc) * ring->size;
1079 size += sizeof(struct Vmxnet3_TxCompDesc) * comp_ring->size;
1080 size += txq->txdata_desc_size * data_ring->size;
1081
1082 mz = rte_eth_dma_zone_reserve(dev, "txdesc", queue_idx, size,
1083 VMXNET3_RING_BA_ALIGN, socket_id);
1084 if (mz == NULL) {
1085 PMD_INIT_LOG(ERR, "ERROR: Creating queue descriptors zone");
1086 return -ENOMEM;
1087 }
1088 txq->mz = mz;
1089 memset(mz->addr, 0, mz->len);
1090
1091
1092 ring->base = mz->addr;
1093 ring->basePA = mz->iova;
1094
1095
1096 comp_ring->base = ring->base + ring->size;
1097 comp_ring->basePA = ring->basePA +
1098 (sizeof(struct Vmxnet3_TxDesc) * ring->size);
1099
1100
1101 data_ring->base = (Vmxnet3_TxDataDesc *)(comp_ring->base + comp_ring->size);
1102 data_ring->basePA = comp_ring->basePA +
1103 (sizeof(struct Vmxnet3_TxCompDesc) * comp_ring->size);
1104
1105
1106 ring->buf_info = rte_zmalloc("tx_ring_buf_info",
1107 ring->size * sizeof(vmxnet3_buf_info_t), RTE_CACHE_LINE_SIZE);
1108 if (ring->buf_info == NULL) {
1109 PMD_INIT_LOG(ERR, "ERROR: Creating tx_buf_info structure");
1110 return -ENOMEM;
1111 }
1112
1113
1114 dev->data->tx_queues[queue_idx] = txq;
1115
1116 return 0;
1117}
1118
1119int
1120vmxnet3_dev_rx_queue_setup(struct rte_eth_dev *dev,
1121 uint16_t queue_idx,
1122 uint16_t nb_desc,
1123 unsigned int socket_id,
1124 __rte_unused const struct rte_eth_rxconf *rx_conf,
1125 struct rte_mempool *mp)
1126{
1127 const struct rte_memzone *mz;
1128 struct vmxnet3_rx_queue *rxq;
1129 struct vmxnet3_hw *hw = dev->data->dev_private;
1130 struct vmxnet3_cmd_ring *ring0, *ring1, *ring;
1131 struct vmxnet3_comp_ring *comp_ring;
1132 struct vmxnet3_rx_data_ring *data_ring;
1133 int size;
1134 uint8_t i;
1135 char mem_name[32];
1136
1137 PMD_INIT_FUNC_TRACE();
1138
1139 rxq = rte_zmalloc("ethdev_rx_queue", sizeof(struct vmxnet3_rx_queue),
1140 RTE_CACHE_LINE_SIZE);
1141 if (rxq == NULL) {
1142 PMD_INIT_LOG(ERR, "Can not allocate rx queue structure");
1143 return -ENOMEM;
1144 }
1145
1146 rxq->mp = mp;
1147 rxq->queue_id = queue_idx;
1148 rxq->port_id = dev->data->port_id;
1149 rxq->shared = NULL;
1150 rxq->hw = hw;
1151 rxq->qid1 = queue_idx;
1152 rxq->qid2 = queue_idx + hw->num_rx_queues;
1153 rxq->data_ring_qid = queue_idx + 2 * hw->num_rx_queues;
1154 rxq->data_desc_size = hw->rxdata_desc_size;
1155 rxq->stopped = TRUE;
1156
1157 ring0 = &rxq->cmd_ring[0];
1158 ring1 = &rxq->cmd_ring[1];
1159 comp_ring = &rxq->comp_ring;
1160 data_ring = &rxq->data_ring;
1161
1162
1163 if (nb_desc < VMXNET3_DEF_RX_RING_SIZE) {
1164 PMD_INIT_LOG(ERR, "VMXNET3 Rx Ring Size Min: 256");
1165 return -EINVAL;
1166 } else if (nb_desc > VMXNET3_RX_RING_MAX_SIZE) {
1167 PMD_INIT_LOG(ERR, "VMXNET3 Rx Ring Size Max: 4096");
1168 return -EINVAL;
1169 } else {
1170 ring0->size = nb_desc;
1171 ring0->size &= ~VMXNET3_RING_SIZE_MASK;
1172 ring1->size = ring0->size;
1173 }
1174
1175 comp_ring->size = ring0->size + ring1->size;
1176 data_ring->size = ring0->size;
1177
1178
1179 ring0->next2fill = 0;
1180 ring1->next2fill = 0;
1181 ring0->next2comp = 0;
1182 ring1->next2comp = 0;
1183 ring0->gen = VMXNET3_INIT_GEN;
1184 ring1->gen = VMXNET3_INIT_GEN;
1185 comp_ring->next2proc = 0;
1186 comp_ring->gen = VMXNET3_INIT_GEN;
1187
1188 size = sizeof(struct Vmxnet3_RxDesc) * (ring0->size + ring1->size);
1189 size += sizeof(struct Vmxnet3_RxCompDesc) * comp_ring->size;
1190 if (VMXNET3_VERSION_GE_3(hw) && rxq->data_desc_size)
1191 size += rxq->data_desc_size * data_ring->size;
1192
1193 mz = rte_eth_dma_zone_reserve(dev, "rxdesc", queue_idx, size,
1194 VMXNET3_RING_BA_ALIGN, socket_id);
1195 if (mz == NULL) {
1196 PMD_INIT_LOG(ERR, "ERROR: Creating queue descriptors zone");
1197 return -ENOMEM;
1198 }
1199 rxq->mz = mz;
1200 memset(mz->addr, 0, mz->len);
1201
1202
1203 ring0->base = mz->addr;
1204 ring0->basePA = mz->iova;
1205
1206
1207 ring1->base = ring0->base + ring0->size;
1208 ring1->basePA = ring0->basePA + sizeof(struct Vmxnet3_RxDesc) * ring0->size;
1209
1210
1211 comp_ring->base = ring1->base + ring1->size;
1212 comp_ring->basePA = ring1->basePA + sizeof(struct Vmxnet3_RxDesc) *
1213 ring1->size;
1214
1215
1216 if (VMXNET3_VERSION_GE_3(hw) && rxq->data_desc_size) {
1217 data_ring->base =
1218 (uint8_t *)(comp_ring->base + comp_ring->size);
1219 data_ring->basePA = comp_ring->basePA +
1220 sizeof(struct Vmxnet3_RxCompDesc) * comp_ring->size;
1221 }
1222
1223
1224 for (i = 0; i < VMXNET3_RX_CMDRING_SIZE; i++) {
1225
1226 ring = &rxq->cmd_ring[i];
1227 ring->rid = i;
1228 snprintf(mem_name, sizeof(mem_name), "rx_ring_%d_buf_info", i);
1229
1230 ring->buf_info = rte_zmalloc(mem_name,
1231 ring->size * sizeof(vmxnet3_buf_info_t),
1232 RTE_CACHE_LINE_SIZE);
1233 if (ring->buf_info == NULL) {
1234 PMD_INIT_LOG(ERR, "ERROR: Creating rx_buf_info structure");
1235 return -ENOMEM;
1236 }
1237 }
1238
1239
1240 dev->data->rx_queues[queue_idx] = rxq;
1241
1242 return 0;
1243}
1244
1245
1246
1247
1248
1249int
1250vmxnet3_dev_rxtx_init(struct rte_eth_dev *dev)
1251{
1252 struct vmxnet3_hw *hw = dev->data->dev_private;
1253
1254 int i, ret;
1255 uint8_t j;
1256
1257 PMD_INIT_FUNC_TRACE();
1258
1259 for (i = 0; i < hw->num_rx_queues; i++) {
1260 vmxnet3_rx_queue_t *rxq = dev->data->rx_queues[i];
1261
1262 for (j = 0; j < VMXNET3_RX_CMDRING_SIZE; j++) {
1263
1264 ret = vmxnet3_post_rx_bufs(rxq, j);
1265 if (ret <= 0) {
1266 PMD_INIT_LOG(ERR,
1267 "ERROR: Posting Rxq: %d buffers ring: %d",
1268 i, j);
1269 return -ret;
1270 }
1271
1272
1273
1274
1275 if (unlikely(rxq->shared->ctrl.updateRxProd)) {
1276 VMXNET3_WRITE_BAR0_REG(hw, rxprod_reg[j] + (rxq->queue_id * VMXNET3_REG_ALIGN),
1277 rxq->cmd_ring[j].next2fill);
1278 }
1279 }
1280 rxq->stopped = FALSE;
1281 rxq->start_seg = NULL;
1282 }
1283
1284 for (i = 0; i < dev->data->nb_tx_queues; i++) {
1285 struct vmxnet3_tx_queue *txq = dev->data->tx_queues[i];
1286
1287 txq->stopped = FALSE;
1288 }
1289
1290 return 0;
1291}
1292
1293static uint8_t rss_intel_key[40] = {
1294 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2,
1295 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0,
1296 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
1297 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C,
1298 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA,
1299};
1300
1301
1302
1303
1304int
1305vmxnet3_v4_rss_configure(struct rte_eth_dev *dev)
1306{
1307 struct vmxnet3_hw *hw = dev->data->dev_private;
1308 Vmxnet3_DriverShared *shared = hw->shared;
1309 Vmxnet3_CmdInfo *cmdInfo = &shared->cu.cmdInfo;
1310 struct rte_eth_rss_conf *port_rss_conf;
1311 uint64_t rss_hf;
1312 uint32_t ret;
1313
1314 PMD_INIT_FUNC_TRACE();
1315
1316 cmdInfo->setRSSFields = 0;
1317 port_rss_conf = &dev->data->dev_conf.rx_adv_conf.rss_conf;
1318
1319 if ((port_rss_conf->rss_hf & VMXNET3_MANDATORY_V4_RSS) !=
1320 VMXNET3_MANDATORY_V4_RSS) {
1321 PMD_INIT_LOG(WARNING, "RSS: IPv4/6 TCP is required for vmxnet3 v4 RSS,"
1322 "automatically setting it");
1323 port_rss_conf->rss_hf |= VMXNET3_MANDATORY_V4_RSS;
1324 }
1325
1326 rss_hf = port_rss_conf->rss_hf &
1327 (VMXNET3_V4_RSS_MASK | VMXNET3_RSS_OFFLOAD_ALL);
1328
1329 if (rss_hf & ETH_RSS_NONFRAG_IPV4_TCP)
1330 cmdInfo->setRSSFields |= VMXNET3_RSS_FIELDS_TCPIP4;
1331 if (rss_hf & ETH_RSS_NONFRAG_IPV6_TCP)
1332 cmdInfo->setRSSFields |= VMXNET3_RSS_FIELDS_TCPIP6;
1333 if (rss_hf & ETH_RSS_NONFRAG_IPV4_UDP)
1334 cmdInfo->setRSSFields |= VMXNET3_RSS_FIELDS_UDPIP4;
1335 if (rss_hf & ETH_RSS_NONFRAG_IPV6_UDP)
1336 cmdInfo->setRSSFields |= VMXNET3_RSS_FIELDS_UDPIP6;
1337
1338 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
1339 VMXNET3_CMD_SET_RSS_FIELDS);
1340 ret = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_CMD);
1341
1342 if (ret != VMXNET3_SUCCESS) {
1343 PMD_DRV_LOG(ERR, "Set RSS fields (v4) failed: %d", ret);
1344 }
1345
1346 return ret;
1347}
1348
1349
1350
1351
1352int
1353vmxnet3_rss_configure(struct rte_eth_dev *dev)
1354{
1355 struct vmxnet3_hw *hw = dev->data->dev_private;
1356 struct VMXNET3_RSSConf *dev_rss_conf;
1357 struct rte_eth_rss_conf *port_rss_conf;
1358 uint64_t rss_hf;
1359 uint8_t i, j;
1360
1361 PMD_INIT_FUNC_TRACE();
1362
1363 dev_rss_conf = hw->rss_conf;
1364 port_rss_conf = &dev->data->dev_conf.rx_adv_conf.rss_conf;
1365
1366
1367 dev_rss_conf->hashFunc = VMXNET3_RSS_HASH_FUNC_TOEPLITZ;
1368
1369 dev_rss_conf->hashKeySize = VMXNET3_RSS_MAX_KEY_SIZE;
1370
1371 dev_rss_conf->indTableSize = (uint16_t)(hw->num_rx_queues * 4);
1372
1373 if (port_rss_conf->rss_key == NULL) {
1374
1375 port_rss_conf->rss_key = rss_intel_key;
1376 }
1377
1378
1379 memcpy(&dev_rss_conf->hashKey[0], port_rss_conf->rss_key,
1380 dev_rss_conf->hashKeySize);
1381
1382
1383 for (i = 0, j = 0; i < dev_rss_conf->indTableSize; i++, j++) {
1384 if (j == dev->data->nb_rx_queues)
1385 j = 0;
1386 dev_rss_conf->indTable[i] = j;
1387 }
1388
1389
1390 dev_rss_conf->hashType = 0;
1391 rss_hf = port_rss_conf->rss_hf & VMXNET3_RSS_OFFLOAD_ALL;
1392 if (rss_hf & ETH_RSS_IPV4)
1393 dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_IPV4;
1394 if (rss_hf & ETH_RSS_NONFRAG_IPV4_TCP)
1395 dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_TCP_IPV4;
1396 if (rss_hf & ETH_RSS_IPV6)
1397 dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_IPV6;
1398 if (rss_hf & ETH_RSS_NONFRAG_IPV6_TCP)
1399 dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_TCP_IPV6;
1400
1401 return VMXNET3_SUCCESS;
1402}
1403