4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/queue.h>
45 #include <rte_byteorder.h>
46 #include <rte_common.h>
47 #include <rte_cycles.h>
49 #include <rte_debug.h>
50 #include <rte_interrupts.h>
52 #include <rte_memory.h>
53 #include <rte_memzone.h>
54 #include <rte_launch.h>
55 #include <rte_tailq.h>
57 #include <rte_per_lcore.h>
58 #include <rte_lcore.h>
59 #include <rte_atomic.h>
60 #include <rte_branch_prediction.h>
62 #include <rte_mempool.h>
63 #include <rte_malloc.h>
65 #include <rte_ether.h>
66 #include <rte_ethdev.h>
67 #include <rte_prefetch.h>
71 #include <rte_string_fns.h>
72 #include <rte_errno.h>
74 #include "vmxnet3/vmxnet3_defs.h"
75 #include "vmxnet3_ring.h"
77 #include "vmxnet3_logs.h"
78 #include "vmxnet3_ethdev.h"
81 #define RTE_MBUF_DATA_DMA_ADDR(mb) \
82 (uint64_t) ((mb)->buf_physaddr + (mb)->data_off)
84 #define RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mb) \
85 (uint64_t) ((mb)->buf_physaddr + RTE_PKTMBUF_HEADROOM)
87 static uint32_t rxprod_reg[2] = {VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2};
89 static inline int vmxnet3_post_rx_bufs(vmxnet3_rx_queue_t* , uint8_t);
90 static inline void vmxnet3_tq_tx_complete(vmxnet3_tx_queue_t *);
91 #ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER_NOT_USED
92 static void vmxnet3_rxq_dump(struct vmxnet3_rx_queue *);
93 static void vmxnet3_txq_dump(struct vmxnet3_tx_queue *);
96 static inline struct rte_mbuf *
97 rte_rxmbuf_alloc(struct rte_mempool *mp)
101 m = __rte_mbuf_raw_alloc(mp);
102 __rte_mbuf_sanity_check_raw(m, 0);
106 #ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER_NOT_USED
108 vmxnet3_rxq_dump(struct vmxnet3_rx_queue *rxq)
116 "RXQ: cmd0 base : 0x%p cmd1 base : 0x%p comp ring base : 0x%p.",
117 rxq->cmd_ring[0].base, rxq->cmd_ring[1].base, rxq->comp_ring.base);
119 "RXQ: cmd0 basePA : 0x%lx cmd1 basePA : 0x%lx comp ring basePA : 0x%lx.",
120 (unsigned long)rxq->cmd_ring[0].basePA,
121 (unsigned long)rxq->cmd_ring[1].basePA,
122 (unsigned long)rxq->comp_ring.basePA);
124 avail = vmxnet3_cmd_ring_desc_avail(&rxq->cmd_ring[0]);
126 "RXQ:cmd0: size=%u; free=%u; next2proc=%u; queued=%u",
127 (uint32_t)rxq->cmd_ring[0].size, avail,
128 rxq->comp_ring.next2proc,
129 rxq->cmd_ring[0].size - avail);
131 avail = vmxnet3_cmd_ring_desc_avail(&rxq->cmd_ring[1]);
132 PMD_RX_LOG(DEBUG, "RXQ:cmd1 size=%u; free=%u; next2proc=%u; queued=%u",
133 (uint32_t)rxq->cmd_ring[1].size, avail, rxq->comp_ring.next2proc,
134 rxq->cmd_ring[1].size - avail);
139 vmxnet3_txq_dump(struct vmxnet3_tx_queue *txq)
146 PMD_TX_LOG(DEBUG, "TXQ: cmd base : 0x%p comp ring base : 0x%p.",
147 txq->cmd_ring.base, txq->comp_ring.base);
148 PMD_TX_LOG(DEBUG, "TXQ: cmd basePA : 0x%lx comp ring basePA : 0x%lx.",
149 (unsigned long)txq->cmd_ring.basePA,
150 (unsigned long)txq->comp_ring.basePA);
152 avail = vmxnet3_cmd_ring_desc_avail(&txq->cmd_ring);
153 PMD_TX_LOG(DEBUG, "TXQ: size=%u; free=%u; next2proc=%u; queued=%u",
154 (uint32_t)txq->cmd_ring.size, avail,
155 txq->comp_ring.next2proc, txq->cmd_ring.size - avail);
160 vmxnet3_cmd_ring_release_mbufs(vmxnet3_cmd_ring_t *ring)
162 while (ring->next2comp != ring->next2fill) {
163 /* No need to worry about tx desc ownership, device is quiesced by now. */
164 vmxnet3_buf_info_t *buf_info = ring->buf_info + ring->next2comp;
167 rte_pktmbuf_free(buf_info->m);
172 vmxnet3_cmd_ring_adv_next2comp(ring);
177 vmxnet3_cmd_ring_release(vmxnet3_cmd_ring_t *ring)
179 vmxnet3_cmd_ring_release_mbufs(ring);
180 rte_free(ring->buf_info);
181 ring->buf_info = NULL;
186 vmxnet3_dev_tx_queue_release(void *txq)
188 vmxnet3_tx_queue_t *tq = txq;
191 /* Release the cmd_ring */
192 vmxnet3_cmd_ring_release(&tq->cmd_ring);
197 vmxnet3_dev_rx_queue_release(void *rxq)
200 vmxnet3_rx_queue_t *rq = rxq;
203 /* Release both the cmd_rings */
204 for (i = 0; i < VMXNET3_RX_CMDRING_SIZE; i++)
205 vmxnet3_cmd_ring_release(&rq->cmd_ring[i]);
210 vmxnet3_dev_tx_queue_reset(void *txq)
212 vmxnet3_tx_queue_t *tq = txq;
213 struct vmxnet3_cmd_ring *ring = &tq->cmd_ring;
214 struct vmxnet3_comp_ring *comp_ring = &tq->comp_ring;
218 /* Release the cmd_ring mbufs */
219 vmxnet3_cmd_ring_release_mbufs(&tq->cmd_ring);
222 /* Tx vmxnet rings structure initialization*/
225 ring->gen = VMXNET3_INIT_GEN;
226 comp_ring->next2proc = 0;
227 comp_ring->gen = VMXNET3_INIT_GEN;
229 size = sizeof(struct Vmxnet3_TxDesc) * ring->size;
230 size += sizeof(struct Vmxnet3_TxCompDesc) * comp_ring->size;
232 memset(ring->base, 0, size);
236 vmxnet3_dev_rx_queue_reset(void *rxq)
239 vmxnet3_rx_queue_t *rq = rxq;
240 struct vmxnet3_cmd_ring *ring0, *ring1;
241 struct vmxnet3_comp_ring *comp_ring;
245 /* Release both the cmd_rings mbufs */
246 for (i = 0; i < VMXNET3_RX_CMDRING_SIZE; i++)
247 vmxnet3_cmd_ring_release_mbufs(&rq->cmd_ring[i]);
250 ring0 = &rq->cmd_ring[0];
251 ring1 = &rq->cmd_ring[1];
252 comp_ring = &rq->comp_ring;
254 /* Rx vmxnet rings structure initialization */
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;
264 size = sizeof(struct Vmxnet3_RxDesc) * (ring0->size + ring1->size);
265 size += sizeof(struct Vmxnet3_RxCompDesc) * comp_ring->size;
267 memset(ring0->base, 0, size);
271 vmxnet3_dev_clear_queues(struct rte_eth_dev *dev)
275 PMD_INIT_FUNC_TRACE();
277 for (i = 0; i < dev->data->nb_tx_queues; i++) {
278 struct vmxnet3_tx_queue *txq = dev->data->tx_queues[i];
282 vmxnet3_dev_tx_queue_reset(txq);
286 for (i = 0; i < dev->data->nb_rx_queues; i++) {
287 struct vmxnet3_rx_queue *rxq = dev->data->rx_queues[i];
291 vmxnet3_dev_rx_queue_reset(rxq);
297 vmxnet3_tq_tx_complete(vmxnet3_tx_queue_t *txq)
300 struct rte_mbuf *mbuf;
301 vmxnet3_comp_ring_t *comp_ring = &txq->comp_ring;
302 struct Vmxnet3_TxCompDesc *tcd = (struct Vmxnet3_TxCompDesc *)
303 (comp_ring->base + comp_ring->next2proc);
305 while (tcd->gen == comp_ring->gen) {
307 /* Release cmd_ring descriptor and free mbuf */
308 #ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER
309 VMXNET3_ASSERT(txq->cmd_ring.base[tcd->txdIdx].txd.eop == 1);
311 mbuf = txq->cmd_ring.buf_info[tcd->txdIdx].m;
312 if (unlikely(mbuf == NULL))
313 rte_panic("EOP desc does not point to a valid mbuf");
315 rte_pktmbuf_free(mbuf);
318 txq->cmd_ring.buf_info[tcd->txdIdx].m = NULL;
319 /* Mark the txd for which tcd was generated as completed */
320 vmxnet3_cmd_ring_adv_next2comp(&txq->cmd_ring);
322 vmxnet3_comp_ring_adv_next2proc(comp_ring);
323 tcd = (struct Vmxnet3_TxCompDesc *)(comp_ring->base +
324 comp_ring->next2proc);
328 PMD_TX_LOG(DEBUG, "Processed %d tx comps & command descs.", completed);
332 vmxnet3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
336 Vmxnet3_TxDesc *txd = NULL;
337 vmxnet3_buf_info_t *tbi = NULL;
338 struct vmxnet3_hw *hw;
339 struct rte_mbuf *txm;
340 vmxnet3_tx_queue_t *txq = tx_queue;
345 PMD_TX_LOG(DEBUG, "Tx queue is stopped.");
349 /* Free up the comp_descriptors aggressively */
350 vmxnet3_tq_tx_complete(txq);
353 while (nb_tx < nb_pkts) {
355 if (vmxnet3_cmd_ring_desc_avail(&txq->cmd_ring)) {
357 txm = tx_pkts[nb_tx];
358 /* Don't support scatter packets yet, free them if met */
359 if (txm->nb_segs != 1) {
360 PMD_TX_LOG(DEBUG, "Don't support scatter packets yet, drop!");
361 rte_pktmbuf_free(tx_pkts[nb_tx]);
362 txq->stats.drop_total++;
368 /* Needs to minus ether header len */
369 if (txm->data_len > (hw->cur_mtu + ETHER_HDR_LEN)) {
370 PMD_TX_LOG(DEBUG, "Packet data_len higher than MTU");
371 rte_pktmbuf_free(tx_pkts[nb_tx]);
372 txq->stats.drop_total++;
378 txd = (Vmxnet3_TxDesc *)(txq->cmd_ring.base + txq->cmd_ring.next2fill);
380 /* Fill the tx descriptor */
381 tbi = txq->cmd_ring.buf_info + txq->cmd_ring.next2fill;
382 tbi->bufPA = RTE_MBUF_DATA_DMA_ADDR(txm);
383 txd->addr = tbi->bufPA;
384 txd->len = txm->data_len;
386 /* Mark the last descriptor as End of Packet. */
390 /* Add VLAN tag if requested */
391 if (txm->ol_flags & PKT_TX_VLAN_PKT) {
393 txd->tci = rte_cpu_to_le_16(txm->vlan_tci);
396 /* Record current mbuf for freeing it later in tx complete */
397 #ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER
402 /* Set the offloading mode to default */
404 txd->om = VMXNET3_OM_NONE;
407 /* finally flip the GEN bit of the SOP desc */
408 txd->gen = txq->cmd_ring.gen;
409 txq->shared->ctrl.txNumDeferred++;
411 /* move to the next2fill descriptor */
412 vmxnet3_cmd_ring_adv_next2fill(&txq->cmd_ring);
416 PMD_TX_LOG(DEBUG, "No free tx cmd desc(s)");
417 txq->stats.drop_total += (nb_pkts - nb_tx);
422 PMD_TX_LOG(DEBUG, "vmxnet3 txThreshold: %u", txq->shared->ctrl.txThreshold);
424 if (txq->shared->ctrl.txNumDeferred >= txq->shared->ctrl.txThreshold) {
426 txq->shared->ctrl.txNumDeferred = 0;
427 /* Notify vSwitch that packets are available. */
428 VMXNET3_WRITE_BAR0_REG(hw, (VMXNET3_REG_TXPROD + txq->queue_id * VMXNET3_REG_ALIGN),
429 txq->cmd_ring.next2fill);
436 * Allocates mbufs and clusters. Post rx descriptors with buffer details
437 * so that device can receive packets in those buffers.
439 * Among the two rings, 1st ring contains buffers of type 0 and type1.
440 * bufs_per_pkt is set such that for non-LRO cases all the buffers required
441 * by a frame will fit in 1st ring (1st buf of type0 and rest of type1).
442 * 2nd ring contains buffers of type 1 alone. Second ring mostly be used
447 vmxnet3_post_rx_bufs(vmxnet3_rx_queue_t *rxq, uint8_t ring_id)
450 uint32_t i = 0, val = 0;
451 struct vmxnet3_cmd_ring *ring = &rxq->cmd_ring[ring_id];
453 while (vmxnet3_cmd_ring_desc_avail(ring) > 0) {
454 struct Vmxnet3_RxDesc *rxd;
455 struct rte_mbuf *mbuf;
456 vmxnet3_buf_info_t *buf_info = &ring->buf_info[ring->next2fill];
458 rxd = (struct Vmxnet3_RxDesc *)(ring->base + ring->next2fill);
460 if (ring->rid == 0) {
461 /* Usually: One HEAD type buf per packet
462 * val = (ring->next2fill % rxq->hw->bufs_per_pkt) ?
463 * VMXNET3_RXD_BTYPE_BODY : VMXNET3_RXD_BTYPE_HEAD;
466 /* We use single packet buffer so all heads here */
467 val = VMXNET3_RXD_BTYPE_HEAD;
469 /* All BODY type buffers for 2nd ring; which won't be used at all by ESXi */
470 val = VMXNET3_RXD_BTYPE_BODY;
473 /* Allocate blank mbuf for the current Rx Descriptor */
474 mbuf = rte_rxmbuf_alloc(rxq->mp);
476 PMD_RX_LOG(ERR, "Error allocating mbuf in %s", __func__);
477 rxq->stats.rx_buf_alloc_failure++;
483 * Load mbuf pointer into buf_info[ring_size]
484 * buf_info structure is equivalent to cookie for virtio-virtqueue
487 buf_info->len = (uint16_t)(mbuf->buf_len -
488 RTE_PKTMBUF_HEADROOM);
489 buf_info->bufPA = RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mbuf);
491 /* Load Rx Descriptor with the buffer's GPA */
492 rxd->addr = buf_info->bufPA;
494 /* After this point rxd->addr MUST not be NULL */
496 rxd->len = buf_info->len;
497 /* Flip gen bit at the end to change ownership */
498 rxd->gen = ring->gen;
500 vmxnet3_cmd_ring_adv_next2fill(ring);
504 /* Return error only if no buffers are posted at present */
505 if (vmxnet3_cmd_ring_desc_avail(ring) >= (ring->size - 1))
512 * Process the Rx Completion Ring of given vmxnet3_rx_queue
513 * for nb_pkts burst and return the number of packets received
516 vmxnet3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
519 uint32_t nb_rxd, idx;
521 vmxnet3_rx_queue_t *rxq;
522 Vmxnet3_RxCompDesc *rcd;
523 vmxnet3_buf_info_t *rbi;
525 struct rte_mbuf *rxm = NULL;
526 struct vmxnet3_hw *hw;
536 rcd = &rxq->comp_ring.base[rxq->comp_ring.next2proc].rcd;
539 PMD_RX_LOG(DEBUG, "Rx queue is stopped.");
543 while (rcd->gen == rxq->comp_ring.gen) {
545 if (nb_rx >= nb_pkts)
548 ring_idx = (uint8_t)((rcd->rqID == rxq->qid1) ? 0 : 1);
549 rxd = (Vmxnet3_RxDesc *)rxq->cmd_ring[ring_idx].base + idx;
550 rbi = rxq->cmd_ring[ring_idx].buf_info + idx;
552 if (rcd->sop != 1 || rcd->eop != 1) {
553 rte_pktmbuf_free_seg(rbi->m);
555 PMD_RX_LOG(DEBUG, "Packet spread across multiple buffers\n)");
560 PMD_RX_LOG(DEBUG, "rxd idx: %d ring idx: %d.", idx, ring_idx);
562 #ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER
563 VMXNET3_ASSERT(rcd->len <= rxd->len);
564 VMXNET3_ASSERT(rbi->m);
567 PMD_RX_LOG(DEBUG, "Rx buf was skipped. rxring[%d][%d]\n)",
569 #ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER
570 VMXNET3_ASSERT(rcd->sop && rcd->eop);
572 rte_pktmbuf_free_seg(rbi->m);
577 /* Assuming a packet is coming in a single packet buffer */
578 if (rxd->btype != VMXNET3_RXD_BTYPE_HEAD) {
580 "Alert : Misbehaving device, incorrect "
581 " buffer type used. iPacket dropped.");
582 rte_pktmbuf_free_seg(rbi->m);
585 #ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER
586 VMXNET3_ASSERT(rxd->btype == VMXNET3_RXD_BTYPE_HEAD);
588 /* Get the packet buffer pointer from buf_info */
591 /* Clear descriptor associated buf_info to be reused */
595 /* Update the index that we received a packet */
596 rxq->cmd_ring[ring_idx].next2comp = idx;
598 /* For RCD with EOP set, check if there is frame error */
600 rxq->stats.drop_total++;
601 rxq->stats.drop_err++;
604 rxq->stats.drop_fcs++;
605 PMD_RX_LOG(ERR, "Recv packet dropped due to frame err.");
607 PMD_RX_LOG(ERR, "Error in received packet rcd#:%d rxd:%d",
608 (int)(rcd - (struct Vmxnet3_RxCompDesc *)
609 rxq->comp_ring.base), rcd->rxdIdx);
610 rte_pktmbuf_free_seg(rxm);
615 /* Check for hardware stripped VLAN tag */
617 PMD_RX_LOG(ERR, "Received packet with vlan ID: %d.",
619 rxm->ol_flags = PKT_RX_VLAN_PKT;
620 #ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER
621 VMXNET3_ASSERT(rxm &&
622 rte_pktmbuf_mtod(rxm, void *));
624 /* Copy vlan tag in packet buffer */
625 rxm->vlan_tci = rte_le_to_cpu_16((uint16_t)rcd->tci);
631 /* Initialize newly received packet buffer */
632 rxm->port = rxq->port_id;
635 rxm->pkt_len = (uint16_t)rcd->len;
636 rxm->data_len = (uint16_t)rcd->len;
637 rxm->port = rxq->port_id;
638 rxm->data_off = RTE_PKTMBUF_HEADROOM;
640 rx_pkts[nb_rx++] = rxm;
642 rxq->cmd_ring[ring_idx].next2comp = idx;
643 VMXNET3_INC_RING_IDX_ONLY(rxq->cmd_ring[ring_idx].next2comp, rxq->cmd_ring[ring_idx].size);
645 /* It's time to allocate some new buf and renew descriptors */
646 vmxnet3_post_rx_bufs(rxq, ring_idx);
647 if (unlikely(rxq->shared->ctrl.updateRxProd)) {
648 VMXNET3_WRITE_BAR0_REG(hw, rxprod_reg[ring_idx] + (rxq->queue_id * VMXNET3_REG_ALIGN),
649 rxq->cmd_ring[ring_idx].next2fill);
652 /* Advance to the next descriptor in comp_ring */
653 vmxnet3_comp_ring_adv_next2proc(&rxq->comp_ring);
655 rcd = &rxq->comp_ring.base[rxq->comp_ring.next2proc].rcd;
657 if (nb_rxd > rxq->cmd_ring[0].size) {
659 "Used up quota of receiving packets,"
660 " relinquish control.");
670 * Create memzone for device rings. malloc can't be used as the physical address is
671 * needed. If the memzone is already created, then this function returns a ptr
674 static const struct rte_memzone *
675 ring_dma_zone_reserve(struct rte_eth_dev *dev, const char *ring_name,
676 uint16_t queue_id, uint32_t ring_size, int socket_id)
678 char z_name[RTE_MEMZONE_NAMESIZE];
679 const struct rte_memzone *mz;
681 snprintf(z_name, sizeof(z_name), "%s_%s_%d_%d",
682 dev->driver->pci_drv.name, ring_name,
683 dev->data->port_id, queue_id);
685 mz = rte_memzone_lookup(z_name);
689 return rte_memzone_reserve_aligned(z_name, ring_size,
690 socket_id, 0, VMXNET3_RING_BA_ALIGN);
694 vmxnet3_dev_tx_queue_setup(struct rte_eth_dev *dev,
697 unsigned int socket_id,
698 __attribute__((unused)) const struct rte_eth_txconf *tx_conf)
700 struct vmxnet3_hw *hw = dev->data->dev_private;
701 const struct rte_memzone *mz;
702 struct vmxnet3_tx_queue *txq;
703 struct vmxnet3_cmd_ring *ring;
704 struct vmxnet3_comp_ring *comp_ring;
707 PMD_INIT_FUNC_TRACE();
709 if ((tx_conf->txq_flags & ETH_TXQ_FLAGS_NOMULTSEGS) !=
710 ETH_TXQ_FLAGS_NOMULTSEGS) {
711 PMD_INIT_LOG(ERR, "TX Multi segment not support yet");
715 if ((tx_conf->txq_flags & ETH_TXQ_FLAGS_NOOFFLOADS) !=
716 ETH_TXQ_FLAGS_NOOFFLOADS) {
717 PMD_INIT_LOG(ERR, "TX not support offload function yet");
721 txq = rte_zmalloc("ethdev_tx_queue", sizeof(struct vmxnet3_tx_queue), CACHE_LINE_SIZE);
723 PMD_INIT_LOG(ERR, "Can not allocate tx queue structure");
727 txq->queue_id = queue_idx;
728 txq->port_id = dev->data->port_id;
729 txq->shared = &hw->tqd_start[queue_idx];
731 txq->qid = queue_idx;
734 ring = &txq->cmd_ring;
735 comp_ring = &txq->comp_ring;
737 /* Tx vmxnet ring length should be between 512-4096 */
738 if (nb_desc < VMXNET3_DEF_TX_RING_SIZE) {
739 PMD_INIT_LOG(ERR, "VMXNET3 Tx Ring Size Min: %u",
740 VMXNET3_DEF_TX_RING_SIZE);
742 } else if (nb_desc > VMXNET3_TX_RING_MAX_SIZE) {
743 PMD_INIT_LOG(ERR, "VMXNET3 Tx Ring Size Max: %u",
744 VMXNET3_TX_RING_MAX_SIZE);
747 ring->size = nb_desc;
748 ring->size &= ~VMXNET3_RING_SIZE_MASK;
750 comp_ring->size = ring->size;
752 /* Tx vmxnet rings structure initialization*/
755 ring->gen = VMXNET3_INIT_GEN;
756 comp_ring->next2proc = 0;
757 comp_ring->gen = VMXNET3_INIT_GEN;
759 size = sizeof(struct Vmxnet3_TxDesc) * ring->size;
760 size += sizeof(struct Vmxnet3_TxCompDesc) * comp_ring->size;
762 mz = ring_dma_zone_reserve(dev, "txdesc", queue_idx, size, socket_id);
764 PMD_INIT_LOG(ERR, "ERROR: Creating queue descriptors zone");
767 memset(mz->addr, 0, mz->len);
769 /* cmd_ring initialization */
770 ring->base = mz->addr;
771 ring->basePA = mz->phys_addr;
773 /* comp_ring initialization */
774 comp_ring->base = ring->base + ring->size;
775 comp_ring->basePA = ring->basePA +
776 (sizeof(struct Vmxnet3_TxDesc) * ring->size);
778 /* cmd_ring0 buf_info allocation */
779 ring->buf_info = rte_zmalloc("tx_ring_buf_info",
780 ring->size * sizeof(vmxnet3_buf_info_t), CACHE_LINE_SIZE);
781 if (ring->buf_info == NULL) {
782 PMD_INIT_LOG(ERR, "ERROR: Creating tx_buf_info structure");
786 /* Update the data portion with txq */
787 dev->data->tx_queues[queue_idx] = txq;
793 vmxnet3_dev_rx_queue_setup(struct rte_eth_dev *dev,
796 unsigned int socket_id,
797 __attribute__((unused)) const struct rte_eth_rxconf *rx_conf,
798 struct rte_mempool *mp)
800 const struct rte_memzone *mz;
801 struct vmxnet3_rx_queue *rxq;
802 struct vmxnet3_hw *hw = dev->data->dev_private;
803 struct vmxnet3_cmd_ring *ring0, *ring1, *ring;
804 struct vmxnet3_comp_ring *comp_ring;
809 struct rte_pktmbuf_pool_private *mbp_priv;
811 PMD_INIT_FUNC_TRACE();
813 mbp_priv = (struct rte_pktmbuf_pool_private *)
814 rte_mempool_get_priv(mp);
815 buf_size = (uint16_t) (mbp_priv->mbuf_data_room_size -
816 RTE_PKTMBUF_HEADROOM);
818 if (dev->data->dev_conf.rxmode.max_rx_pkt_len > buf_size) {
819 PMD_INIT_LOG(ERR, "buf_size = %u, max_pkt_len = %u, "
820 "VMXNET3 don't support scatter packets yet",
821 buf_size, dev->data->dev_conf.rxmode.max_rx_pkt_len);
825 rxq = rte_zmalloc("ethdev_rx_queue", sizeof(struct vmxnet3_rx_queue), CACHE_LINE_SIZE);
827 PMD_INIT_LOG(ERR, "Can not allocate rx queue structure");
832 rxq->queue_id = queue_idx;
833 rxq->port_id = dev->data->port_id;
834 rxq->shared = &hw->rqd_start[queue_idx];
836 rxq->qid1 = queue_idx;
837 rxq->qid2 = queue_idx + hw->num_rx_queues;
840 ring0 = &rxq->cmd_ring[0];
841 ring1 = &rxq->cmd_ring[1];
842 comp_ring = &rxq->comp_ring;
844 /* Rx vmxnet rings length should be between 256-4096 */
845 if (nb_desc < VMXNET3_DEF_RX_RING_SIZE) {
846 PMD_INIT_LOG(ERR, "VMXNET3 Rx Ring Size Min: 256");
848 } else if (nb_desc > VMXNET3_RX_RING_MAX_SIZE) {
849 PMD_INIT_LOG(ERR, "VMXNET3 Rx Ring Size Max: 4096");
852 ring0->size = nb_desc;
853 ring0->size &= ~VMXNET3_RING_SIZE_MASK;
854 ring1->size = ring0->size;
857 comp_ring->size = ring0->size + ring1->size;
859 /* Rx vmxnet rings structure initialization */
860 ring0->next2fill = 0;
861 ring1->next2fill = 0;
862 ring0->next2comp = 0;
863 ring1->next2comp = 0;
864 ring0->gen = VMXNET3_INIT_GEN;
865 ring1->gen = VMXNET3_INIT_GEN;
866 comp_ring->next2proc = 0;
867 comp_ring->gen = VMXNET3_INIT_GEN;
869 size = sizeof(struct Vmxnet3_RxDesc) * (ring0->size + ring1->size);
870 size += sizeof(struct Vmxnet3_RxCompDesc) * comp_ring->size;
872 mz = ring_dma_zone_reserve(dev, "rxdesc", queue_idx, size, socket_id);
874 PMD_INIT_LOG(ERR, "ERROR: Creating queue descriptors zone");
877 memset(mz->addr, 0, mz->len);
879 /* cmd_ring0 initialization */
880 ring0->base = mz->addr;
881 ring0->basePA = mz->phys_addr;
883 /* cmd_ring1 initialization */
884 ring1->base = ring0->base + ring0->size;
885 ring1->basePA = ring0->basePA + sizeof(struct Vmxnet3_RxDesc) * ring0->size;
887 /* comp_ring initialization */
888 comp_ring->base = ring1->base + ring1->size;
889 comp_ring->basePA = ring1->basePA + sizeof(struct Vmxnet3_RxDesc) *
892 /* cmd_ring0-cmd_ring1 buf_info allocation */
893 for (i = 0; i < VMXNET3_RX_CMDRING_SIZE; i++) {
895 ring = &rxq->cmd_ring[i];
897 snprintf(mem_name, sizeof(mem_name), "rx_ring_%d_buf_info", i);
899 ring->buf_info = rte_zmalloc(mem_name, ring->size * sizeof(vmxnet3_buf_info_t), CACHE_LINE_SIZE);
900 if (ring->buf_info == NULL) {
901 PMD_INIT_LOG(ERR, "ERROR: Creating rx_buf_info structure");
906 /* Update the data portion with rxq */
907 dev->data->rx_queues[queue_idx] = rxq;
913 * Initializes Receive Unit
914 * Load mbufs in rx queue in advance
917 vmxnet3_dev_rxtx_init(struct rte_eth_dev *dev)
919 struct vmxnet3_hw *hw = dev->data->dev_private;
924 PMD_INIT_FUNC_TRACE();
926 for (i = 0; i < hw->num_rx_queues; i++) {
927 vmxnet3_rx_queue_t *rxq = dev->data->rx_queues[i];
929 for (j = 0; j < VMXNET3_RX_CMDRING_SIZE; j++) {
930 /* Passing 0 as alloc_num will allocate full ring */
931 ret = vmxnet3_post_rx_bufs(rxq, j);
933 PMD_INIT_LOG(ERR, "ERROR: Posting Rxq: %d buffers ring: %d", i, j);
936 /* Updating device with the index:next2fill to fill the mbufs for coming packets */
937 if (unlikely(rxq->shared->ctrl.updateRxProd)) {
938 VMXNET3_WRITE_BAR0_REG(hw, rxprod_reg[j] + (rxq->queue_id * VMXNET3_REG_ALIGN),
939 rxq->cmd_ring[j].next2fill);
942 rxq->stopped = FALSE;
945 for (i = 0; i < dev->data->nb_tx_queues; i++) {
946 struct vmxnet3_tx_queue *txq = dev->data->tx_queues[i];
948 txq->stopped = FALSE;
954 static uint8_t rss_intel_key[40] = {
955 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2,
956 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0,
957 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
958 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C,
959 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA,
963 * Configure RSS feature
966 vmxnet3_rss_configure(struct rte_eth_dev *dev)
968 #define VMXNET3_RSS_OFFLOAD_ALL ( \
974 struct vmxnet3_hw *hw = dev->data->dev_private;
975 struct VMXNET3_RSSConf *dev_rss_conf;
976 struct rte_eth_rss_conf *port_rss_conf;
980 PMD_INIT_FUNC_TRACE();
982 dev_rss_conf = hw->rss_conf;
983 port_rss_conf = &dev->data->dev_conf.rx_adv_conf.rss_conf;
985 /* loading hashFunc */
986 dev_rss_conf->hashFunc = VMXNET3_RSS_HASH_FUNC_TOEPLITZ;
987 /* loading hashKeySize */
988 dev_rss_conf->hashKeySize = VMXNET3_RSS_MAX_KEY_SIZE;
989 /* loading indTableSize : Must not exceed VMXNET3_RSS_MAX_IND_TABLE_SIZE (128)*/
990 dev_rss_conf->indTableSize = (uint16_t)(hw->num_rx_queues * 4);
992 if (port_rss_conf->rss_key == NULL) {
993 /* Default hash key */
994 port_rss_conf->rss_key = rss_intel_key;
997 /* loading hashKey */
998 memcpy(&dev_rss_conf->hashKey[0], port_rss_conf->rss_key, dev_rss_conf->hashKeySize);
1000 /* loading indTable */
1001 for (i = 0, j = 0; i < dev_rss_conf->indTableSize; i++, j++) {
1002 if (j == dev->data->nb_rx_queues)
1004 dev_rss_conf->indTable[i] = j;
1007 /* loading hashType */
1008 dev_rss_conf->hashType = 0;
1009 rss_hf = port_rss_conf->rss_hf & VMXNET3_RSS_OFFLOAD_ALL;
1010 if (rss_hf & ETH_RSS_IPV4)
1011 dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_IPV4;
1012 if (rss_hf & ETH_RSS_IPV4_TCP)
1013 dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_TCP_IPV4;
1014 if (rss_hf & ETH_RSS_IPV6)
1015 dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_IPV6;
1016 if (rss_hf & ETH_RSS_IPV6_TCP)
1017 dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_TCP_IPV6;
1019 return VMXNET3_SUCCESS;
1023 * Configure VLAN Filter feature
1026 vmxnet3_vlan_configure(struct rte_eth_dev *dev)
1029 struct vmxnet3_hw *hw = dev->data->dev_private;
1030 uint32_t *vf_table = hw->shared->devRead.rxFilterConf.vfTable;
1032 PMD_INIT_FUNC_TRACE();
1034 /* Verify if this tag is already set */
1035 for (i = 0; i < VMXNET3_VFT_SIZE; i++) {
1036 /* Filter all vlan tags out by default */
1038 /* To-Do: Provide another routine in dev_ops for user config */
1040 PMD_INIT_LOG(DEBUG, "Registering VLAN portid: %"PRIu8" tag %u",
1041 dev->data->port_id, vf_table[i]);
1044 return VMXNET3_SUCCESS;