Type: fix
Fixes: 01fe7ab
Change-Id: I46782c69773085f9e6a8dfff798bb42b1e822c32
Signed-off-by: Damjan Marion <damarion@cisco.com>
313 lines
7.4 KiB
C
313 lines
7.4 KiB
C
/* SPDX-License-Identifier: Apache-2.0
|
|
* Copyright (c) 2023 Cisco Systems, Inc.
|
|
*/
|
|
|
|
#include <vnet/vnet.h>
|
|
#include <vnet/dev/dev.h>
|
|
#include <vnet/dev/pci.h>
|
|
#include <vnet/dev/counters.h>
|
|
#include <vnet/ethernet/ethernet.h>
|
|
#include <vnet/plugin/plugin.h>
|
|
#include <vpp/app/version.h>
|
|
#include <dev_octeon/octeon.h>
|
|
|
|
#include <base/roc_api.h>
|
|
#include <common.h>
|
|
|
|
struct roc_model oct_model;
|
|
|
|
VLIB_REGISTER_LOG_CLASS (oct_log, static) = {
|
|
.class_name = "octeon",
|
|
.subclass_name = "init",
|
|
};
|
|
|
|
#define _(f, n, s, d) \
|
|
{ .name = #n, .desc = d, .severity = VL_COUNTER_SEVERITY_##s },
|
|
|
|
vlib_error_desc_t oct_tx_node_counters[] = { foreach_oct_tx_node_counter };
|
|
#undef _
|
|
|
|
vnet_dev_node_t oct_rx_node = {
|
|
.format_trace = format_oct_rx_trace,
|
|
};
|
|
|
|
vnet_dev_node_t oct_tx_node = {
|
|
.format_trace = format_oct_tx_trace,
|
|
.error_counters = oct_tx_node_counters,
|
|
.n_error_counters = ARRAY_LEN (oct_tx_node_counters),
|
|
};
|
|
|
|
static struct
|
|
{
|
|
u16 device_id;
|
|
oct_device_type_t type;
|
|
char *description;
|
|
} oct_dev_types[] = {
|
|
|
|
#define _(id, device_type, desc) \
|
|
{ \
|
|
.device_id = (id), .type = OCT_DEVICE_TYPE_##device_type, \
|
|
.description = (desc) \
|
|
}
|
|
|
|
_ (0xa063, RVU_PF, "Marvell Octeon Resource Virtualization Unit PF"),
|
|
_ (0xa0f8, RVU_VF, "Marvell Octeon Resource Virtualization Unit VF"),
|
|
_ (0xa0f7, SDP_VF, "Marvell Octeon System DPI Packet Interface Unit VF"),
|
|
_ (0xa0f3, CPT_VF, "Marvell Octeon Cryptographic Accelerator Unit VF"),
|
|
#undef _
|
|
};
|
|
|
|
static u8 *
|
|
oct_probe (vlib_main_t *vm, vnet_dev_bus_index_t bus_index, void *dev_info)
|
|
{
|
|
vnet_dev_bus_pci_device_info_t *di = dev_info;
|
|
|
|
if (di->vendor_id != 0x177d) /* Cavium */
|
|
return 0;
|
|
|
|
FOREACH_ARRAY_ELT (dt, oct_dev_types)
|
|
{
|
|
if (dt->device_id == di->device_id)
|
|
return format (0, "%s", dt->description);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
vnet_dev_rv_t
|
|
cnx_return_roc_err (vnet_dev_t *dev, int rrv, char *fmt, ...)
|
|
{
|
|
va_list va;
|
|
va_start (va, fmt);
|
|
u8 *s = va_format (0, fmt, &va);
|
|
va_end (va);
|
|
|
|
log_err (dev, "%v: %s [%d]", s, roc_error_msg_get (rrv), rrv);
|
|
vec_free (s);
|
|
|
|
return VNET_DEV_ERR_UNSUPPORTED_DEVICE;
|
|
}
|
|
|
|
static vnet_dev_rv_t
|
|
oct_alloc (vlib_main_t *vm, vnet_dev_t *dev)
|
|
{
|
|
oct_device_t *cd = vnet_dev_get_data (dev);
|
|
cd->nix =
|
|
clib_mem_alloc_aligned (sizeof (struct roc_nix), CLIB_CACHE_LINE_BYTES);
|
|
return VNET_DEV_OK;
|
|
}
|
|
|
|
static vnet_dev_rv_t
|
|
oct_init_nix (vlib_main_t *vm, vnet_dev_t *dev)
|
|
{
|
|
oct_device_t *cd = vnet_dev_get_data (dev);
|
|
u8 mac_addr[6];
|
|
int rrv;
|
|
oct_port_t oct_port = {};
|
|
|
|
*cd->nix = (struct roc_nix){
|
|
.reta_sz = ROC_NIX_RSS_RETA_SZ_256,
|
|
.max_sqb_count = 512,
|
|
.pci_dev = &cd->plt_pci_dev,
|
|
};
|
|
|
|
if ((rrv = roc_nix_dev_init (cd->nix)))
|
|
return cnx_return_roc_err (dev, rrv, "roc_nix_dev_init");
|
|
|
|
if ((rrv = roc_nix_npc_mac_addr_get (cd->nix, mac_addr)))
|
|
return cnx_return_roc_err (dev, rrv, "roc_nix_npc_mac_addr_get");
|
|
|
|
vnet_dev_port_add_args_t port_add_args = {
|
|
.port = {
|
|
.attr = {
|
|
.type = VNET_DEV_PORT_TYPE_ETHERNET,
|
|
.max_rx_queues = 64,
|
|
.max_tx_queues = 64,
|
|
.max_supported_rx_frame_size = roc_nix_max_pkt_len (cd->nix),
|
|
.caps = {
|
|
.rss = 1,
|
|
},
|
|
.rx_offloads = {
|
|
.ip4_cksum = 1,
|
|
},
|
|
},
|
|
.ops = {
|
|
.init = oct_port_init,
|
|
.deinit = oct_port_deinit,
|
|
.start = oct_port_start,
|
|
.stop = oct_port_stop,
|
|
.config_change = oct_port_cfg_change,
|
|
.config_change_validate = oct_port_cfg_change_validate,
|
|
.format_status = format_oct_port_status,
|
|
.format_flow = format_oct_port_flow,
|
|
},
|
|
.data_size = sizeof (oct_port_t),
|
|
.initial_data = &oct_port,
|
|
},
|
|
.rx_node = &oct_rx_node,
|
|
.tx_node = &oct_tx_node,
|
|
.rx_queue = {
|
|
.config = {
|
|
.data_size = sizeof (oct_rxq_t),
|
|
.default_size = 1024,
|
|
.multiplier = 32,
|
|
.min_size = 256,
|
|
.max_size = 16384,
|
|
},
|
|
.ops = {
|
|
.alloc = oct_rx_queue_alloc,
|
|
.free = oct_rx_queue_free,
|
|
.format_info = format_oct_rxq_info,
|
|
},
|
|
},
|
|
.tx_queue = {
|
|
.config = {
|
|
.data_size = sizeof (oct_txq_t),
|
|
.default_size = 1024,
|
|
.multiplier = 32,
|
|
.min_size = 256,
|
|
.max_size = 16384,
|
|
},
|
|
.ops = {
|
|
.alloc = oct_tx_queue_alloc,
|
|
.free = oct_tx_queue_free,
|
|
.format_info = format_oct_txq_info,
|
|
},
|
|
},
|
|
};
|
|
|
|
vnet_dev_set_hw_addr_eth_mac (&port_add_args.port.attr.hw_addr, mac_addr);
|
|
|
|
log_info (dev, "MAC address is %U", format_ethernet_address, mac_addr);
|
|
|
|
return vnet_dev_port_add (vm, dev, 0, &port_add_args);
|
|
}
|
|
|
|
static vnet_dev_rv_t
|
|
oct_init_cpt (vlib_main_t *vm, vnet_dev_t *dev)
|
|
{
|
|
oct_device_t *cd = vnet_dev_get_data (dev);
|
|
int rrv;
|
|
struct roc_cpt cpt = {
|
|
.pci_dev = &cd->plt_pci_dev,
|
|
};
|
|
|
|
if ((rrv = roc_cpt_dev_init (&cpt)))
|
|
return cnx_return_roc_err (dev, rrv, "roc_cpt_dev_init");
|
|
return VNET_DEV_OK;
|
|
}
|
|
|
|
static vnet_dev_rv_t
|
|
oct_init (vlib_main_t *vm, vnet_dev_t *dev)
|
|
{
|
|
oct_device_t *cd = vnet_dev_get_data (dev);
|
|
vlib_pci_config_hdr_t pci_hdr;
|
|
vnet_dev_rv_t rv;
|
|
|
|
rv = vnet_dev_pci_read_config_header (vm, dev, &pci_hdr);
|
|
if (rv != VNET_DEV_OK)
|
|
return rv;
|
|
|
|
if (pci_hdr.vendor_id != 0x177d)
|
|
return VNET_DEV_ERR_UNSUPPORTED_DEVICE;
|
|
|
|
FOREACH_ARRAY_ELT (dt, oct_dev_types)
|
|
{
|
|
if (dt->device_id == pci_hdr.device_id)
|
|
cd->type = dt->type;
|
|
}
|
|
|
|
if (cd->type == OCT_DEVICE_TYPE_UNKNOWN)
|
|
return rv;
|
|
|
|
rv = VNET_DEV_ERR_UNSUPPORTED_DEVICE;
|
|
|
|
cd->plt_pci_dev = (struct plt_pci_device){
|
|
.id.vendor_id = pci_hdr.vendor_id,
|
|
.id.device_id = pci_hdr.device_id,
|
|
.id.class_id = pci_hdr.class << 16 | pci_hdr.subclass,
|
|
.pci_handle = vnet_dev_get_pci_handle (dev),
|
|
};
|
|
|
|
foreach_int (i, 2, 4)
|
|
{
|
|
rv = vnet_dev_pci_map_region (vm, dev, i,
|
|
&cd->plt_pci_dev.mem_resource[i].addr);
|
|
if (rv != VNET_DEV_OK)
|
|
return rv;
|
|
}
|
|
|
|
strncpy ((char *) cd->plt_pci_dev.name, dev->device_id,
|
|
sizeof (cd->plt_pci_dev.name) - 1);
|
|
|
|
switch (cd->type)
|
|
{
|
|
case OCT_DEVICE_TYPE_RVU_PF:
|
|
case OCT_DEVICE_TYPE_RVU_VF:
|
|
case OCT_DEVICE_TYPE_SDP_VF:
|
|
return oct_init_nix (vm, dev);
|
|
|
|
case OCT_DEVICE_TYPE_CPT_VF:
|
|
return oct_init_cpt (vm, dev);
|
|
|
|
default:
|
|
return VNET_DEV_ERR_UNSUPPORTED_DEVICE;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
oct_deinit (vlib_main_t *vm, vnet_dev_t *dev)
|
|
{
|
|
oct_device_t *cd = vnet_dev_get_data (dev);
|
|
|
|
if (cd->nix_initialized)
|
|
roc_nix_dev_fini (cd->nix);
|
|
}
|
|
|
|
static void
|
|
oct_free (vlib_main_t *vm, vnet_dev_t *dev)
|
|
{
|
|
oct_device_t *cd = vnet_dev_get_data (dev);
|
|
|
|
if (cd->nix_initialized)
|
|
roc_nix_dev_fini (cd->nix);
|
|
}
|
|
|
|
VNET_DEV_REGISTER_DRIVER (octeon) = {
|
|
.name = "octeon",
|
|
.bus = "pci",
|
|
.device_data_sz = sizeof (oct_device_t),
|
|
.ops = {
|
|
.alloc = oct_alloc,
|
|
.init = oct_init,
|
|
.deinit = oct_deinit,
|
|
.free = oct_free,
|
|
.probe = oct_probe,
|
|
},
|
|
};
|
|
|
|
static clib_error_t *
|
|
oct_plugin_init (vlib_main_t *vm)
|
|
{
|
|
int rv;
|
|
extern oct_plt_init_param_t oct_plt_init_param;
|
|
|
|
rv = oct_plt_init (&oct_plt_init_param);
|
|
if (rv)
|
|
return clib_error_return (0, "oct_plt_init failed");
|
|
|
|
rv = roc_model_init (&oct_model);
|
|
if (rv)
|
|
return clib_error_return (0, "roc_model_init failed");
|
|
return 0;
|
|
}
|
|
|
|
VLIB_INIT_FUNCTION (oct_plugin_init);
|
|
|
|
VLIB_PLUGIN_REGISTER () = {
|
|
.version = VPP_BUILD_VER,
|
|
.description = "dev_octeon",
|
|
};
|