vcl: add api to retrieve num bytes for tx
[vpp.git] / src / plugins / dev_octeon / init.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 <vnet/ethernet/ethernet.h>
10 #include <vnet/plugin/plugin.h>
11 #include <vpp/app/version.h>
12 #include <dev_octeon/octeon.h>
13
14 #include <base/roc_api.h>
15 #include <common.h>
16
17 struct roc_model oct_model;
18
19 VLIB_REGISTER_LOG_CLASS (oct_log, static) = {
20   .class_name = "octeon",
21   .subclass_name = "init",
22 };
23
24 #define _(f, n, s, d)                                                         \
25   { .name = #n, .desc = d, .severity = VL_COUNTER_SEVERITY_##s },
26
27 vlib_error_desc_t oct_tx_node_counters[] = { foreach_oct_tx_node_counter };
28 #undef _
29
30 vnet_dev_node_t oct_rx_node = {
31   .format_trace = format_oct_rx_trace,
32 };
33
34 vnet_dev_node_t oct_tx_node = {
35   .format_trace = format_oct_tx_trace,
36   .error_counters = oct_tx_node_counters,
37   .n_error_counters = ARRAY_LEN (oct_tx_node_counters),
38 };
39
40 static struct
41 {
42   u16 device_id;
43   oct_device_type_t type;
44   char *description;
45 } oct_dev_types[] = {
46
47 #define _(id, device_type, desc)                                              \
48   {                                                                           \
49     .device_id = (id), .type = OCT_DEVICE_TYPE_##device_type,                 \
50     .description = (desc)                                                     \
51   }
52
53   _ (0xa063, RVU_PF, "Marvell Octeon Resource Virtualization Unit PF"),
54   _ (0xa0f8, RVU_VF, "Marvell Octeon Resource Virtualization Unit VF"),
55   _ (0xa0f3, CPT_VF, "Marvell Octeon Cryptographic Accelerator Unit VF"),
56 #undef _
57 };
58
59 static u8 *
60 oct_probe (vlib_main_t *vm, vnet_dev_bus_index_t bus_index, void *dev_info)
61 {
62   vnet_dev_bus_pci_device_info_t *di = dev_info;
63
64   if (di->vendor_id != 0x177d) /* Cavium */
65     return 0;
66
67   FOREACH_ARRAY_ELT (dt, oct_dev_types)
68     {
69       if (dt->device_id == di->device_id)
70         return format (0, "%s", dt->description);
71     }
72
73   return 0;
74 }
75
76 vnet_dev_rv_t
77 cnx_return_roc_err (vnet_dev_t *dev, int rrv, char *fmt, ...)
78 {
79   va_list va;
80   va_start (va, fmt);
81   u8 *s = va_format (0, fmt, &va);
82   va_end (va);
83
84   log_err (dev, "%v: %s [%d]", s, roc_error_msg_get (rrv), rrv);
85   vec_free (s);
86
87   return VNET_DEV_ERR_UNSUPPORTED_DEVICE;
88 }
89
90 static vnet_dev_rv_t
91 oct_alloc (vlib_main_t *vm, vnet_dev_t *dev)
92 {
93   oct_device_t *cd = vnet_dev_get_data (dev);
94   cd->nix =
95     clib_mem_alloc_aligned (sizeof (struct roc_nix), CLIB_CACHE_LINE_BYTES);
96   return VNET_DEV_OK;
97 }
98
99 static vnet_dev_rv_t
100 oct_init_nix (vlib_main_t *vm, vnet_dev_t *dev)
101 {
102   oct_device_t *cd = vnet_dev_get_data (dev);
103   u8 mac_addr[6];
104   int rrv;
105   oct_port_t oct_port = {};
106
107   *cd->nix = (struct roc_nix){
108     .reta_sz = ROC_NIX_RSS_RETA_SZ_256,
109     .max_sqb_count = 512,
110     .pci_dev = &cd->plt_pci_dev,
111   };
112
113   if ((rrv = roc_nix_dev_init (cd->nix)))
114     return cnx_return_roc_err (dev, rrv, "roc_nix_dev_init");
115
116   if (roc_nix_npc_mac_addr_get (cd->nix, mac_addr))
117     return cnx_return_roc_err (dev, rrv, "roc_nix_npc_mac_addr_get");
118
119   vnet_dev_port_add_args_t port_add_args = {
120     .port = {
121       .attr = {
122         .type = VNET_DEV_PORT_TYPE_ETHERNET,
123         .max_rx_queues = 64,
124         .max_tx_queues = 64,
125         .max_supported_rx_frame_size = roc_nix_max_pkt_len (cd->nix),
126         .caps = {
127           .rss = 1,
128         },
129         .rx_offloads = {
130           .ip4_cksum = 1,
131         },
132       },
133       .ops = {
134         .init = oct_port_init,
135         .deinit = oct_port_deinit,
136         .start = oct_port_start,
137         .stop = oct_port_stop,
138         .config_change = oct_port_cfg_change,
139         .config_change_validate = oct_port_cfg_change_validate,
140         .format_status = format_oct_port_status,
141         .format_flow = format_oct_port_flow,
142       },
143       .data_size = sizeof (oct_port_t),
144       .initial_data = &oct_port,
145     },
146     .rx_node = &oct_rx_node,
147     .tx_node = &oct_tx_node,
148     .rx_queue = {
149       .config = {
150         .data_size = sizeof (oct_rxq_t),
151         .default_size = 1024,
152         .multiplier = 32,
153         .min_size = 256,
154         .max_size = 16384,
155       },
156       .ops = {
157         .alloc = oct_rx_queue_alloc,
158         .free = oct_rx_queue_free,
159         .format_info = format_oct_rxq_info,
160       },
161     },
162     .tx_queue = {
163       .config = {
164         .data_size = sizeof (oct_txq_t),
165         .default_size = 1024,
166         .multiplier = 32,
167         .min_size = 256,
168         .max_size = 16384,
169       },
170       .ops = {
171         .alloc = oct_tx_queue_alloc,
172         .free = oct_tx_queue_free,
173         .format_info = format_oct_txq_info,
174       },
175     },
176   };
177
178   vnet_dev_set_hw_addr_eth_mac (&port_add_args.port.attr.hw_addr, mac_addr);
179
180   log_info (dev, "MAC address is %U", format_ethernet_address, mac_addr);
181
182   return vnet_dev_port_add (vm, dev, 0, &port_add_args);
183 }
184
185 static vnet_dev_rv_t
186 oct_init_cpt (vlib_main_t *vm, vnet_dev_t *dev)
187 {
188   oct_device_t *cd = vnet_dev_get_data (dev);
189   int rrv;
190   struct roc_cpt cpt = {
191     .pci_dev = &cd->plt_pci_dev,
192   };
193
194   if ((rrv = roc_cpt_dev_init (&cpt)))
195     return cnx_return_roc_err (dev, rrv, "roc_cpt_dev_init");
196   return VNET_DEV_OK;
197 }
198
199 static vnet_dev_rv_t
200 oct_init (vlib_main_t *vm, vnet_dev_t *dev)
201 {
202   oct_device_t *cd = vnet_dev_get_data (dev);
203   vlib_pci_config_hdr_t pci_hdr;
204   vnet_dev_rv_t rv;
205
206   rv = vnet_dev_pci_read_config_header (vm, dev, &pci_hdr);
207   if (rv != VNET_DEV_OK)
208     return rv;
209
210   if (pci_hdr.vendor_id != 0x177d)
211     return VNET_DEV_ERR_UNSUPPORTED_DEVICE;
212
213   FOREACH_ARRAY_ELT (dt, oct_dev_types)
214     {
215       if (dt->device_id == pci_hdr.device_id)
216         cd->type = dt->type;
217     }
218
219   if (cd->type == OCT_DEVICE_TYPE_UNKNOWN)
220     return rv;
221
222   rv = VNET_DEV_ERR_UNSUPPORTED_DEVICE;
223
224   cd->plt_pci_dev = (struct plt_pci_device){
225     .id.vendor_id = pci_hdr.vendor_id,
226     .id.device_id = pci_hdr.device_id,
227     .id.class_id = pci_hdr.class << 16 | pci_hdr.subclass,
228     .pci_handle = vnet_dev_get_pci_handle (dev),
229   };
230
231   foreach_int (i, 2, 4)
232     {
233       rv = vnet_dev_pci_map_region (vm, dev, i,
234                                     &cd->plt_pci_dev.mem_resource[i].addr);
235       if (rv != VNET_DEV_OK)
236         return rv;
237     }
238
239   strncpy ((char *) cd->plt_pci_dev.name, dev->device_id,
240            sizeof (cd->plt_pci_dev.name) - 1);
241
242   if (cd->type == OCT_DEVICE_TYPE_RVU_PF || cd->type == OCT_DEVICE_TYPE_RVU_VF)
243     return oct_init_nix (vm, dev);
244   else if (cd->type == OCT_DEVICE_TYPE_CPT_VF)
245     return oct_init_cpt (vm, dev);
246   else
247     return VNET_DEV_ERR_UNSUPPORTED_DEVICE;
248
249   return 0;
250 }
251
252 static void
253 oct_deinit (vlib_main_t *vm, vnet_dev_t *dev)
254 {
255   oct_device_t *cd = vnet_dev_get_data (dev);
256
257   if (cd->nix_initialized)
258     roc_nix_dev_fini (cd->nix);
259 }
260
261 static void
262 oct_free (vlib_main_t *vm, vnet_dev_t *dev)
263 {
264   oct_device_t *cd = vnet_dev_get_data (dev);
265
266   if (cd->nix_initialized)
267     roc_nix_dev_fini (cd->nix);
268 }
269
270 VNET_DEV_REGISTER_DRIVER (octeon) = {
271   .name = "octeon",
272   .bus = "pci",
273   .device_data_sz = sizeof (oct_device_t),
274   .ops = {
275     .alloc = oct_alloc,
276     .init = oct_init,
277     .deinit = oct_deinit,
278     .free = oct_free,
279     .probe = oct_probe,
280   },
281 };
282
283 static clib_error_t *
284 oct_plugin_init (vlib_main_t *vm)
285 {
286   int rv;
287   extern oct_plt_init_param_t oct_plt_init_param;
288
289   rv = oct_plt_init (&oct_plt_init_param);
290   if (rv)
291     return clib_error_return (0, "oct_plt_init failed");
292
293   rv = roc_model_init (&oct_model);
294   if (rv)
295     return clib_error_return (0, "roc_model_init failed");
296   return 0;
297 }
298
299 VLIB_INIT_FUNCTION (oct_plugin_init);
300
301 VLIB_PLUGIN_REGISTER () = {
302   .version = VPP_BUILD_VER,
303   .description = "dev_octeon",
304 };