/*
* Copyright (c) 2015 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long *//* SPDX-License-Identifier: Apache-2.0
* Copyright (c) 2023 Cisco Systems, Inc.
*/
#include <vnet/vnet.h>
#include <vnet/dev/dev.h>
#include <vnet/dev/bus/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 <dev_octeon/crypto.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"),
_ (0xa064, RVU_VF, "Marvell Octeon Resource Virtualization Unit VF"),
_ (0xa0f8, LBK_VF, "Marvell Octeon Loopback Unit VF"),
_ (0xa0f7, SDP_VF, "Marvell Octeon System DPI Packet Interface Unit VF"),
_ (0xa0f3, O10K_CPT_VF,
"Marvell Octeon-10 Cryptographic Accelerator Unit VF"),
_ (0xa0fe, O9K_CPT_VF, "Marvell Octeon-9 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,
.hw_vlan_ins = true,
};
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,
},
.tx_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,
.clear_counters = oct_port_clear_counters,
},
.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,
.clear_counters = oct_rxq_clear_counters,
},
},
.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,
.clear_counters = oct_txq_clear_counters,
},
},
};
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 int
oct_conf_cpt (vlib_main_t *vm, vnet_dev_t *dev, oct_crypto_dev_t *ocd,
int nb_lf)
{
struct roc_cpt *roc_cpt = ocd->roc_cpt;
int rrv;
if ((rrv = roc_cpt_eng_grp_add (roc_cpt, CPT_ENG_TYPE_SE)) < 0)
{
log_err (dev, "Could not add CPT SE engines");
return cnx_return_roc_err (dev, rrv, "roc_cpt_eng_grp_add");
}
if ((rrv = roc_cpt_eng_grp_add (roc_cpt, CPT_ENG_TYPE_IE)) < 0)
{
log_err (dev, "Could not add CPT IE engines");
return cnx_return_roc_err (dev, rrv, "roc_cpt_eng_grp_add");
}
if (roc_cpt->eng_grp[CPT_ENG_TYPE_IE] != ROC_CPT_DFLT_ENG_GRP_SE_IE)
{
log_err (dev, "Invalid CPT IE engine group configuration");
return -1;
}
if (roc_cpt->eng_grp[CPT_ENG_TYPE_SE] != ROC_CPT_DFLT_ENG_GRP_SE)
{
log_err (dev, "Invalid CPT SE engine group configuration");
return -1;
}
if ((rrv = roc_cpt_dev_configure (roc_cpt, nb_lf, false, 0)) < 0)
{
log_err (dev, "could not configure crypto device %U",
format_vlib_pci_addr, roc_cpt->pci_dev->addr);
return cnx_return_roc_err (dev, rrv, "roc_cpt_dev_configure");
}
return 0;
}
static vnet_dev_rv_t
oct_conf_cpt_queue (vlib_main_t *vm, vnet_dev_t *dev, oct_crypto_dev_t *ocd)
{
struct roc_cpt *roc_cpt = ocd->roc_cpt;
struct roc_cpt_lmtline *cpt_lmtline;
struct roc_cpt_lf *cpt_lf;
int rrv;
cpt_lf = &ocd->lf;
cpt_lmtline = &ocd->lmtline;
cpt_lf->nb_desc = OCT_CPT_LF_MAX_NB_DESC;
cpt_lf->lf_id = 0;
if ((rrv = roc_cpt_lf_init (roc_cpt, cpt_lf)) < 0)
return cnx_return_roc_err (dev, rrv, "roc_cpt_lf_init");
roc_cpt_iq_enable (cpt_lf);
if ((rrv = roc_cpt_lmtline_init (roc_cpt, cpt_lmtline, 0) < 0))
return cnx_return_roc_err (dev, rrv, "roc_cpt_lmtline_init");
return 0;
}
static vnet_dev_rv_t
oct_init_cpt (vlib_main_t *vm, vnet_dev_t *dev)
{
oct_crypto_main_t *ocm = &oct_crypto_main;
extern oct_plt_init_param_t oct_plt_init_param;
oct_device_t *cd = vnet_dev_get_data (dev);
oct_crypto_dev_t *ocd = NULL;
int rrv;
if (ocm->n_cpt == OCT_MAX_N_CPT_DEV || ocm->started)
return VNET_DEV_ERR_NOT_SUPPORTED;
ocd = oct_plt_init_param.oct_plt_zmalloc (sizeof (oct_crypto_dev_t),
CLIB_CACHE_LINE_BYTES);
ocd->roc_cpt = oct_plt_init_param.oct_plt_zmalloc (sizeof (struct roc_cpt),
CLIB_CACHE_LINE_BYTES);
ocd->roc_cpt->pci_dev = &cd->plt_pci_dev;
ocd->dev = dev;
if ((rrv = roc_cpt_dev_init (ocd->roc_cpt)))
return cnx_return_roc_err (dev, rrv, "roc_cpt_dev_init");
if ((rrv = oct_conf_cpt (vm, dev, ocd, 1)))
return rrv;
if ((rrv = oct_conf_cpt_queue (vm, dev, ocd)))
return rrv;
if (!ocm->n_cpt)
{
/*
* Initialize s/w queues, which are common across multiple
* crypto devices
*/
oct_conf_sw_queue (vm, dev);
ocm->crypto_dev[0] = ocd;
}
ocm->crypto_dev[1] = ocd;
oct_init_crypto_engine_handlers (vm, dev);
ocm->n_cpt++;
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_LBK_VF:
case OCT_DEVICE_TYPE_SDP_VF:
return oct_init_nix (vm, dev);
case OCT_DEVICE_TYPE_O10K_CPT_VF:
case OCT_DEVICE_TYPE_O9K_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",
};