1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2015 Intel Corporation
16 #include <rte_byteorder.h>
17 #include <rte_common.h>
18 #include <rte_cycles.h>
20 #include <rte_debug.h>
21 #include <rte_interrupts.h>
23 #include <rte_memory.h>
24 #include <rte_memzone.h>
25 #include <rte_launch.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>
34 #include <rte_ether.h>
35 #include <ethdev_driver.h>
36 #include <rte_prefetch.h>
41 #include <rte_string_fns.h>
42 #include <rte_errno.h>
45 #include "base/vmxnet3_defs.h"
46 #include "vmxnet3_ring.h"
48 #include "vmxnet3_logs.h"
49 #include "vmxnet3_ethdev.h"
51 #define VMXNET3_TX_OFFLOAD_MASK (RTE_MBUF_F_TX_VLAN | \
52 RTE_MBUF_F_TX_IPV6 | \
53 RTE_MBUF_F_TX_IPV4 | \
54 RTE_MBUF_F_TX_L4_MASK | \
55 RTE_MBUF_F_TX_TCP_SEG)
57 #define VMXNET3_TX_OFFLOAD_NOTSUP_MASK \
58 (RTE_MBUF_F_TX_OFFLOAD_MASK ^ VMXNET3_TX_OFFLOAD_MASK)
60 static const uint32_t rxprod_reg[2] = {VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2};
62 static int vmxnet3_post_rx_bufs(vmxnet3_rx_queue_t*, uint8_t);
63 static void vmxnet3_tq_tx_complete(vmxnet3_tx_queue_t *);
64 #ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER_NOT_USED
65 static void vmxnet3_rxq_dump(struct vmxnet3_rx_queue *);
66 static void vmxnet3_txq_dump(struct vmxnet3_tx_queue *);
69 #ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER_NOT_USED
71 vmxnet3_rxq_dump(struct vmxnet3_rx_queue *rxq)
79 "RXQ: cmd0 base : %p cmd1 base : %p comp ring base : %p.",
80 rxq->cmd_ring[0].base, rxq->cmd_ring[1].base, rxq->comp_ring.base);
82 "RXQ: cmd0 basePA : 0x%lx cmd1 basePA : 0x%lx comp ring basePA : 0x%lx.",
83 (unsigned long)rxq->cmd_ring[0].basePA,
84 (unsigned long)rxq->cmd_ring[1].basePA,
85 (unsigned long)rxq->comp_ring.basePA);
87 avail = vmxnet3_cmd_ring_desc_avail(&rxq->cmd_ring[0]);
89 "RXQ:cmd0: size=%u; free=%u; next2proc=%u; queued=%u",
90 (uint32_t)rxq->cmd_ring[0].size, avail,
91 rxq->comp_ring.next2proc,
92 rxq->cmd_ring[0].size - avail);
94 avail = vmxnet3_cmd_ring_desc_avail(&rxq->cmd_ring[1]);
95 PMD_RX_LOG(DEBUG, "RXQ:cmd1 size=%u; free=%u; next2proc=%u; queued=%u",
96 (uint32_t)rxq->cmd_ring[1].size, avail, rxq->comp_ring.next2proc,
97 rxq->cmd_ring[1].size - avail);
102 vmxnet3_txq_dump(struct vmxnet3_tx_queue *txq)
109 PMD_TX_LOG(DEBUG, "TXQ: cmd base : %p comp ring base : %p data ring base : %p.",
110 txq->cmd_ring.base, txq->comp_ring.base, txq->data_ring.base);
111 PMD_TX_LOG(DEBUG, "TXQ: cmd basePA : 0x%lx comp ring basePA : 0x%lx data ring basePA : 0x%lx.",
112 (unsigned long)txq->cmd_ring.basePA,
113 (unsigned long)txq->comp_ring.basePA,
114 (unsigned long)txq->data_ring.basePA);
116 avail = vmxnet3_cmd_ring_desc_avail(&txq->cmd_ring);
117 PMD_TX_LOG(DEBUG, "TXQ: size=%u; free=%u; next2proc=%u; queued=%u",
118 (uint32_t)txq->cmd_ring.size, avail,
119 txq->comp_ring.next2proc, txq->cmd_ring.size - avail);
124 vmxnet3_tx_cmd_ring_release_mbufs(vmxnet3_cmd_ring_t *ring)
126 while (ring->next2comp != ring->next2fill) {
127 /* No need to worry about desc ownership, device is quiesced by now. */
128 vmxnet3_buf_info_t *buf_info = ring->buf_info + ring->next2comp;
131 rte_pktmbuf_free(buf_info->m);
136 vmxnet3_cmd_ring_adv_next2comp(ring);
141 vmxnet3_rx_cmd_ring_release_mbufs(vmxnet3_cmd_ring_t *ring)
145 for (i = 0; i < ring->size; i++) {
146 /* No need to worry about desc ownership, device is quiesced by now. */
147 vmxnet3_buf_info_t *buf_info = &ring->buf_info[i];
150 rte_pktmbuf_free_seg(buf_info->m);
155 vmxnet3_cmd_ring_adv_next2comp(ring);
160 vmxnet3_cmd_ring_release(vmxnet3_cmd_ring_t *ring)
162 rte_free(ring->buf_info);
163 ring->buf_info = NULL;
167 vmxnet3_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
169 vmxnet3_tx_queue_t *tq = dev->data->tx_queues[qid];
173 vmxnet3_tx_cmd_ring_release_mbufs(&tq->cmd_ring);
174 /* Release the cmd_ring */
175 vmxnet3_cmd_ring_release(&tq->cmd_ring);
176 /* Release the memzone */
177 rte_memzone_free(tq->mz);
178 /* Release the queue */
184 vmxnet3_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
187 vmxnet3_rx_queue_t *rq = dev->data->rx_queues[qid];
191 for (i = 0; i < VMXNET3_RX_CMDRING_SIZE; i++)
192 vmxnet3_rx_cmd_ring_release_mbufs(&rq->cmd_ring[i]);
194 /* Release both the cmd_rings */
195 for (i = 0; i < VMXNET3_RX_CMDRING_SIZE; i++)
196 vmxnet3_cmd_ring_release(&rq->cmd_ring[i]);
198 /* Release the memzone */
199 rte_memzone_free(rq->mz);
201 /* Release the queue */
207 vmxnet3_dev_tx_queue_reset(void *txq)
209 vmxnet3_tx_queue_t *tq = txq;
210 struct vmxnet3_cmd_ring *ring = &tq->cmd_ring;
211 struct vmxnet3_comp_ring *comp_ring = &tq->comp_ring;
212 struct vmxnet3_data_ring *data_ring = &tq->data_ring;
216 /* Release the cmd_ring mbufs */
217 vmxnet3_tx_cmd_ring_release_mbufs(&tq->cmd_ring);
220 /* Tx vmxnet rings structure initialization*/
223 ring->gen = VMXNET3_INIT_GEN;
224 comp_ring->next2proc = 0;
225 comp_ring->gen = VMXNET3_INIT_GEN;
227 size = sizeof(struct Vmxnet3_TxDesc) * ring->size;
228 size += sizeof(struct Vmxnet3_TxCompDesc) * comp_ring->size;
229 size += tq->txdata_desc_size * data_ring->size;
231 memset(ring->base, 0, size);
235 vmxnet3_dev_rx_queue_reset(void *rxq)
238 vmxnet3_rx_queue_t *rq = rxq;
239 struct vmxnet3_hw *hw = rq->hw;
240 struct vmxnet3_cmd_ring *ring0, *ring1;
241 struct vmxnet3_comp_ring *comp_ring;
242 struct vmxnet3_rx_data_ring *data_ring = &rq->data_ring;
245 /* Release both the cmd_rings mbufs */
246 for (i = 0; i < VMXNET3_RX_CMDRING_SIZE; i++)
247 vmxnet3_rx_cmd_ring_release_mbufs(&rq->cmd_ring[i]);
249 ring0 = &rq->cmd_ring[0];
250 ring1 = &rq->cmd_ring[1];
251 comp_ring = &rq->comp_ring;
253 /* Rx vmxnet rings structure initialization */
254 ring0->next2fill = 0;
255 ring1->next2fill = 0;
256 ring0->next2comp = 0;
257 ring1->next2comp = 0;
258 ring0->gen = VMXNET3_INIT_GEN;
259 ring1->gen = VMXNET3_INIT_GEN;
260 comp_ring->next2proc = 0;
261 comp_ring->gen = VMXNET3_INIT_GEN;
263 size = sizeof(struct Vmxnet3_RxDesc) * (ring0->size + ring1->size);
264 size += sizeof(struct Vmxnet3_RxCompDesc) * comp_ring->size;
265 if (VMXNET3_VERSION_GE_3(hw) && rq->data_desc_size)
266 size += rq->data_desc_size * data_ring->size;
268 memset(ring0->base, 0, size);
272 vmxnet3_dev_clear_queues(struct rte_eth_dev *dev)
276 PMD_INIT_FUNC_TRACE();
278 for (i = 0; i < dev->data->nb_tx_queues; i++) {
279 struct vmxnet3_tx_queue *txq = dev->data->tx_queues[i];
283 vmxnet3_dev_tx_queue_reset(txq);
287 for (i = 0; i < dev->data->nb_rx_queues; i++) {
288 struct vmxnet3_rx_queue *rxq = dev->data->rx_queues[i];
292 vmxnet3_dev_rx_queue_reset(rxq);
298 vmxnet3_unmap_pkt(uint16_t eop_idx, vmxnet3_tx_queue_t *txq)
301 struct rte_mbuf *mbuf;
303 /* Release cmd_ring descriptor and free mbuf */
304 RTE_ASSERT(txq->cmd_ring.base[eop_idx].txd.eop == 1);
306 mbuf = txq->cmd_ring.buf_info[eop_idx].m;
308 rte_panic("EOP desc does not point to a valid mbuf");
309 rte_pktmbuf_free(mbuf);
311 txq->cmd_ring.buf_info[eop_idx].m = NULL;
313 while (txq->cmd_ring.next2comp != eop_idx) {
314 /* no out-of-order completion */
315 RTE_ASSERT(txq->cmd_ring.base[txq->cmd_ring.next2comp].txd.cq == 0);
316 vmxnet3_cmd_ring_adv_next2comp(&txq->cmd_ring);
320 /* Mark the txd for which tcd was generated as completed */
321 vmxnet3_cmd_ring_adv_next2comp(&txq->cmd_ring);
323 return completed + 1;
327 vmxnet3_tq_tx_complete(vmxnet3_tx_queue_t *txq)
330 vmxnet3_comp_ring_t *comp_ring = &txq->comp_ring;
331 struct Vmxnet3_TxCompDesc *tcd = (struct Vmxnet3_TxCompDesc *)
332 (comp_ring->base + comp_ring->next2proc);
334 while (tcd->gen == comp_ring->gen) {
335 completed += vmxnet3_unmap_pkt(tcd->txdIdx, txq);
337 vmxnet3_comp_ring_adv_next2proc(comp_ring);
338 tcd = (struct Vmxnet3_TxCompDesc *)(comp_ring->base +
339 comp_ring->next2proc);
342 PMD_TX_LOG(DEBUG, "Processed %d tx comps & command descs.", completed);
344 /* To avoid compiler warnings when not in DEBUG mode. */
345 RTE_SET_USED(completed);
349 vmxnet3_prep_pkts(__rte_unused void *tx_queue, struct rte_mbuf **tx_pkts,
357 for (i = 0; i != nb_pkts; i++) {
359 ol_flags = m->ol_flags;
361 /* Non-TSO packet cannot occupy more than
362 * VMXNET3_MAX_TXD_PER_PKT TX descriptors.
364 if ((ol_flags & RTE_MBUF_F_TX_TCP_SEG) == 0 &&
365 m->nb_segs > VMXNET3_MAX_TXD_PER_PKT) {
370 /* check that only supported TX offloads are requested. */
371 if ((ol_flags & VMXNET3_TX_OFFLOAD_NOTSUP_MASK) != 0 ||
372 (ol_flags & RTE_MBUF_F_TX_L4_MASK) ==
373 RTE_MBUF_F_TX_SCTP_CKSUM) {
378 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
379 ret = rte_validate_tx_offload(m);
385 ret = rte_net_intel_cksum_prepare(m);
396 vmxnet3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
400 vmxnet3_tx_queue_t *txq = tx_queue;
401 struct vmxnet3_hw *hw = txq->hw;
402 Vmxnet3_TxQueueCtrl *txq_ctrl = &txq->shared->ctrl;
403 uint32_t deferred = rte_le_to_cpu_32(txq_ctrl->txNumDeferred);
405 if (unlikely(txq->stopped)) {
406 PMD_TX_LOG(DEBUG, "Tx queue is stopped.");
410 /* Free up the comp_descriptors aggressively */
411 vmxnet3_tq_tx_complete(txq);
414 while (nb_tx < nb_pkts) {
415 Vmxnet3_GenericDesc *gdesc;
416 vmxnet3_buf_info_t *tbi;
417 uint32_t first2fill, avail, dw2;
418 struct rte_mbuf *txm = tx_pkts[nb_tx];
419 struct rte_mbuf *m_seg = txm;
421 bool tso = (txm->ol_flags & RTE_MBUF_F_TX_TCP_SEG) != 0;
422 /* # of descriptors needed for a packet. */
423 unsigned count = txm->nb_segs;
425 avail = vmxnet3_cmd_ring_desc_avail(&txq->cmd_ring);
427 /* Is command ring full? */
428 if (unlikely(avail == 0)) {
429 PMD_TX_LOG(DEBUG, "No free ring descriptors");
430 txq->stats.tx_ring_full++;
431 txq->stats.drop_total += (nb_pkts - nb_tx);
435 /* Command ring is not full but cannot handle the
436 * multi-segmented packet. Let's try the next packet
439 PMD_TX_LOG(DEBUG, "Running out of ring descriptors "
440 "(avail %d needed %d)", avail, count);
441 txq->stats.drop_total++;
443 txq->stats.drop_tso++;
444 rte_pktmbuf_free(txm);
449 /* Drop non-TSO packet that is excessively fragmented */
450 if (unlikely(!tso && count > VMXNET3_MAX_TXD_PER_PKT)) {
451 PMD_TX_LOG(ERR, "Non-TSO packet cannot occupy more than %d tx "
452 "descriptors. Packet dropped.", VMXNET3_MAX_TXD_PER_PKT);
453 txq->stats.drop_too_many_segs++;
454 txq->stats.drop_total++;
455 rte_pktmbuf_free(txm);
460 if (txm->nb_segs == 1 &&
461 rte_pktmbuf_pkt_len(txm) <= txq->txdata_desc_size) {
462 struct Vmxnet3_TxDataDesc *tdd;
464 /* Skip empty packets */
465 if (unlikely(rte_pktmbuf_pkt_len(txm) == 0)) {
466 txq->stats.drop_total++;
467 rte_pktmbuf_free(txm);
472 tdd = (struct Vmxnet3_TxDataDesc *)
473 ((uint8 *)txq->data_ring.base +
474 txq->cmd_ring.next2fill *
475 txq->txdata_desc_size);
476 copy_size = rte_pktmbuf_pkt_len(txm);
477 rte_memcpy(tdd->data, rte_pktmbuf_mtod(txm, char *), copy_size);
480 /* use the previous gen bit for the SOP desc */
481 dw2 = (txq->cmd_ring.gen ^ 0x1) << VMXNET3_TXD_GEN_SHIFT;
482 first2fill = txq->cmd_ring.next2fill;
484 /* Remember the transmit buffer for cleanup */
485 tbi = txq->cmd_ring.buf_info + txq->cmd_ring.next2fill;
487 /* NB: the following assumes that VMXNET3 maximum
488 * transmit buffer size (16K) is greater than
489 * maximum size of mbuf segment size.
491 gdesc = txq->cmd_ring.base + txq->cmd_ring.next2fill;
493 /* Skip empty segments */
494 if (unlikely(m_seg->data_len == 0))
499 (uint64)txq->cmd_ring.next2fill *
500 txq->txdata_desc_size;
502 rte_cpu_to_le_64(txq->data_ring.basePA +
505 gdesc->txd.addr = rte_mbuf_data_iova(m_seg);
508 gdesc->dword[2] = dw2 | m_seg->data_len;
511 /* move to the next2fill descriptor */
512 vmxnet3_cmd_ring_adv_next2fill(&txq->cmd_ring);
514 /* use the right gen for non-SOP desc */
515 dw2 = txq->cmd_ring.gen << VMXNET3_TXD_GEN_SHIFT;
516 } while ((m_seg = m_seg->next) != NULL);
518 /* set the last buf_info for the pkt */
520 /* Update the EOP descriptor */
521 gdesc->dword[3] |= VMXNET3_TXD_EOP | VMXNET3_TXD_CQ;
523 /* Add VLAN tag if present */
524 gdesc = txq->cmd_ring.base + first2fill;
525 if (txm->ol_flags & RTE_MBUF_F_TX_VLAN) {
527 gdesc->txd.tci = txm->vlan_tci;
531 uint16_t mss = txm->tso_segsz;
535 gdesc->txd.hlen = txm->l2_len + txm->l3_len + txm->l4_len;
536 gdesc->txd.om = VMXNET3_OM_TSO;
537 gdesc->txd.msscof = mss;
539 deferred += (rte_pktmbuf_pkt_len(txm) - gdesc->txd.hlen + mss - 1) / mss;
540 } else if (txm->ol_flags & RTE_MBUF_F_TX_L4_MASK) {
541 gdesc->txd.om = VMXNET3_OM_CSUM;
542 gdesc->txd.hlen = txm->l2_len + txm->l3_len;
544 switch (txm->ol_flags & RTE_MBUF_F_TX_L4_MASK) {
545 case RTE_MBUF_F_TX_TCP_CKSUM:
546 gdesc->txd.msscof = gdesc->txd.hlen +
547 offsetof(struct rte_tcp_hdr, cksum);
549 case RTE_MBUF_F_TX_UDP_CKSUM:
550 gdesc->txd.msscof = gdesc->txd.hlen +
551 offsetof(struct rte_udp_hdr,
555 PMD_TX_LOG(WARNING, "requested cksum offload not supported %#llx",
556 txm->ol_flags & RTE_MBUF_F_TX_L4_MASK);
562 gdesc->txd.om = VMXNET3_OM_NONE;
563 gdesc->txd.msscof = 0;
567 /* flip the GEN bit on the SOP */
568 rte_compiler_barrier();
569 gdesc->dword[2] ^= VMXNET3_TXD_GEN;
571 txq_ctrl->txNumDeferred = rte_cpu_to_le_32(deferred);
575 PMD_TX_LOG(DEBUG, "vmxnet3 txThreshold: %u", rte_le_to_cpu_32(txq_ctrl->txThreshold));
577 if (deferred >= rte_le_to_cpu_32(txq_ctrl->txThreshold)) {
578 txq_ctrl->txNumDeferred = 0;
579 /* Notify vSwitch that packets are available. */
580 VMXNET3_WRITE_BAR0_REG(hw, (VMXNET3_REG_TXPROD + txq->queue_id * VMXNET3_REG_ALIGN),
581 txq->cmd_ring.next2fill);
588 vmxnet3_renew_desc(vmxnet3_rx_queue_t *rxq, uint8_t ring_id,
589 struct rte_mbuf *mbuf)
592 struct vmxnet3_cmd_ring *ring = &rxq->cmd_ring[ring_id];
593 struct Vmxnet3_RxDesc *rxd =
594 (struct Vmxnet3_RxDesc *)(ring->base + ring->next2fill);
595 vmxnet3_buf_info_t *buf_info = &ring->buf_info[ring->next2fill];
598 /* Usually: One HEAD type buf per packet
599 * val = (ring->next2fill % rxq->hw->bufs_per_pkt) ?
600 * VMXNET3_RXD_BTYPE_BODY : VMXNET3_RXD_BTYPE_HEAD;
603 /* We use single packet buffer so all heads here */
604 val = VMXNET3_RXD_BTYPE_HEAD;
606 /* All BODY type buffers for 2nd ring */
607 val = VMXNET3_RXD_BTYPE_BODY;
611 * Load mbuf pointer into buf_info[ring_size]
612 * buf_info structure is equivalent to cookie for virtio-virtqueue
615 buf_info->len = (uint16_t)(mbuf->buf_len - RTE_PKTMBUF_HEADROOM);
616 buf_info->bufPA = rte_mbuf_data_iova_default(mbuf);
618 /* Load Rx Descriptor with the buffer's GPA */
619 rxd->addr = buf_info->bufPA;
621 /* After this point rxd->addr MUST not be NULL */
623 rxd->len = buf_info->len;
624 /* Flip gen bit at the end to change ownership */
625 rxd->gen = ring->gen;
627 vmxnet3_cmd_ring_adv_next2fill(ring);
630 * Allocates mbufs and clusters. Post rx descriptors with buffer details
631 * so that device can receive packets in those buffers.
633 * Among the two rings, 1st ring contains buffers of type 0 and type 1.
634 * bufs_per_pkt is set such that for non-LRO cases all the buffers required
635 * by a frame will fit in 1st ring (1st buf of type0 and rest of type1).
636 * 2nd ring contains buffers of type 1 alone. Second ring mostly be used
640 vmxnet3_post_rx_bufs(vmxnet3_rx_queue_t *rxq, uint8_t ring_id)
644 struct vmxnet3_cmd_ring *ring = &rxq->cmd_ring[ring_id];
646 while (vmxnet3_cmd_ring_desc_avail(ring) > 0) {
647 struct rte_mbuf *mbuf;
649 /* Allocate blank mbuf for the current Rx Descriptor */
650 mbuf = rte_mbuf_raw_alloc(rxq->mp);
651 if (unlikely(mbuf == NULL)) {
652 PMD_RX_LOG(ERR, "Error allocating mbuf");
653 rxq->stats.rx_buf_alloc_failure++;
658 vmxnet3_renew_desc(rxq, ring_id, mbuf);
662 /* Return error only if no buffers are posted at present */
663 if (vmxnet3_cmd_ring_desc_avail(ring) >= (ring->size - 1))
669 /* MSS not provided by vmxnet3, guess one with available information */
671 vmxnet3_guess_mss(struct vmxnet3_hw *hw, const Vmxnet3_RxCompDesc *rcd,
672 struct rte_mbuf *rxm)
675 struct rte_ipv4_hdr *ipv4_hdr;
676 struct rte_ipv6_hdr *ipv6_hdr;
677 struct rte_tcp_hdr *tcp_hdr;
681 RTE_ASSERT(rcd->tcp);
683 ptr = rte_pktmbuf_mtod(rxm, char *);
684 slen = rte_pktmbuf_data_len(rxm);
685 hlen = sizeof(struct rte_ether_hdr);
688 if (unlikely(slen < hlen + sizeof(struct rte_ipv4_hdr)))
689 return hw->mtu - sizeof(struct rte_ipv4_hdr)
690 - sizeof(struct rte_tcp_hdr);
692 ipv4_hdr = (struct rte_ipv4_hdr *)(ptr + hlen);
693 hlen += rte_ipv4_hdr_len(ipv4_hdr);
694 } else if (rcd->v6) {
695 if (unlikely(slen < hlen + sizeof(struct rte_ipv6_hdr)))
696 return hw->mtu - sizeof(struct rte_ipv6_hdr) -
697 sizeof(struct rte_tcp_hdr);
699 ipv6_hdr = (struct rte_ipv6_hdr *)(ptr + hlen);
700 hlen += sizeof(struct rte_ipv6_hdr);
701 if (unlikely(ipv6_hdr->proto != IPPROTO_TCP)) {
704 rte_net_skip_ip6_ext(ipv6_hdr->proto, rxm,
709 if (unlikely(slen < hlen + sizeof(struct rte_tcp_hdr)))
710 return hw->mtu - hlen - sizeof(struct rte_tcp_hdr) +
711 sizeof(struct rte_ether_hdr);
713 tcp_hdr = (struct rte_tcp_hdr *)(ptr + hlen);
714 hlen += (tcp_hdr->data_off & 0xf0) >> 2;
716 segs = *vmxnet3_segs_dynfield(rxm);
718 return (rte_pktmbuf_pkt_len(rxm) - hlen + segs - 1) / segs;
720 return hw->mtu - hlen + sizeof(struct rte_ether_hdr);
723 /* Receive side checksum and other offloads */
725 vmxnet3_rx_offload(struct vmxnet3_hw *hw, const Vmxnet3_RxCompDesc *rcd,
726 struct rte_mbuf *rxm, const uint8_t sop)
728 uint64_t ol_flags = rxm->ol_flags;
729 uint32_t packet_type = rxm->packet_type;
731 /* Offloads set in sop */
733 /* Set packet type */
734 packet_type |= RTE_PTYPE_L2_ETHER;
736 /* Check large packet receive */
737 if (VMXNET3_VERSION_GE_2(hw) &&
738 rcd->type == VMXNET3_CDTYPE_RXCOMP_LRO) {
739 const Vmxnet3_RxCompDescExt *rcde =
740 (const Vmxnet3_RxCompDescExt *)rcd;
742 rxm->tso_segsz = rcde->mss;
743 *vmxnet3_segs_dynfield(rxm) = rcde->segCnt;
744 ol_flags |= RTE_MBUF_F_RX_LRO;
746 } else { /* Offloads set in eop */
748 if (rcd->rssType != VMXNET3_RCD_RSS_TYPE_NONE) {
749 ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
750 rxm->hash.rss = rcd->rssHash;
753 /* Check for hardware stripped VLAN tag */
755 ol_flags |= (RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED);
756 rxm->vlan_tci = rte_le_to_cpu_16((uint16_t)rcd->tci);
759 /* Check packet type, checksum errors, etc. */
761 ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN;
764 packet_type |= RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
767 ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
769 ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
772 ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
774 packet_type |= RTE_PTYPE_L4_TCP;
776 packet_type |= RTE_PTYPE_L4_UDP;
779 packet_type |= RTE_PTYPE_L4_TCP;
780 ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
781 } else if (rcd->udp) {
782 packet_type |= RTE_PTYPE_L4_UDP;
783 ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
786 } else if (rcd->v6) {
787 packet_type |= RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
790 ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
792 packet_type |= RTE_PTYPE_L4_TCP;
794 packet_type |= RTE_PTYPE_L4_UDP;
797 packet_type |= RTE_PTYPE_L4_TCP;
798 ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
799 } else if (rcd->udp) {
800 packet_type |= RTE_PTYPE_L4_UDP;
801 ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
805 packet_type |= RTE_PTYPE_UNKNOWN;
808 /* Old variants of vmxnet3 do not provide MSS */
809 if ((ol_flags & RTE_MBUF_F_RX_LRO) && rxm->tso_segsz == 0)
810 rxm->tso_segsz = vmxnet3_guess_mss(hw,
815 rxm->ol_flags = ol_flags;
816 rxm->packet_type = packet_type;
820 * Process the Rx Completion Ring of given vmxnet3_rx_queue
821 * for nb_pkts burst and return the number of packets received
824 vmxnet3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
827 uint32_t nb_rxd, idx;
829 vmxnet3_rx_queue_t *rxq;
830 Vmxnet3_RxCompDesc *rcd;
831 vmxnet3_buf_info_t *rbi;
833 struct rte_mbuf *rxm = NULL;
834 struct vmxnet3_hw *hw;
844 rcd = &rxq->comp_ring.base[rxq->comp_ring.next2proc].rcd;
846 if (unlikely(rxq->stopped)) {
847 PMD_RX_LOG(DEBUG, "Rx queue is stopped.");
851 while (rcd->gen == rxq->comp_ring.gen) {
852 struct rte_mbuf *newm;
854 if (nb_rx >= nb_pkts)
857 newm = rte_mbuf_raw_alloc(rxq->mp);
858 if (unlikely(newm == NULL)) {
859 PMD_RX_LOG(ERR, "Error allocating mbuf");
860 rxq->stats.rx_buf_alloc_failure++;
865 ring_idx = vmxnet3_get_ring_idx(hw, rcd->rqID);
866 rxd = (Vmxnet3_RxDesc *)rxq->cmd_ring[ring_idx].base + idx;
867 RTE_SET_USED(rxd); /* used only for assert when enabled */
868 rbi = rxq->cmd_ring[ring_idx].buf_info + idx;
870 PMD_RX_LOG(DEBUG, "rxd idx: %d ring idx: %d.", idx, ring_idx);
872 RTE_ASSERT(rcd->len <= rxd->len);
875 /* Get the packet buffer pointer from buf_info */
878 /* Clear descriptor associated buf_info to be reused */
882 /* Update the index that we received a packet */
883 rxq->cmd_ring[ring_idx].next2comp = idx;
885 /* For RCD with EOP set, check if there is frame error */
886 if (unlikely(rcd->eop && rcd->err)) {
887 rxq->stats.drop_total++;
888 rxq->stats.drop_err++;
891 rxq->stats.drop_fcs++;
892 PMD_RX_LOG(ERR, "Recv packet dropped due to frame err.");
894 PMD_RX_LOG(ERR, "Error in received packet rcd#:%d rxd:%d",
895 (int)(rcd - (struct Vmxnet3_RxCompDesc *)
896 rxq->comp_ring.base), rcd->rxdIdx);
897 rte_pktmbuf_free_seg(rxm);
898 if (rxq->start_seg) {
899 struct rte_mbuf *start = rxq->start_seg;
901 rxq->start_seg = NULL;
902 rte_pktmbuf_free(start);
907 /* Initialize newly received packet buffer */
908 rxm->port = rxq->port_id;
911 rxm->pkt_len = (uint16_t)rcd->len;
912 rxm->data_len = (uint16_t)rcd->len;
913 rxm->data_off = RTE_PKTMBUF_HEADROOM;
916 rxm->packet_type = 0;
919 * If this is the first buffer of the received packet,
920 * set the pointer to the first mbuf of the packet
921 * Otherwise, update the total length and the number of segments
922 * of the current scattered packet, and update the pointer to
923 * the last mbuf of the current packet.
926 RTE_ASSERT(rxd->btype == VMXNET3_RXD_BTYPE_HEAD);
928 if (unlikely(rcd->len == 0)) {
929 RTE_ASSERT(rcd->eop);
932 "Rx buf was skipped. rxring[%d][%d])",
934 rte_pktmbuf_free_seg(rxm);
938 if (vmxnet3_rx_data_ring(hw, rcd->rqID)) {
939 uint8_t *rdd = rxq->data_ring.base +
940 idx * rxq->data_desc_size;
942 RTE_ASSERT(VMXNET3_VERSION_GE_3(hw));
943 rte_memcpy(rte_pktmbuf_mtod(rxm, char *),
947 rxq->start_seg = rxm;
949 vmxnet3_rx_offload(hw, rcd, rxm, 1);
951 struct rte_mbuf *start = rxq->start_seg;
953 RTE_ASSERT(rxd->btype == VMXNET3_RXD_BTYPE_BODY);
955 if (likely(start && rxm->data_len > 0)) {
956 start->pkt_len += rxm->data_len;
959 rxq->last_seg->next = rxm;
962 PMD_RX_LOG(ERR, "Error received empty or out of order frame.");
963 rxq->stats.drop_total++;
964 rxq->stats.drop_err++;
966 rte_pktmbuf_free_seg(rxm);
971 struct rte_mbuf *start = rxq->start_seg;
973 vmxnet3_rx_offload(hw, rcd, start, 0);
974 rx_pkts[nb_rx++] = start;
975 rxq->start_seg = NULL;
979 rxq->cmd_ring[ring_idx].next2comp = idx;
980 VMXNET3_INC_RING_IDX_ONLY(rxq->cmd_ring[ring_idx].next2comp,
981 rxq->cmd_ring[ring_idx].size);
983 /* It's time to renew descriptors */
984 vmxnet3_renew_desc(rxq, ring_idx, newm);
985 if (unlikely(rxq->shared->ctrl.updateRxProd)) {
986 VMXNET3_WRITE_BAR0_REG(hw, rxprod_reg[ring_idx] + (rxq->queue_id * VMXNET3_REG_ALIGN),
987 rxq->cmd_ring[ring_idx].next2fill);
990 /* Advance to the next descriptor in comp_ring */
991 vmxnet3_comp_ring_adv_next2proc(&rxq->comp_ring);
993 rcd = &rxq->comp_ring.base[rxq->comp_ring.next2proc].rcd;
995 if (nb_rxd > rxq->cmd_ring[0].size) {
996 PMD_RX_LOG(ERR, "Used up quota of receiving packets,"
997 " relinquish control.");
1002 if (unlikely(nb_rxd == 0)) {
1004 for (ring_idx = 0; ring_idx < VMXNET3_RX_CMDRING_SIZE; ring_idx++) {
1005 avail = vmxnet3_cmd_ring_desc_avail(&rxq->cmd_ring[ring_idx]);
1006 if (unlikely(avail > 0)) {
1007 /* try to alloc new buf and renew descriptors */
1008 vmxnet3_post_rx_bufs(rxq, ring_idx);
1011 if (unlikely(rxq->shared->ctrl.updateRxProd)) {
1012 for (ring_idx = 0; ring_idx < VMXNET3_RX_CMDRING_SIZE; ring_idx++) {
1013 VMXNET3_WRITE_BAR0_REG(hw, rxprod_reg[ring_idx] + (rxq->queue_id * VMXNET3_REG_ALIGN),
1014 rxq->cmd_ring[ring_idx].next2fill);
1023 vmxnet3_dev_rx_queue_count(void *rx_queue)
1025 const vmxnet3_rx_queue_t *rxq;
1026 const Vmxnet3_RxCompDesc *rcd;
1027 uint32_t idx, nb_rxd = 0;
1031 if (unlikely(rxq->stopped)) {
1032 PMD_RX_LOG(DEBUG, "Rx queue is stopped.");
1036 gen = rxq->comp_ring.gen;
1037 idx = rxq->comp_ring.next2proc;
1038 rcd = &rxq->comp_ring.base[idx].rcd;
1039 while (rcd->gen == gen) {
1042 if (++idx == rxq->comp_ring.size) {
1046 rcd = &rxq->comp_ring.base[idx].rcd;
1053 vmxnet3_dev_tx_queue_setup(struct rte_eth_dev *dev,
1056 unsigned int socket_id,
1057 const struct rte_eth_txconf *tx_conf __rte_unused)
1059 struct vmxnet3_hw *hw = dev->data->dev_private;
1060 const struct rte_memzone *mz;
1061 struct vmxnet3_tx_queue *txq;
1062 struct vmxnet3_cmd_ring *ring;
1063 struct vmxnet3_comp_ring *comp_ring;
1064 struct vmxnet3_data_ring *data_ring;
1067 PMD_INIT_FUNC_TRACE();
1069 txq = rte_zmalloc("ethdev_tx_queue", sizeof(struct vmxnet3_tx_queue),
1070 RTE_CACHE_LINE_SIZE);
1072 PMD_INIT_LOG(ERR, "Can not allocate tx queue structure");
1076 txq->queue_id = queue_idx;
1077 txq->port_id = dev->data->port_id;
1078 txq->shared = NULL; /* set in vmxnet3_setup_driver_shared() */
1080 txq->qid = queue_idx;
1081 txq->stopped = TRUE;
1082 txq->txdata_desc_size = hw->txdata_desc_size;
1084 ring = &txq->cmd_ring;
1085 comp_ring = &txq->comp_ring;
1086 data_ring = &txq->data_ring;
1088 /* Tx vmxnet ring length should be between 512-4096 */
1089 if (nb_desc < VMXNET3_DEF_TX_RING_SIZE) {
1090 PMD_INIT_LOG(ERR, "VMXNET3 Tx Ring Size Min: %u",
1091 VMXNET3_DEF_TX_RING_SIZE);
1093 } else if (nb_desc > VMXNET3_TX_RING_MAX_SIZE) {
1094 PMD_INIT_LOG(ERR, "VMXNET3 Tx Ring Size Max: %u",
1095 VMXNET3_TX_RING_MAX_SIZE);
1098 ring->size = nb_desc;
1099 ring->size &= ~VMXNET3_RING_SIZE_MASK;
1101 comp_ring->size = data_ring->size = ring->size;
1103 /* Tx vmxnet rings structure initialization*/
1104 ring->next2fill = 0;
1105 ring->next2comp = 0;
1106 ring->gen = VMXNET3_INIT_GEN;
1107 comp_ring->next2proc = 0;
1108 comp_ring->gen = VMXNET3_INIT_GEN;
1110 size = sizeof(struct Vmxnet3_TxDesc) * ring->size;
1111 size += sizeof(struct Vmxnet3_TxCompDesc) * comp_ring->size;
1112 size += txq->txdata_desc_size * data_ring->size;
1114 mz = rte_eth_dma_zone_reserve(dev, "txdesc", queue_idx, size,
1115 VMXNET3_RING_BA_ALIGN, socket_id);
1117 PMD_INIT_LOG(ERR, "ERROR: Creating queue descriptors zone");
1121 memset(mz->addr, 0, mz->len);
1123 /* cmd_ring initialization */
1124 ring->base = mz->addr;
1125 ring->basePA = mz->iova;
1127 /* comp_ring initialization */
1128 comp_ring->base = ring->base + ring->size;
1129 comp_ring->basePA = ring->basePA +
1130 (sizeof(struct Vmxnet3_TxDesc) * ring->size);
1132 /* data_ring initialization */
1133 data_ring->base = (Vmxnet3_TxDataDesc *)(comp_ring->base + comp_ring->size);
1134 data_ring->basePA = comp_ring->basePA +
1135 (sizeof(struct Vmxnet3_TxCompDesc) * comp_ring->size);
1137 /* cmd_ring0 buf_info allocation */
1138 ring->buf_info = rte_zmalloc("tx_ring_buf_info",
1139 ring->size * sizeof(vmxnet3_buf_info_t), RTE_CACHE_LINE_SIZE);
1140 if (ring->buf_info == NULL) {
1141 PMD_INIT_LOG(ERR, "ERROR: Creating tx_buf_info structure");
1145 /* Update the data portion with txq */
1146 dev->data->tx_queues[queue_idx] = txq;
1152 vmxnet3_dev_rx_queue_setup(struct rte_eth_dev *dev,
1155 unsigned int socket_id,
1156 __rte_unused const struct rte_eth_rxconf *rx_conf,
1157 struct rte_mempool *mp)
1159 const struct rte_memzone *mz;
1160 struct vmxnet3_rx_queue *rxq;
1161 struct vmxnet3_hw *hw = dev->data->dev_private;
1162 struct vmxnet3_cmd_ring *ring0, *ring1, *ring;
1163 struct vmxnet3_comp_ring *comp_ring;
1164 struct vmxnet3_rx_data_ring *data_ring;
1169 PMD_INIT_FUNC_TRACE();
1171 rxq = rte_zmalloc("ethdev_rx_queue", sizeof(struct vmxnet3_rx_queue),
1172 RTE_CACHE_LINE_SIZE);
1174 PMD_INIT_LOG(ERR, "Can not allocate rx queue structure");
1179 rxq->queue_id = queue_idx;
1180 rxq->port_id = dev->data->port_id;
1181 rxq->shared = NULL; /* set in vmxnet3_setup_driver_shared() */
1183 rxq->qid1 = queue_idx;
1184 rxq->qid2 = queue_idx + hw->num_rx_queues;
1185 rxq->data_ring_qid = queue_idx + 2 * hw->num_rx_queues;
1186 rxq->data_desc_size = hw->rxdata_desc_size;
1187 rxq->stopped = TRUE;
1189 ring0 = &rxq->cmd_ring[0];
1190 ring1 = &rxq->cmd_ring[1];
1191 comp_ring = &rxq->comp_ring;
1192 data_ring = &rxq->data_ring;
1194 /* Rx vmxnet rings length should be between 256-4096 */
1195 if (nb_desc < VMXNET3_DEF_RX_RING_SIZE) {
1196 PMD_INIT_LOG(ERR, "VMXNET3 Rx Ring Size Min: 256");
1198 } else if (nb_desc > VMXNET3_RX_RING_MAX_SIZE) {
1199 PMD_INIT_LOG(ERR, "VMXNET3 Rx Ring Size Max: 4096");
1202 ring0->size = nb_desc;
1203 ring0->size &= ~VMXNET3_RING_SIZE_MASK;
1204 ring1->size = ring0->size;
1207 comp_ring->size = ring0->size + ring1->size;
1208 data_ring->size = ring0->size;
1210 /* Rx vmxnet rings structure initialization */
1211 ring0->next2fill = 0;
1212 ring1->next2fill = 0;
1213 ring0->next2comp = 0;
1214 ring1->next2comp = 0;
1215 ring0->gen = VMXNET3_INIT_GEN;
1216 ring1->gen = VMXNET3_INIT_GEN;
1217 comp_ring->next2proc = 0;
1218 comp_ring->gen = VMXNET3_INIT_GEN;
1220 size = sizeof(struct Vmxnet3_RxDesc) * (ring0->size + ring1->size);
1221 size += sizeof(struct Vmxnet3_RxCompDesc) * comp_ring->size;
1222 if (VMXNET3_VERSION_GE_3(hw) && rxq->data_desc_size)
1223 size += rxq->data_desc_size * data_ring->size;
1225 mz = rte_eth_dma_zone_reserve(dev, "rxdesc", queue_idx, size,
1226 VMXNET3_RING_BA_ALIGN, socket_id);
1228 PMD_INIT_LOG(ERR, "ERROR: Creating queue descriptors zone");
1232 memset(mz->addr, 0, mz->len);
1234 /* cmd_ring0 initialization */
1235 ring0->base = mz->addr;
1236 ring0->basePA = mz->iova;
1238 /* cmd_ring1 initialization */
1239 ring1->base = ring0->base + ring0->size;
1240 ring1->basePA = ring0->basePA + sizeof(struct Vmxnet3_RxDesc) * ring0->size;
1242 /* comp_ring initialization */
1243 comp_ring->base = ring1->base + ring1->size;
1244 comp_ring->basePA = ring1->basePA + sizeof(struct Vmxnet3_RxDesc) *
1247 /* data_ring initialization */
1248 if (VMXNET3_VERSION_GE_3(hw) && rxq->data_desc_size) {
1250 (uint8_t *)(comp_ring->base + comp_ring->size);
1251 data_ring->basePA = comp_ring->basePA +
1252 sizeof(struct Vmxnet3_RxCompDesc) * comp_ring->size;
1255 /* cmd_ring0-cmd_ring1 buf_info allocation */
1256 for (i = 0; i < VMXNET3_RX_CMDRING_SIZE; i++) {
1258 ring = &rxq->cmd_ring[i];
1260 snprintf(mem_name, sizeof(mem_name), "rx_ring_%d_buf_info", i);
1262 ring->buf_info = rte_zmalloc(mem_name,
1263 ring->size * sizeof(vmxnet3_buf_info_t),
1264 RTE_CACHE_LINE_SIZE);
1265 if (ring->buf_info == NULL) {
1266 PMD_INIT_LOG(ERR, "ERROR: Creating rx_buf_info structure");
1271 /* Update the data portion with rxq */
1272 dev->data->rx_queues[queue_idx] = rxq;
1278 * Initializes Receive Unit
1279 * Load mbufs in rx queue in advance
1282 vmxnet3_dev_rxtx_init(struct rte_eth_dev *dev)
1284 struct vmxnet3_hw *hw = dev->data->dev_private;
1289 PMD_INIT_FUNC_TRACE();
1291 for (i = 0; i < hw->num_rx_queues; i++) {
1292 vmxnet3_rx_queue_t *rxq = dev->data->rx_queues[i];
1294 for (j = 0; j < VMXNET3_RX_CMDRING_SIZE; j++) {
1295 /* Passing 0 as alloc_num will allocate full ring */
1296 ret = vmxnet3_post_rx_bufs(rxq, j);
1299 "ERROR: Posting Rxq: %d buffers ring: %d",
1304 * Updating device with the index:next2fill to fill the
1305 * mbufs for coming packets.
1307 if (unlikely(rxq->shared->ctrl.updateRxProd)) {
1308 VMXNET3_WRITE_BAR0_REG(hw, rxprod_reg[j] + (rxq->queue_id * VMXNET3_REG_ALIGN),
1309 rxq->cmd_ring[j].next2fill);
1312 rxq->stopped = FALSE;
1313 rxq->start_seg = NULL;
1316 for (i = 0; i < dev->data->nb_tx_queues; i++) {
1317 struct vmxnet3_tx_queue *txq = dev->data->tx_queues[i];
1319 txq->stopped = FALSE;
1325 static uint8_t rss_intel_key[40] = {
1326 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2,
1327 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0,
1328 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
1329 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C,
1330 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA,
1334 * Additional RSS configurations based on vmxnet v4+ APIs
1337 vmxnet3_v4_rss_configure(struct rte_eth_dev *dev)
1339 struct vmxnet3_hw *hw = dev->data->dev_private;
1340 Vmxnet3_DriverShared *shared = hw->shared;
1341 Vmxnet3_CmdInfo *cmdInfo = &shared->cu.cmdInfo;
1342 struct rte_eth_rss_conf *port_rss_conf;
1346 PMD_INIT_FUNC_TRACE();
1348 cmdInfo->setRSSFields = 0;
1349 port_rss_conf = &dev->data->dev_conf.rx_adv_conf.rss_conf;
1351 if ((port_rss_conf->rss_hf & VMXNET3_MANDATORY_V4_RSS) !=
1352 VMXNET3_MANDATORY_V4_RSS) {
1353 PMD_INIT_LOG(WARNING, "RSS: IPv4/6 TCP is required for vmxnet3 v4 RSS,"
1354 "automatically setting it");
1355 port_rss_conf->rss_hf |= VMXNET3_MANDATORY_V4_RSS;
1358 rss_hf = port_rss_conf->rss_hf &
1359 (VMXNET3_V4_RSS_MASK | VMXNET3_RSS_OFFLOAD_ALL);
1361 if (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP)
1362 cmdInfo->setRSSFields |= VMXNET3_RSS_FIELDS_TCPIP4;
1363 if (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP)
1364 cmdInfo->setRSSFields |= VMXNET3_RSS_FIELDS_TCPIP6;
1365 if (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP)
1366 cmdInfo->setRSSFields |= VMXNET3_RSS_FIELDS_UDPIP4;
1367 if (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP)
1368 cmdInfo->setRSSFields |= VMXNET3_RSS_FIELDS_UDPIP6;
1370 VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD,
1371 VMXNET3_CMD_SET_RSS_FIELDS);
1372 ret = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_CMD);
1374 if (ret != VMXNET3_SUCCESS) {
1375 PMD_DRV_LOG(ERR, "Set RSS fields (v4) failed: %d", ret);
1382 * Configure RSS feature
1385 vmxnet3_rss_configure(struct rte_eth_dev *dev)
1387 struct vmxnet3_hw *hw = dev->data->dev_private;
1388 struct VMXNET3_RSSConf *dev_rss_conf;
1389 struct rte_eth_rss_conf *port_rss_conf;
1393 PMD_INIT_FUNC_TRACE();
1395 dev_rss_conf = hw->rss_conf;
1396 port_rss_conf = &dev->data->dev_conf.rx_adv_conf.rss_conf;
1398 /* loading hashFunc */
1399 dev_rss_conf->hashFunc = VMXNET3_RSS_HASH_FUNC_TOEPLITZ;
1400 /* loading hashKeySize */
1401 dev_rss_conf->hashKeySize = VMXNET3_RSS_MAX_KEY_SIZE;
1402 /* loading indTableSize: Must not exceed VMXNET3_RSS_MAX_IND_TABLE_SIZE (128)*/
1403 dev_rss_conf->indTableSize = (uint16_t)((MAX_RX_QUEUES(hw)) * 4);
1405 if (port_rss_conf->rss_key == NULL) {
1406 /* Default hash key */
1407 port_rss_conf->rss_key = rss_intel_key;
1410 /* loading hashKey */
1411 memcpy(&dev_rss_conf->hashKey[0], port_rss_conf->rss_key,
1412 dev_rss_conf->hashKeySize);
1414 /* loading indTable */
1415 for (i = 0, j = 0; i < dev_rss_conf->indTableSize; i++, j++) {
1416 if (j == dev->data->nb_rx_queues)
1418 dev_rss_conf->indTable[i] = j;
1421 /* loading hashType */
1422 dev_rss_conf->hashType = 0;
1423 rss_hf = port_rss_conf->rss_hf & VMXNET3_RSS_OFFLOAD_ALL;
1424 if (rss_hf & RTE_ETH_RSS_IPV4)
1425 dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_IPV4;
1426 if (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP)
1427 dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_TCP_IPV4;
1428 if (rss_hf & RTE_ETH_RSS_IPV6)
1429 dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_IPV6;
1430 if (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP)
1431 dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_TCP_IPV6;
1433 return VMXNET3_SUCCESS;