diff options
Diffstat (limited to 'src/plugins/dev_iavf/queue.c')
-rw-r--r-- | src/plugins/dev_iavf/queue.c | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/src/plugins/dev_iavf/queue.c b/src/plugins/dev_iavf/queue.c new file mode 100644 index 00000000000..113c0dbdfc7 --- /dev/null +++ b/src/plugins/dev_iavf/queue.c @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2023 Cisco Systems, Inc. + */ + +#include <vnet/vnet.h> +#include <vnet/dev/dev.h> +#include <vnet/dev/pci.h> +#include <vnet/dev/counters.h> +#include <vppinfra/ring.h> +#include <dev_iavf/iavf.h> +#include <dev_iavf/virtchnl.h> +#include <dev_iavf/virtchnl_funcs.h> +#include <vnet/ethernet/ethernet.h> +#include <vnet/plugin/plugin.h> +#include <vpp/app/version.h> + +VLIB_REGISTER_LOG_CLASS (iavf_log, static) = { + .class_name = "iavf", + .subclass_name = "queue", +}; + +vnet_dev_rv_t +iavf_rx_queue_alloc (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq) +{ + vnet_dev_port_t *port = rxq->port; + vnet_dev_t *dev = port->dev; + iavf_device_t *ad = vnet_dev_get_data (dev); + iavf_rxq_t *arq = vnet_dev_get_rx_queue_data (rxq); + vnet_dev_rv_t rv; + + arq->buffer_indices = clib_mem_alloc_aligned ( + rxq->size * sizeof (arq->buffer_indices[0]), CLIB_CACHE_LINE_BYTES); + + if ((rv = + vnet_dev_dma_mem_alloc (vm, dev, sizeof (iavf_rx_desc_t) * rxq->size, + 0, (void **) &arq->descs))) + return rv; + + arq->qrx_tail = ad->bar0 + IAVF_QRX_TAIL (rxq->queue_id); + + log_debug (dev, "queue %u alocated", rxq->queue_id); + return rv; +} + +void +iavf_rx_queue_free (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq) +{ + vnet_dev_t *dev = rxq->port->dev; + iavf_rxq_t *aq = vnet_dev_get_rx_queue_data (rxq); + + log_debug (dev, "queue %u", rxq->queue_id); + + vnet_dev_dma_mem_free (vm, dev, aq->descs); + + foreach_pointer (p, aq->buffer_indices) + if (p) + clib_mem_free (p); +} + +vnet_dev_rv_t +iavf_tx_queue_alloc (vlib_main_t *vm, vnet_dev_tx_queue_t *txq) +{ + vnet_dev_t *dev = txq->port->dev; + iavf_device_t *ad = vnet_dev_get_data (dev); + iavf_txq_t *atq = vnet_dev_get_tx_queue_data (txq); + vnet_dev_rv_t rv; + + if ((rv = + vnet_dev_dma_mem_alloc (vm, dev, sizeof (iavf_tx_desc_t) * txq->size, + 0, (void **) &atq->descs))) + return rv; + + clib_ring_new_aligned (atq->rs_slots, 32, CLIB_CACHE_LINE_BYTES); + atq->buffer_indices = clib_mem_alloc_aligned ( + txq->size * sizeof (atq->buffer_indices[0]), CLIB_CACHE_LINE_BYTES); + atq->tmp_descs = clib_mem_alloc_aligned ( + sizeof (atq->tmp_descs[0]) * txq->size, CLIB_CACHE_LINE_BYTES); + atq->tmp_bufs = clib_mem_alloc_aligned ( + sizeof (atq->tmp_bufs[0]) * txq->size, CLIB_CACHE_LINE_BYTES); + + atq->qtx_tail = ad->bar0 + IAVF_QTX_TAIL (txq->queue_id); + + log_debug (dev, "queue %u alocated", txq->queue_id); + return VNET_DEV_OK; +} + +void +iavf_tx_queue_free (vlib_main_t *vm, vnet_dev_tx_queue_t *txq) +{ + vnet_dev_t *dev = txq->port->dev; + iavf_txq_t *atq = vnet_dev_get_tx_queue_data (txq); + iavf_txq_t *aq = vnet_dev_get_tx_queue_data (txq); + + log_debug (dev, "queue %u", txq->queue_id); + vnet_dev_dma_mem_free (vm, dev, aq->descs); + clib_ring_free (atq->rs_slots); + + foreach_pointer (p, aq->tmp_descs, aq->tmp_bufs, aq->buffer_indices) + if (p) + clib_mem_free (p); +} + +vnet_dev_rv_t +iavf_rx_queue_start (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq) +{ + vnet_dev_t *dev = rxq->port->dev; + iavf_rxq_t *arq = vnet_dev_get_rx_queue_data (rxq); + iavf_rx_desc_t *d = arq->descs; + u32 n_enq, *bi = arq->buffer_indices; + u8 bpi = vnet_dev_get_rx_queue_buffer_pool_index (rxq); + + n_enq = vlib_buffer_alloc_from_pool (vm, bi, rxq->size - 8, bpi); + + if (n_enq < 8) + { + if (n_enq) + vlib_buffer_free (vm, bi, n_enq); + return VNET_DEV_ERR_BUFFER_ALLOC_FAIL; + } + + for (u32 i = 0; i < n_enq; i++) + { + vlib_buffer_t *b = vlib_get_buffer (vm, bi[i]); + u64 dma_addr = vnet_dev_get_dma_addr (vm, dev, b->data); + d[i] = (iavf_rx_desc_t){ .addr = dma_addr }; + } + + arq->n_enqueued = n_enq; + arq->next = 0; + __atomic_store_n (arq->qrx_tail, n_enq, __ATOMIC_RELEASE); + return VNET_DEV_OK; +} + +void +iavf_rx_queue_stop (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq) +{ + iavf_rxq_t *arq = vnet_dev_get_rx_queue_data (rxq); + + __atomic_store_n (arq->qrx_tail, 0, __ATOMIC_RELAXED); + if (arq->n_enqueued) + { + vlib_buffer_free_from_ring_no_next (vm, arq->buffer_indices, arq->next, + rxq->size, arq->n_enqueued); + log_debug (rxq->port->dev, "%u buffers freed from rx queue %u", + arq->n_enqueued, rxq->queue_id); + } + arq->n_enqueued = arq->next = 0; +} + +vnet_dev_rv_t +iavf_tx_queue_start (vlib_main_t *vm, vnet_dev_tx_queue_t *txq) +{ + iavf_txq_t *atq = vnet_dev_get_tx_queue_data (txq); + atq->next = 0; + atq->n_enqueued = 0; + clib_ring_reset (atq->rs_slots); + __atomic_store_n (atq->qtx_tail, 0, __ATOMIC_RELAXED); + return VNET_DEV_OK; +} + +void +iavf_tx_queue_stop (vlib_main_t *vm, vnet_dev_tx_queue_t *txq) +{ + iavf_txq_t *atq = vnet_dev_get_tx_queue_data (txq); + + log_debug (txq->port->dev, "queue %u", txq->queue_id); + + __atomic_store_n (atq->qtx_tail, 0, __ATOMIC_RELAXED); + if (atq->n_enqueued) + { + vlib_buffer_free_from_ring_no_next (vm, atq->buffer_indices, + atq->next - atq->n_enqueued, + txq->size, atq->n_enqueued); + log_debug (txq->port->dev, "%u buffers freed from tx queue %u", + atq->n_enqueued, txq->queue_id); + } + atq->n_enqueued = atq->next = 0; +} |