diff options
author | Damjan Marion <damarion@cisco.com> | 2024-08-27 18:12:33 +0200 |
---|---|---|
committer | Mohammed HAWARI <momohawari@gmail.com> | 2024-09-09 14:43:22 +0000 |
commit | 4e518418964d0597df8a9b1f34b01d2f9500b47b (patch) | |
tree | d2b904b3721f753cc435af0ecd18cf5460dbc72c | |
parent | 1f7d14c810900c476b7f32781414a2e903a90e07 (diff) |
armada: introduce dev_armada plugin
Also retires old marvell plugin.
Change-Id: Icedec11f5661909058fdfe8d5fc455306adafacd
Type: feature
Signed-off-by: Damjan Marion <damarion@cisco.com>
27 files changed, 1364 insertions, 1813 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 4a65b35bce2..c6dbd8bc903 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -500,10 +500,10 @@ I: memif M: Damjan Marion <damarion@cisco.com> F: src/plugins/memif/ -Plugin - Marvell MUSDK device driver -I: marvell +Plugin - Marvell Armada device driver +I: armada M: Damjan Marion <damarion@cisco.com> -F: src/plugins/marvell/ +F: src/plugins/dev_armada/ Plugin - performance counter I: perfmon diff --git a/docs/developer/plugins/dev_armada.rst b/docs/developer/plugins/dev_armada.rst new file mode 120000 index 00000000000..a545313ec9c --- /dev/null +++ b/docs/developer/plugins/dev_armada.rst @@ -0,0 +1 @@ +../../../src/plugins/dev_armada/README.rst
\ No newline at end of file diff --git a/docs/developer/plugins/index.rst b/docs/developer/plugins/index.rst index c9081a8caaf..393eefec535 100644 --- a/docs/developer/plugins/index.rst +++ b/docs/developer/plugins/index.rst @@ -19,9 +19,9 @@ For more on plugins please refer to :ref:`add_plugin`. quic cnat + dev_armada lcp srv6/index - marvell lldp nat64 nat44_ei_ha diff --git a/docs/developer/plugins/marvell.rst b/docs/developer/plugins/marvell.rst deleted file mode 120000 index 28f0cd0f664..00000000000 --- a/docs/developer/plugins/marvell.rst +++ /dev/null @@ -1 +0,0 @@ -../../../src/plugins/marvell/README.rst
\ No newline at end of file diff --git a/src/plugins/dev_armada/CMakeLists.txt b/src/plugins/dev_armada/CMakeLists.txt new file mode 100644 index 00000000000..f955a9baa91 --- /dev/null +++ b/src/plugins/dev_armada/CMakeLists.txt @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright(c) 2022 Cisco Systems, Inc. + + +find_path(MUSDK_INCLUDE_DIR NAMES mv_std.h) +find_library(MUSDK_LIB NAMES libmusdk.a) + +if(NOT MUSDK_INCLUDE_DIR OR NOT MUSDK_LIB) + message(WARNING "Marvell MUSDK not found - dev_armada plugin disabled") + return() +endif() + +get_filename_component(MUSDK_LIB_DIR ${MUSDK_LIB} DIRECTORY) +set(MUSDK_LINK_FLAGS "-Wl,--whole-archive,${MUSDK_LIB_DIR}/libmusdk.a,--no-whole-archive") + +add_vpp_plugin(dev_armada + SOURCES + plugin.c + pp2/init.c + pp2/format.c + pp2/port.c + pp2/queue.c + pp2/rx.c + pp2/tx.c + + LINK_FLAGS + ${MUSDK_LINK_FLAGS} +) +include_directories(${MUSDK_INCLUDE_DIR}) + diff --git a/src/plugins/dev_armada/README.rst b/src/plugins/dev_armada/README.rst new file mode 100644 index 00000000000..2c757d04a06 --- /dev/null +++ b/src/plugins/dev_armada/README.rst @@ -0,0 +1,61 @@ +Armada device plugin +===================== + +Overview +-------- + +This plugins provides native device support for Marvell PP2 network +device, found in Marvel Armada family of SOCs. +It uses Marvell Usermode SDK +(`MUSDK <https://github.com/MarvellEmbeddedProcessors/musdk-marvell>`__). + +Prerequisites +------------- + +Plugins depends on installed MUSDK and Marvell provided linux in Marvell SDK. +Following kernel modules from MUSDK must be loaded for plugin to work: +``musdk_cma.ko`` +``mv_pp_uio.ko`` + +Musdk 18.09.3 compilation steps +------------------------------- + +:: + + ./bootstrap + ./configure --prefix=/opt/vpp/external/aarch64/ CFLAGS="-Wno-error=unused-result -g -fPIC" --enable-shared=no + sed -i -e 's/marvell,mv-pp-uio/generic-uio/' modules/pp2/mv_pp_uio.c + sed -i -e 's/O_CREAT/O_CREAT, S_IRUSR | S_IWUSR/' src/lib/file_utils.c + make + sudo make install + +Usage +----- + +Interface Creation and Deletion +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Interfaces are using new vnet dev APIs, CLIs or startup.conf to create and +delete interfaces. + +Sample startup.conf: + +:: + + devices { + dev platform/f2000000.ethernet { + port 1 { name ppio1 } + } + +Device identifier in this example is 'platform/f2000000.ethernet' where +'platform' is bus name and 'f2000000.ethernet' is linux platform bus +identifier for specific PP2. + +Platform identifier can be found in sysfs: + +:: + + $ ls /sys/bus/platform/devices | grep ethernet + f2000000.ethernet + + diff --git a/src/plugins/dev_armada/musdk.h b/src/plugins/dev_armada/musdk.h new file mode 100644 index 00000000000..aad2f4a1cef --- /dev/null +++ b/src/plugins/dev_armada/musdk.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2023 Cisco Systems, Inc. + */ + +#ifndef _MUSDK_H_ +#define _MUSDK_H_ + +#define MVCONF_DBG_LEVEL 0 +#define MVCONF_PP2_BPOOL_COOKIE_SIZE 32 +#define MVCONF_PP2_BPOOL_DMA_ADDR_SIZE 64 +#define MVCONF_DMA_PHYS_ADDR_T_SIZE 64 +#define MVCONF_SYS_DMA_UIO +#define MVCONF_TYPES_PUBLIC +#define MVCONF_DMA_PHYS_ADDR_T_PUBLIC + +#include <mv_std.h> +#include <env/mv_sys_dma.h> +#include <drivers/mv_pp2.h> +#include <drivers/mv_pp2_bpool.h> +#include <drivers/mv_pp2_ppio.h> + +#endif /* _MUSDK_H_ */ diff --git a/src/plugins/dev_armada/plugin.c b/src/plugins/dev_armada/plugin.c new file mode 100644 index 00000000000..1dc465c9a25 --- /dev/null +++ b/src/plugins/dev_armada/plugin.c @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2023 Cisco Systems, Inc. + */ + +#include <vlib/vlib.h> +#include <vnet/plugin/plugin.h> +#include <vpp/app/version.h> + +VLIB_PLUGIN_REGISTER () = { + .version = VPP_BUILD_VER, + .description = "Marvell Armada Drivers", +}; diff --git a/src/plugins/dev_armada/pp2/format.c b/src/plugins/dev_armada/pp2/format.c new file mode 100644 index 00000000000..37d482b5ce8 --- /dev/null +++ b/src/plugins/dev_armada/pp2/format.c @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2023 Cisco Systems, Inc. + */ + +#include <vnet/vnet.h> +#include <vnet/dev/dev.h> +#include <vnet/dev/counters.h> +#include <vnet/dev/bus/platform.h> +#include <dev_armada/musdk.h> +#include <dev_armada/pp2/pp2.h> + +static inline u32 +mrvl_get_u32_bits (void *start, int offset, int first, int last) +{ + u32 value = *(u32 *) (((u8 *) start) + offset); + if ((last == 0) && (first == 31)) + return value; + value >>= last; + value &= (1 << (first - last + 1)) - 1; + return value; +} + +u8 * +format_pp2_ppio_link_info (u8 *s, va_list *args) +{ + struct pp2_ppio_link_info *li = va_arg (*args, struct pp2_ppio_link_info *); + + char *port_duplex[] = { + [MV_NET_LINK_DUPLEX_HALF] = "half", + [MV_NET_LINK_DUPLEX_FULL] = "full", + }; + + u32 port_speeds[] = { + [MV_NET_LINK_SPEED_10] = 10, [MV_NET_LINK_SPEED_100] = 100, + [MV_NET_LINK_SPEED_1000] = 1000, [MV_NET_LINK_SPEED_2500] = 2500, + [MV_NET_LINK_SPEED_10000] = 10000, + }; + + char *port_phy_modes[] = { + [MV_NET_PHY_MODE_NONE] = "NONE", + [MV_NET_PHY_MODE_MII] = "MII", + [MV_NET_PHY_MODE_GMII] = "GMII", + [MV_NET_PHY_MODE_SGMII] = "SGMII", + [MV_NET_PHY_MODE_TBI] = "TBI", + [MV_NET_PHY_MODE_REVMII] = "REVMII", + [MV_NET_PHY_MODE_RMII] = "RMII", + [MV_NET_PHY_MODE_RGMII] = "RGMII", + [MV_NET_PHY_MODE_RGMII_ID] = "RGMII_ID", + [MV_NET_PHY_MODE_RGMII_RXID] = "RGMII_RXID", + [MV_NET_PHY_MODE_RGMII_TXID] = "RGMII_TXID", + [MV_NET_PHY_MODE_RTBI] = "RTBI", + [MV_NET_PHY_MODE_SMII] = "SMII", + [MV_NET_PHY_MODE_XGMII] = "XGMII", + [MV_NET_PHY_MODE_MOCA] = "MOCA", + [MV_NET_PHY_MODE_QSGMII] = "QSGMII", + [MV_NET_PHY_MODE_XAUI] = "XAUI", + [MV_NET_PHY_MODE_RXAUI] = "RXAUI", + [MV_NET_PHY_MODE_KR] = "KR", + }; + + s = + format (s, "duplex %s speed %d up %d phy_mode %s", port_duplex[li->duplex], + port_speeds[li->speed], li->up, port_phy_modes[li->phy_mode]); + + return s; +} + +u8 * +format_mvpp2_port_status (u8 *s, va_list *args) +{ + vnet_dev_format_args_t __clib_unused *a = + va_arg (*args, vnet_dev_format_args_t *); + vnet_dev_port_t *port = va_arg (*args, vnet_dev_port_t *); + mvpp2_port_t *mp = vnet_dev_get_port_data (port); + struct pp2_ppio_link_info li = {}; + + if (mp->ppio == 0 || pp2_ppio_get_link_info (mp->ppio, &li)) + return format (s, "link info not available"); + + return format (s, "%U", format_pp2_ppio_link_info, &li); +} + +u8 * +format_mvpp2_dev_info (u8 *s, va_list *args) +{ + vnet_dev_format_args_t __clib_unused *a = + va_arg (*args, vnet_dev_format_args_t *); + vnet_dev_t *dev = va_arg (*args, vnet_dev_t *); + mvpp2_device_t *md = vnet_dev_get_data (dev); + + format (s, "pp_id is %u", md->pp_id); + return s; +} + +#define foreach_pp2_rx_desc_field \ + _ (0x00, 6, 0, l3_offset) \ + _ (0x00, 12, 8, ip_hdlen) \ + _ (0x00, 14, 13, ec) \ + _ (0x00, 15, 15, es) \ + _ (0x00, 19, 16, pool_id) \ + _ (0x00, 21, 21, hwf_sync) \ + _ (0x00, 22, 22, l4_chk_ok) \ + _ (0x00, 23, 23, ip_frg) \ + _ (0x00, 24, 24, ipv4_hdr_err) \ + _ (0x00, 27, 25, l4_info) \ + _ (0x00, 30, 28, l3_info) \ + _ (0x00, 31, 31, buf_header) \ + _ (0x04, 5, 0, lookup_id) \ + _ (0x04, 8, 6, cpu_code) \ + _ (0x04, 9, 9, pppoe) \ + _ (0x04, 11, 10, l3_cast_info) \ + _ (0x04, 13, 12, l2_cast_info) \ + _ (0x04, 15, 14, vlan_info) \ + _ (0x04, 31, 16, byte_count) \ + _ (0x08, 11, 0, gem_port_id) \ + _ (0x08, 13, 12, color) \ + _ (0x08, 14, 14, gop_sop_u) \ + _ (0x08, 15, 15, key_hash_enable) \ + _ (0x08, 31, 16, l4chk) \ + _ (0x0c, 31, 0, timestamp) \ + _ (0x10, 31, 0, buf_phys_ptr_lo) \ + _ (0x14, 7, 0, buf_phys_ptr_hi) \ + _ (0x14, 31, 8, key_hash) \ + _ (0x18, 31, 0, buf_virt_ptr_lo) \ + _ (0x1c, 7, 0, buf_virt_ptr_hi) \ + _ (0x1c, 14, 8, buf_qset_no) \ + _ (0x1c, 15, 15, buf_type) \ + _ (0x1c, 21, 16, mod_dscp) \ + _ (0x1c, 24, 22, mod_pri) \ + _ (0x1c, 25, 25, mdscp) \ + _ (0x1c, 26, 26, mpri) \ + _ (0x1c, 27, 27, mgpid) \ + _ (0x1c, 31, 29, port_num) + +u8 * +format_mvpp2_rx_desc (u8 *s, va_list *args) + +{ + struct pp2_ppio_desc *d = va_arg (*args, struct pp2_ppio_desc *); + u32 indent = format_get_indent (s); + u32 r32; + +#define _(a, b, c, n) \ + r32 = mrvl_get_u32_bits (d, a, b, c); \ + if (r32 > 9) \ + s = format (s, "%s %u (0x%x)", #n, r32, r32); \ + else \ + s = format (s, "%s %u", #n, r32); \ + if (format_get_indent (s) > 72) \ + s = format (s, "\n%U", format_white_space, indent + 2); \ + else \ + s = format (s, " "); + + foreach_pp2_rx_desc_field; + return s; +} + +u8 * +format_mvpp2_rx_trace (u8 *s, va_list *args) +{ + vlib_main_t *vm = va_arg (*args, vlib_main_t *); + vlib_node_t *node = va_arg (*args, vlib_node_t *); + mvpp2_rx_trace_t *t = va_arg (*args, mvpp2_rx_trace_t *); + vnet_main_t *vnm = vnet_get_main (); + u32 hw_if_index = t->rxq->port->intf.hw_if_index; + vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index); + u32 indent = format_get_indent (s); + struct pp2_ppio_desc *d = &t->desc; + + s = format (s, "pp2: %v (%d) next-node %U", hi->name, hw_if_index, + format_vlib_next_node_name, vm, node->index, t->rxq->next_index); + s = format (s, "\n%U%U", format_white_space, indent + 2, + format_mvpp2_rx_desc, d); + + return s; +} diff --git a/src/plugins/dev_armada/pp2/init.c b/src/plugins/dev_armada/pp2/init.c new file mode 100644 index 00000000000..38ff32d8f53 --- /dev/null +++ b/src/plugins/dev_armada/pp2/init.c @@ -0,0 +1,343 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2023 Cisco Systems, Inc. + */ + +#include <vnet/vnet.h> +#include <vnet/dev/dev.h> +#include <vnet/dev/counters.h> +#include <vnet/dev/bus/platform.h> +#include <vppinfra/ring.h> +#include <dev_armada/musdk.h> +#include <dev_armada/pp2/pp2.h> +#include <vnet/ethernet/ethernet.h> +#include <vnet/plugin/plugin.h> +#include <vpp/app/version.h> + +#include <linux/if.h> +#include <sys/ioctl.h> + +#define MV_SYS_DMA_MEM_SZ (2 << 20) + +VLIB_REGISTER_LOG_CLASS (mvpp2_log, static) = { + .class_name = "armada", + .subclass_name = "init", +}; + +static int num_pp2_in_use = 0; +static int dma_mem_initialized = 0; +static int global_pp2_initialized = 0; + +#define _(f, n, s, d) \ + { .name = #n, .desc = d, .severity = VL_COUNTER_SEVERITY_##s }, + +vlib_error_desc_t mvpp2_rx_node_counters[] = { foreach_mvpp2_rx_node_counter }; +vlib_error_desc_t mvpp2_tx_node_counters[] = { foreach_mvpp2_tx_node_counter }; +#undef _ + +vnet_dev_node_t mvpp2_rx_node = { + .error_counters = mvpp2_rx_node_counters, + .n_error_counters = ARRAY_LEN (mvpp2_rx_node_counters), + .format_trace = format_mvpp2_rx_trace, +}; + +vnet_dev_node_t mvpp2_tx_node = { + .error_counters = mvpp2_tx_node_counters, + .n_error_counters = ARRAY_LEN (mvpp2_tx_node_counters), +}; + +static u8 * +mvpp2_probe (vlib_main_t *vm, vnet_dev_bus_index_t bus_index, void *dev_info) +{ + vnet_dev_bus_platform_device_info_t *di = dev_info; + + if (clib_dt_node_is_compatible (di->node, "marvell,armada-7k-pp22")) + return format (0, "Marvell Armada Packet Processor v2.2"); + return 0; +} +static void +mvpp2_global_deinit (vlib_main_t *vm, vnet_dev_t *dev) +{ + mvpp2_device_t *md = vnet_dev_get_data (dev); + log_debug (dev, ""); + if (--num_pp2_in_use == 0) + { + if (global_pp2_initialized) + { + for (u32 i = 0; i < ARRAY_LEN (md->thread); i++) + if (md->thread[i].bpool) + { + pp2_bpool_deinit (md->thread[i].bpool); + md->thread[i].bpool = 0; + } + for (u32 i = 0; i < ARRAY_LEN (md->hif); i++) + if (md->hif[i]) + { + pp2_hif_deinit (md->hif[i]); + md->hif[i] = 0; + } + + pp2_deinit (); + global_pp2_initialized = 0; + } + if (dma_mem_initialized) + { + mv_sys_dma_mem_destroy (); + log_debug (0, "mv_sys_dma_mem_destroy()"); + dma_mem_initialized = 0; + } + } +} + +static void +mvpp2_deinit (vlib_main_t *vm, vnet_dev_t *dev) +{ + log_debug (dev, ""); + mvpp2_global_deinit (vm, dev); +} + +static vnet_dev_rv_t +mvpp2_global_init (vlib_main_t *vm, vnet_dev_t *dev) +{ + mvpp2_device_t *md = vnet_dev_get_data (dev); + vnet_dev_rv_t rv = VNET_DEV_OK; + int mrv; + u16 free_hifs, free_bpools; + u16 n_threads = vlib_get_n_threads (); + + struct pp2_init_params init_params = { + .hif_reserved_map = 0xf, + .bm_pool_reserved_map = 0x7, + }; + + if (num_pp2_in_use++) + return rv; + + mrv = mv_sys_dma_mem_init (MV_SYS_DMA_MEM_SZ); + if (mrv < 0) + { + log_err (0, "mv_sys_dma_mem_init failed, err %d", mrv); + rv = VNET_DEV_ERR_INIT_FAILED; + goto done; + } + + dma_mem_initialized = 1; + log_debug (0, "mv_sys_dma_mem_init(%u) ok", MV_SYS_DMA_MEM_SZ); + + if ((mrv = pp2_init (&init_params))) + { + log_err (dev, "pp2_init failed, err %d", mrv); + rv = VNET_DEV_ERR_INIT_FAILED; + goto done; + } + + log_debug (dev, "pp2_init() ok"); + + free_hifs = pow2_mask (MVPP2_NUM_HIFS) ^ init_params.hif_reserved_map; + free_bpools = + pow2_mask (MVPP2_NUM_BPOOLS) ^ init_params.bm_pool_reserved_map; + + if (n_threads > count_set_bits (free_hifs)) + { + log_err (dev, "no enough HIFs (needed %u available %u)", n_threads, + count_set_bits (free_hifs)); + rv = VNET_DEV_ERR_INIT_FAILED; + goto done; + } + + for (u32 i = 0; i < n_threads; i++) + { + char match[16]; + u8 index; + struct pp2_hif_params hif_params = { + .match = match, + .out_size = 2048, + }; + struct pp2_bpool_params bpool_params = { + .match = match, + .buff_len = vlib_buffer_get_default_data_size (vm), + }; + + index = get_lowest_set_bit_index (free_hifs); + free_hifs ^= 1 << index; + snprintf (match, sizeof (match), "hif-%u", index); + + mrv = pp2_hif_init (&hif_params, md->hif + i); + if (mrv < 0) + { + log_err (dev, "pp2_hif_init failed for hif %u thread %u, err %d", + index, i, mrv); + rv = VNET_DEV_ERR_INIT_FAILED; + goto done; + } + log_debug (dev, "pp2_hif_init(hif %u, thread %u) ok", index, i); + + index = get_lowest_set_bit_index (free_bpools); + free_bpools ^= 1 << index; + snprintf (match, sizeof (match), "pool-%u:%u", md->pp_id, index); + + mrv = pp2_bpool_init (&bpool_params, &md->thread[i].bpool); + if (mrv < 0) + { + log_err (dev, "pp2_bpool_init failed for bpool %u thread %u, err %d", + index, i, mrv); + rv = VNET_DEV_ERR_INIT_FAILED; + goto done; + } + log_debug (dev, "pp2_bpool_init(bpool %u, thread %u) pool-%u:%u ok", + index, i, md->thread[i].bpool->pp2_id, + md->thread[i].bpool->id); + for (u32 j = 0; j < ARRAY_LEN (md->thread[0].bre); j++) + md->thread[i].bre[j].bpool = md->thread[i].bpool; + } + +done: + return rv; +} + +static vnet_dev_rv_t +mvpp2_init (vlib_main_t *vm, vnet_dev_t *dev) +{ + mvpp2_device_t *md = vnet_dev_get_data (dev); + vnet_dev_rv_t rv = VNET_DEV_OK; + vnet_dev_bus_platform_device_data_t *dd = vnet_dev_get_bus_data (dev); + clib_dt_node_t *sc; + int pp_id = -1; + + if (!clib_dt_node_is_compatible (dd->node, "marvell,armada-7k-pp22")) + return VNET_DEV_ERR_NOT_SUPPORTED; + + sc = clib_dt_dereference_node (dd->node, "marvell,system-controller"); + + if (sc && vec_len (sc->path) > strlen ("/cpX/")) + { + if (strncmp ((char *) sc->path, "/cp0/", 4) == 0) + pp_id = 0; + else if (strncmp ((char *) sc->path, "/cp1/", 4) == 0) + pp_id = 1; + } + + if (pp_id < 0) + return VNET_DEV_ERR_UNKNOWN_DEVICE; + + if ((mvpp2_global_init (vm, dev)) != VNET_DEV_OK) + return rv; + + md->pp_id = pp_id; + + vec_foreach_pointer (cn, dd->node->child_nodes) + { + clib_dt_property_t *p; + char netdev_name[IFNAMSIZ]; + struct ifreq s = {}; + u8 ppio_id; + int fd, srv; + + p = clib_dt_get_node_property_by_name (cn, "port-id"); + + if (!clib_dt_proprerty_is_u32 (p)) + continue; + + ppio_id = clib_dt_proprerty_get_u32 (p); + log_debug (dev, "found port with ppio id %u", ppio_id); + + if (pp2_ppio_available (md->pp_id, ppio_id) == 0) + continue; + + if (pp2_netdev_get_ifname (md->pp_id, ppio_id, netdev_name) < 0) + { + log_warn (dev, "failed to get ifname, skipping port %u ", ppio_id); + continue; + } + + srv = -1; + if ((fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_IP)) >= 0) + { + strcpy (s.ifr_name, netdev_name); + srv = ioctl (fd, SIOCGIFHWADDR, &s); + close (fd); + } + + if (srv < 0) + { + log_warn (dev, "unable to get hw address, skipping port %u", + ppio_id); + continue; + } + + log_debug (dev, "adding ppio %u (netdev name %s, hwaddr %U)", ppio_id, + netdev_name, format_ethernet_address, s.ifr_addr.sa_data); + + mvpp2_port_t mvpp2_port = { + .ppio_id = ppio_id, + }; + + vnet_dev_port_add_args_t port_add_args = { + .port = { + .attr = { + .type = VNET_DEV_PORT_TYPE_ETHERNET, + .max_rx_queues = PP2_PPIO_MAX_NUM_INQS, + .max_tx_queues = PP2_PPIO_MAX_NUM_OUTQS, + .max_supported_rx_frame_size = 9216, + }, + .ops = { + .init = mvpp2_port_init, + .deinit = mvpp2_port_deinit, + .start = mvpp2_port_start, + .stop = mvpp2_port_stop, + .config_change = mvpp2_port_cfg_change, + .config_change_validate = mvpp2_port_cfg_change_validate, + .format_status = format_mvpp2_port_status, + }, + .data_size = sizeof (mvpp2_port_t), + .initial_data = &mvpp2_port, + }, + .rx_node = &mvpp2_rx_node, + .tx_node = &mvpp2_tx_node, + .rx_queue = { + .config = { + .data_size = sizeof (mvpp2_rxq_t), + .default_size = 512, + .multiplier = 32, + .min_size = 32, + .max_size = 4096, + .size_is_power_of_two = 1, + }, + }, + .tx_queue = { + .config = { + .data_size = sizeof (mvpp2_txq_t), + .default_size = 512, + .multiplier = 32, + .min_size = 32, + .max_size = 4096, + .size_is_power_of_two = 1, + }, + .ops = { + .alloc = mvpp2_txq_alloc, + .free = mvpp2_txq_free, + }, + }, + }; + + vnet_dev_set_hw_addr_eth_mac (&port_add_args.port.attr.hw_addr, + (u8 *) s.ifr_addr.sa_data); + + vnet_dev_port_add (vm, dev, ppio_id, &port_add_args); + } + + if (rv != VNET_DEV_OK) + mvpp2_deinit (vm, dev); + return rv; +} + +VNET_DEV_REGISTER_DRIVER (pp2) = { + .name = "mvpp2", + .bus = PLATFORM_BUS_NAME, + .device_data_sz = sizeof (mvpp2_device_t), + .ops = { + .init = mvpp2_init, + .deinit = mvpp2_deinit, + .probe = mvpp2_probe, + .format_info = format_mvpp2_dev_info, + }, +}; diff --git a/src/plugins/dev_armada/pp2/port.c b/src/plugins/dev_armada/pp2/port.c new file mode 100644 index 00000000000..8e785e5e0e4 --- /dev/null +++ b/src/plugins/dev_armada/pp2/port.c @@ -0,0 +1,280 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2023 Cisco Systems, Inc. + */ + +#include <vnet/vnet.h> +#include <vnet/ethernet/ethernet.h> +#include <vnet/dev/dev.h> +#include <vnet/dev/counters.h> +#include <vnet/dev/bus/platform.h> +#include <vppinfra/ring.h> +#include <dev_armada/musdk.h> +#include <dev_armada/pp2/pp2.h> + +VLIB_REGISTER_LOG_CLASS (mvpp2_log, static) = { + .class_name = "armada", + .subclass_name = "pp2-port", +}; + +vnet_dev_rv_t +mvpp2_port_init (vlib_main_t *vm, vnet_dev_port_t *port) +{ + vnet_dev_t *dev = port->dev; + mvpp2_device_t *md = vnet_dev_get_data (dev); + mvpp2_port_t *mp = vnet_dev_get_port_data (port); + vnet_dev_rv_t rv = VNET_DEV_OK; + struct pp2_ppio_link_info li; + char match[16]; + int mrv; + + log_debug (port->dev, ""); + + snprintf (match, sizeof (match), "ppio-%d:%d", md->pp_id, port->port_id); + + struct pp2_ppio_params ppio_params = { + .match = match, + .type = PP2_PPIO_T_NIC, + .eth_start_hdr = mp->is_dsa ? PP2_PPIO_HDR_ETH_DSA : PP2_PPIO_HDR_ETH, + .inqs_params = { + .num_tcs = 1, + .tcs_params[0] = { + .pkt_offset = 0, + .num_in_qs = 1, + .inqs_params = &(struct pp2_ppio_inq_params) { .size = 512 }, + .pools[0][0] = md->thread[0].bpool, + }, + }, + }; + + foreach_vnet_dev_port_rx_queue (q, port) + { + struct pp2_ppio_outqs_params *oqs = &ppio_params.outqs_params; + oqs->outqs_params[0].weight = 1; + oqs->outqs_params[0].size = q->size; + oqs->num_outqs++; + } + + mrv = pp2_ppio_init (&ppio_params, &mp->ppio); + if (mrv) + { + rv = VNET_DEV_ERR_INIT_FAILED; + log_err (dev, "port %u ppio '%s' init failed, rv %d", port->port_id, + match, mrv); + goto done; + } + log_debug (dev, "port %u ppio '%s' init ok", port->port_id, match); + + mrv = pp2_ppio_get_link_info (mp->ppio, &li); + if (mrv) + { + rv = VNET_DEV_ERR_INIT_FAILED; + log_err (dev, "failed to get link info for port %u, rv %d", + port->port_id, mrv); + goto done; + } + + log_debug (dev, "port %u %U", port->port_id, format_pp2_ppio_link_info, &li); + +done: + if (rv != VNET_DEV_OK) + mvpp2_port_stop (vm, port); + return rv; +} + +void +mvpp2_port_deinit (vlib_main_t *vm, vnet_dev_port_t *port) +{ + mvpp2_port_t *mp = vnet_dev_get_port_data (port); + + log_debug (port->dev, ""); + + if (mp->ppio) + { + pp2_ppio_deinit (mp->ppio); + mp->ppio = 0; + } +} + +void +mvpp2_port_poll (vlib_main_t *vm, vnet_dev_port_t *port) +{ + mvpp2_port_t *mp = vnet_dev_get_port_data (port); + vnet_dev_t *dev = port->dev; + vnet_dev_port_state_changes_t changes = {}; + struct pp2_ppio_link_info li; + int mrv; + + mrv = pp2_ppio_get_link_info (mp->ppio, &li); + + if (mrv) + { + log_debug (dev, "pp2_ppio_get_link_info: failed, rv %d", mrv); + return; + } + + if (mp->last_link_info.up != li.up) + { + changes.change.link_state = 1; + changes.link_state = li.up != 0; + log_debug (dev, "link state changed to %u", changes.link_state); + } + + if (mp->last_link_info.duplex != li.duplex) + { + changes.change.link_duplex = 1; + changes.full_duplex = li.duplex != 0; + log_debug (dev, "link full duplex changed to %u", changes.full_duplex); + } + + if (mp->last_link_info.speed != li.speed) + { + u32 speeds[] = { + [MV_NET_LINK_SPEED_AN] = 0, + [MV_NET_LINK_SPEED_10] = 10000, + [MV_NET_LINK_SPEED_100] = 100000, + [MV_NET_LINK_SPEED_1000] = 1000000, + [MV_NET_LINK_SPEED_2500] = 2500000, + [MV_NET_LINK_SPEED_10000] = 10000000, + }; + + if (li.speed < ARRAY_LEN (speeds)) + { + changes.change.link_speed = 1; + changes.link_speed = speeds[li.speed]; + log_debug (dev, "link speed changed to %u", changes.link_speed); + } + } + + if (changes.change.any == 0) + return; + + mp->last_link_info = li; + + vnet_dev_port_state_change (vm, port, changes); +} + +vnet_dev_rv_t +mvpp2_port_start (vlib_main_t *vm, vnet_dev_port_t *port) +{ + mvpp2_port_t *mp = vnet_dev_get_port_data (port); + int mrv; + + log_debug (port->dev, ""); + + mrv = pp2_ppio_enable (mp->ppio); + if (mrv) + { + log_err (port->dev, "pp2_ppio_enable() failed, rv %d", mrv); + return VNET_DEV_ERR_NOT_READY; + } + + mp->is_enabled = 1; + + vnet_dev_poll_port_add (vm, port, 0.5, mvpp2_port_poll); + + return VNET_DEV_OK; +} + +void +mvpp2_port_stop (vlib_main_t *vm, vnet_dev_port_t *port) +{ + int rv; + mvpp2_port_t *mp = vnet_dev_get_port_data (port); + + log_debug (port->dev, ""); + + if (mp->is_enabled) + { + vnet_dev_poll_port_remove (vm, port, mvpp2_port_poll); + + rv = pp2_ppio_disable (mp->ppio); + if (rv) + log_err (port->dev, "pp2_ppio_disable() failed, rv %d", rv); + + vnet_dev_port_state_change (vm, port, + (vnet_dev_port_state_changes_t){ + .change.link_state = 1, + .change.link_speed = 1, + .link_speed = 0, + .link_state = 0, + }); + mp->is_enabled = 0; + } +} + +vnet_dev_rv_t +mvpp2_port_cfg_change_validate (vlib_main_t *vm, vnet_dev_port_t *port, + vnet_dev_port_cfg_change_req_t *req) +{ + vnet_dev_rv_t rv = VNET_DEV_OK; + + switch (req->type) + { + case VNET_DEV_PORT_CFG_PROMISC_MODE: + case VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR: + case VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR: + break; + + default: + rv = VNET_DEV_ERR_NOT_SUPPORTED; + }; + + return rv; +} + +vnet_dev_rv_t +mvpp2_port_cfg_change (vlib_main_t *vm, vnet_dev_port_t *port, + vnet_dev_port_cfg_change_req_t *req) +{ + mvpp2_port_t *mp = vnet_dev_get_port_data (port); + vnet_dev_rv_t rv = VNET_DEV_OK; + eth_addr_t addr; + int mrv; + + switch (req->type) + { + + case VNET_DEV_PORT_CFG_PROMISC_MODE: + mrv = pp2_ppio_set_promisc (mp->ppio, req->promisc); + if (mrv) + { + log_err (port->dev, "pp2_ppio_set_promisc: failed, rv %d", mrv); + rv = VNET_DEV_ERR_INTERNAL; + } + else + log_debug (port->dev, "pp2_ppio_set_promisc: promisc %u", + req->promisc); + break; + + case VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR: + clib_memcpy (&addr, req->addr.eth_mac, sizeof (addr)); + mrv = pp2_ppio_add_mac_addr (mp->ppio, addr); + if (mrv) + { + log_err (port->dev, "pp2_ppio_add_mac_addr: failed, rv %d", mrv); + rv = VNET_DEV_ERR_INTERNAL; + } + else + log_debug (port->dev, "pp2_ppio_add_mac_addr: %U added", + format_ethernet_address, &addr); + break; + + case VNET_DEV_PORT_CFG_REMOVE_SECONDARY_HW_ADDR: + clib_memcpy (&addr, req->addr.eth_mac, sizeof (addr)); + mrv = pp2_ppio_remove_mac_addr (mp->ppio, addr); + if (mrv) + { + log_err (port->dev, "pp2_ppio_remove_mac_addr: failed, rv %d", mrv); + rv = VNET_DEV_ERR_INTERNAL; + } + else + log_debug (port->dev, "pp2_ppio_remove_mac_addr: %U added", + format_ethernet_address, &addr); + break; + + default: + return VNET_DEV_ERR_NOT_SUPPORTED; + }; + + return rv; +} diff --git a/src/plugins/dev_armada/pp2/pp2.h b/src/plugins/dev_armada/pp2/pp2.h new file mode 100644 index 00000000000..6b12dc737a7 --- /dev/null +++ b/src/plugins/dev_armada/pp2/pp2.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2023 Cisco Systems, Inc. + */ + +#ifndef _PP2_H_ +#define _PP2_H_ + +#include <vppinfra/clib.h> +#include <vppinfra/error_bootstrap.h> +#include <vppinfra/format.h> +#include <vnet/vnet.h> +#include <vnet/dev/dev.h> + +#define MVCONF_DBG_LEVEL 0 +#define MVCONF_PP2_BPOOL_COOKIE_SIZE 32 +#define MVCONF_PP2_BPOOL_DMA_ADDR_SIZE 64 +#define MVCONF_DMA_PHYS_ADDR_T_SIZE 64 +#define MVCONF_SYS_DMA_UIO +#define MVCONF_TYPES_PUBLIC +#define MVCONF_DMA_PHYS_ADDR_T_PUBLIC + +#include "mv_std.h" +#include "env/mv_sys_dma.h" +#include "drivers/mv_pp2.h" +#include <drivers/mv_pp2_bpool.h> +#include <drivers/mv_pp2_ppio.h> + +#define MVPP2_NUM_HIFS 9 +#define MVPP2_NUM_BPOOLS 16 +#define MVPP2_MAX_THREADS 4 +#define MRVL_PP2_BUFF_BATCH_SZ 32 + +typedef struct +{ + u8 pp_id; + struct pp2_hif *hif[MVPP2_NUM_HIFS]; + struct + { + struct pp2_bpool *bpool; + struct buff_release_entry bre[MRVL_PP2_BUFF_BATCH_SZ]; + } thread[MVPP2_NUM_BPOOLS]; + +} mvpp2_device_t; + +typedef struct +{ + u8 is_enabled : 1; + u8 is_dsa : 1; + struct pp2_ppio *ppio; + u8 ppio_id; + struct pp2_ppio_link_info last_link_info; +} mvpp2_port_t; + +typedef struct +{ + u16 next; + u16 n_enq; + u32 *buffers; +} mvpp2_txq_t; + +typedef struct +{ +} mvpp2_rxq_t; + +typedef struct +{ + struct pp2_ppio_desc desc; + vnet_dev_rx_queue_t *rxq; +} mvpp2_rx_trace_t; + +/* format.c */ +format_function_t format_pp2_ppio_link_info; +format_function_t format_mvpp2_port_status; +format_function_t format_mvpp2_dev_info; +format_function_t format_mvpp2_rx_trace; +format_function_t format_mvpp2_rx_desc; + +/* port.c */ +vnet_dev_port_op_t mvpp2_port_init; +vnet_dev_port_op_no_rv_t mvpp2_port_deinit; +vnet_dev_port_op_t mvpp2_port_start; +vnet_dev_port_op_no_rv_t mvpp2_port_stop; +vnet_dev_rv_t mvpp2_port_cfg_change (vlib_main_t *, vnet_dev_port_t *, + vnet_dev_port_cfg_change_req_t *); +vnet_dev_rv_t +mvpp2_port_cfg_change_validate (vlib_main_t *, vnet_dev_port_t *, + vnet_dev_port_cfg_change_req_t *); + +/* queue.c */ +vnet_dev_tx_queue_op_t mvpp2_txq_alloc; +vnet_dev_tx_queue_op_no_rv_t mvpp2_txq_free; + +/* inline funcs */ + +#define log_debug(dev, f, ...) \ + vlib_log (VLIB_LOG_LEVEL_DEBUG, mvpp2_log.class, "%U" f, \ + format_vnet_dev_log, (dev), \ + clib_string_skip_prefix (__func__, "mvpp2_"), ##__VA_ARGS__) +#define log_info(dev, f, ...) \ + vlib_log (VLIB_LOG_LEVEL_INFO, mvpp2_log.class, "%U" f, \ + format_vnet_dev_log, (dev), 0, ##__VA_ARGS__) +#define log_notice(dev, f, ...) \ + vlib_log (VLIB_LOG_LEVEL_NOTICE, mvpp2_log.class, "%U" f, \ + format_vnet_dev_log, (dev), 0, ##__VA_ARGS__) +#define log_warn(dev, f, ...) \ + vlib_log (VLIB_LOG_LEVEL_WARNING, mvpp2_log.class, "%U" f, \ + format_vnet_dev_log, (dev), 0, ##__VA_ARGS__) +#define log_err(dev, f, ...) \ + vlib_log (VLIB_LOG_LEVEL_ERR, mvpp2_log.class, "%U" f, format_vnet_dev_log, \ + (dev), 0, ##__VA_ARGS__) + +#define foreach_mvpp2_tx_node_counter \ + _ (NO_FREE_SLOTS, no_free_slots, ERROR, "no free tx slots") \ + _ (PPIO_SEND, ppio_semd, ERROR, "pp2_ppio_send errors") \ + _ (PPIO_GET_NUM_OUTQ_DONE, ppio_get_num_outq_done, ERROR, \ + "pp2_ppio_get_num_outq_done errors") + +typedef enum +{ +#define _(f, n, s, d) MVPP2_TX_NODE_CTR_##f, + foreach_mvpp2_tx_node_counter +#undef _ +} mvpp2_tx_node_counter_t; + +#define foreach_mvpp2_rx_node_counter \ + _ (PPIO_RECV, ppio_recv, ERROR, "pp2_ppio_recv error") \ + _ (BPOOL_GET_NUM_BUFFS, bpool_get_num_bufs, ERROR, \ + "pp2_bpool_get_num_buffs error") \ + _ (BPOOL_PUT_BUFFS, bpool_put_buffs, ERROR, "pp2_bpool_put_buffs error") \ + _ (BUFFER_ALLOC, buffer_alloc, ERROR, "buffer alloc error") \ + _ (MAC_CE, mac_ce, ERROR, "MAC error (CRC error)") \ + _ (MAC_OR, mac_or, ERROR, "overrun error") \ + _ (MAC_RSVD, mac_rsvd, ERROR, "unknown MAC error") \ + _ (MAC_RE, mac_re, ERROR, "resource error") \ + _ (IP_HDR, ip_hdr, ERROR, "ip4 header error") + +typedef enum +{ +#define _(f, n, s, d) MVPP2_RX_NODE_CTR_##f, + foreach_mvpp2_rx_node_counter +#undef _ +} mvpp2_rx_node_counter_t; + +#endif /* _PP2_H_ */ diff --git a/src/plugins/dev_armada/pp2/queue.c b/src/plugins/dev_armada/pp2/queue.c new file mode 100644 index 00000000000..05015414816 --- /dev/null +++ b/src/plugins/dev_armada/pp2/queue.c @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2023 Cisco Systems, Inc. + */ + +#include <vnet/vnet.h> +#include <vnet/ethernet/ethernet.h> +#include <vnet/dev/dev.h> +#include <vnet/dev/counters.h> +#include <vnet/dev/bus/platform.h> +#include <vppinfra/ring.h> +#include <dev_armada/musdk.h> +#include <dev_armada/pp2/pp2.h> + +VLIB_REGISTER_LOG_CLASS (mvpp2_log, static) = { + .class_name = "armada", + .subclass_name = "pp2-queue", +}; + +vnet_dev_rv_t +mvpp2_txq_alloc (vlib_main_t *vm, vnet_dev_tx_queue_t *txq) +{ + vnet_dev_rv_t rv = VNET_DEV_OK; + mvpp2_txq_t *mtq = vnet_dev_get_tx_queue_data (txq); + log_debug (txq->port->dev, ""); + + ASSERT (mtq->buffers == 0); + if (mtq->buffers == 0) + { + u32 sz = sizeof (u32) * txq->size; + mtq->buffers = clib_mem_alloc_aligned (sz, CLIB_CACHE_LINE_BYTES); + clib_memset (mtq->buffers, 0, sz); + } + + return rv; +} + +void +mvpp2_txq_free (vlib_main_t *vm, vnet_dev_tx_queue_t *txq) +{ + mvpp2_txq_t *mtq = vnet_dev_get_tx_queue_data (txq); + + log_debug (txq->port->dev, ""); + if (mtq->buffers) + { + clib_mem_free (mtq->buffers); + mtq->buffers = 0; + } +} diff --git a/src/plugins/dev_armada/pp2/rx.c b/src/plugins/dev_armada/pp2/rx.c new file mode 100644 index 00000000000..81101ef9313 --- /dev/null +++ b/src/plugins/dev_armada/pp2/rx.c @@ -0,0 +1,158 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2024 Cisco Systems, Inc. + */ + +#include <vlib/vlib.h> +#include <vnet/dev/dev.h> +#include <vnet/ethernet/ethernet.h> + +#include <dev_armada/pp2/pp2.h> + +static_always_inline void +mvpp2_rx_trace (vlib_main_t *vm, vlib_node_runtime_t *node, + vnet_dev_rx_queue_t *rxq, vlib_buffer_t *b0, uword *n_trace, + struct pp2_ppio_desc *d) +{ + if (PREDICT_TRUE (vlib_trace_buffer (vm, node, rxq->next_index, b0, + /* follow_chain */ 0))) + { + mvpp2_rx_trace_t *tr; + vlib_set_trace_count (vm, node, --(*n_trace)); + tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); + tr->desc = *d; + tr->rxq = rxq; + } +} + +static_always_inline uword +mrvl_pp2_rx_inline (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame, vnet_dev_rx_queue_t *rxq) +{ + vnet_main_t *vnm = vnet_get_main (); + vnet_dev_port_t *port = rxq->port; + vnet_dev_t *dev = port->dev; + mvpp2_device_t *md = vnet_dev_get_data (dev); + mvpp2_port_t *mp = vnet_dev_get_port_data (port); + vlib_buffer_template_t bt = rxq->buffer_template; + u32 thread_index = vm->thread_index; + uword n_trace = vlib_get_trace_count (vm, node); + u32 next_index = rxq->next_index; + u32 n_rx_packets = 0, n_rx_bytes = 0; + struct pp2_hif *hif = md->hif[thread_index]; + struct pp2_ppio_desc descs[VLIB_FRAME_SIZE], *d; + struct pp2_bpool *bpool = md->thread[thread_index].bpool; + struct buff_release_entry *bre = md->thread[thread_index].bre; + u16 n_desc = VLIB_FRAME_SIZE; + u32 buffers[VLIB_FRAME_SIZE]; + u32 n_bufs, *bi, i; + vlib_buffer_t *b0, *b1; + + if (PREDICT_FALSE ( + pp2_ppio_recv (mp->ppio, 0, rxq->queue_id, descs, &n_desc))) + { + vlib_error_count (vm, node->node_index, MVPP2_RX_NODE_CTR_PPIO_RECV, 1); + n_desc = 0; + } + + n_rx_packets = n_desc; + + for (i = 0; i < n_desc; i++) + buffers[i] = pp2_ppio_inq_desc_get_cookie (descs + i); + + bt.current_data = 2; + + for (d = descs, bi = buffers; n_desc >= 4; d += 2, bi += 2, n_desc -= 2) + { + /* prefetch */ + b0 = vlib_get_buffer (vm, bi[0]); + b1 = vlib_get_buffer (vm, bi[1]); + b0->template = bt; + b1->template = bt; + + n_rx_bytes += b0->current_length = pp2_ppio_inq_desc_get_pkt_len (d); + n_rx_bytes += b1->current_length = pp2_ppio_inq_desc_get_pkt_len (d + 1); + + if (PREDICT_FALSE (n_trace > 0)) + { + mvpp2_rx_trace (vm, node, rxq, b0, &n_trace, d); + if (n_trace > 0) + mvpp2_rx_trace (vm, node, rxq, b1, &n_trace, d + 1); + } + } + + for (; n_desc; d++, bi++, n_desc--) + { + b0 = vlib_get_buffer (vm, bi[0]); + b0->template = bt; + + n_rx_bytes += b0->current_length = pp2_ppio_inq_desc_get_pkt_len (d); + + if (PREDICT_FALSE (n_trace > 0)) + mvpp2_rx_trace (vm, node, rxq, b0, &n_trace, d); + } + + vlib_buffer_enqueue_to_single_next (vm, node, buffers, next_index, + n_rx_packets); + + vlib_increment_combined_counter ( + vnm->interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, + thread_index, port->intf.sw_if_index, n_rx_packets, n_rx_bytes); + + if (PREDICT_FALSE (pp2_bpool_get_num_buffs (bpool, &n_bufs))) + { + vlib_error_count (vm, node->node_index, + MVPP2_RX_NODE_CTR_BPOOL_GET_NUM_BUFFS, 1); + goto done; + } + + n_bufs = rxq->size - n_bufs; + while (n_bufs >= MRVL_PP2_BUFF_BATCH_SZ) + { + u16 n_alloc, i; + struct buff_release_entry *e = bre; + + n_alloc = vlib_buffer_alloc (vm, buffers, MRVL_PP2_BUFF_BATCH_SZ); + i = n_alloc; + + if (PREDICT_FALSE (n_alloc == 0)) + { + vlib_error_count (vm, node->node_index, + MVPP2_RX_NODE_CTR_BUFFER_ALLOC, 1); + goto done; + } + + for (bi = buffers; i--; e++, bi++) + { + + vlib_buffer_t *b = vlib_get_buffer (vm, bi[0]); + e->buff.addr = vlib_buffer_get_pa (vm, b) - 64; + e->buff.cookie = bi[0]; + } + + i = n_alloc; + if (PREDICT_FALSE (pp2_bpool_put_buffs (hif, bre, &i))) + { + vlib_error_count (vm, node->node_index, + MVPP2_RX_NODE_CTR_BPOOL_PUT_BUFFS, 1); + vlib_buffer_free (vm, buffers, n_alloc); + goto done; + } + + if (PREDICT_FALSE (i != n_alloc)) + vlib_buffer_free (vm, buffers + i, n_alloc - i); + + n_bufs -= i; + } + +done: + return n_rx_packets; +} + +VNET_DEV_NODE_FN (mvpp2_rx_node) +(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame) +{ + u32 n_rx = 0; + foreach_vnet_dev_rx_queue_runtime (rxq, node) + n_rx += mrvl_pp2_rx_inline (vm, node, frame, rxq); + return n_rx; +} diff --git a/src/plugins/dev_armada/pp2/tx.c b/src/plugins/dev_armada/pp2/tx.c new file mode 100644 index 00000000000..1e6675c9746 --- /dev/null +++ b/src/plugins/dev_armada/pp2/tx.c @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2024 Cisco Systems, Inc. + */ + +#include <vlib/vlib.h> +#include <vnet/dev/dev.h> +#include <vnet/ethernet/ethernet.h> + +#include <dev_armada/pp2/pp2.h> + +VNET_DEV_NODE_FN (mvpp2_tx_node) +(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame) +{ + vnet_dev_tx_node_runtime_t *rt = vnet_dev_get_tx_node_runtime (node); + vnet_dev_tx_queue_t *txq = rt->tx_queue; + vnet_dev_port_t *port = txq->port; + vnet_dev_t *dev = port->dev; + mvpp2_txq_t *mtq = vnet_dev_get_tx_queue_data (txq); + mvpp2_port_t *mp = vnet_dev_get_port_data (port); + mvpp2_device_t *md = vnet_dev_get_data (dev); + u8 qid = txq->queue_id; + u32 *buffers = vlib_frame_vector_args (frame); + u32 n_vectors = frame->n_vectors, n_left; + u16 n_sent; + struct pp2_ppio *ppio = mp->ppio; + struct pp2_hif *hif = md->hif[vm->thread_index]; + struct pp2_ppio_desc descs[VLIB_FRAME_SIZE], *d = descs; + u16 sz = txq->size; + u16 mask = sz - 1; + + if (mtq->n_enq) + { + u16 n_done = 0; + if (PREDICT_FALSE (pp2_ppio_get_num_outq_done (ppio, hif, qid, &n_done))) + vlib_error_count (vm, node->node_index, + MVPP2_TX_NODE_CTR_PPIO_GET_NUM_OUTQ_DONE, 1); + + if (n_done) + { + vlib_buffer_free_from_ring ( + vm, mtq->buffers, (mtq->next - mtq->n_enq) & mask, sz, n_done); + mtq->n_enq -= n_done; + } + } + + n_sent = clib_min (n_vectors, sz - mtq->n_enq); + + for (d = descs, n_left = n_sent; n_left; d++, buffers++, n_left--) + { + vlib_buffer_t *b0 = vlib_get_buffer (vm, buffers[0]); + u64 paddr = vlib_buffer_get_pa (vm, b0); + + pp2_ppio_outq_desc_reset (d); + pp2_ppio_outq_desc_set_phys_addr (d, paddr + b0->current_data); + pp2_ppio_outq_desc_set_pkt_offset (d, 0); + pp2_ppio_outq_desc_set_pkt_len (d, b0->current_length); + } + + buffers = vlib_frame_vector_args (frame); + + if (pp2_ppio_send (ppio, hif, qid, descs, &n_sent)) + { + n_sent = 0; + vlib_error_count (vm, node->node_index, MVPP2_TX_NODE_CTR_PPIO_SEND, 1); + } + else if (n_sent) + { + vlib_buffer_copy_indices_to_ring (mtq->buffers, buffers, + mtq->next & mask, sz, n_sent); + mtq->next += n_sent; + mtq->n_enq += n_sent; + } + + /* free unsent buffers */ + if (PREDICT_FALSE (n_sent != n_vectors)) + { + vlib_buffer_free (vm, buffers + n_sent, n_vectors - n_sent); + vlib_error_count (vm, node->node_index, MVPP2_TX_NODE_CTR_NO_FREE_SLOTS, + n_vectors - n_sent); + } + + return n_sent; +} diff --git a/src/plugins/marvell/CMakeLists.txt b/src/plugins/marvell/CMakeLists.txt deleted file mode 100644 index b48ac72aa08..00000000000 --- a/src/plugins/marvell/CMakeLists.txt +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (c) 2018 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 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)") - return() -endif() - -find_path(MUSDK_INCLUDE_DIR NAMES mv_std.h) -find_library(MUSDK_LIB NAMES libmusdk.a) - -if(MUSDK_INCLUDE_DIR AND MUSDK_LIB) - get_filename_component(MUSDK_LIB_DIR ${MUSDK_LIB} DIRECTORY) - set(MUSDK_LINK_FLAGS "-Wl,--whole-archive,${MUSDK_LIB_DIR}/libmusdk.a,--no-whole-archive") - add_vpp_plugin(marvell - SOURCES - plugin.c - pp2/cli.c - pp2/format.c - pp2/input.c - pp2/output.c - pp2/pp2.c - pp2/pp2_api.c - - API_FILES - pp2/pp2.api - - API_TEST_SOURCES - pp2/pp2_test.c - - LINK_FLAGS - ${MUSDK_LINK_FLAGS} - ) - include_directories(${MUSDK_INCLUDE_DIR}) - message(STATUS "Found Marvell MUSDK in ${MUSDK_INCLUDE_DIR}") -else() - message(WARNING "Marvell MUSDK not found - marvell_plugin disabled") -endif() diff --git a/src/plugins/marvell/README.rst b/src/plugins/marvell/README.rst deleted file mode 100644 index 19cf1c49d0e..00000000000 --- a/src/plugins/marvell/README.rst +++ /dev/null @@ -1,85 +0,0 @@ -Marvell device plugin -===================== - -Overview --------- - -This plugins provides native device support for Marvell PP2 network -device, by use of Marvell Usermode SDK -(`MUSDK <https://github.com/MarvellEmbeddedProcessors/musdk-marvell>`__). -Code is developed and tested on -`MACCHIATObin <http://macchiatobin.net>`__ board. - -Prerequisites -------------- - -Plugins depends on installed MUSDK and Marvell provided linux -`kernel <https://github.com/MarvellEmbeddedProcessors/linux-marvell>`__ -with MUSDK provided kernel patches (see ``patches/linux`` in musdk repo -and relevant documentation. Kernel version used: **4.14.22 -armada-18.09.3** MUSDK version used: **armada-18.09.3** Following kernel -modules from MUSDK must be loaded for plugin to work: \* -``musdk_cma.ko`` \* ``mv_pp_uio.ko`` - -Musdk 18.09.3 compilation steps -------------------------------- - -:: - - ./bootstrap - ./configure --prefix=/opt/vpp/external/aarch64/ CFLAGS="-Wno-error=unused-result -g -fPIC" --enable-shared=no - sed -i -e 's/marvell,mv-pp-uio/generic-uio/' modules/pp2/mv_pp_uio.c - sed -i -e 's/O_CREAT/O_CREAT, S_IRUSR | S_IWUSR/' src/lib/file_utils.c - make - sudo make install - -Usage ------ - -Interface Creation -~~~~~~~~~~~~~~~~~~ - -Interfaces are dynamically created with following CLI: - -:: - - create interface marvell pp2 name eth0 - set interface state mv-ppio-0/0 up - -Where ``eth0`` is linux interface name and ``mv-ppio-X/Y`` is VPP -interface name where X is PP2 device ID and Y is PPIO ID Interface needs -to be assigned to MUSDK in FDT configuration and linux interface state -must be up. - -Interface Deletion -~~~~~~~~~~~~~~~~~~ - -Interface can be deleted with following CLI: - -:: - - delete interface marvell pp2 <interface name> - -Interface Statistics -~~~~~~~~~~~~~~~~~~~~ - -Interface statistics can be displayed with -``sh hardware-interface mv-ppio0/0`` command. - -Interaction with DPDK plugin -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This plugin doesn’t have any dependency on DPDK or DPDK plugin but it -can work with DPDK plugin enabled or disabled. It is observed that -performance is better around 30% when DPDK plugin is disabled, as DPDK -plugin registers own buffer manager, which needs to deal with additional -metadata in each packet. - -DPKD plugin can be disabled by adding following config to the -startup.conf. - -:: - - plugins { - dpdk_plugin.so { disable } - } diff --git a/src/plugins/marvell/plugin.c b/src/plugins/marvell/plugin.c deleted file mode 100644 index ed90776ba95..00000000000 --- a/src/plugins/marvell/plugin.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2018 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 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#include <vlib/vlib.h> -#include <vnet/plugin/plugin.h> -#include <vpp/app/version.h> - -VLIB_PLUGIN_REGISTER () = { - .version = VPP_BUILD_VER, - .description = "Marvell PP2 Device Driver", -}; - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/marvell/pp2/cli.c b/src/plugins/marvell/pp2/cli.c deleted file mode 100644 index 5072a3c035b..00000000000 --- a/src/plugins/marvell/pp2/cli.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2018 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 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ -#include <stdint.h> -#include <net/if.h> -#include <sys/ioctl.h> -#include <inttypes.h> - -#include <vlib/vlib.h> -#include <vlib/unix/unix.h> -#include <vnet/ethernet/ethernet.h> - -#include <marvell/pp2/pp2.h> - -static clib_error_t * -mrvl_pp2_create_command_fn (vlib_main_t * vm, unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - mrvl_pp2_create_if_args_t args = { 0 }; - unsigned int val; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "name %s", &args.name)) - ; - else if (unformat (line_input, "rx-queue-size %u", &val)) - args.rx_q_sz = val; - else if (unformat (line_input, "tx-queue-size %u", &val)) - args.tx_q_sz = val; - else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); - } - unformat_free (line_input); - - - mrvl_pp2_create_if (&args); - - vec_free (args.name); - - return args.error; -} - -VLIB_CLI_COMMAND (mrvl_pp2_create_command, static) = { - .path = "create interface marvell pp2", - .short_help = "create interface marvell pp2 [name <ifname>] [rx-queue-size slots] [tx-queue-size slots]", - .function = mrvl_pp2_create_command_fn, -}; - -static clib_error_t * -mrvl_pp2_delete_command_fn (vlib_main_t * vm, unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - u32 sw_if_index = ~0; - vnet_hw_interface_t *hw; - mrvl_pp2_main_t *mm = &mrvl_pp2_main; - mrvl_pp2_if_t *dif; - vnet_main_t *vnm = vnet_get_main (); - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "sw_if_index %d", &sw_if_index)) - ; - else if (unformat (line_input, "%U", unformat_vnet_sw_interface, - vnm, &sw_if_index)) - ; - else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); - } - unformat_free (line_input); - - if (sw_if_index == ~0) - return clib_error_return (0, - "please specify interface name or sw_if_index"); - - hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index); - if (hw == NULL || mrvl_pp2_device_class.index != hw->dev_class_index) - return clib_error_return (0, "not a Marvell PP2 interface"); - - dif = pool_elt_at_index (mm->interfaces, hw->dev_instance); - - mrvl_pp2_delete_if (dif); - - return 0; -} - -VLIB_CLI_COMMAND (mrvl_pp2_delete_command, static) = { - .path = "delete interface marvell pp2", - .short_help = "delete interface marvell pp2 " - "{<interface> | sw_if_index <sw_idx>}", - .function = mrvl_pp2_delete_command_fn, -}; - -clib_error_t * -mrvl_pp2_cli_init (vlib_main_t * vm) -{ - /* initialize binary API */ - mrvl_pp2_plugin_api_hookup (vm); - - return 0; -} - -VLIB_INIT_FUNCTION (mrvl_pp2_cli_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/marvell/pp2/format.c b/src/plugins/marvell/pp2/format.c deleted file mode 100644 index 877010ea561..00000000000 --- a/src/plugins/marvell/pp2/format.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2018 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 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/ioctl.h> - -#include <vlib/vlib.h> -#include <vlib/unix/unix.h> -#include <vnet/plugin/plugin.h> -#include <marvell/pp2/pp2.h> - -static inline u32 -mrvl_get_u32_bits (void *start, int offset, int first, int last) -{ - u32 value = *(u32 *) (((u8 *) start) + offset); - if ((last == 0) && (first == 31)) - return value; - value >>= last; - value &= (1 << (first - last + 1)) - 1; - return value; -} - -u8 * -format_mrvl_pp2_interface_name (u8 * s, va_list * args) -{ - mrvl_pp2_main_t *ppm = &mrvl_pp2_main; - u32 dev_instance = va_arg (*args, u32); - mrvl_pp2_if_t *ppif = pool_elt_at_index (ppm->interfaces, dev_instance); - return format (s, "mv-ppio-%d/%d", ppif->ppio->pp2_id, ppif->ppio->port_id); -} - -#define foreach_ppio_statistics_entry \ - _(rx_packets) \ - _(rx_fullq_dropped) \ - _(rx_bm_dropped) \ - _(rx_early_dropped) \ - _(rx_fifo_dropped) \ - _(rx_cls_dropped) \ - _(tx_packets) - -#define foreach_ppio_inq_statistics_entry \ - _(enq_desc) \ - _(drop_early) \ - _(drop_fullq) \ - _(drop_bm) - -#define foreach_ppio_outq_statistics_entry \ - _(enq_desc) \ - _(enq_dec_to_ddr) \ - _(enq_buf_to_ddr) \ - _(deq_desc) - -u8 * -format_mrvl_pp2_interface (u8 * s, va_list * args) -{ - mrvl_pp2_main_t *ppm = &mrvl_pp2_main; - u32 dev_instance = va_arg (*args, u32); - u32 indent = format_get_indent (s); - mrvl_pp2_if_t *ppif = pool_elt_at_index (ppm->interfaces, dev_instance); - struct pp2_ppio_statistics stat; - int i; - u8 *s2 = 0; - - pp2_ppio_get_statistics (ppif->ppio, &stat, 0); - -#define _(c) if (stat.c) \ - s2 = format (s2, "\n%U%-25U%16Ld", \ - format_white_space, indent + 2, \ - format_c_identifier, #c, stat.c); - foreach_ppio_statistics_entry; - - if (vec_len (s2)) - s = format (s, "Interface statistics:%v", s2); - vec_reset_length (s2); - - vec_foreach_index (i, ppif->inqs) - { - struct pp2_ppio_inq_statistics stat = { 0 }; - pp2_ppio_inq_get_statistics (ppif->ppio, 0, i, &stat, 0); - - foreach_ppio_inq_statistics_entry; - - if (vec_len (s2)) - s = format (s, "\n%UInput queue %u statistics:%v", - format_white_space, indent, i, s2); - vec_reset_length (s2); - } - vec_foreach_index (i, ppif->outqs) - { - struct pp2_ppio_outq_statistics stat = { 0 }; - - pp2_ppio_outq_get_statistics (ppif->ppio, i, &stat, 0); - - foreach_ppio_outq_statistics_entry; - - if (vec_len (s2)) - s = format (s, "\n%UOutput queue %u statistics:%v", - format_white_space, indent, i, s2); - vec_reset_length (s2); - } -#undef _ - vec_free (s2); - return s; -} - -#define foreach_pp2_rx_desc_field \ - _(0x00, 6, 0, l3_offset) \ - _(0x00, 12, 8, ip_hdlen) \ - _(0x00, 14, 13, ec) \ - _(0x00, 15, 15, es) \ - _(0x00, 19, 16, pool_id) \ - _(0x00, 21, 21, hwf_sync) \ - _(0x00, 22, 22, l4_chk_ok) \ - _(0x00, 23, 23, ip_frg) \ - _(0x00, 24, 24, ipv4_hdr_err) \ - _(0x00, 27, 25, l4_info) \ - _(0x00, 30, 28, l3_info) \ - _(0x00, 31, 31, buf_header) \ - _(0x04, 5, 0, lookup_id) \ - _(0x04, 8, 6, cpu_code) \ - _(0x04, 9, 9, pppoe) \ - _(0x04, 11, 10, l3_cast_info) \ - _(0x04, 13, 12, l2_cast_info) \ - _(0x04, 15, 14, vlan_info) \ - _(0x04, 31, 16, byte_count) \ - _(0x08, 11, 0, gem_port_id) \ - _(0x08, 13, 12, color) \ - _(0x08, 14, 14, gop_sop_u) \ - _(0x08, 15, 15, key_hash_enable) \ - _(0x08, 31, 16, l4chk) \ - _(0x0c, 31, 0, timestamp) \ - _(0x10, 31, 0, buf_phys_ptr_lo) \ - _(0x14, 7, 0, buf_phys_ptr_hi) \ - _(0x14, 31, 8, key_hash) \ - _(0x18, 31, 0, buf_virt_ptr_lo) \ - _(0x1c, 7, 0, buf_virt_ptr_hi) \ - _(0x1c, 14, 8, buf_qset_no) \ - _(0x1c, 15, 15, buf_type) \ - _(0x1c, 21, 16, mod_dscp) \ - _(0x1c, 24, 22, mod_pri) \ - _(0x1c, 25, 25, mdscp) \ - _(0x1c, 26, 26, mpri) \ - _(0x1c, 27, 27, mgpid) \ - _(0x1c, 31, 29, port_num) - -u8 * -format_mrvl_pp2_input_trace (u8 * s, va_list * args) -{ - vlib_main_t *vm = va_arg (*args, vlib_main_t *); - vlib_node_t *node = va_arg (*args, vlib_node_t *); - mrvl_pp2_input_trace_t *t = va_arg (*args, mrvl_pp2_input_trace_t *); - vnet_main_t *vnm = vnet_get_main (); - vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, t->hw_if_index); - u32 indent = format_get_indent (s); - struct pp2_ppio_desc *d = &t->desc; - u32 r32; - - s = format (s, "pp2: %v (%d) next-node %U", - hi->name, t->hw_if_index, format_vlib_next_node_name, vm, - node->index, t->next_index); - s = format (s, "\n%U", format_white_space, indent + 2); - -#define _(a, b, c, n) \ - r32 = mrvl_get_u32_bits (d, a, b, c); \ - if (r32 > 9) \ - s = format (s, "%s %u (0x%x)", #n, r32, r32); \ - else \ - s = format (s, "%s %u", #n,r32); \ - if (format_get_indent (s) > 72) \ - s = format (s, "\n%U", format_white_space, indent + 2); \ - else s = format (s, " "); - - foreach_pp2_rx_desc_field; -#undef _ - return s; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/marvell/pp2/input.c b/src/plugins/marvell/pp2/input.c deleted file mode 100644 index 2545f91becb..00000000000 --- a/src/plugins/marvell/pp2/input.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2018 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 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#define _GNU_SOURCE -#include <stdint.h> -#include <net/if.h> -#include <sys/ioctl.h> -#include <sys/uio.h> - -#include <vlib/vlib.h> -#include <vlib/unix/unix.h> -#include <vnet/ethernet/ethernet.h> -#include <vnet/devices/devices.h> -#include <vnet/interface/rx_queue_funcs.h> - -#include <marvell/pp2/pp2.h> - -#define foreach_mrvl_pp2_input_error \ - _(PPIO_RECV, "pp2_ppio_recv error") \ - _(BPOOL_GET_NUM_BUFFS, "pp2_bpool_get_num_buffs error") \ - _(BPOOL_PUT_BUFFS, "pp2_bpool_put_buffs error") \ - _(BUFFER_ALLOC, "buffer alloc error") \ - _(MAC_CE, "MAC error (CRC error)") \ - _(MAC_OR, "overrun error") \ - _(MAC_RSVD, "unknown MAC error") \ - _(MAC_RE, "resource error") \ - _(IP_HDR, "ip4 header error") - -typedef enum -{ -#define _(f,s) MRVL_PP2_INPUT_ERROR_##f, - foreach_mrvl_pp2_input_error -#undef _ - MRVL_PP2_INPUT_N_ERROR, -} mrvl_pp2_input_error_t; - -static __clib_unused char *mrvl_pp2_input_error_strings[] = { -#define _(n,s) s, - foreach_mrvl_pp2_input_error -#undef _ -}; - -static_always_inline void -mrvl_pp2_input_trace (vlib_main_t * vm, vlib_node_runtime_t * node, u32 next0, - vlib_buffer_t * b0, uword * n_trace, - mrvl_pp2_if_t * ppif, struct pp2_ppio_desc *d) -{ - if (PREDICT_TRUE ( - vlib_trace_buffer (vm, node, next0, b0, /* follow_chain */ 0))) - { - mrvl_pp2_input_trace_t *tr; - vlib_set_trace_count (vm, node, --(*n_trace)); - tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); - tr->next_index = next0; - tr->hw_if_index = ppif->hw_if_index; - clib_memcpy_fast (&tr->desc, d, sizeof (struct pp2_ppio_desc)); - } -} - -static_always_inline u16 -mrvl_pp2_set_buf_data_len_flags (vlib_buffer_t * b, struct pp2_ppio_desc *d, - u32 add_flags) -{ - u16 len; - len = pp2_ppio_inq_desc_get_pkt_len (d); - b->total_length_not_including_first_buffer = 0; - b->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID | add_flags; - - if (add_flags & VNET_BUFFER_F_L2_HDR_OFFSET_VALID) - vnet_buffer (b)->l2_hdr_offset = 2; - - if (add_flags & VNET_BUFFER_F_L3_HDR_OFFSET_VALID) - { - u16 offset = DM_RXD_GET_L3_OFF (d); - vnet_buffer (b)->l3_hdr_offset = offset; - b->current_data = offset; - b->current_length = len - offset + 2; - } - else - { - b->current_data = 2; - b->current_length = len; - } - - if (add_flags & VNET_BUFFER_F_L3_HDR_OFFSET_VALID) - vnet_buffer (b)->l4_hdr_offset = vnet_buffer (b)->l3_hdr_offset + - DM_RXD_GET_IPHDR_LEN (d) * 4; - - return len; -} - -static_always_inline u16 -mrvl_pp2_next_from_desc (vlib_node_runtime_t * node, struct pp2_ppio_desc * d, - vlib_buffer_t * b, u32 * next) -{ - u8 l3_info; - /* ES bit set means MAC error - drop and count */ - if (PREDICT_FALSE (DM_RXD_GET_ES (d))) - { - *next = VNET_DEVICE_INPUT_NEXT_DROP; - u8 ec = DM_RXD_GET_EC (d); - if (ec == 0) - b->error = node->errors[MRVL_PP2_INPUT_ERROR_MAC_CE]; - else if (ec == 1) - b->error = node->errors[MRVL_PP2_INPUT_ERROR_MAC_OR]; - else if (ec == 2) - b->error = node->errors[MRVL_PP2_INPUT_ERROR_MAC_RSVD]; - else if (ec == 3) - b->error = node->errors[MRVL_PP2_INPUT_ERROR_MAC_RE]; - return mrvl_pp2_set_buf_data_len_flags (b, d, 0); - } - l3_info = DM_RXD_GET_L3_PRS_INFO (d); - - /* ipv4 packet can be value 1, 2 or 3 */ - if (PREDICT_TRUE ((l3_info - 1) < 3)) - { - if (PREDICT_FALSE (DM_RXD_GET_L3_IP4_HDR_ERR (d) != 0)) - { - *next = VNET_DEVICE_INPUT_NEXT_DROP; - b->error = node->errors[MRVL_PP2_INPUT_ERROR_IP_HDR]; - return mrvl_pp2_set_buf_data_len_flags (b, d, 0); - } - *next = VNET_DEVICE_INPUT_NEXT_IP4_NCS_INPUT; - return mrvl_pp2_set_buf_data_len_flags - (b, d, - VNET_BUFFER_F_L2_HDR_OFFSET_VALID | - VNET_BUFFER_F_L3_HDR_OFFSET_VALID | - VNET_BUFFER_F_L4_HDR_OFFSET_VALID | VNET_BUFFER_F_IS_IP4); - } - - /* ipv4 packet can be value 4 or 5 */ - if (PREDICT_TRUE ((l3_info - 4) < 2)) - { - *next = VNET_DEVICE_INPUT_NEXT_IP6_INPUT; - return mrvl_pp2_set_buf_data_len_flags - (b, d, - VNET_BUFFER_F_L2_HDR_OFFSET_VALID | - VNET_BUFFER_F_L3_HDR_OFFSET_VALID | - VNET_BUFFER_F_L4_HDR_OFFSET_VALID | VNET_BUFFER_F_IS_IP6); - } - - *next = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT; - return mrvl_pp2_set_buf_data_len_flags (b, d, - VNET_BUFFER_F_L2_HDR_OFFSET_VALID); -} - -static_always_inline uword -mrvl_pp2_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame, mrvl_pp2_if_t * ppif, - u16 qid) -{ - vnet_main_t *vnm = vnet_get_main (); - mrvl_pp2_main_t *ppm = &mrvl_pp2_main; - u32 thread_index = vm->thread_index; - mrvl_pp2_inq_t *inq = vec_elt_at_index (ppif->inqs, qid); - uword n_trace = vlib_get_trace_count (vm, node); - mrvl_pp2_per_thread_data_t *ptd = - vec_elt_at_index (ppm->per_thread_data, thread_index); - u32 next_index = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT; - u32 sw_if_index[VLIB_N_RX_TX]; - u32 n_rx_packets = 0; - u32 n_rx_bytes = 0; - u32 *to_next = 0; - struct pp2_ppio_desc *d; - u16 n_desc = VLIB_FRAME_SIZE; - u32 n_bufs; - u32 *buffers; - int i; - - vec_validate_aligned (ptd->descs, n_desc, CLIB_CACHE_LINE_BYTES); - if (PREDICT_FALSE (pp2_ppio_recv (ppif->ppio, 0, qid, ptd->descs, &n_desc))) - { - vlib_error_count (vm, node->node_index, MRVL_PP2_INPUT_ERROR_PPIO_RECV, - 1); - n_desc = 0; - } - n_rx_packets = n_desc; - - for (i = 0; i < n_desc; i++) - ptd->buffers[i] = pp2_ppio_inq_desc_get_cookie (&ptd->descs[i]); - - d = ptd->descs; - buffers = ptd->buffers; - sw_if_index[VLIB_RX] = ppif->sw_if_index; - sw_if_index[VLIB_TX] = (u32) ~ 0; - while (n_desc) - { - u32 n_left_to_next; - vlib_buffer_t *b0, *b1; - u32 bi0, bi1; - u32 next0, next1; - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - while (n_desc >= 4 && n_left_to_next >= 2) - { - /* prefetch */ - bi0 = buffers[0]; - bi1 = buffers[1]; - to_next[0] = bi0; - to_next[1] = bi1; - b0 = vlib_get_buffer (vm, bi0); - b1 = vlib_get_buffer (vm, bi1); - - if (PREDICT_TRUE (ppif->per_interface_next_index == ~0)) - { - n_rx_bytes += mrvl_pp2_next_from_desc (node, d, b0, &next0); - n_rx_bytes += mrvl_pp2_next_from_desc (node, d + 1, b1, &next1); - vnet_feature_start_device_input (ppif->sw_if_index, &next0, b0); - vnet_feature_start_device_input (ppif->sw_if_index, &next1, b1); - } - else - { - n_rx_bytes += mrvl_pp2_set_buf_data_len_flags (b0, d, 0); - n_rx_bytes += mrvl_pp2_set_buf_data_len_flags (b1, d + 1, 0); - next0 = next1 = ppif->per_interface_next_index; - } - - clib_memcpy_fast (vnet_buffer (b0)->sw_if_index, sw_if_index, - sizeof (sw_if_index)); - clib_memcpy_fast (vnet_buffer (b1)->sw_if_index, sw_if_index, - sizeof (sw_if_index)); - - if (PREDICT_FALSE (n_trace > 0)) - { - mrvl_pp2_input_trace (vm, node, next0, b0, &n_trace, ppif, d); - if (n_trace > 0) - mrvl_pp2_input_trace (vm, node, next1, b1, &n_trace, ppif, - d + 1); - } - - to_next += 2; - n_left_to_next -= 2; - d += 2; - buffers += 2; - n_desc -= 2; - - /* enqueue */ - vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, - n_left_to_next, bi0, bi1, next0, - next1); - - } - while (n_desc && n_left_to_next) - { - u32 bi0 = buffers[0]; - to_next[0] = bi0; - b0 = vlib_get_buffer (vm, bi0); - - if (PREDICT_TRUE (ppif->per_interface_next_index == ~0)) - { - n_rx_bytes += mrvl_pp2_next_from_desc (node, d, b0, &next0); - vnet_feature_start_device_input (ppif->sw_if_index, &next0, b0); - } - else - { - n_rx_bytes += mrvl_pp2_set_buf_data_len_flags (b0, d, 0); - next0 = ppif->per_interface_next_index; - } - - clib_memcpy_fast (vnet_buffer (b0)->sw_if_index, sw_if_index, - sizeof (sw_if_index)); - - if (PREDICT_FALSE (n_trace > 0)) - mrvl_pp2_input_trace (vm, node, next0, b0, &n_trace, ppif, d); - - to_next += 1; - n_left_to_next--; - d++; - buffers++; - n_desc--; - - /* enqueue */ - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, - n_left_to_next, bi0, next0); - } - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - vlib_increment_combined_counter (vnm-> - interface_main.combined_sw_if_counters + - VNET_INTERFACE_COUNTER_RX, thread_index, - ppif->hw_if_index, n_rx_packets, - n_rx_bytes); - - if (PREDICT_FALSE (pp2_bpool_get_num_buffs (inq->bpool, &n_bufs))) - { - vlib_error_count (vm, node->node_index, - MRVL_PP2_INPUT_ERROR_BPOOL_GET_NUM_BUFFS, 1); - goto done; - } - - n_bufs = inq->size - n_bufs; - while (n_bufs >= MRVL_PP2_BUFF_BATCH_SZ) - { - u16 n_alloc, i; - struct buff_release_entry *e = ptd->bre; - u32 *buffers = ptd->buffers; - - n_alloc = vlib_buffer_alloc (vm, ptd->buffers, MRVL_PP2_BUFF_BATCH_SZ); - i = n_alloc; - - if (PREDICT_FALSE (n_alloc == 0)) - { - vlib_error_count (vm, node->node_index, - MRVL_PP2_INPUT_ERROR_BUFFER_ALLOC, 1); - goto done; - } - - while (i--) - { - u32 bi = buffers[0]; - vlib_buffer_t *b = vlib_get_buffer (vm, bi); - e->buff.addr = vlib_buffer_get_pa (vm, b) - 64; - e->buff.cookie = bi; - e->bpool = inq->bpool; - e++; - buffers++; - } - - i = n_alloc; - if (PREDICT_FALSE (pp2_bpool_put_buffs (ptd->hif, ptd->bre, &i))) - { - vlib_error_count (vm, node->node_index, - MRVL_PP2_INPUT_ERROR_BPOOL_PUT_BUFFS, 1); - vlib_buffer_free (vm, ptd->buffers, n_alloc); - goto done; - } - - if (PREDICT_FALSE (i != n_alloc)) - vlib_buffer_free (vm, ptd->buffers + i, n_alloc - i); - - n_bufs -= i; - } - -done: - return n_rx_packets; -} - -uword -mrvl_pp2_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_rx = 0; - mrvl_pp2_main_t *ppm = &mrvl_pp2_main; - vnet_hw_if_rxq_poll_vector_t *pv; - - pv = vnet_hw_if_get_rxq_poll_vector (vm, node); - - for (int i = 0; i < vec_len (pv); i++) - { - mrvl_pp2_if_t *ppif; - ppif = vec_elt_at_index (ppm->interfaces, pv[i].dev_instance); - if (ppif->flags & MRVL_PP2_IF_F_ADMIN_UP) - n_rx += - mrvl_pp2_device_input_inline (vm, node, frame, ppif, pv[i].queue_id); - } - return n_rx; -} - -VLIB_REGISTER_NODE (mrvl_pp2_input_node) = { - .function = mrvl_pp2_input_fn, - .flags = VLIB_NODE_FLAG_TRACE_SUPPORTED, - .name = "mrvl-pp2-input", - .sibling_of = "device-input", - .format_trace = format_mrvl_pp2_input_trace, - .type = VLIB_NODE_TYPE_INPUT, - .state = VLIB_NODE_STATE_POLLING, - .n_errors = MRVL_PP2_INPUT_N_ERROR, - .error_strings = mrvl_pp2_input_error_strings, -}; - - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/marvell/pp2/output.c b/src/plugins/marvell/pp2/output.c deleted file mode 100644 index 911b2f55a17..00000000000 --- a/src/plugins/marvell/pp2/output.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2018 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 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#include <stdint.h> -#include <net/if.h> -#include <sys/ioctl.h> -#include <sys/uio.h> - -#include <vlib/vlib.h> -#include <vlib/unix/unix.h> -#include <vnet/ethernet/ethernet.h> -#include <vnet/devices/devices.h> - -#include <marvell/pp2/pp2.h> - -uword -mrvl_pp2_interface_tx (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame) -{ - mrvl_pp2_main_t *ppm = &mrvl_pp2_main; - vnet_interface_output_runtime_t *rd = (void *) node->runtime_data; - mrvl_pp2_if_t *ppif = pool_elt_at_index (ppm->interfaces, rd->dev_instance); - u32 thread_index = vm->thread_index; - mrvl_pp2_per_thread_data_t *ptd = - vec_elt_at_index (ppm->per_thread_data, thread_index); - u8 qid = thread_index; - mrvl_pp2_outq_t *outq = vec_elt_at_index (ppif->outqs, qid); - u32 *buffers = vlib_frame_vector_args (frame); - u16 n_desc = frame->n_vectors, n_left = n_desc, n_sent = n_desc, n_done; - struct pp2_ppio_desc *d; - u16 mask = outq->size - 1; - - if (PREDICT_FALSE (pp2_ppio_get_num_outq_done (ppif->ppio, ptd->hif, qid, - &n_done))) - { - n_done = 0; - vlib_error_count (vm, node->node_index, - MRVL_PP2_TX_ERROR_PPIO_GET_NUM_OUTQ_DONE, 1); - } - - if (n_done) - { - u16 n_free = clib_min (n_done, outq->size - (outq->tail & mask)); - vlib_buffer_free (vm, outq->buffers + (outq->tail & mask), n_free); - if (PREDICT_FALSE (n_free < n_done)) - vlib_buffer_free (vm, outq->buffers, n_done - n_free); - outq->tail += n_done; - } - - vec_validate_aligned (ptd->descs, n_left, CLIB_CACHE_LINE_BYTES); - d = ptd->descs; - while (n_left) - { - u32 bi0 = buffers[0]; - vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0); - u64 paddr = vlib_buffer_get_pa (vm, b0); - - pp2_ppio_outq_desc_reset (d); - pp2_ppio_outq_desc_set_phys_addr (d, paddr + b0->current_data); - pp2_ppio_outq_desc_set_pkt_offset (d, 0); - pp2_ppio_outq_desc_set_pkt_len (d, b0->current_length); - d++; - buffers++; - n_left--; - } - - if (pp2_ppio_send (ppif->ppio, ptd->hif, qid, ptd->descs, &n_sent)) - { - n_sent = 0; - vlib_error_count (vm, node->node_index, MRVL_PP2_TX_ERROR_PPIO_SEND, 1); - } - - /* free unsent buffers */ - if (PREDICT_FALSE (n_sent != n_desc)) - { - vlib_buffer_free (vm, vlib_frame_vector_args (frame) + n_sent, - frame->n_vectors - n_sent); - vlib_error_count (vm, node->node_index, MRVL_PP2_TX_ERROR_NO_FREE_SLOTS, - frame->n_vectors - n_sent); - } - - /* store buffer index for each enqueued packet into the ring - so we can know what to free after packet is sent */ - if (n_sent) - { - u16 slot = outq->head & mask; - buffers = vlib_frame_vector_args (frame); - u16 n_copy = clib_min (outq->size - slot, n_sent); - - vlib_buffer_copy_indices (outq->buffers + slot, buffers, n_copy); - if (PREDICT_FALSE (n_copy < n_sent)) - clib_memcpy_fast (outq->buffers, buffers + n_copy, - (n_sent - n_copy) * sizeof (u32)); - - outq->head += n_sent; - } - - return n_sent; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/marvell/pp2/pp2.c b/src/plugins/marvell/pp2/pp2.c deleted file mode 100644 index 030ab9b4496..00000000000 --- a/src/plugins/marvell/pp2/pp2.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2018 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 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/ioctl.h> - -#include <vlib/vlib.h> -#include <vlib/unix/unix.h> -#include <vnet/plugin/plugin.h> -#include <marvell/pp2/pp2.h> -#include <vnet/interface/rx_queue_funcs.h> - -/* size of DMA memory used by musdk (not used for buffers) */ -#define MV_SYS_DMA_MEM_SZ (2 << 20) -/* number of HIFs reserved (first X) */ -#define NUM_HIFS_RSVD 4 -/* number of buffer pools reserved (first X) */ -#define NUM_BPOOLS_RSVD 7 - -mrvl_pp2_main_t mrvl_pp2_main; -extern vnet_device_class_t ppa2_device_class; - -static void -mrvl_pp2_main_deinit () -{ - mrvl_pp2_main_t *ppm = &mrvl_pp2_main; - int i; - vec_foreach_index (i, ppm->per_thread_data) - { - mrvl_pp2_per_thread_data_t *ptd = vec_elt_at_index (ppm->per_thread_data, - i); - if (ptd->hif) - pp2_hif_deinit (ptd->hif); - vec_free (ptd->descs); - } - vec_free (ppm->per_thread_data); - pp2_deinit (); - mv_sys_dma_mem_destroy (); -} - -static clib_error_t * -mrvl_pp2_main_init () -{ - mrvl_pp2_main_t *ppm = &mrvl_pp2_main; - vlib_thread_main_t *tm = vlib_get_thread_main (); - clib_error_t *err = 0; - struct pp2_init_params init_params = { 0 }; - int i, rv; - u8 *s = 0; - - rv = mv_sys_dma_mem_init (MV_SYS_DMA_MEM_SZ); - if (rv) - return clib_error_return (0, "mv_sys_dma_mem_init failed, rv = %u", rv); - - init_params.hif_reserved_map = ((1 << NUM_HIFS_RSVD) - 1); - init_params.bm_pool_reserved_map = ((1 << NUM_BPOOLS_RSVD) - 1); - rv = pp2_init (&init_params); - if (rv) - { - err = clib_error_return (0, "mrvl_pp2_init failed, rv = %u", rv); - goto done; - } - - vec_validate_aligned (ppm->per_thread_data, tm->n_vlib_mains - 1, - CLIB_CACHE_LINE_BYTES); - - vec_foreach_index (i, ppm->per_thread_data) - { - mrvl_pp2_per_thread_data_t *ptd = vec_elt_at_index (ppm->per_thread_data, - i); - struct pp2_hif_params hif_params = { 0 }; - vec_reset_length (s); - s = format (s, "hif-%d%c", NUM_HIFS_RSVD + i, 0); - hif_params.match = (char *) s; - hif_params.out_size = 2048; /* FIXME */ - if (pp2_hif_init (&hif_params, &ptd->hif)) - { - err = clib_error_return (0, "hif '%s' init failed", s); - goto done; - } - } - -done: - if (err) - mrvl_pp2_main_deinit (); - vec_free (s); - return err; -} - -static u32 -mrvl_pp2_eth_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi, - u32 flags) -{ - /* nothing for now */ - return 0; -} - -void -mrvl_pp2_delete_if (mrvl_pp2_if_t * ppif) -{ - vlib_main_t *vm = vlib_get_main (); - vnet_main_t *vnm = vnet_get_main (); - mrvl_pp2_main_t *ppm = &mrvl_pp2_main; - mrvl_pp2_outq_t *outq; - mrvl_pp2_inq_t *inq; - - if (ppif->hw_if_index != ~0) - ethernet_delete_interface (vnm, ppif->hw_if_index); - - if (ppif->ppio) - { - pp2_ppio_disable (ppif->ppio); - pp2_ppio_deinit (ppif->ppio); - } - - /* free buffers hanging in the tx ring */ - vec_foreach (outq, ppif->outqs) - { - while (outq->tail < outq->head) - { - u16 slot = outq->tail & (outq->size - 1); - vlib_buffer_free (vm, outq->buffers + slot, 1); - outq->tail++; - } - vec_free (outq->buffers); - } - vec_free (ppif->outqs); - - /* free buffers hangin in the rx buffer pool */ - vec_foreach (inq, ppif->inqs) - if (inq->bpool) - { - u32 n_bufs = 0; - pp2_bpool_get_num_buffs (inq->bpool, &n_bufs); - while (n_bufs--) - { - struct pp2_buff_inf binf; - if (pp2_bpool_get_buff (ppm->per_thread_data[0].hif, inq->bpool, - &binf) == 0) - { - u32 bi = binf.cookie; - vlib_buffer_free (vm, &bi, 1); - } - } - pp2_bpool_deinit (inq->bpool); - } - vec_free (ppif->inqs); - - - pool_put (ppm->interfaces, ppif); - - if (pool_elts (ppm->interfaces) == 0) - mrvl_pp2_main_deinit (); -} - -void -mrvl_pp2_create_if (mrvl_pp2_create_if_args_t * args) -{ - vlib_main_t *vm = vlib_get_main (); - vnet_main_t *vnm = vnet_get_main (); - vlib_thread_main_t *tm = vlib_get_thread_main (); - vnet_eth_interface_registration_t eir = {}; - mrvl_pp2_main_t *ppm = &mrvl_pp2_main; - struct pp2_bpool_params bpool_params = { 0 }; - struct pp2_ppio_params ppio_params = { 0 }; - struct pp2_ppio_inq_params inq_params = { 0 }; - vnet_sw_interface_t *sw; - mrvl_pp2_if_t *ppif = 0; - u8 pp2_id, port_id, *s = 0; - eth_addr_t mac_addr; - u8 n_outqs, n_inqs = 1; - int i; - - if (tm->n_vlib_mains > PP2_PPIO_MAX_NUM_OUTQS) - { - args->rv = VNET_API_ERROR_INIT_FAILED; - args->error = clib_error_return (0, "number of threads (main + workers)" - " is bigger than number of output " - "queues (%u)", PP2_PPIO_MAX_NUM_OUTQS); - return; - } - n_outqs = tm->n_vlib_mains; - - /* defaults */ - args->tx_q_sz = args->tx_q_sz ? args->tx_q_sz : 2 * VLIB_FRAME_SIZE; - args->rx_q_sz = args->rx_q_sz ? args->rx_q_sz : 2 * VLIB_FRAME_SIZE; - - if (vec_len (ppm->per_thread_data) == 0) - { - if ((args->error = mrvl_pp2_main_init ()) != 0) - { - args->rv = VNET_API_ERROR_INIT_FAILED; - return; - } - } - - pool_get_zero (ppm->interfaces, ppif); - ppif->dev_instance = ppif - ppm->interfaces; - ppif->hw_if_index = ~0; - vec_validate_aligned (ppif->inqs, n_inqs - 1, CLIB_CACHE_LINE_BYTES); - vec_validate_aligned (ppif->outqs, n_outqs - 1, CLIB_CACHE_LINE_BYTES); - - for (i = 0; i < n_inqs; i++) - { - mrvl_pp2_inq_t *inq = vec_elt_at_index (ppif->inqs, i); - inq->size = args->rx_q_sz; - } - for (i = 0; i < n_outqs; i++) - { - mrvl_pp2_outq_t *outq = vec_elt_at_index (ppif->outqs, i); - outq->size = args->tx_q_sz; - vec_validate_aligned (outq->buffers, outq->size, CLIB_CACHE_LINE_BYTES); - } - - if (pp2_netdev_get_ppio_info ((char *) args->name, &pp2_id, &port_id)) - { - args->rv = VNET_API_ERROR_INVALID_INTERFACE; - args->error = clib_error_return (0, "Invalid interface '%s'", - args->name); - goto error; - } - - /* FIXME bpool bit select per pp */ - s = format (s, "pool-%d:%d%c", pp2_id, pp2_id + 8, 0); - bpool_params.match = (char *) s; - bpool_params.buff_len = vlib_buffer_get_default_data_size (vm); - /* FIXME +64 ? */ - if (pp2_bpool_init (&bpool_params, &ppif->inqs[0].bpool)) - { - args->rv = VNET_API_ERROR_INIT_FAILED; - args->error = clib_error_return (0, "bpool '%s' init failed", s); - goto error; - } - vec_reset_length (s); - - s = format (s, "ppio-%d:%d%c", pp2_id, port_id, 0); - ppio_params.match = (char *) s; - ppio_params.type = PP2_PPIO_T_NIC; - inq_params.size = args->rx_q_sz; - ppio_params.inqs_params.num_tcs = 1; - ppio_params.inqs_params.tcs_params[0].pkt_offset = 0; - ppio_params.inqs_params.tcs_params[0].num_in_qs = n_inqs; - ppio_params.inqs_params.tcs_params[0].inqs_params = &inq_params; - ppio_params.inqs_params.tcs_params[0].pools[0][0] = ppif->inqs[0].bpool; - ppio_params.outqs_params.num_outqs = n_outqs; - for (i = 0; i < n_outqs; i++) - { - ppio_params.outqs_params.outqs_params[i].weight = 1; - ppio_params.outqs_params.outqs_params[i].size = args->tx_q_sz; - } - if (pp2_ppio_init (&ppio_params, &ppif->ppio)) - { - args->rv = VNET_API_ERROR_INIT_FAILED; - args->error = clib_error_return (0, "ppio '%s' init failed", s); - goto error; - } - vec_reset_length (s); - - if (pp2_ppio_get_mac_addr (ppif->ppio, mac_addr)) - { - args->rv = VNET_API_ERROR_INIT_FAILED; - args->error = - clib_error_return (0, "%s: pp2_ppio_get_mac_addr failed", s); - goto error; - } - - eir.dev_class_index = mrvl_pp2_device_class.index; - eir.dev_instance = ppif->dev_instance; - eir.address = mac_addr; - eir.cb.flag_change = mrvl_pp2_eth_flag_change; - ppif->hw_if_index = vnet_eth_register_interface (vnm, &eir); - - sw = vnet_get_hw_sw_interface (vnm, ppif->hw_if_index); - ppif->sw_if_index = sw->sw_if_index; - ppif->per_interface_next_index = ~0; - args->sw_if_index = sw->sw_if_index; - vnet_hw_if_set_input_node (vnm, ppif->hw_if_index, - mrvl_pp2_input_node.index); - /* FIXME: only one RX queue ? */ - ppif->inqs[0].queue_index = vnet_hw_if_register_rx_queue ( - vnm, ppif->hw_if_index, 0, VNET_HW_IF_RXQ_THREAD_ANY); - - vnet_hw_if_set_rx_queue_mode (vnm, ppif->inqs[0].queue_index, - VNET_HW_IF_RX_MODE_POLLING); - vnet_hw_if_update_runtime_data (vnm, ppif->hw_if_index); - vnet_hw_interface_set_flags (vnm, ppif->hw_if_index, - VNET_HW_INTERFACE_FLAG_LINK_UP); - goto done; - -error: - mrvl_pp2_delete_if (ppif); -done: - vec_free (s); -} - -static clib_error_t * -mrvl_pp2_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, - u32 flags) -{ - mrvl_pp2_main_t *ppm = &mrvl_pp2_main; - vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index); - mrvl_pp2_if_t *ppif = pool_elt_at_index (ppm->interfaces, hw->dev_instance); - static clib_error_t *error = 0; - int is_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0; - int rv; - - if (is_up) - rv = pp2_ppio_enable (ppif->ppio); - else - rv = pp2_ppio_disable (ppif->ppio); - - if (rv) - return clib_error_return (0, "failed to %s interface", - is_up ? "enable" : "disable"); - - if (is_up) - ppif->flags |= MRVL_PP2_IF_F_ADMIN_UP; - else - ppif->flags &= ~MRVL_PP2_IF_F_ADMIN_UP; - - return error; -} - -static void -mrvl_pp2_clear_interface_counters (u32 instance) -{ - mrvl_pp2_main_t *ppm = &mrvl_pp2_main; - mrvl_pp2_if_t *ppif = pool_elt_at_index (ppm->interfaces, instance); - struct pp2_ppio_statistics stats; - - pp2_ppio_get_statistics (ppif->ppio, &stats, 1); -} - -static void -mrvl_pp2_set_interface_next_node (vnet_main_t * vnm, u32 hw_if_index, - u32 node_index) -{ - mrvl_pp2_main_t *ppm = &mrvl_pp2_main; - vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index); - mrvl_pp2_if_t *ppif = pool_elt_at_index (ppm->interfaces, hw->dev_instance); - - /* Shut off redirection */ - if (node_index == ~0) - { - ppif->per_interface_next_index = node_index; - return; - } - - ppif->per_interface_next_index = - vlib_node_add_next (vlib_get_main (), mrvl_pp2_input_node.index, - node_index); -} - -static char *mrvl_pp2_tx_func_error_strings[] = { -#define _(n,s) s, - foreach_mrvl_pp2_tx_func_error -#undef _ -}; - -VNET_DEVICE_CLASS (mrvl_pp2_device_class,) = -{ - .name = "Marvell PPv2 interface", - .format_device_name = format_mrvl_pp2_interface_name, - .format_device = format_mrvl_pp2_interface, - .tx_function = mrvl_pp2_interface_tx, - .tx_function_n_errors = MRVL_PP2_TX_N_ERROR, - .tx_function_error_strings = mrvl_pp2_tx_func_error_strings, - .admin_up_down_function = mrvl_pp2_interface_admin_up_down, - .clear_counters = mrvl_pp2_clear_interface_counters, - .rx_redirect_to_node = mrvl_pp2_set_interface_next_node, -}; - -static clib_error_t * -mrvl_pp2_init (vlib_main_t * vm) -{ - return 0; -} - -VLIB_INIT_FUNCTION (mrvl_pp2_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/marvell/pp2/pp2.h b/src/plugins/marvell/pp2/pp2.h deleted file mode 100644 index abb8e573a37..00000000000 --- a/src/plugins/marvell/pp2/pp2.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2018 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 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#define MVCONF_DBG_LEVEL 0 -#define MVCONF_PP2_BPOOL_COOKIE_SIZE 32 -#define MVCONF_PP2_BPOOL_DMA_ADDR_SIZE 64 -#define MVCONF_DMA_PHYS_ADDR_T_SIZE 64 -#define MVCONF_SYS_DMA_UIO -#define MVCONF_TYPES_PUBLIC -#define MVCONF_DMA_PHYS_ADDR_T_PUBLIC - -#include <vlib/vlib.h> - -#include "mv_std.h" -#include "env/mv_sys_dma.h" -#include "drivers/mv_pp2.h" -#include <drivers/mv_pp2_bpool.h> -#include <drivers/mv_pp2_ppio.h> - -typedef struct -{ - CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); - u16 size; - u32 queue_index; - struct pp2_bpool *bpool; -} mrvl_pp2_inq_t; - -typedef struct -{ - CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); - u16 size; - u32 *buffers; - u16 head; - u16 tail; -} mrvl_pp2_outq_t; - -typedef struct -{ - CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); - u32 flags; -#define MRVL_PP2_IF_F_ADMIN_UP (1 << 0) - struct pp2_ppio *ppio; - u32 per_interface_next_index; - - mrvl_pp2_inq_t *inqs; - mrvl_pp2_outq_t *outqs; - - u32 dev_instance; - u32 sw_if_index; - u32 hw_if_index; -} mrvl_pp2_if_t; - -#define MRVL_PP2_BUFF_BATCH_SZ VLIB_FRAME_SIZE - -typedef struct -{ - CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); - struct pp2_hif *hif; - struct pp2_ppio_desc *descs; - struct buff_release_entry bre[MRVL_PP2_BUFF_BATCH_SZ]; - u32 buffers[VLIB_FRAME_SIZE]; -} mrvl_pp2_per_thread_data_t; - -typedef struct -{ - mrvl_pp2_if_t *interfaces; - mrvl_pp2_per_thread_data_t *per_thread_data; - - /* API message ID base */ - u16 msg_id_base; -} mrvl_pp2_main_t; - -extern vnet_device_class_t mrvl_pp2_device_class; -extern mrvl_pp2_main_t mrvl_pp2_main; - -typedef struct -{ - u8 *name; - u16 rx_q_sz; - u16 tx_q_sz; - - /* return */ - i32 rv; - u32 sw_if_index; - clib_error_t *error; -} mrvl_pp2_create_if_args_t; - -void mrvl_pp2_create_if (mrvl_pp2_create_if_args_t * args); -void mrvl_pp2_delete_if (mrvl_pp2_if_t * dfif); -clib_error_t *mrvl_pp2_plugin_api_hookup (vlib_main_t * vm); - -/* output.c */ - -#define foreach_mrvl_pp2_tx_func_error \ - _(NO_FREE_SLOTS, "no free tx slots") \ - _(PPIO_SEND, "pp2_ppio_send errors") \ - _(PPIO_GET_NUM_OUTQ_DONE, "pp2_ppio_get_num_outq_done errors") - -typedef enum -{ -#define _(f,s) MRVL_PP2_TX_ERROR_##f, - foreach_mrvl_pp2_tx_func_error -#undef _ - MRVL_PP2_TX_N_ERROR, -} mrvl_pp2_tx_func_error_t; - -uword mrvl_pp2_interface_tx (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame); - -/* input.c */ - -typedef struct -{ - u32 next_index; - u32 hw_if_index; - struct pp2_ppio_desc desc; -} mrvl_pp2_input_trace_t; - -extern vlib_node_registration_t mrvl_pp2_input_node; - -/* format.c */ -format_function_t format_mrvl_pp2_input_trace; -format_function_t format_mrvl_pp2_interface; -format_function_t format_mrvl_pp2_interface_name; - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/marvell/pp2/pp2_api.c b/src/plugins/marvell/pp2/pp2_api.c deleted file mode 100644 index c1f3a9e1d1d..00000000000 --- a/src/plugins/marvell/pp2/pp2_api.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2019 Arm Limited. - * 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 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#include <vlib/vlib.h> -#include <vlib/unix/unix.h> -#include <vnet/ethernet/ethernet.h> - -#include <marvell/pp2/pp2.h> - -#include <vlibapi/api.h> -#include <vlibmemory/api.h> - -/* define message IDs */ -#include <marvell/pp2/pp2.api_enum.h> -#include <marvell/pp2/pp2.api_types.h> - -#define REPLY_MSG_ID_BASE (pp2->msg_id_base) -#include <vlibapi/api_helper_macros.h> - -static void -vl_api_mrvl_pp2_create_t_handler (vl_api_mrvl_pp2_create_t * mp) -{ - mrvl_pp2_main_t *pp2 = &mrvl_pp2_main; - mrvl_pp2_create_if_args_t args = { 0 }; - vl_api_mrvl_pp2_create_reply_t *rmp; - int rv; - - args.name = format (0, "%s", mp->if_name); - args.rx_q_sz = ntohs (mp->rx_q_sz); - args.tx_q_sz = ntohs (mp->tx_q_sz); - mrvl_pp2_create_if (&args); - rv = args.rv; - vec_free (args.name); - if (args.error) - { - clib_error_free (args.error); - } - REPLY_MACRO2 (VL_API_MRVL_PP2_CREATE_REPLY, - ({ rmp->sw_if_index = ntohl (args.sw_if_index); })); -} - -static void -vl_api_mrvl_pp2_delete_t_handler (vl_api_mrvl_pp2_delete_t * mp) -{ - vnet_main_t *vnm = vnet_get_main (); - vnet_hw_interface_t *hw; - mrvl_pp2_main_t *pp2 = &mrvl_pp2_main; - vl_api_mrvl_pp2_delete_reply_t *rmp; - mrvl_pp2_if_t *dif; - int rv = 0; - mp->sw_if_index = ntohl (mp->sw_if_index); - hw = vnet_get_sup_hw_interface (vnm, mp->sw_if_index); - if (hw == NULL || mrvl_pp2_device_class.index != hw->dev_class_index) - { - rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; - goto reply; - } - - dif = pool_elt_at_index (pp2->interfaces, hw->dev_instance); - - mrvl_pp2_delete_if (dif); - -reply: - REPLY_MACRO (VL_API_MRVL_PP2_DELETE_REPLY); -} - -#include <marvell/pp2/pp2.api.c> -/* set up the API message handling tables */ -clib_error_t * -mrvl_pp2_plugin_api_hookup (vlib_main_t * vm) -{ - mrvl_pp2_main_t *pp2 = &mrvl_pp2_main; - - /* ask for a correctly-sized block of API message decode slots */ - pp2->msg_id_base = setup_message_id_table (); - - return 0; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/marvell/pp2/pp2_test.c b/src/plugins/marvell/pp2/pp2_test.c deleted file mode 100644 index 26a9e9a6e34..00000000000 --- a/src/plugins/marvell/pp2/pp2_test.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2019 Arm Limited. - * 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 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#include <vlib/vlib.h> -#include <vlib/unix/unix.h> -#include <vnet/ethernet/ethernet.h> - -#include <vat/vat.h> -#include <vlibapi/api.h> -#include <vlibmemory/api.h> - -#include <vppinfra/error.h> -#include <marvell/pp2/pp2.h> - -#define __plugin_msg_base pp2_test_main.msg_id_base -#include <vlibapi/vat_helper_macros.h> - -/* declare message IDs */ -#include <marvell/pp2/pp2.api_enum.h> -#include <marvell/pp2/pp2.api_types.h> - -typedef struct -{ - /* API message ID base */ - u16 msg_id_base; - vat_main_t *vat_main; -} pp2_test_main_t; - -pp2_test_main_t pp2_test_main; - -/* mrvl_pp2 create API */ -static int -api_mrvl_pp2_create (vat_main_t * vam) -{ - unformat_input_t *i = vam->input; - vl_api_mrvl_pp2_create_t *mp; - mrvl_pp2_create_if_args_t args; - int ret; - u16 size; - - clib_memset (&args, 0, sizeof (mrvl_pp2_create_if_args_t)); - while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) - { - if (unformat (i, "name %s", &args.name)) - ; - else if (unformat (i, "rx-queue-size %u", &size)) - args.rx_q_sz = size; - else if (unformat (i, "tx-queue-size %u", &size)) - args.tx_q_sz = size; - else - { - clib_warning ("unknown input '%U'", format_unformat_error, i); - return -99; - } - } - - M (MRVL_PP2_CREATE, mp); - - strncpy_s ((char *) mp->if_name, ARRAY_LEN (mp->if_name), - (char *) (args.name), strlen ((char *) args.name)); - mp->rx_q_sz = clib_host_to_net_u16 (args.rx_q_sz); - mp->tx_q_sz = clib_host_to_net_u16 (args.tx_q_sz); - - S (mp); - W (ret); - - vec_free (args.name); - - return ret; -} - -/* mrvl_pp2 create reply handler */ -static void -vl_api_mrvl_pp2_create_reply_t_handler (vl_api_mrvl_pp2_create_reply_t * mp) -{ - vat_main_t *vam = pp2_test_main.vat_main; - i32 retval = ntohl (mp->retval); - - if (retval == 0) - { - fformat (vam->ofp, "created mrvl_pp2 with sw_if_index %d\n", - ntohl (mp->sw_if_index)); - } - - vam->retval = retval; - vam->result_ready = 1; - vam->regenerate_interface_table = 1; -} - - -/* mrvl_pp2 delete API */ -static int -api_mrvl_pp2_delete (vat_main_t * vam) -{ - unformat_input_t *i = vam->input; - //vnet_main_t *vnm = vnet_get_main (); - vl_api_mrvl_pp2_delete_t *mp; - u32 sw_if_index = 0; - int ret; - - while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) - { - if (unformat (i, "sw_if_index %d", &sw_if_index)) - ; - else - { - clib_warning ("unknown input '%U'", format_unformat_error, i); - return -99; - } - } - - M (MRVL_PP2_DELETE, mp); - - mp->sw_if_index = clib_host_to_net_u32 (sw_if_index); - - S (mp); - W (ret); - - return ret; -} - -#include <marvell/pp2/pp2.api_test.c> - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/dev/errors.h b/src/vnet/dev/errors.h index 430a6aef282..6ececad12ec 100644 --- a/src/vnet/dev/errors.h +++ b/src/vnet/dev/errors.h @@ -41,6 +41,7 @@ _ (UNSUPPORTED_DEVICE, "unsupported device") \ _ (UNSUPPORTED_DEVICE_VER, "unsupported device version") \ _ (ALREADY_DONE, "already done") \ - _ (NO_SUCH_INTERFACE, "no such interface") + _ (NO_SUCH_INTERFACE, "no such interface") \ + _ (INIT_FAILED, "init failed") #endif /* _VNET_DEV_ERRORS_H_ */ |