ip6: fix ip6-michain trace function
[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   _ (0xa064, RVU_VF, "Marvell Octeon Resource Virtualization Unit VF"),
55   _ (0xa0f8, LBK_VF, "Marvell Octeon Loopback Unit VF"),
56   _ (0xa0f7, SDP_VF, "Marvell Octeon System DPI Packet Interface Unit VF"),
57   _ (0xa0f3, CPT_VF, "Marvell Octeon Cryptographic Accelerator Unit VF"),
58 #undef _
59 };
60
61 static u8 *
62 oct_probe (vlib_main_t *vm, vnet_dev_bus_index_t bus_index, void *dev_info)
63 {
64   vnet_dev_bus_pci_device_info_t *di = dev_info;
65
66   if (di->vendor_id != 0x177d) /* Cavium */
67     return 0;
68
69   FOREACH_ARRAY_ELT (dt, oct_dev_types)
70     {
71       if (dt->device_id == di->device_id)
72         return format (0, "%s", dt->description);
73     }
74
75   return 0;
76 }
77
78 vnet_dev_rv_t
79 cnx_return_roc_err (vnet_dev_t *dev, int rrv, char *fmt, ...)
80 {
81   va_list va;
82   va_start (va, fmt);
83   u8 *s = va_format (0, fmt, &va);
84   va_end (va);
85
86   log_err (dev, "%v: %s [%d]", s, roc_error_msg_get (rrv), rrv);
87   vec_free (s);
88
89   return VNET_DEV_ERR_UNSUPPORTED_DEVICE;
90 }
91
92 static vnet_dev_rv_t
93 oct_alloc (vlib_main_t *vm, vnet_dev_t *dev)
94 {
95   oct_device_t *cd = vnet_dev_get_data (dev);
96   cd->nix =
97     clib_mem_alloc_aligned (sizeof (struct roc_nix), CLIB_CACHE_LINE_BYTES);
98   return VNET_DEV_OK;
99 }
100
101 static vnet_dev_rv_t
102 oct_init_nix (vlib_main_t *vm, vnet_dev_t *dev)
103 {
104   oct_device_t *cd = vnet_dev_get_data (dev);
105   u8 mac_addr[6];
106   int rrv;
107   oct_port_t oct_port = {};
108
109   *cd->nix = (struct roc_nix){
110     .reta_sz = ROC_NIX_RSS_RETA_SZ_256,
111     .max_sqb_count = 512,
112     .pci_dev = &cd->plt_pci_dev,
113   };
114
115   if ((rrv = roc_nix_dev_init (cd->nix)))
116     return cnx_return_roc_err (dev, rrv, "roc_nix_dev_init");
117
118   if ((rrv = roc_nix_npc_mac_addr_get (cd->nix, mac_addr)))
119     return cnx_return_roc_err (dev, rrv, "roc_nix_npc_mac_addr_get");
120
121   vnet_dev_port_add_args_t port_add_args = {
122     .port = {
123       .attr = {
124         .type = VNET_DEV_PORT_TYPE_ETHERNET,
125         .max_rx_queues = 64,
126         .max_tx_queues = 64,
127         .max_supported_rx_frame_size = roc_nix_max_pkt_len (cd->nix),
128         .caps = {
129           .rss = 1,
130         },
131         .rx_offloads = {
132           .ip4_cksum = 1,
133         },
134       },
135       .ops = {
136         .init = oct_port_init,
137         .deinit = oct_port_deinit,
138         .start = oct_port_start,
139         .stop = oct_port_stop,
140         .config_change = oct_port_cfg_change,
141         .config_change_validate = oct_port_cfg_change_validate,
142         .format_status = format_oct_port_status,
143         .format_flow = format_oct_port_flow,
144         .clear_counters = oct_port_clear_counters,
145       },
146       .data_size = sizeof (oct_port_t),
147       .initial_data = &oct_port,
148     },
149     .rx_node = &oct_rx_node,
150     .tx_node = &oct_tx_node,
151     .rx_queue = {
152       .config = {
153         .data_size = sizeof (oct_rxq_t),
154         .default_size = 1024,
155         .multiplier = 32,
156         .min_size = 256,
157         .max_size = 16384,
158       },
159       .ops = {
160         .alloc = oct_rx_queue_alloc,
161         .free = oct_rx_queue_free,
162         .format_info = format_oct_rxq_info,
163         .clear_counters = oct_rxq_clear_counters,
164       },
165     },
166     .tx_queue = {
167       .config = {
168         .data_size = sizeof (oct_txq_t),
169         .default_size = 1024,
170         .multiplier = 32,
171         .min_size = 256,
172         .max_size = 16384,
173       },
174       .ops = {
175         .alloc = oct_tx_queue_alloc,
176         .free = oct_tx_queue_free,
177         .format_info = format_oct_txq_info,
178         .clear_counters = oct_txq_clear_counters,
179       },
180     },
181   };
182
183   vnet_dev_set_hw_addr_eth_mac (&port_add_args.port.attr.hw_addr, mac_addr);
184
185   log_info (dev, "MAC address is %U", format_ethernet_address, mac_addr);
186
187   return vnet_dev_port_add (vm, dev, 0, &port_add_args);
188 }
189
190 static vnet_dev_rv_t
191 oct_init_cpt (vlib_main_t *vm, vnet_dev_t *dev)
192 {
193   oct_device_t *cd = vnet_dev_get_data (dev);
194   int rrv;
195   struct roc_cpt cpt = {
196     .pci_dev = &cd->plt_pci_dev,
197   };
198
199   if ((rrv = roc_cpt_dev_init (&cpt)))
200     return cnx_return_roc_err (dev, rrv, "roc_cpt_dev_init");
201   return VNET_DEV_OK;
202 }
203
204 static vnet_dev_rv_t
205 oct_init (vlib_main_t *vm, vnet_dev_t *dev)
206 {
207   oct_device_t *cd = vnet_dev_get_data (dev);
208   vlib_pci_config_hdr_t pci_hdr;
209   vnet_dev_rv_t rv;
210
211   rv = vnet_dev_pci_read_config_header (vm, dev, &pci_hdr);
212   if (rv != VNET_DEV_OK)
213     return rv;
214
215   if (pci_hdr.vendor_id != 0x177d)
216     return VNET_DEV_ERR_UNSUPPORTED_DEVICE;
217
218   FOREACH_ARRAY_ELT (dt, oct_dev_types)
219     {
220       if (dt->device_id == pci_hdr.device_id)
221         cd->type = dt->type;
222     }
223
224   if (cd->type == OCT_DEVICE_TYPE_UNKNOWN)
225     return rv;
226
227   rv = VNET_DEV_ERR_UNSUPPORTED_DEVICE;
228
229   cd->plt_pci_dev = (struct plt_pci_device){
230     .id.vendor_id = pci_hdr.vendor_id,
231     .id.device_id = pci_hdr.device_id,
232     .id.class_id = pci_hdr.class << 16 | pci_hdr.subclass,
233     .pci_handle = vnet_dev_get_pci_handle (dev),
234   };
235
236   foreach_int (i, 2, 4)
237     {
238       rv = vnet_dev_pci_map_region (vm, dev, i,
239                                     &cd->plt_pci_dev.mem_resource[i].addr);
240       if (rv != VNET_DEV_OK)
241         return rv;
242     }
243
244   strncpy ((char *) cd->plt_pci_dev.name, dev->device_id,
245            sizeof (cd->plt_pci_dev.name) - 1);
246
247   switch (cd->type)
248     {
249     case OCT_DEVICE_TYPE_RVU_PF:
250     case OCT_DEVICE_TYPE_RVU_VF:
251     case OCT_DEVICE_TYPE_LBK_VF:
252     case OCT_DEVICE_TYPE_SDP_VF:
253       return oct_init_nix (vm, dev);
254
255     case OCT_DEVICE_TYPE_CPT_VF:
256       return oct_init_cpt (vm, dev);
257
258     default:
259       return VNET_DEV_ERR_UNSUPPORTED_DEVICE;
260     }
261
262   return 0;
263 }
264
265 static void
266 oct_deinit (vlib_main_t *vm, vnet_dev_t *dev)
267 {
268   oct_device_t *cd = vnet_dev_get_data (dev);
269
270   if (cd->nix_initialized)
271     roc_nix_dev_fini (cd->nix);
272 }
273
274 static void
275 oct_free (vlib_main_t *vm, vnet_dev_t *dev)
276 {
277   oct_device_t *cd = vnet_dev_get_data (dev);
278
279   if (cd->nix_initialized)
280     roc_nix_dev_fini (cd->nix);
281 }
282
283 VNET_DEV_REGISTER_DRIVER (octeon) = {
284   .name = "octeon",
285   .bus = "pci",
286   .device_data_sz = sizeof (oct_device_t),
287   .ops = {
288     .alloc = oct_alloc,
289     .init = oct_init,
290     .deinit = oct_deinit,
291     .free = oct_free,
292     .probe = oct_probe,
293   },
294 };
295
296 static clib_error_t *
297 oct_plugin_init (vlib_main_t *vm)
298 {
299   int rv;
300   extern oct_plt_init_param_t oct_plt_init_param;
301
302   rv = oct_plt_init (&oct_plt_init_param);
303   if (rv)
304     return clib_error_return (0, "oct_plt_init failed");
305
306   rv = roc_model_init (&oct_model);
307   if (rv)
308     return clib_error_return (0, "roc_model_init failed");
309   return 0;
310 }
311
312 VLIB_INIT_FUNCTION (oct_plugin_init);
313
314 VLIB_PLUGIN_REGISTER () = {
315   .version = VPP_BUILD_VER,
316   .description = "dev_octeon",
317 };