From patchwork Thu Sep 20 09:05:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Ostruszka X-Patchwork-Id: 44996 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 1D0715F48; Thu, 20 Sep 2018 11:05:47 +0200 (CEST) Received: from mail-lj1-f194.google.com (mail-lj1-f194.google.com [209.85.208.194]) by dpdk.org (Postfix) with ESMTP id 3097C5F2E for ; Thu, 20 Sep 2018 11:05:44 +0200 (CEST) Received: by mail-lj1-f194.google.com with SMTP id p6-v6so7675033ljc.5 for ; Thu, 20 Sep 2018 02:05:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=2SCvZEKjWUcJ9WWqcsH8Jg1e1qPrrUxFvJGu5BXB9s8=; b=LwMni8T8l1vA39QiWPoTjAN1ak36QukDmdtRLCjcarf9fR3j8xejlAaeInDJc8XVPp TMhROhXC52BDOwf9YiAa4/dBFbOMa2a44iDr89HL0DD6nV9loZR4KzK27iaPfGT5gM7a 9mYBgBai9FUA5/WtONWKWEZYzKNPSdMse5KfuSZKf6uhjVuGlvw3kPVDw+RvJ/WiB56j /VHWVvVXnp3B0WpLYaNlf67hS8vz+EOYOMwPypNYtYuG4+YVMUuKVcGTCcx/k3VnOt+3 HZfvdQXdLxNLSdMQBnV1uwzTbCDsj+2xHvHOSuKXe8w2G9pq4OPTveEtLRQ4vw6HVakr UeEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=2SCvZEKjWUcJ9WWqcsH8Jg1e1qPrrUxFvJGu5BXB9s8=; b=Abc/MolXEGXyXHgxD+Owagoj7uyrS2aiugtIhZxqsS0xquItZDfBj5IAu4Z2FBMH9h KMOe9NcSIti9c/u3rtUSgHFKnfWgbu3/UFEY84aOJGUv4bUHaF+mBIOq/KnXVMhO6qqS F9cUpoV7RfQJaOE9ZELUsoPVL5tKL9WDGZRBYltYUhGEXGcBEKVSPPIksAWvtnim7t5D pRy2BKSo6Vohs72coBLQNQ4Xnj7dKt71frqoe5UHdpHV3vK9ssuSHzPpK8mt6y+4D+wC +KYRMSreu3B0VwtC0mfA4CPJXqMDvAg+9oXBDIx879me/tqLELxyR8YdVs42b6bmOJw6 UieA== X-Gm-Message-State: APzg51CxDXL/esY8UtIzdJwg7weDB8CIFcx4Se7EwjX2NhIE4SXnheQS 0gM4Ceq3mKYtjSKvgmucwWAZMaw1cDM= X-Google-Smtp-Source: ANB0VdYd39phn9hRAuavwakzCbMoCa/eKpLI7sPAJTaHvT36eYi32OVxQw52Aes6TcLrYBkUqOhujw== X-Received: by 2002:a2e:8457:: with SMTP id u23-v6mr23683547ljh.95.1537434343072; Thu, 20 Sep 2018 02:05:43 -0700 (PDT) Received: from amok.semihalf.local (31-172-191-173.noc.fibertech.net.pl. [31.172.191.173]) by smtp.googlemail.com with ESMTPSA id g16-v6sm4338106lje.1.2018.09.20.02.05.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 20 Sep 2018 02:05:42 -0700 (PDT) From: Andrzej Ostruszka To: dev@dpdk.org Cc: mw@semihalf.com, zr@semihalf.com, tdu@semihalf.com, nadavh@marvell.com Date: Thu, 20 Sep 2018 11:05:32 +0200 Message-Id: <1537434339-22570-2-git-send-email-amo@semihalf.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1537434339-22570-1-git-send-email-amo@semihalf.com> References: <1537369294-17099-1-git-send-email-amo@semihalf.com> <1537434339-22570-1-git-send-email-amo@semihalf.com> Subject: [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Zyta Szpak Add neta pmd driver skeleton providing base for the further development. Signed-off-by: Natalie Samsonov Signed-off-by: Yelena Krivosheev Signed-off-by: Dmitri Epshtein Signed-off-by: Zyta Szpak Signed-off-by: Andrzej Ostruszka --- MAINTAINERS | 8 + config/common_base | 5 + devtools/test-build.sh | 2 + doc/guides/nics/features/mvneta.ini | 11 + doc/guides/nics/mvneta.rst | 152 +++++++ doc/guides/rel_notes/release_18_11.rst | 4 + drivers/common/Makefile | 4 +- drivers/common/mvep/rte_mvep_common.h | 1 + drivers/net/Makefile | 1 + drivers/net/meson.build | 1 + drivers/net/mvneta/Makefile | 42 ++ drivers/net/mvneta/meson.build | 27 ++ drivers/net/mvneta/mvneta_ethdev.c | 629 ++++++++++++++++++++++++++ drivers/net/mvneta/mvneta_ethdev.h | 75 +++ drivers/net/mvneta/rte_pmd_mvneta_version.map | 3 + mk/rte.app.mk | 7 +- 16 files changed, 969 insertions(+), 3 deletions(-) create mode 100644 doc/guides/nics/features/mvneta.ini create mode 100644 doc/guides/nics/mvneta.rst create mode 100644 drivers/net/mvneta/Makefile create mode 100644 drivers/net/mvneta/meson.build create mode 100644 drivers/net/mvneta/mvneta_ethdev.c create mode 100644 drivers/net/mvneta/mvneta_ethdev.h create mode 100644 drivers/net/mvneta/rte_pmd_mvneta_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 5967c1d..bbc4d40 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -586,6 +586,14 @@ F: drivers/net/mvpp2/ F: doc/guides/nics/mvpp2.rst F: doc/guides/nics/features/mvpp2.ini +Marvell mvneta +M: Zyta Szpak +M: Dmitri Epshtein +M: Natalie Samsonov +F: drivers/net/mvneta/ +F: doc/guides/nics/mvneta.rst +F: doc/guides/nics/features/mvneta.ini + Mellanox mlx4 M: Matan Azrad M: Shahaf Shuler diff --git a/config/common_base b/config/common_base index 155c7d4..1f8410b 100644 --- a/config/common_base +++ b/config/common_base @@ -400,6 +400,11 @@ CONFIG_RTE_LIBRTE_PMD_FAILSAFE=y CONFIG_RTE_LIBRTE_MVPP2_PMD=n # +# Compile Marvell MVNETA PMD driver +# +CONFIG_RTE_LIBRTE_MVNETA_PMD=n + +# # Compile support for VMBus library # CONFIG_RTE_LIBRTE_VMBUS=n diff --git a/devtools/test-build.sh b/devtools/test-build.sh index 1eee241..2990978 100755 --- a/devtools/test-build.sh +++ b/devtools/test-build.sh @@ -182,6 +182,8 @@ config () # sed -ri 's,(PMD_MVSAM_CRYPTO=)n,\1y,' $1/.config test -z "$LIBMUSDK_PATH" || \ sed -ri 's,(MVPP2_PMD=)n,\1y,' $1/.config + test -z "$LIBMUSDK_PATH" || \ + sed -ri 's,(MVNETA_PMD=)n,\1y,' $1/.config build_config_hook $1 $2 $3 # Explicit enabler/disabler (uppercase) diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini new file mode 100644 index 0000000..ba6fe4b --- /dev/null +++ b/doc/guides/nics/features/mvneta.ini @@ -0,0 +1,11 @@ +; +; Supported features of the 'mvneta' network poll mode driver. +; +; Refer to default.ini for the full list of available PMD features. +; +[Features] +Speed capabilities = Y +Jumbo frame = Y +CRC offload = Y +ARMv8 = Y +Usage doc = Y diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst new file mode 100644 index 0000000..bf08417 --- /dev/null +++ b/doc/guides/nics/mvneta.rst @@ -0,0 +1,152 @@ +.. SPDX-License-Identifier: BSD-3-Clause + Copyright(c) 2018 Marvell International Ltd. + Copyright(c) 2018 Semihalf. + All rights reserved. + +MVNETA Poll Mode Driver +======================= + +The MVNETA PMD (librte_pmd_mvneta) provides poll mode driver support +for the Marvell NETA 1/2.5 Gbps adapter. + +Detailed information about SoCs that use PPv2 can be obtained here: + +* https://www.marvell.com/embedded-processors/armada-3700/ + +.. Note:: + + Due to external dependencies, this driver is disabled by default. It must + be enabled manually by setting relevant configuration option manually. + Please refer to `Config File Options`_ section for further details. + + +Features +-------- + +Features of the MVNETA PMD are: + +- Start/stop +- tx/rx_queue_setup +- Speed capabilities +- Jumbo frame +- CRC offload + + +Limitations +----------- + +- Flushing vlans added for filtering is not possible due to MUSDK missing + functionality. Current workaround is to reset board so that NETA has a + chance to start in a sane state. + +Prerequisites +------------- + +- Custom Linux Kernel sources + + .. code-block:: console + + git clone https://github.com/MarvellEmbeddedProcessors/linux-marvell.git -b linux-4.4.52-armada-17.10 + + +- MUSDK (Marvell User-Space SDK) sources + + .. code-block:: console + + git clone git@github.com:Semihalf/marvell-dpdk.git -b musdk-armada-17.10-mvneta + + MUSDK is a light-weight library that provides direct access to Marvell's + NETA. Alternatively prebuilt MUSDK library can be + requested from `Marvell Extranet `_. Once + approval has been granted, library can be found by typing ``musdk`` in + the search box. + + MUSDK must be configured with the following features: + + .. code-block:: console + + --enable-bpool-dma=64 --enable-pp2=no --enable-neta + +- DPDK environment + + Follow the DPDK :ref:`Getting Started Guide for Linux ` to setup + DPDK environment. + + +Config File Options +------------------- + +The following options can be modified in the ``config`` file. + +- ``CONFIG_RTE_LIBRTE_MVNETA_PMD`` (default ``n``) + + Toggle compilation of the librte_pmd_mvneta driver. + + +Usage example +^^^^^^^^^^^^^ + +.. code-block:: console + + ./testpmd --vdev=net_mvneta,iface=eth0,iface=eth1 \ + -c 3 -- -i --p 3 -a + + +Building DPDK +------------- + +Driver needs precompiled MUSDK library during compilation. + +.. code-block:: console + + export CROSS_COMPILE=/bin/aarch64-linux-gnu- + ./bootstrap + ./configure --host=aarch64-linux-gnu --enable-bpool-dma=64 + make install + +MUSDK will be installed to `usr/local` under current directory. +For the detailed build instructions please consult ``doc/musdk_get_started.txt``. + +Before the DPDK build process the environmental variable ``LIBMUSDK_PATH`` with +the path to the MUSDK installation directory needs to be exported. + +.. code-block:: console + + export LIBMUSDK_PATH=/usr/local + export CROSS=aarch64-linux-gnu- + make config T=arm64-armv8a-linuxapp-gcc + sed -ri 's,(MVNETA_PMD=)n,\1y,' build/.config + make + +Usage Example +------------- + +MVNETA PMD requires extra out of tree kernel modules to function properly. +`musdk_uio` and `mv_neta_uio` sources are part of the MUSDK. Please consult +``doc/musdk_get_started.txt`` for the detailed build instructions. + +.. code-block:: console + + insmod musdk_uio.ko + insmod mv_neta_uio.ko + +Additionally interfaces used by DPDK application need to be put up: + +.. code-block:: console + + ip link set eth0 up + ip link set eth1 up + +In order to run testpmd example application following command can be used: + +.. code-block:: console + + ./testpmd --vdev=net_mvneta,iface=eth0,iface=eth1 -c 3 -- \ + -i --p 3 -a --txd 256 --rxd 128 --rxq=1 --txq=1 --nb-cores=1 + + +In order to run l2fwd example application following command can be used: + +.. code-block:: console + + ./l2fwd --vdev=net_mvneta,iface=eth0,iface=eth1 -c 3 -- -T 1 -p 3 diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst index 8c4bb54..5f51a8a 100644 --- a/doc/guides/rel_notes/release_18_11.rst +++ b/doc/guides/rel_notes/release_18_11.rst @@ -67,6 +67,10 @@ New Features SR-IOV option in Hyper-V and Azure. This is an alternative to the previous vdev_netvsc, tap, and failsafe drivers combination. +* **Added a new net driver for Marvell Armada 3k device.** + + Added the new ``mvneta`` net driver for Marvell Armada 3k device. See the + :doc:`../nics/mvneta` NIC guide for more details on this new driver. API Changes ----------- diff --git a/drivers/common/Makefile b/drivers/common/Makefile index 5f72da0..b498c23 100644 --- a/drivers/common/Makefile +++ b/drivers/common/Makefile @@ -8,7 +8,9 @@ ifeq ($(CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF)$(CONFIG_RTE_LIBRTE_OCTEONTX_MEMPOO DIRS-y += octeontx endif -ifeq ($(CONFIG_RTE_LIBRTE_MVPP2_PMD),y) +MVEP-y := $(CONFIG_RTE_LIBRTE_MVPP2_PMD) +MVEP-y += $(CONFIG_RTE_LIBRTE_MVNETA_PMD) +ifneq (,$(findstring y,$(MVEP-y))) DIRS-y += mvep endif diff --git a/drivers/common/mvep/rte_mvep_common.h b/drivers/common/mvep/rte_mvep_common.h index ba47e16..0593cef 100644 --- a/drivers/common/mvep/rte_mvep_common.h +++ b/drivers/common/mvep/rte_mvep_common.h @@ -11,6 +11,7 @@ enum mvep_module_type { MVEP_MOD_T_NONE = 0, MVEP_MOD_T_PP2, MVEP_MOD_T_SAM, + MVEP_MOD_T_NETA, MVEP_MOD_T_LAST }; diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 664398d..0d2c5b8 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -33,6 +33,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_LIO_PMD) += liquidio DIRS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += mlx4 DIRS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5 DIRS-$(CONFIG_RTE_LIBRTE_MVPP2_PMD) += mvpp2 +DIRS-$(CONFIG_RTE_LIBRTE_MVNETA_PMD) += mvneta DIRS-$(CONFIG_RTE_LIBRTE_NETVSC_PMD) += netvsc DIRS-$(CONFIG_RTE_LIBRTE_NFP_PMD) += nfp DIRS-$(CONFIG_RTE_LIBRTE_BNXT_PMD) += bnxt diff --git a/drivers/net/meson.build b/drivers/net/meson.build index 9c28ed4..852a720 100644 --- a/drivers/net/meson.build +++ b/drivers/net/meson.build @@ -19,6 +19,7 @@ drivers = ['af_packet', 'kni', 'liquidio', 'mvpp2', + 'mvneta', 'netvsc', 'nfp', 'null', 'octeontx', 'pcap', 'ring', diff --git a/drivers/net/mvneta/Makefile b/drivers/net/mvneta/Makefile new file mode 100644 index 0000000..149992e --- /dev/null +++ b/drivers/net/mvneta/Makefile @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Marvell International Ltd. +# Copyright(c) 2018 Semihalf. +# All rights reserved. + +include $(RTE_SDK)/mk/rte.vars.mk + +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(MAKECMDGOALS),config) +ifeq ($(LIBMUSDK_PATH),) +$(error "Please define LIBMUSDK_PATH environment variable") +endif +endif +endif + +# library name +LIB = librte_pmd_mvneta.a + +# library version +LIBABIVER := 1 + +# versioning export map +EXPORT_MAP := rte_pmd_mvneta_version.map + +# external library dependencies +CFLAGS += -I$(RTE_SDK)/drivers/common/mvep +CFLAGS += -I$(LIBMUSDK_PATH)/include +CFLAGS += -DMVCONF_TYPES_PUBLIC +CFLAGS += -DMVCONF_DMA_PHYS_ADDR_T_PUBLIC +CFLAGS += -DMVCONF_DMA_PHYS_ADDR_T_SIZE=64 +CFLAGS += $(WERROR_FLAGS) +CFLAGS += -O3 +LDLIBS += -L$(LIBMUSDK_PATH)/lib +LDLIBS += -lmusdk +LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring +LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs -lrte_cfgfile +LDLIBS += -lrte_bus_vdev + +# library source files +SRCS-$(CONFIG_RTE_LIBRTE_MVNETA_PMD) += mvneta_ethdev.c + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/drivers/net/mvneta/meson.build b/drivers/net/mvneta/meson.build new file mode 100644 index 0000000..2f31954 --- /dev/null +++ b/drivers/net/mvneta/meson.build @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Marvell International Ltd. +# Copyright(c) 2018 Semihalf. +# All rights reserved. + +path = get_option('lib_musdk_dir') +lib_dir = path + '/lib' +inc_dir = path + '/include' + +lib = cc.find_library('libmusdk', dirs : [lib_dir], required: false) +if not lib.found() + build = false +else + ext_deps += lib + includes += include_directories(inc_dir) + cflags += [ + '-DMVCONF_TYPES_PUBLIC', + '-DMVCONF_DMA_PHYS_ADDR_T_PUBLIC', + '-DMVCONF_DMA_PHYS_ADDR_T_SIZE=64' + ] +endif + +sources = files( + 'mvneta_ethdev.c' +) + +deps += ['cfgfile', 'common_mvep'] diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c new file mode 100644 index 0000000..9ee197a --- /dev/null +++ b/drivers/net/mvneta/mvneta_ethdev.c @@ -0,0 +1,629 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Marvell International Ltd. + * Copyright(c) 2018 Semihalf. + * All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "mvneta_ethdev.h" + + +#define MVNETA_IFACE_NAME_ARG "iface" + +#define MVNETA_RX_OFFLOADS (DEV_RX_OFFLOAD_JUMBO_FRAME | \ + DEV_RX_OFFLOAD_CHECKSUM) + +/** Port Tx offloads capabilities */ +#define MVNETA_TX_OFFLOADS (DEV_TX_OFFLOAD_IPV4_CKSUM | \ + DEV_TX_OFFLOAD_UDP_CKSUM | \ + DEV_TX_OFFLOAD_TCP_CKSUM | \ + DEV_TX_OFFLOAD_MULTI_SEGS) + +#define MVNETA_PKT_SIZE_MAX (16382 - MV_MH_SIZE) /* 9700B */ +#define MVNETA_DEFAULT_MTU 1500 + +#define MVNETA_MAC_ADDRS_MAX 256 /*16 UC, 256 IP, 256 MC/BC */ +/** Maximum length of a match string */ +#define MVNETA_MATCH_LEN 16 + +int mvneta_logtype; + +static const char * const valid_args[] = { + MVNETA_IFACE_NAME_ARG, + NULL +}; + +struct mvneta_ifnames { + const char *names[NETA_NUM_ETH_PPIO]; + int idx; +}; + +static int mvneta_dev_num; +static int mvneta_lcore_first; +static int mvneta_lcore_last; + +/** + * Deinitialize packet processor. + */ +static void +mvneta_neta_deinit(void) +{ + neta_deinit(); +} + +/** + * Initialize packet processor. + * + * @return + * 0 on success, negative error value otherwise. + */ +static int +mvneta_neta_init(void) +{ + return neta_init(); +} + +/** + * Callback used by rte_kvargs_process() during argument parsing. + * + * @param key + * Pointer to the parsed key (unused). + * @param value + * Pointer to the parsed value. + * @param extra_args + * Pointer to the extra arguments which contains address of the + * table of pointers to parsed interface names. + * + * @return + * Always 0. + */ +static int +mvneta_ifnames_get(const char *key __rte_unused, const char *value, + void *extra_args) +{ + struct mvneta_ifnames *ifnames = extra_args; + + ifnames->names[ifnames->idx++] = value; + + return 0; +} + +/** + * Ethernet device configuration. + * + * Prepare the driver for a given number of TX and RX queues and + * configure RSS if supported. + * + * @param dev + * Pointer to Ethernet device structure. + * + * @return + * 0 on success, negative error value otherwise. + */ +static int +mvneta_dev_configure(struct rte_eth_dev *dev) +{ + struct mvneta_priv *priv = dev->data->dev_private; + struct neta_ppio_params *ppio_params; + + if (dev->data->dev_conf.rxmode.mq_mode != ETH_MQ_RX_NONE) { + MVNETA_LOG(INFO, "Unsupported RSS and rx multi queue mode %d", + dev->data->dev_conf.rxmode.mq_mode); + if (dev->data->nb_rx_queues > 1) + return -EINVAL; + } + + if (dev->data->dev_conf.rxmode.split_hdr_size) { + MVNETA_LOG(INFO, "Split headers not supported"); + return -EINVAL; + } + + if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) + dev->data->mtu = dev->data->dev_conf.rxmode.max_rx_pkt_len - + MRVL_NETA_ETH_HDRS_LEN; + + if (dev->data->dev_conf.txmode.offloads & DEV_TX_OFFLOAD_MULTI_SEGS) + priv->multiseg = 1; + + ppio_params = &priv->ppio_params; + ppio_params->outqs_params.num_outqs = dev->data->nb_tx_queues; + priv->nb_rx_queues = dev->data->nb_rx_queues; + /* Default: 1 TC, no QoS supported. */ + ppio_params->inqs_params.num_tcs = 1; + ppio_params->inqs_params.tcs_params[0].pkt_offset = MRVL_NETA_PKT_OFFS; + priv->ppio_id = dev->data->port_id; + + return 0; +} + +/** + * DPDK callback to get information about the device. + * + * @param dev + * Pointer to Ethernet device structure (unused). + * @param info + * Info structure output buffer. + */ +static void +mvneta_dev_infos_get(struct rte_eth_dev *dev __rte_unused, + struct rte_eth_dev_info *info) +{ + info->speed_capa = ETH_LINK_SPEED_10M | + ETH_LINK_SPEED_100M | + ETH_LINK_SPEED_1G | + ETH_LINK_SPEED_2_5G; + + info->max_rx_queues = MRVL_NETA_RXQ_MAX; + info->max_tx_queues = MRVL_NETA_TXQ_MAX; + info->max_mac_addrs = MVNETA_MAC_ADDRS_MAX; + + info->rx_desc_lim.nb_max = MRVL_NETA_RXD_MAX; + info->rx_desc_lim.nb_min = MRVL_NETA_RXD_MIN; + info->rx_desc_lim.nb_align = MRVL_NETA_RXD_ALIGN; + + info->tx_desc_lim.nb_max = MRVL_NETA_TXD_MAX; + info->tx_desc_lim.nb_min = MRVL_NETA_TXD_MIN; + info->tx_desc_lim.nb_align = MRVL_NETA_TXD_ALIGN; + + info->rx_offload_capa = MVNETA_RX_OFFLOADS; + info->rx_queue_offload_capa = MVNETA_RX_OFFLOADS; + + info->tx_offload_capa = MVNETA_TX_OFFLOADS; + info->tx_queue_offload_capa = MVNETA_TX_OFFLOADS; + + /* By default packets are dropped if no descriptors are available */ + info->default_rxconf.rx_drop_en = 1; + /* Deferred tx queue start is not supported */ + info->default_txconf.tx_deferred_start = 0; + info->default_txconf.offloads = 0; + + info->max_rx_pktlen = MVNETA_PKT_SIZE_MAX; +} + +/** + * Return supported packet types. + * + * @param dev + * Pointer to Ethernet device structure (unused). + * + * @return + * Const pointer to the table with supported packet types. + */ +static const uint32_t * +mvneta_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused) +{ + static const uint32_t ptypes[] = { + RTE_PTYPE_L2_ETHER, + RTE_PTYPE_L2_ETHER_VLAN, + RTE_PTYPE_L3_IPV4, + RTE_PTYPE_L3_IPV6, + RTE_PTYPE_L4_TCP, + RTE_PTYPE_L4_UDP + }; + + return ptypes; +} + +/** + * DPDK callback to bring the link up. + * + * @param dev + * Pointer to Ethernet device structure. + * + * @return + * 0 on success, negative error value otherwise. + */ +static int +mvneta_dev_set_link_up(struct rte_eth_dev *dev) +{ + struct mvneta_priv *priv = dev->data->dev_private; + + if (!priv->ppio) + return 0; + + return neta_ppio_enable(priv->ppio); +} + +/** + * DPDK callback to bring the link down. + * + * @param dev + * Pointer to Ethernet device structure. + * + * @return + * 0 on success, negative error value otherwise. + */ +static int +mvneta_dev_set_link_down(struct rte_eth_dev *dev) +{ + struct mvneta_priv *priv = dev->data->dev_private; + + if (!priv->ppio) + return 0; + + return neta_ppio_disable(priv->ppio); +} + +/** + * DPDK callback to start the device. + * + * @param dev + * Pointer to Ethernet device structure. + * + * @return + * 0 on success, negative errno value on failure. + */ +static int +mvneta_dev_start(struct rte_eth_dev *dev) +{ + struct mvneta_priv *priv = dev->data->dev_private; + char match[MVNETA_MATCH_LEN]; + int ret = 0, i; + + if (priv->ppio) + return mvneta_dev_set_link_up(dev); + + snprintf(match, sizeof(match), "%s", dev->data->name); + priv->ppio_params.match = match; + priv->ppio_params.inqs_params.mtu = dev->data->mtu; + + ret = neta_ppio_init(&priv->ppio_params, &priv->ppio); + if (ret) { + MVNETA_LOG(ERR, "Failed to init ppio"); + return ret; + } + priv->ppio_id = priv->ppio->port_id; + + /* + * In case there are some some stale uc/mc mac addresses flush them + * here. It cannot be done during mvneta_dev_close() as port information + * is already gone at that point (due to neta_ppio_deinit() in + * mvneta_dev_stop()). + */ + if (!priv->uc_mc_flushed) { + ret = neta_ppio_flush_mac_addrs(priv->ppio, 0, 1); + if (ret) { + MVNETA_LOG(ERR, + "Failed to flush uc/mc filter list"); + goto out; + } + priv->uc_mc_flushed = 1; + } + + ret = mvneta_dev_set_link_up(dev); + if (ret) { + MVNETA_LOG(ERR, "Failed to set link up"); + goto out; + } + + /* start tx queues */ + for (i = 0; i < dev->data->nb_tx_queues; i++) + dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; + + return 0; + +out: + MVNETA_LOG(ERR, "Failed to start device"); + neta_ppio_deinit(priv->ppio); + return ret; +} + +/** + * DPDK callback to stop the device. + * + * @param dev + * Pointer to Ethernet device structure. + */ +static void +mvneta_dev_stop(struct rte_eth_dev *dev) +{ + struct mvneta_priv *priv = dev->data->dev_private; + + if (!priv->ppio) + return; + + mvneta_dev_set_link_down(dev); + + neta_ppio_deinit(priv->ppio); + + priv->ppio = NULL; +} + +/** + * DPDK callback to close the device. + * + * @param dev + * Pointer to Ethernet device structure. + */ +static void +mvneta_dev_close(struct rte_eth_dev *dev) +{ + struct mvneta_priv *priv = dev->data->dev_private; + + if (priv->ppio) + mvneta_dev_stop(dev); +} + +/** + * DPDK callback to set the primary MAC address. + * + * @param dev + * Pointer to Ethernet device structure. + * @param mac_addr + * MAC address to register. + */ +static int +mvneta_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr) +{ + struct mvneta_priv *priv = dev->data->dev_private; + int ret; + + if (!priv->ppio) + return -EINVAL; + + ret = neta_ppio_set_mac_addr(priv->ppio, mac_addr->addr_bytes); + if (ret) { + char buf[ETHER_ADDR_FMT_SIZE]; + ether_format_addr(buf, sizeof(buf), mac_addr); + MVNETA_LOG(ERR, "Failed to set mac to %s", buf); + } + return 0; +} + +static const struct eth_dev_ops mvneta_ops = { + .dev_configure = mvneta_dev_configure, + .dev_start = mvneta_dev_start, + .dev_stop = mvneta_dev_stop, + .dev_set_link_up = mvneta_dev_set_link_up, + .dev_set_link_down = mvneta_dev_set_link_down, + .dev_close = mvneta_dev_close, + .mac_addr_set = mvneta_mac_addr_set, + .dev_infos_get = mvneta_dev_infos_get, + .dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get, +}; + +/** + * Create device representing Ethernet port. + * + * @param name + * Pointer to the port's name. + * + * @return + * 0 on success, negative error value otherwise. + */ +static int +mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name) +{ + int ret, fd = socket(AF_INET, SOCK_DGRAM, 0); + struct rte_eth_dev *eth_dev; + struct mvneta_priv *priv; + struct ifreq req; + + eth_dev = rte_eth_dev_allocate(name); + if (!eth_dev) + return -ENOMEM; + + priv = rte_zmalloc_socket(name, sizeof(*priv), 0, rte_socket_id()); + if (!priv) { + ret = -ENOMEM; + goto out_free_dev; + } + + eth_dev->data->mac_addrs = + rte_zmalloc("mac_addrs", + ETHER_ADDR_LEN * MVNETA_MAC_ADDRS_MAX, 0); + if (!eth_dev->data->mac_addrs) { + MVNETA_LOG(ERR, "Failed to allocate space for eth addrs"); + ret = -ENOMEM; + goto out_free_priv; + } + + memset(&req, 0, sizeof(req)); + strcpy(req.ifr_name, name); + ret = ioctl(fd, SIOCGIFHWADDR, &req); + if (ret) + goto out_free_mac; + + memcpy(eth_dev->data->mac_addrs[0].addr_bytes, + req.ifr_addr.sa_data, ETHER_ADDR_LEN); + + eth_dev->data->kdrv = RTE_KDRV_NONE; + eth_dev->data->dev_private = priv; + eth_dev->device = &vdev->device; + eth_dev->dev_ops = &mvneta_ops; + + return 0; +out_free_mac: + rte_free(eth_dev->data->mac_addrs); +out_free_priv: + rte_free(priv); +out_free_dev: + rte_eth_dev_release_port(eth_dev); + + return ret; +} + +/** + * Cleanup previously created device representing Ethernet port. + * + * @param eth_dev + * Pointer to the corresponding rte_eth_dev structure. + */ +static void +mvneta_eth_dev_destroy(struct rte_eth_dev *eth_dev) +{ + rte_free(eth_dev->data->dev_private); + rte_free(eth_dev->data->mac_addrs); + rte_eth_dev_release_port(eth_dev); +} + +/** + * Cleanup previously created device representing Ethernet port. + * + * @param name + * Pointer to the port name. + */ +static void +mvneta_eth_dev_destroy_name(const char *name) +{ + struct rte_eth_dev *eth_dev; + + eth_dev = rte_eth_dev_allocated(name); + if (!eth_dev) + return; + + mvneta_eth_dev_destroy(eth_dev); +} + +/** + * DPDK callback to register the virtual device. + * + * @param vdev + * Pointer to the virtual device. + * + * @return + * 0 on success, negative error value otherwise. + */ +static int +rte_pmd_mvneta_probe(struct rte_vdev_device *vdev) +{ + struct rte_kvargs *kvlist; + struct mvneta_ifnames ifnames; + int ret = -EINVAL; + uint32_t i, ifnum; + const char *params; + + params = rte_vdev_device_args(vdev); + if (!params) + return -EINVAL; + + kvlist = rte_kvargs_parse(params, valid_args); + if (!kvlist) + return -EINVAL; + + ifnum = rte_kvargs_count(kvlist, MVNETA_IFACE_NAME_ARG); + if (ifnum > RTE_DIM(ifnames.names)) + goto out_free_kvlist; + + ifnames.idx = 0; + rte_kvargs_process(kvlist, MVNETA_IFACE_NAME_ARG, + mvneta_ifnames_get, &ifnames); + + /* + * The below system initialization should be done only once, + * on the first provided configuration file + */ + if (mvneta_dev_num) + goto init_devices; + + MVNETA_LOG(INFO, "Perform MUSDK initializations"); + + ret = rte_mvep_init(MVEP_MOD_T_NETA, kvlist); + if (ret) + goto out_free_kvlist; + + ret = mvneta_neta_init(); + if (ret) { + MVNETA_LOG(ERR, "Failed to init NETA!"); + rte_mvep_deinit(MVEP_MOD_T_NETA); + goto out_free_kvlist; + } + + mvneta_lcore_first = RTE_MAX_LCORE; + mvneta_lcore_last = 0; + +init_devices: + for (i = 0; i < ifnum; i++) { + MVNETA_LOG(INFO, "Creating %s", ifnames.names[i]); + ret = mvneta_eth_dev_create(vdev, ifnames.names[i]); + if (ret) + goto out_cleanup; + } + mvneta_dev_num += ifnum; + + rte_kvargs_free(kvlist); + + return 0; +out_cleanup: + for (; i > 0; i--) + mvneta_eth_dev_destroy_name(ifnames.names[i]); + + if (mvneta_dev_num == 0) { + mvneta_neta_deinit(); + rte_mvep_deinit(MVEP_MOD_T_NETA); + } +out_free_kvlist: + rte_kvargs_free(kvlist); + + return ret; +} + +/** + * DPDK callback to remove virtual device. + * + * @param vdev + * Pointer to the removed virtual device. + * + * @return + * 0 on success, negative error value otherwise. + */ +static int +rte_pmd_mvneta_remove(struct rte_vdev_device *vdev) +{ + int i; + const char *name; + + name = rte_vdev_device_name(vdev); + if (!name) + return -EINVAL; + + MVNETA_LOG(INFO, "Removing %s", name); + + RTE_ETH_FOREACH_DEV(i) { + if (rte_eth_devices[i].device != &vdev->device) + continue; + + mvneta_eth_dev_destroy(&rte_eth_devices[i]); + mvneta_dev_num--; + } + + if (mvneta_dev_num == 0) { + MVNETA_LOG(INFO, "Perform MUSDK deinit"); + mvneta_neta_deinit(); + rte_mvep_deinit(MVEP_MOD_T_NETA); + } + + return 0; +} + +static struct rte_vdev_driver pmd_mvneta_drv = { + .probe = rte_pmd_mvneta_probe, + .remove = rte_pmd_mvneta_remove, +}; + +RTE_PMD_REGISTER_VDEV(net_mvneta, pmd_mvneta_drv); + +RTE_INIT(mvneta_init_log) +{ + mvneta_logtype = rte_log_register("pmd.net.mvneta"); + if (mvneta_logtype >= 0) + rte_log_set_level(mvneta_logtype, RTE_LOG_NOTICE); +} diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h new file mode 100644 index 0000000..8b8d726 --- /dev/null +++ b/drivers/net/mvneta/mvneta_ethdev.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Marvell International Ltd. + * Copyright(c) 2018 Semihalf. + * All rights reserved. + */ + +#ifndef _MVNETA_ETHDEV_H_ +#define _MVNETA_ETHDEV_H_ + +/* + * container_of is defined by both DPDK and MUSDK, + * we'll declare only one version. + * + * Note that it is not used in this PMD anyway. + */ +#ifdef container_of +#undef container_of +#endif + +#include +#include + +/** Packet offset inside RX buffer. */ +#define MRVL_NETA_PKT_OFFS 64 + +/** Maximum number of rx/tx queues per port */ +#define MRVL_NETA_RXQ_MAX 8 +#define MRVL_NETA_TXQ_MAX 8 + +/** Minimum/maximum number of descriptors in tx queue */ +#define MRVL_NETA_TXD_MIN 16 +#define MRVL_NETA_TXD_MAX 2048 + +/** Tx queue descriptors alignment in B */ +#define MRVL_NETA_TXD_ALIGN 32 + +/** Minimum/maximum number of descriptors in rx queue */ +#define MRVL_NETA_RXD_MIN 16 +#define MRVL_NETA_RXD_MAX 2048 + +/** Rx queue descriptors alignment in B */ +#define MRVL_NETA_RXD_ALIGN 32 + +#define MRVL_NETA_VLAN_TAG_LEN 4 +#define MRVL_NETA_ETH_HDRS_LEN (ETHER_HDR_LEN + ETHER_CRC_LEN + \ + MRVL_NETA_VLAN_TAG_LEN) + +#define MRVL_NETA_HDRS_LEN (MV_MH_SIZE + MRVL_NETA_ETH_HDRS_LEN) +#define MRVL_NETA_MTU_TO_MRU(mtu) ((mtu) + MRVL_NETA_HDRS_LEN) +#define MRVL_NETA_MRU_TO_MTU(mru) ((mru) - MRVL_NETA_HDRS_LEN) + + +struct mvneta_priv { + /* Hot fields, used in fast path. */ + struct neta_ppio *ppio; /**< Port handler pointer */ + + uint8_t pp_id; + uint8_t ppio_id; /* ppio port id */ + uint8_t uc_mc_flushed; + uint8_t multiseg; + + struct neta_ppio_params ppio_params; + uint16_t nb_rx_queues; + + uint64_t rate_max; +}; + +/** Current log type. */ +extern int mvneta_logtype; + +#define MVNETA_LOG(level, fmt, args...) \ + rte_log(RTE_LOG_ ## level, mvneta_logtype, "%s(): " fmt "\n", \ + __func__, ##args) + +#endif /* _MVNETA_ETHDEV_H_ */ diff --git a/drivers/net/mvneta/rte_pmd_mvneta_version.map b/drivers/net/mvneta/rte_pmd_mvneta_version.map new file mode 100644 index 0000000..24bd5cd --- /dev/null +++ b/drivers/net/mvneta/rte_pmd_mvneta_version.map @@ -0,0 +1,3 @@ +DPDK_18.11 { + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 899d51a..66f9199 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -98,7 +98,9 @@ ifeq ($(CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF)$(CONFIG_RTE_LIBRTE_OCTEONTX_MEMPOO _LDLIBS-y += -lrte_common_octeontx endif -ifeq ($(CONFIG_RTE_LIBRTE_MVPP2_PMD),y) +MVEP-y := $(CONFIG_RTE_LIBRTE_MVPP2_PMD) +MVEP-y += $(CONFIG_RTE_LIBRTE_MVNETA_PMD) +ifneq (,$(findstring y,$(MVEP-y))) _LDLIBS-y += -lrte_common_mvep -L$(LIBMUSDK_PATH)/lib -lmusdk endif @@ -157,7 +159,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += -lrte_pmd_mlx5 -ldl -lmnl else _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += -lrte_pmd_mlx5 -libverbs -lmlx5 -lmnl endif -_LDLIBS-$(CONFIG_RTE_LIBRTE_MVPP2_PMD) += -lrte_pmd_mvpp2 -L$(LIBMUSDK_PATH)/lib -lmusdk +_LDLIBS-$(CONFIG_RTE_LIBRTE_MVPP2_PMD) += -lrte_pmd_mvpp2 +_LDLIBS-$(CONFIG_RTE_LIBRTE_MVNETA_PMD) += -lrte_pmd_mvneta _LDLIBS-$(CONFIG_RTE_LIBRTE_NFP_PMD) += -lrte_pmd_nfp _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += -lrte_pmd_null _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += -lrte_pmd_pcap -lpcap