iavf: new driver using new dev infra
[vpp.git] / src / plugins / dev_iavf / queue.c
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright (c) 2023 Cisco Systems, Inc.
3  */
4
5 #include <vnet/vnet.h>
6 #include <vnet/dev/dev.h>
7 #include <vnet/dev/pci.h>
8 #include <vnet/dev/counters.h>
9 #include <vppinfra/ring.h>
10 #include <dev_iavf/iavf.h>
11 #include <dev_iavf/virtchnl.h>
12 #include <dev_iavf/virtchnl_funcs.h>
13 #include <vnet/ethernet/ethernet.h>
14 #include <vnet/plugin/plugin.h>
15 #include <vpp/app/version.h>
16
17 VLIB_REGISTER_LOG_CLASS (iavf_log, static) = {
18   .class_name = "iavf",
19   .subclass_name = "queue",
20 };
21
22 vnet_dev_rv_t
23 iavf_rx_queue_alloc (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
24 {
25   vnet_dev_port_t *port = rxq->port;
26   vnet_dev_t *dev = port->dev;
27   iavf_device_t *ad = vnet_dev_get_data (dev);
28   iavf_rxq_t *arq = vnet_dev_get_rx_queue_data (rxq);
29   vnet_dev_rv_t rv;
30
31   arq->buffer_indices = clib_mem_alloc_aligned (
32     rxq->size * sizeof (arq->buffer_indices[0]), CLIB_CACHE_LINE_BYTES);
33
34   if ((rv =
35          vnet_dev_dma_mem_alloc (vm, dev, sizeof (iavf_rx_desc_t) * rxq->size,
36                                  0, (void **) &arq->descs)))
37     return rv;
38
39   arq->qrx_tail = ad->bar0 + IAVF_QRX_TAIL (rxq->queue_id);
40
41   log_debug (dev, "queue %u alocated", rxq->queue_id);
42   return rv;
43 }
44
45 void
46 iavf_rx_queue_free (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
47 {
48   vnet_dev_t *dev = rxq->port->dev;
49   iavf_rxq_t *aq = vnet_dev_get_rx_queue_data (rxq);
50
51   log_debug (dev, "queue %u", rxq->queue_id);
52
53   vnet_dev_dma_mem_free (vm, dev, aq->descs);
54
55   foreach_pointer (p, aq->buffer_indices)
56     if (p)
57       clib_mem_free (p);
58 }
59
60 vnet_dev_rv_t
61 iavf_tx_queue_alloc (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
62 {
63   vnet_dev_t *dev = txq->port->dev;
64   iavf_device_t *ad = vnet_dev_get_data (dev);
65   iavf_txq_t *atq = vnet_dev_get_tx_queue_data (txq);
66   vnet_dev_rv_t rv;
67
68   if ((rv =
69          vnet_dev_dma_mem_alloc (vm, dev, sizeof (iavf_tx_desc_t) * txq->size,
70                                  0, (void **) &atq->descs)))
71     return rv;
72
73   clib_ring_new_aligned (atq->rs_slots, 32, CLIB_CACHE_LINE_BYTES);
74   atq->buffer_indices = clib_mem_alloc_aligned (
75     txq->size * sizeof (atq->buffer_indices[0]), CLIB_CACHE_LINE_BYTES);
76   atq->tmp_descs = clib_mem_alloc_aligned (
77     sizeof (atq->tmp_descs[0]) * txq->size, CLIB_CACHE_LINE_BYTES);
78   atq->tmp_bufs = clib_mem_alloc_aligned (
79     sizeof (atq->tmp_bufs[0]) * txq->size, CLIB_CACHE_LINE_BYTES);
80
81   atq->qtx_tail = ad->bar0 + IAVF_QTX_TAIL (txq->queue_id);
82
83   log_debug (dev, "queue %u alocated", txq->queue_id);
84   return VNET_DEV_OK;
85 }
86
87 void
88 iavf_tx_queue_free (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
89 {
90   vnet_dev_t *dev = txq->port->dev;
91   iavf_txq_t *atq = vnet_dev_get_tx_queue_data (txq);
92   iavf_txq_t *aq = vnet_dev_get_tx_queue_data (txq);
93
94   log_debug (dev, "queue %u", txq->queue_id);
95   vnet_dev_dma_mem_free (vm, dev, aq->descs);
96   clib_ring_free (atq->rs_slots);
97
98   foreach_pointer (p, aq->tmp_descs, aq->tmp_bufs, aq->buffer_indices)
99     if (p)
100       clib_mem_free (p);
101 }
102
103 vnet_dev_rv_t
104 iavf_rx_queue_start (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
105 {
106   vnet_dev_t *dev = rxq->port->dev;
107   iavf_rxq_t *arq = vnet_dev_get_rx_queue_data (rxq);
108   iavf_rx_desc_t *d = arq->descs;
109   u32 n_enq, *bi = arq->buffer_indices;
110   u8 bpi = vnet_dev_get_rx_queue_buffer_pool_index (rxq);
111
112   n_enq = vlib_buffer_alloc_from_pool (vm, bi, rxq->size - 8, bpi);
113
114   if (n_enq < 8)
115     {
116       if (n_enq)
117         vlib_buffer_free (vm, bi, n_enq);
118       return VNET_DEV_ERR_BUFFER_ALLOC_FAIL;
119     }
120
121   for (u32 i = 0; i < n_enq; i++)
122     {
123       vlib_buffer_t *b = vlib_get_buffer (vm, bi[i]);
124       u64 dma_addr = vnet_dev_get_dma_addr (vm, dev, b->data);
125       d[i] = (iavf_rx_desc_t){ .addr = dma_addr };
126     }
127
128   arq->n_enqueued = n_enq;
129   arq->next = 0;
130   __atomic_store_n (arq->qrx_tail, n_enq, __ATOMIC_RELEASE);
131   return VNET_DEV_OK;
132 }
133
134 void
135 iavf_rx_queue_stop (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
136 {
137   iavf_rxq_t *arq = vnet_dev_get_rx_queue_data (rxq);
138
139   __atomic_store_n (arq->qrx_tail, 0, __ATOMIC_RELAXED);
140   if (arq->n_enqueued)
141     {
142       vlib_buffer_free_from_ring_no_next (vm, arq->buffer_indices, arq->next,
143                                           rxq->size, arq->n_enqueued);
144       log_debug (rxq->port->dev, "%u buffers freed from rx queue %u",
145                  arq->n_enqueued, rxq->queue_id);
146     }
147   arq->n_enqueued = arq->next = 0;
148 }
149
150 vnet_dev_rv_t
151 iavf_tx_queue_start (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
152 {
153   iavf_txq_t *atq = vnet_dev_get_tx_queue_data (txq);
154   atq->next = 0;
155   atq->n_enqueued = 0;
156   clib_ring_reset (atq->rs_slots);
157   __atomic_store_n (atq->qtx_tail, 0, __ATOMIC_RELAXED);
158   return VNET_DEV_OK;
159 }
160
161 void
162 iavf_tx_queue_stop (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
163 {
164   iavf_txq_t *atq = vnet_dev_get_tx_queue_data (txq);
165
166   log_debug (txq->port->dev, "queue %u", txq->queue_id);
167
168   __atomic_store_n (atq->qtx_tail, 0, __ATOMIC_RELAXED);
169   if (atq->n_enqueued)
170     {
171       vlib_buffer_free_from_ring_no_next (vm, atq->buffer_indices,
172                                           atq->next - atq->n_enqueued,
173                                           txq->size, atq->n_enqueued);
174       log_debug (txq->port->dev, "%u buffers freed from tx queue %u",
175                  atq->n_enqueued, txq->queue_id);
176     }
177   atq->n_enqueued = atq->next = 0;
178 }