octeon: native driver for Marvell Octeon SoC
[vpp.git] / src / plugins / dev_octeon / 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 <dev_octeon/octeon.h>
10 #include <vnet/ethernet/ethernet.h>
11 #include <vnet/plugin/plugin.h>
12 #include <vpp/app/version.h>
13
14 VLIB_REGISTER_LOG_CLASS (oct_log, static) = {
15   .class_name = "octeon",
16   .subclass_name = "queue",
17 };
18
19 static vnet_dev_rv_t
20 oct_roc_err (vnet_dev_t *dev, int rv, char *fmt, ...)
21 {
22   u8 *s = 0;
23   va_list va;
24
25   va_start (va, fmt);
26   s = va_format (s, fmt, &va);
27   va_end (va);
28
29   log_err (dev, "%v - ROC error %s (%d)", s, roc_error_msg_get (rv), rv);
30
31   vec_free (s);
32   return VNET_DEV_ERR_INTERNAL;
33 }
34
35 vnet_dev_rv_t
36 oct_rx_queue_alloc (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
37 {
38   vnet_dev_port_t *port = rxq->port;
39   vnet_dev_t *dev = port->dev;
40
41   log_debug (dev, "rx_queue_alloc: queue %u alocated", rxq->queue_id);
42   return VNET_DEV_OK;
43 }
44
45 void
46 oct_rx_queue_free (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
47 {
48   vnet_dev_port_t *port = rxq->port;
49   vnet_dev_t *dev = port->dev;
50
51   log_debug (dev, "rx_queue_free: queue %u", rxq->queue_id);
52 }
53
54 vnet_dev_rv_t
55 oct_tx_queue_alloc (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
56 {
57   oct_txq_t *ctq = vnet_dev_get_tx_queue_data (txq);
58   vnet_dev_port_t *port = txq->port;
59   vnet_dev_t *dev = port->dev;
60
61   log_debug (dev, "tx_queue_alloc: queue %u alocated", txq->queue_id);
62
63   return vnet_dev_dma_mem_alloc (
64     vm, dev, sizeof (void *) * ROC_CN10K_NPA_BATCH_ALLOC_MAX_PTRS, 128,
65     (void **) &ctq->ba_buffer);
66 }
67
68 void
69 oct_tx_queue_free (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
70 {
71   oct_txq_t *ctq = vnet_dev_get_tx_queue_data (txq);
72   vnet_dev_port_t *port = txq->port;
73   vnet_dev_t *dev = port->dev;
74
75   log_debug (dev, "tx_queue_free: queue %u", txq->queue_id);
76
77   vnet_dev_dma_mem_free (vm, dev, ctq->ba_buffer);
78 }
79
80 vnet_dev_rv_t
81 oct_rxq_init (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
82 {
83   oct_rxq_t *crq = vnet_dev_get_rx_queue_data (rxq);
84   vnet_dev_t *dev = rxq->port->dev;
85   oct_device_t *cd = vnet_dev_get_data (dev);
86   vlib_buffer_pool_t *bp =
87     vlib_get_buffer_pool (vm, vnet_dev_get_rx_queue_buffer_pool_index (rxq));
88   struct roc_nix *nix = cd->nix;
89   int rrv;
90
91   struct npa_aura_s aura = {};
92   struct npa_pool_s npapool = { .nat_align = 1 };
93
94   if ((rrv = roc_npa_pool_create (&crq->aura_handle, bp->alloc_size, rxq->size,
95                                   &aura, &npapool, 0)))
96     {
97       oct_rxq_deinit (vm, rxq);
98       return oct_roc_err (dev, rrv, "roc_npa_pool_create() failed");
99     }
100
101   crq->npa_pool_initialized = 1;
102   log_notice (dev, "NPA pool created, aura_handle = 0x%lx", crq->aura_handle);
103
104   crq->cq = (struct roc_nix_cq){
105     .nb_desc = rxq->size,
106     .qid = rxq->queue_id,
107   };
108
109   if ((rrv = roc_nix_cq_init (nix, &crq->cq)))
110     {
111       oct_rxq_deinit (vm, rxq);
112       return oct_roc_err (dev, rrv,
113                           "roc_nix_cq_init(qid = %u, nb_desc = %u) failed",
114                           crq->cq.nb_desc, crq->cq.nb_desc);
115     }
116
117   crq->cq_initialized = 1;
118   log_debug (dev, "CQ %u initialised (qmask 0x%x wdata 0x%lx)", crq->cq.qid,
119              crq->cq.qmask, crq->cq.wdata);
120
121   crq->hdr_off = vm->buffer_main->ext_hdr_size;
122
123   crq->rq = (struct roc_nix_rq){
124     .qid = rxq->queue_id,
125     .cqid = crq->cq.qid,
126     .aura_handle = crq->aura_handle,
127     .first_skip = crq->hdr_off + sizeof (vlib_buffer_t),
128     .later_skip = crq->hdr_off + sizeof (vlib_buffer_t),
129     .lpb_size = bp->data_size + crq->hdr_off + sizeof (vlib_buffer_t),
130     .flow_tag_width = 32,
131   };
132
133   if ((rrv = roc_nix_rq_init (nix, &crq->rq, 1 /* disable */)))
134     {
135       oct_rxq_deinit (vm, rxq);
136       return oct_roc_err (dev, rrv, "roc_nix_rq_init(qid = %u) failed",
137                           crq->rq.qid);
138     }
139
140   crq->rq_initialized = 1;
141   crq->lmt_base_addr = roc_idev_lmt_base_addr_get ();
142   crq->aura_batch_free_ioaddr =
143     (roc_npa_aura_handle_to_base (crq->aura_handle) +
144      NPA_LF_AURA_BATCH_FREE0) |
145     (0x7 << 4);
146
147   log_debug (dev, "RQ %u initialised", crq->cq.qid);
148
149   return VNET_DEV_OK;
150 }
151
152 void
153 oct_rxq_deinit (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
154 {
155   oct_rxq_t *crq = vnet_dev_get_rx_queue_data (rxq);
156   vnet_dev_t *dev = rxq->port->dev;
157   int rrv;
158
159   if (crq->rq_initialized)
160     {
161       rrv = roc_nix_rq_fini (&crq->rq);
162       if (rrv)
163         oct_roc_err (dev, rrv, "roc_nix_rq_fini() failed");
164       crq->rq_initialized = 0;
165     }
166
167   if (crq->cq_initialized)
168     {
169       rrv = roc_nix_cq_fini (&crq->cq);
170       if (rrv)
171         oct_roc_err (dev, rrv, "roc_nix_cq_fini() failed");
172       crq->cq_initialized = 0;
173     }
174
175   if (crq->npa_pool_initialized)
176     {
177       rrv = roc_npa_pool_destroy (crq->aura_handle);
178       if (rrv)
179         oct_roc_err (dev, rrv, "roc_npa_pool_destroy() failed");
180       crq->npa_pool_initialized = 0;
181     }
182 }
183
184 vnet_dev_rv_t
185 oct_txq_init (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
186 {
187   oct_txq_t *ctq = vnet_dev_get_tx_queue_data (txq);
188   vnet_dev_t *dev = txq->port->dev;
189   oct_device_t *cd = vnet_dev_get_data (dev);
190   struct roc_nix *nix = cd->nix;
191   struct npa_aura_s aura = {};
192   struct npa_pool_s npapool = { .nat_align = 1 };
193   int rrv;
194   vlib_buffer_pool_t *bp = vlib_get_buffer_pool (vm, 0);
195
196   if ((rrv = roc_npa_pool_create (
197          &ctq->aura_handle, bp->alloc_size,
198          txq->size * 6 /* worst case - two SG with 3 segs each = 6 */, &aura,
199          &npapool, 0)))
200     {
201       oct_txq_deinit (vm, txq);
202       return oct_roc_err (dev, rrv, "roc_npa_pool_create() failed");
203     }
204
205   ctq->npa_pool_initialized = 1;
206   log_notice (dev, "NPA pool created, aura_handle = 0x%lx", ctq->aura_handle);
207
208   ctq->sq = (struct roc_nix_sq){
209     .nb_desc = txq->size,
210     .qid = txq->queue_id,
211     .max_sqe_sz = NIX_MAXSQESZ_W16,
212   };
213
214   if ((rrv = roc_nix_sq_init (nix, &ctq->sq)))
215     {
216       oct_txq_deinit (vm, txq);
217       return oct_roc_err (
218         dev, rrv,
219         "roc_nix_sq_init(qid = %u, nb_desc = %u, max_sqe_sz = %u) failed",
220         ctq->sq.nb_desc, ctq->sq.max_sqe_sz);
221     }
222
223   ctq->sq_initialized = 1;
224   log_debug (dev, "SQ initialised, qid %u, nb_desc %u, max_sqe_sz %u",
225              ctq->sq.qid, ctq->sq.nb_desc, ctq->sq.max_sqe_sz);
226
227   ctq->hdr_off = vm->buffer_main->ext_hdr_size;
228
229   if (ctq->sq.lmt_addr == 0)
230     ctq->sq.lmt_addr = (void *) nix->lmt_base;
231   ctq->io_addr = ctq->sq.io_addr & ~0x7fULL;
232   ctq->lmt_addr = ctq->sq.lmt_addr;
233
234   return VNET_DEV_OK;
235 }
236
237 void
238 oct_txq_deinit (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
239 {
240   oct_txq_t *ctq = vnet_dev_get_tx_queue_data (txq);
241   vnet_dev_t *dev = txq->port->dev;
242   int rrv;
243
244   if (ctq->sq_initialized)
245     {
246       rrv = roc_nix_sq_fini (&ctq->sq);
247       if (rrv)
248         oct_roc_err (dev, rrv, "roc_nix_sq_fini() failed");
249       ctq->sq_initialized = 0;
250     }
251
252   if (ctq->npa_pool_initialized)
253     {
254       rrv = roc_npa_pool_destroy (ctq->aura_handle);
255       if (rrv)
256         oct_roc_err (dev, rrv, "roc_npa_pool_destroy() failed");
257       ctq->npa_pool_initialized = 0;
258     }
259 }
260
261 u8 *
262 format_oct_rxq_info (u8 *s, va_list *args)
263 {
264   vnet_dev_format_args_t *a = va_arg (*args, vnet_dev_format_args_t *);
265   vnet_dev_rx_queue_t *rxq = va_arg (*args, vnet_dev_rx_queue_t *);
266   oct_rxq_t *crq = vnet_dev_get_rx_queue_data (rxq);
267   u32 indent = format_get_indent (s);
268
269   if (a->debug)
270     {
271       s = format (s, "n_enq %u cq_nb_desc %u", crq->n_enq, crq->cq.nb_desc);
272       s = format (s, "\n%Uaura: id 0x%x count %u limit %u avail %u",
273                   format_white_space, indent,
274                   roc_npa_aura_handle_to_aura (crq->aura_handle),
275                   roc_npa_aura_op_cnt_get (crq->aura_handle),
276                   roc_npa_aura_op_limit_get (crq->aura_handle),
277                   roc_npa_aura_op_available (crq->aura_handle));
278     }
279   return s;
280 }
281
282 u8 *
283 format_oct_txq_info (u8 *s, va_list *args)
284 {
285   vnet_dev_format_args_t *a = va_arg (*args, vnet_dev_format_args_t *);
286   vnet_dev_tx_queue_t *txq = va_arg (*args, vnet_dev_tx_queue_t *);
287   oct_txq_t *ctq = vnet_dev_get_tx_queue_data (txq);
288   u32 indent = format_get_indent (s);
289
290   if (a->debug)
291     {
292       s = format (s, "n_enq %u sq_nb_desc %u io_addr %p lmt_addr %p",
293                   ctq->n_enq, ctq->sq.nb_desc, ctq->io_addr, ctq->lmt_addr);
294       s = format (s, "\n%Uaura: id 0x%x count %u limit %u avail %u",
295                   format_white_space, indent,
296                   roc_npa_aura_handle_to_aura (ctq->aura_handle),
297                   roc_npa_aura_op_cnt_get (ctq->aura_handle),
298                   roc_npa_aura_op_limit_get (ctq->aura_handle),
299                   roc_npa_aura_op_available (ctq->aura_handle));
300     }
301
302   return s;
303 }