aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/dev_armada/pp2/tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/dev_armada/pp2/tx.c')
-rw-r--r--src/plugins/dev_armada/pp2/tx.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/src/plugins/dev_armada/pp2/tx.c b/src/plugins/dev_armada/pp2/tx.c
new file mode 100644
index 00000000000..1e6675c9746
--- /dev/null
+++ b/src/plugins/dev_armada/pp2/tx.c
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright (c) 2024 Cisco Systems, Inc.
+ */
+
+#include <vlib/vlib.h>
+#include <vnet/dev/dev.h>
+#include <vnet/ethernet/ethernet.h>
+
+#include <dev_armada/pp2/pp2.h>
+
+VNET_DEV_NODE_FN (mvpp2_tx_node)
+(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
+{
+ vnet_dev_tx_node_runtime_t *rt = vnet_dev_get_tx_node_runtime (node);
+ vnet_dev_tx_queue_t *txq = rt->tx_queue;
+ vnet_dev_port_t *port = txq->port;
+ vnet_dev_t *dev = port->dev;
+ mvpp2_txq_t *mtq = vnet_dev_get_tx_queue_data (txq);
+ mvpp2_port_t *mp = vnet_dev_get_port_data (port);
+ mvpp2_device_t *md = vnet_dev_get_data (dev);
+ u8 qid = txq->queue_id;
+ u32 *buffers = vlib_frame_vector_args (frame);
+ u32 n_vectors = frame->n_vectors, n_left;
+ u16 n_sent;
+ struct pp2_ppio *ppio = mp->ppio;
+ struct pp2_hif *hif = md->hif[vm->thread_index];
+ struct pp2_ppio_desc descs[VLIB_FRAME_SIZE], *d = descs;
+ u16 sz = txq->size;
+ u16 mask = sz - 1;
+
+ if (mtq->n_enq)
+ {
+ u16 n_done = 0;
+ if (PREDICT_FALSE (pp2_ppio_get_num_outq_done (ppio, hif, qid, &n_done)))
+ vlib_error_count (vm, node->node_index,
+ MVPP2_TX_NODE_CTR_PPIO_GET_NUM_OUTQ_DONE, 1);
+
+ if (n_done)
+ {
+ vlib_buffer_free_from_ring (
+ vm, mtq->buffers, (mtq->next - mtq->n_enq) & mask, sz, n_done);
+ mtq->n_enq -= n_done;
+ }
+ }
+
+ n_sent = clib_min (n_vectors, sz - mtq->n_enq);
+
+ for (d = descs, n_left = n_sent; n_left; d++, buffers++, n_left--)
+ {
+ vlib_buffer_t *b0 = vlib_get_buffer (vm, buffers[0]);
+ u64 paddr = vlib_buffer_get_pa (vm, b0);
+
+ pp2_ppio_outq_desc_reset (d);
+ pp2_ppio_outq_desc_set_phys_addr (d, paddr + b0->current_data);
+ pp2_ppio_outq_desc_set_pkt_offset (d, 0);
+ pp2_ppio_outq_desc_set_pkt_len (d, b0->current_length);
+ }
+
+ buffers = vlib_frame_vector_args (frame);
+
+ if (pp2_ppio_send (ppio, hif, qid, descs, &n_sent))
+ {
+ n_sent = 0;
+ vlib_error_count (vm, node->node_index, MVPP2_TX_NODE_CTR_PPIO_SEND, 1);
+ }
+ else if (n_sent)
+ {
+ vlib_buffer_copy_indices_to_ring (mtq->buffers, buffers,
+ mtq->next & mask, sz, n_sent);
+ mtq->next += n_sent;
+ mtq->n_enq += n_sent;
+ }
+
+ /* free unsent buffers */
+ if (PREDICT_FALSE (n_sent != n_vectors))
+ {
+ vlib_buffer_free (vm, buffers + n_sent, n_vectors - n_sent);
+ vlib_error_count (vm, node->node_index, MVPP2_TX_NODE_CTR_NO_FREE_SLOTS,
+ n_vectors - n_sent);
+ }
+
+ return n_sent;
+}