1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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;
}
|