1 /* SPDX-License-Identifier: Apache-2.0
2 * Copyright (c) 2023 Cisco Systems, Inc.
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>
14 #include <base/roc_api.h>
17 struct roc_model oct_model;
19 VLIB_REGISTER_LOG_CLASS (oct_log, static) = {
20 .class_name = "octeon",
21 .subclass_name = "init",
24 #define _(f, n, s, d) \
25 { .name = #n, .desc = d, .severity = VL_COUNTER_SEVERITY_##s },
27 vlib_error_desc_t oct_tx_node_counters[] = { foreach_oct_tx_node_counter };
30 vnet_dev_node_t oct_rx_node = {
31 .format_trace = format_oct_rx_trace,
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),
43 oct_device_type_t type;
47 #define _(id, device_type, desc) \
49 .device_id = (id), .type = OCT_DEVICE_TYPE_##device_type, \
50 .description = (desc) \
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"),
62 oct_probe (vlib_main_t *vm, vnet_dev_bus_index_t bus_index, void *dev_info)
64 vnet_dev_bus_pci_device_info_t *di = dev_info;
66 if (di->vendor_id != 0x177d) /* Cavium */
69 FOREACH_ARRAY_ELT (dt, oct_dev_types)
71 if (dt->device_id == di->device_id)
72 return format (0, "%s", dt->description);
79 cnx_return_roc_err (vnet_dev_t *dev, int rrv, char *fmt, ...)
83 u8 *s = va_format (0, fmt, &va);
86 log_err (dev, "%v: %s [%d]", s, roc_error_msg_get (rrv), rrv);
89 return VNET_DEV_ERR_UNSUPPORTED_DEVICE;
93 oct_alloc (vlib_main_t *vm, vnet_dev_t *dev)
95 oct_device_t *cd = vnet_dev_get_data (dev);
97 clib_mem_alloc_aligned (sizeof (struct roc_nix), CLIB_CACHE_LINE_BYTES);
102 oct_init_nix (vlib_main_t *vm, vnet_dev_t *dev)
104 oct_device_t *cd = vnet_dev_get_data (dev);
107 oct_port_t oct_port = {};
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,
115 if ((rrv = roc_nix_dev_init (cd->nix)))
116 return cnx_return_roc_err (dev, rrv, "roc_nix_dev_init");
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");
121 vnet_dev_port_add_args_t port_add_args = {
124 .type = VNET_DEV_PORT_TYPE_ETHERNET,
127 .max_supported_rx_frame_size = roc_nix_max_pkt_len (cd->nix),
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,
146 .data_size = sizeof (oct_port_t),
147 .initial_data = &oct_port,
149 .rx_node = &oct_rx_node,
150 .tx_node = &oct_tx_node,
153 .data_size = sizeof (oct_rxq_t),
154 .default_size = 1024,
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,
168 .data_size = sizeof (oct_txq_t),
169 .default_size = 1024,
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,
183 vnet_dev_set_hw_addr_eth_mac (&port_add_args.port.attr.hw_addr, mac_addr);
185 log_info (dev, "MAC address is %U", format_ethernet_address, mac_addr);
187 return vnet_dev_port_add (vm, dev, 0, &port_add_args);
191 oct_init_cpt (vlib_main_t *vm, vnet_dev_t *dev)
193 oct_device_t *cd = vnet_dev_get_data (dev);
195 struct roc_cpt cpt = {
196 .pci_dev = &cd->plt_pci_dev,
199 if ((rrv = roc_cpt_dev_init (&cpt)))
200 return cnx_return_roc_err (dev, rrv, "roc_cpt_dev_init");
205 oct_init (vlib_main_t *vm, vnet_dev_t *dev)
207 oct_device_t *cd = vnet_dev_get_data (dev);
208 vlib_pci_config_hdr_t pci_hdr;
211 rv = vnet_dev_pci_read_config_header (vm, dev, &pci_hdr);
212 if (rv != VNET_DEV_OK)
215 if (pci_hdr.vendor_id != 0x177d)
216 return VNET_DEV_ERR_UNSUPPORTED_DEVICE;
218 FOREACH_ARRAY_ELT (dt, oct_dev_types)
220 if (dt->device_id == pci_hdr.device_id)
224 if (cd->type == OCT_DEVICE_TYPE_UNKNOWN)
227 rv = VNET_DEV_ERR_UNSUPPORTED_DEVICE;
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),
236 foreach_int (i, 2, 4)
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)
244 strncpy ((char *) cd->plt_pci_dev.name, dev->device_id,
245 sizeof (cd->plt_pci_dev.name) - 1);
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);
255 case OCT_DEVICE_TYPE_CPT_VF:
256 return oct_init_cpt (vm, dev);
259 return VNET_DEV_ERR_UNSUPPORTED_DEVICE;
266 oct_deinit (vlib_main_t *vm, vnet_dev_t *dev)
268 oct_device_t *cd = vnet_dev_get_data (dev);
270 if (cd->nix_initialized)
271 roc_nix_dev_fini (cd->nix);
275 oct_free (vlib_main_t *vm, vnet_dev_t *dev)
277 oct_device_t *cd = vnet_dev_get_data (dev);
279 if (cd->nix_initialized)
280 roc_nix_dev_fini (cd->nix);
283 VNET_DEV_REGISTER_DRIVER (octeon) = {
286 .device_data_sz = sizeof (oct_device_t),
290 .deinit = oct_deinit,
296 static clib_error_t *
297 oct_plugin_init (vlib_main_t *vm)
300 extern oct_plt_init_param_t oct_plt_init_param;
302 rv = oct_plt_init (&oct_plt_init_param);
304 return clib_error_return (0, "oct_plt_init failed");
306 rv = roc_model_init (&oct_model);
308 return clib_error_return (0, "roc_model_init failed");
312 VLIB_INIT_FUNCTION (oct_plugin_init);
314 VLIB_PLUGIN_REGISTER () = {
315 .version = VPP_BUILD_VER,
316 .description = "dev_octeon",