DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/8] Add Marvell NETA PMD
@ 2018-08-28 15:10 Andrzej Ostruszka
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
                   ` (8 more replies)
  0 siblings, 9 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-28 15:10 UTC (permalink / raw)
  To: dev; +Cc: nsamsono

This patch series introduces new PMD for Marvell NETA adapters (MVNETA).
See the documentation for more info.

It is split for easier reviewing.

Natalie Samsonov (4):
  net/mvneta: add neta PMD skeleton
  net/mvneta: support for setting of MTU
  net/mvneta: add link update
  net/mvneta: add reset statistics callback

Yelena Krivosheev (4):
  net/mvneta: add Rx/Tx support
  net/mvneta: support for promiscuous
  net/mvneta: add MAC filtering
  net/mvneta: add support for basic stats

 MAINTAINERS                                   |    8 +
 config/common_base                            |    5 +
 devtools/test-build.sh                        |    2 +
 doc/guides/nics/features/mvneta.ini           |   18 +
 doc/guides/nics/mvneta.rst                    |  182 +++
 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            | 2023 +++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h            |   90 ++
 drivers/net/mvneta/rte_pmd_mvneta_version.map |    3 +
 mk/rte.app.mk                                 |    7 +-
 16 files changed, 2415 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

-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH 1/8] net/mvneta: add neta PMD skeleton
  2018-08-28 15:10 [dpdk-dev] [PATCH 0/8] Add Marvell NETA PMD Andrzej Ostruszka
@ 2018-08-28 15:10 ` Andrzej Ostruszka
  2018-08-30  8:42   ` Hemant
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-28 15:10 UTC (permalink / raw)
  To: dev; +Cc: nsamsono

From: Natalie Samsonov <nsamsono@marvell.com>

Add neta pmd driver skeleton providing base for the further
development.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
Signed-off-by: Andrzej Ostruszka <amo@semihalf.com>
---
 MAINTAINERS                                   |   8 +
 config/common_base                            |   5 +
 devtools/test-build.sh                        |   2 +
 doc/guides/nics/features/mvneta.ini           |  18 +
 doc/guides/nics/mvneta.rst                    | 182 ++++++
 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            | 883 ++++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h            |  78 +++
 drivers/net/mvneta/rte_pmd_mvneta_version.map |   3 +
 mk/rte.app.mk                                 |   7 +-
 16 files changed, 1263 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 9fd258f..18858b9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -585,6 +585,14 @@ F: drivers/net/mvpp2/
 F: doc/guides/nics/mvpp2.rst
 F: doc/guides/nics/features/mvpp2.ini
 
+Marvell mvneta
+M: Zyta Szpak <zr@semihalf.com>
+M: Dmitri Epshtein <dima@marvell.com>
+M: Natalie Samsonov <nsamsono@marvell.com>
+F: drivers/net/mvneta/
+F: doc/guides/nics/mvneta.rst
+F: doc/guides/nics/features/mvneta.ini
+
 Mellanox mlx4
 M: Matan Azrad <matan@mellanox.com>
 M: Shahaf Shuler <shahafs@mellanox.com>
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 () # <directory> <target> <options>
 		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..3f02f84
--- /dev/null
+++ b/doc/guides/nics/features/mvneta.ini
@@ -0,0 +1,18 @@
+;
+; 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
+Link status          = Y
+MTU update           = Y
+Jumbo frame          = Y
+Promiscuous mode     = Y
+CRC offload          = Y
+L3 checksum offload  = Y
+L4 checksum offload  = Y
+Packet type parsing  = Y
+Basic stats          = 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..6e9f511
--- /dev/null
+++ b/doc/guides/nics/mvneta.rst
@@ -0,0 +1,182 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2018 Marvell International Ltd.
+    Copyright(c) 2018 Semihalf.
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+      * Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+      * Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in
+        the documentation and/or other materials provided with the
+        distribution.
+      * Neither the name of the copyright holder nor the names of its
+        contributors may be used to endorse or promote products derived
+        from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+.. _mvneta_poll_mode_driver:
+
+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
+- tx/rx_burst
+- Speed capabilities
+- Link status
+- CRC offload
+- Packet type parsing
+
+
+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 <https://extranet.marvell.com>`_. 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 <linux_gsg>` 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=eth_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=<toolchain>/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=<musdk>/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=eth_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=eth_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 24204e6..0586715 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -54,6 +54,10 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **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..db43f39
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -0,0 +1,883 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Marvell International Ltd.
+ * Copyright(c) 2018 Semihalf.
+ * All rights reserved.
+ */
+
+#include <rte_ethdev_driver.h>
+#include <rte_kvargs.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_bus_vdev.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <rte_mvep_common.h>
+#include "mvneta_ethdev.h"
+
+
+#define MVNETA_IFACE_NAME_ARG "iface"
+
+
+#define MVNETA_MUSDK_DMA_MEMSIZE 41943040 /* (40 * 1024 * 1024) */
+
+#define MVNETA_RX_OFFLOADS (DEV_RX_OFFLOAD_JUMBO_FRAME | \
+			  DEV_RX_OFFLOAD_CRC_STRIP | \
+			  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
+
+#define MVNETA_PKT_EFFEC_OFFS (MRVL_NETA_PKT_OFFS + MV_MH_SIZE)
+
+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;
+};
+
+
+struct mvneta_rxq {
+	struct mvneta_priv *priv;
+	struct rte_mempool *mp;
+	int queue_id;
+	int port_id;
+	int size;
+	int cksum_enabled;
+	uint64_t bytes_recv;
+	uint64_t drop_mac;
+	uint64_t pkts_processed;
+};
+
+
+struct mvneta_txq {
+	struct mvneta_priv *priv;
+	int queue_id;
+	int port_id;
+	uint64_t bytes_sent;
+	int tx_deferred_start;
+};
+
+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\n",
+			dev->data->dev_conf.rxmode.mq_mode);
+		if (dev->data->nb_rx_queues > 1)
+			return -EINVAL;
+	}
+
+	if (!(dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_CRC_STRIP)) {
+		MVNETA_LOG(INFO,
+			"L2 CRC stripping is always enabled in hw\n");
+		dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CRC_STRIP;
+	}
+
+	if (dev->data->dev_conf.rxmode.split_hdr_size) {
+		MVNETA_LOG(INFO, "Split headers not supported\n");
+		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;
+	info->default_rxconf.offloads = DEV_RX_OFFLOAD_CRC_STRIP;
+	/* 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 get information about specific receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param rx_queue_id
+ *   Receive queue index.
+ * @param qinfo
+ *   Receive queue information structure.
+ */
+static void mvneta_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+			      struct rte_eth_rxq_info *qinfo)
+{
+	struct mvneta_rxq *q = dev->data->rx_queues[rx_queue_id];
+
+	qinfo->mp = q->mp;
+	qinfo->nb_desc = q->size;
+}
+
+/**
+ * DPDK callback to get information about specific transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param tx_queue_id
+ *   Transmit queue index.
+ * @param qinfo
+ *   Transmit queue information structure.
+ */
+static void mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+			      struct rte_eth_txq_info *qinfo)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	qinfo->nb_desc =
+		priv->ppio_params.outqs_params.outqs_params[tx_queue_id].size;
+}
+
+/**
+ * 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 configure the receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   RX queue index.
+ * @param desc
+ *   Number of descriptors to configure in queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Thresholds parameters (unused_).
+ * @param mp
+ *   Memory pool for buffer allocations.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		    unsigned int socket,
+		    const struct rte_eth_rxconf *conf __rte_unused,
+		    struct rte_mempool *mp)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_rxq *rxq;
+	uint32_t frame_size, buf_size = rte_pktmbuf_data_room_size(mp);
+	uint32_t max_rx_pkt_len = dev->data->dev_conf.rxmode.max_rx_pkt_len;
+
+	frame_size = buf_size - RTE_PKTMBUF_HEADROOM - MVNETA_PKT_EFFEC_OFFS;
+
+	if (frame_size < max_rx_pkt_len) {
+		MVNETA_LOG(ERR,
+			"Mbuf size must be increased to %u bytes to hold up "
+			"to %u bytes of data.\n",
+			buf_size + max_rx_pkt_len - frame_size,
+			max_rx_pkt_len);
+		dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
+		MVNETA_LOG(INFO, "Setting max rx pkt len to %u\n",
+			dev->data->dev_conf.rxmode.max_rx_pkt_len);
+	}
+
+	if (dev->data->rx_queues[idx]) {
+		rte_free(dev->data->rx_queues[idx]);
+		dev->data->rx_queues[idx] = NULL;
+	}
+
+	rxq = rte_zmalloc_socket("rxq", sizeof(*rxq), 0, socket);
+	if (!rxq)
+		return -ENOMEM;
+
+	rxq->priv = priv;
+	rxq->mp = mp;
+	rxq->cksum_enabled = dev->data->dev_conf.rxmode.offloads &
+			     DEV_RX_OFFLOAD_IPV4_CKSUM;
+	rxq->queue_id = idx;
+	rxq->port_id = dev->data->port_id;
+	rxq->size = desc;
+	priv->ppio_params.inqs_params.tcs_params[MRVL_NETA_DEFAULT_TC].size =
+		desc;
+
+	dev->data->rx_queues[idx] = rxq;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to release the receive queue.
+ *
+ * @param rxq
+ *   Generic receive queue pointer.
+ */
+static void
+mvneta_rx_queue_release(void *rxq)
+{
+	struct mvneta_rxq *q = rxq;
+
+	if (!q)
+		return;
+
+	rte_free(rxq);
+}
+
+/**
+ * DPDK callback to configure the transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   Transmit queue index.
+ * @param desc
+ *   Number of descriptors to configure in the queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Tx queue configuration parameters.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		    unsigned int socket, const struct rte_eth_txconf *conf)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_txq *txq;
+
+	if (dev->data->tx_queues[idx]) {
+		rte_free(dev->data->tx_queues[idx]);
+		dev->data->tx_queues[idx] = NULL;
+	}
+
+	txq = rte_zmalloc_socket("txq", sizeof(*txq), 0, socket);
+	if (!txq)
+		return -ENOMEM;
+
+	txq->priv = priv;
+	txq->queue_id = idx;
+	txq->port_id = dev->data->port_id;
+	txq->tx_deferred_start = conf->tx_deferred_start;
+	dev->data->tx_queues[idx] = txq;
+
+	priv->ppio_params.outqs_params.outqs_params[idx].size = desc;
+	priv->ppio_params.outqs_params.outqs_params[idx].weight = 1;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to release the transmit queue.
+ *
+ * @param txq
+ *   Generic transmit queue pointer.
+ */
+static void
+mvneta_tx_queue_release(void *txq)
+{
+	struct mvneta_txq *q = txq;
+
+	if (!q)
+		return;
+
+	rte_free(q);
+}
+
+
+/**
+ * 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\n");
+		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\n");
+			goto out;
+		}
+		priv->uc_mc_flushed = 1;
+	}
+
+	ret = mvneta_dev_set_link_up(dev);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to set link up\n");
+		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\n");
+	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;
+	int i;
+
+	if (priv->ppio)
+		mvneta_dev_stop(dev);
+
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		mvneta_rx_queue_release(dev->data->rx_queues[i]);
+		dev->data->rx_queues[i] = NULL;
+	}
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		mvneta_tx_queue_release(dev->data->tx_queues[i]);
+		dev->data->tx_queues[i] = NULL;
+	}
+}
+
+/**
+ * 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\n", 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,
+	.rxq_info_get = mvneta_rxq_info_get,
+	.txq_info_get = mvneta_txq_info_get,
+	.rx_queue_setup = mvneta_rx_queue_setup,
+	.rx_queue_release = mvneta_rx_queue_release,
+	.tx_queue_setup = mvneta_tx_queue_setup,
+	.tx_queue_release = mvneta_tx_queue_release,
+};
+
+/**
+ * Create private device structure.
+ *
+ * @param dev_name
+ *   Pointer to the port name passed in the initialization parameters.
+ *
+ * @return
+ *   Pointer to the newly allocated private device structure.
+ */
+static struct mvneta_priv *
+mvneta_priv_create(const char *dev_name)
+{
+	struct mvneta_priv *priv;
+
+	priv = rte_zmalloc_socket(dev_name, sizeof(*priv), 0, rte_socket_id());
+	if (!priv)
+		return NULL;
+
+	return priv;
+}
+
+/**
+ * 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 = mvneta_priv_create(name);
+
+	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\n");
+		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_dev:
+	rte_eth_dev_release_port(eth_dev);
+out_free_priv:
+	rte_free(priv);
+
+	return ret;
+}
+
+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\n");
+
+	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!\n");
+		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\n", 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\n", 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\n");
+		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_PMD_REGISTER_ALIAS(net_mvneta, eth_mvneta);
+
+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..8957034
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -0,0 +1,78 @@
+/* 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 <drivers/mv_neta.h>
+#include <drivers/mv_neta_ppio.h>
+
+/** 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 TODO is it? */
+#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 TODO is it? */
+#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_DEFAULT_TC 0
+
+
+#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
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH 2/8] net/mvneta: add Rx/Tx support
  2018-08-28 15:10 [dpdk-dev] [PATCH 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
@ 2018-08-28 15:10 ` Andrzej Ostruszka
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-28 15:10 UTC (permalink / raw)
  To: dev; +Cc: nsamsono

From: Yelena Krivosheev <yelena@marvell.com>

Add part of PMD for actual reception/transmission.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 795 +++++++++++++++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h |  11 +
 2 files changed, 806 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index db43f39..a480b14 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -27,6 +27,10 @@
 
 #define MVNETA_IFACE_NAME_ARG "iface"
 
+#define MVNETA_COOKIE_ADDR_INVALID ~0ULL
+
+#define MVNETA_COOKIE_HIGH_ADDR_SHIFT	(sizeof(neta_cookie_t) * 8)
+#define MVNETA_COOKIE_HIGH_ADDR_MASK	(~0ULL << MVNETA_COOKIE_HIGH_ADDR_SHIFT)
 
 #define MVNETA_MUSDK_DMA_MEMSIZE 41943040 /* (40 * 1024 * 1024) */
 
@@ -49,6 +53,19 @@
 
 #define MVNETA_PKT_EFFEC_OFFS (MRVL_NETA_PKT_OFFS + MV_MH_SIZE)
 
+static uint64_t cookie_addr_high = MVNETA_COOKIE_ADDR_INVALID;
+static uint16_t rx_desc_free_thresh = MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN;
+
+#define MVNETA_SET_COOKIE_HIGH_ADDR(addr) {				\
+	if (unlikely(cookie_addr_high == MVNETA_COOKIE_ADDR_INVALID))	\
+		cookie_addr_high =					\
+			(uint64_t)addr & MVNETA_COOKIE_HIGH_ADDR_MASK;	\
+}
+
+#define MVNETA_CHECK_COOKIE_HIGH_ADDR(addr)			\
+	((likely(cookie_addr_high ==				\
+	((uint64_t)addr & MVNETA_COOKIE_HIGH_ADDR_MASK))) ? 1 : 0)
+
 int mvneta_logtype;
 
 static const char * const valid_args[] = {
@@ -61,6 +78,24 @@ struct mvneta_ifnames {
 	int idx;
 };
 
+/*
+ * To use buffer harvesting based on loopback port shadow queue structure
+ * was introduced for buffers information bookkeeping.
+ *
+ * Before sending the packet, related buffer information is
+ * stored in shadow queue. After packet is transmitted no longer used
+ * packet buffer is released back to it's original hardware pool,
+ * on condition it originated from interface.
+ * In case it  was generated by application itself i.e: mbuf->port field is
+ * 0xff then its released to software mempool.
+ */
+struct mvneta_shadow_txq {
+	int head;           /* write index - used when sending buffers */
+	int tail;           /* read index - used when releasing buffers */
+	u16 size;           /* queue occupied size */
+	struct neta_buff_inf ent[MRVL_NETA_TX_SHADOWQ_SIZE]; /* q entries */
+};
+
 
 struct mvneta_rxq {
 	struct mvneta_priv *priv;
@@ -80,6 +115,7 @@ struct mvneta_txq {
 	int queue_id;
 	int port_id;
 	uint64_t bytes_sent;
+	struct mvneta_shadow_txq shadow_txq;
 	int tx_deferred_start;
 };
 
@@ -87,6 +123,248 @@ static int mvneta_dev_num;
 static int mvneta_lcore_first;
 static int mvneta_lcore_last;
 
+static inline void
+mvneta_fill_shadowq(struct mvneta_shadow_txq *sq, struct rte_mbuf *buf)
+{
+	sq->ent[sq->head].cookie = (uint64_t)buf;
+	sq->ent[sq->head].addr = buf ?
+		rte_mbuf_data_iova_default(buf) : 0;
+
+	sq->head = (sq->head + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	sq->size++;
+}
+
+static inline void
+mvneta_fill_desc(struct neta_ppio_desc *desc, struct rte_mbuf *buf)
+{
+	neta_ppio_outq_desc_reset(desc);
+	neta_ppio_outq_desc_set_phys_addr(desc, rte_pktmbuf_iova(buf));
+	neta_ppio_outq_desc_set_pkt_offset(desc, 0);
+	neta_ppio_outq_desc_set_pkt_len(desc, rte_pktmbuf_data_len(buf));
+}
+
+static inline int
+mvneta_buffs_refill(struct mvneta_priv *priv, struct mvneta_rxq *rxq, u16 *num)
+{
+	struct rte_mbuf *mbufs[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	struct neta_buff_inf entries[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	int i, ret;
+	uint16_t nb_desc = *num;
+
+	ret = rte_pktmbuf_alloc_bulk(rxq->mp, mbufs, nb_desc);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to allocate %u mbufs.\n", nb_desc);
+		*num = 0;
+		return -1;
+	}
+
+	MVNETA_SET_COOKIE_HIGH_ADDR(mbufs[0]);
+
+	for (i = 0; i < nb_desc; i++) {
+		if (unlikely(!MVNETA_CHECK_COOKIE_HIGH_ADDR(mbufs[i]))) {
+			MVNETA_LOG(ERR,
+				"mbuf virt high addr 0x%lx out of range 0x%lx\n",
+				(uint64_t)mbufs[i] >> 32,
+				cookie_addr_high >> 32);
+			*num = 0;
+			goto out;
+		}
+		entries[i].addr = rte_mbuf_data_iova_default(mbufs[i]);
+		entries[i].cookie = (neta_cookie_t)(uint64_t)mbufs[i];
+	}
+	neta_ppio_inq_put_buffs(priv->ppio, rxq->queue_id, entries, num);
+
+out:
+	for (i = *num; i < nb_desc; i++)
+		rte_pktmbuf_free(mbufs[i]);
+
+	return 0;
+}
+
+
+/**
+ * Allocate buffers from mempool
+ * and store addresses in rx descriptors.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_buffs_alloc(struct mvneta_priv *priv, struct mvneta_rxq *rxq, int *num)
+{
+	uint16_t nb_desc, nb_desc_burst, sent = 0;
+	int ret = 0;
+
+	nb_desc = *num;
+
+	do {
+		nb_desc_burst =
+			(nb_desc < MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX) ?
+			nb_desc : MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX;
+
+		ret = mvneta_buffs_refill(priv, rxq, &nb_desc_burst);
+		if (unlikely(ret || !nb_desc_burst))
+			break;
+
+		sent += nb_desc_burst;
+		nb_desc -= nb_desc_burst;
+
+	} while (nb_desc);
+
+	*num = sent;
+
+	return ret;
+}
+
+/**
+ * Return mbufs to mempool.
+ *
+ * @param rxq
+ *    Pointer to rx queue structure
+ * @param desc
+ *    Array of rx descriptors
+ */
+static void
+mvneta_recv_buffs_free(struct neta_ppio_desc *desc, uint16_t num)
+{
+	uint64_t addr;
+	uint8_t i;
+
+	for (i = 0; i < num; i++) {
+		if (desc) {
+			addr = cookie_addr_high |
+					neta_ppio_inq_desc_get_cookie(desc);
+			if (addr)
+				rte_pktmbuf_free((struct rte_mbuf *)addr);
+			desc++;
+		}
+	}
+}
+
+/**
+ * Release already sent buffers to mempool.
+ *
+ * @param ppio
+ *   Pointer to the port structure.
+ * @param sq
+ *   Pointer to the shadow queue.
+ * @param qid
+ *   Queue id number.
+ * @param force
+ *   Force releasing packets.
+ */
+static inline void
+mvneta_sent_buffers_free(struct neta_ppio *ppio,
+			 struct mvneta_shadow_txq *sq, int qid)
+{
+	struct neta_buff_inf *entry;
+	uint16_t nb_done = 0;
+	int i;
+	int tail = sq->tail;
+
+	neta_ppio_get_num_outq_done(ppio, qid, &nb_done);
+
+	if (nb_done > sq->size) {
+		printf("%s: ERROR nb_done: %d, sq->size %d\n",
+			__func__, nb_done, sq->size);
+		return;
+	}
+
+	for (i = 0; i < nb_done; i++) {
+		entry = &sq->ent[tail];
+
+		if (unlikely(!entry->addr)) {
+			MVNETA_LOG(DEBUG,
+				"Shadow memory @%d: cookie(%lx), pa(%lx)!\n",
+				tail, (u64)entry->cookie,
+				(u64)entry->addr);
+			tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+			continue;
+		}
+
+		struct rte_mbuf *mbuf;
+
+		mbuf = (struct rte_mbuf *)
+			   (cookie_addr_high | entry->cookie);
+		rte_pktmbuf_free(mbuf);
+		tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+
+	sq->tail = tail;
+	sq->size -= nb_done;
+}
+
+/**
+ * Flush single receive queue.
+ *
+ * @param rxq
+ *   Pointer to rx queue structure.
+ * @param descs
+ *   Array of rx descriptors
+ */
+static void
+mvneta_rx_queue_flush(struct mvneta_rxq *rxq)
+{
+	struct neta_ppio_desc *descs;
+	struct neta_buff_inf *bufs;
+	uint16_t num;
+	int ret, i;
+
+	descs = rte_malloc("rxdesc", MRVL_NETA_RXD_MAX * sizeof(*descs), 0);
+	bufs = rte_malloc("buffs", MRVL_NETA_RXD_MAX * sizeof(*bufs), 0);
+
+	do {
+		num = MRVL_NETA_RXD_MAX;
+		ret = neta_ppio_recv(rxq->priv->ppio,
+				     rxq->queue_id,
+				     descs, &num);
+		mvneta_recv_buffs_free(descs, num);
+	} while (ret == 0 && num);
+
+	rxq->pkts_processed = 0;
+
+	num = MRVL_NETA_RXD_MAX;
+
+	neta_ppio_inq_get_all_buffs(rxq->priv->ppio, rxq->queue_id, bufs, &num);
+	MVNETA_LOG(INFO, "%s: freeing %u unused bufs.\n", __func__, num);
+
+	for (i = 0; i < num; i++) {
+		uint64_t addr;
+		if (bufs[i].cookie) {
+			addr = cookie_addr_high | bufs[i].cookie;
+			rte_pktmbuf_free((struct rte_mbuf *)addr);
+		}
+	}
+
+	rte_free(descs);
+	rte_free(bufs);
+}
+
+/**
+ * Flush single transmit queue.
+ *
+ * @param txq
+ *     Pointer to tx queue structure
+ */
+static void
+mvneta_tx_queue_flush(struct mvneta_txq *txq)
+{
+	struct mvneta_shadow_txq *sq = &txq->shadow_txq;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(txq->priv->ppio, sq,
+					 txq->queue_id);
+
+	/* free the rest of them */
+	while (sq->tail != sq->head) {
+		uint64_t addr = cookie_addr_high |
+			sq->ent[sq->tail].cookie;
+		rte_pktmbuf_free(
+			(struct rte_mbuf *)addr);
+		sq->tail = (sq->tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+	memset(sq, 0, sizeof(*sq));
+}
 
 /**
  * Deinitialize packet processor.
@@ -135,6 +413,464 @@ mvneta_ifnames_get(const char *key __rte_unused, const char *value,
 }
 
 /**
+ * Return packet type information and l3/l4 offsets.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ * @param l3_offset
+ *   l3 packet offset.
+ * @param l4_offset
+ *   l4 packet offset.
+ *
+ * @return
+ *   Packet type information.
+ */
+static inline uint64_t
+mvneta_desc_to_packet_type_and_offset(struct neta_ppio_desc *desc,
+				    uint8_t *l3_offset, uint8_t *l4_offset)
+{
+	enum neta_inq_l3_type l3_type;
+	enum neta_inq_l4_type l4_type;
+	uint64_t packet_type;
+
+	neta_ppio_inq_desc_get_l3_info(desc, &l3_type, l3_offset);
+	neta_ppio_inq_desc_get_l4_info(desc, &l4_type, l4_offset);
+
+	packet_type = RTE_PTYPE_L2_ETHER;
+
+	if (NETA_RXD_GET_VLAN_INFO(desc))
+		packet_type |= RTE_PTYPE_L2_ETHER_VLAN;
+
+	switch (l3_type) {
+	case NETA_INQ_L3_TYPE_IPV4_BAD:
+	case NETA_INQ_L3_TYPE_IPV4_OK:
+		packet_type |= RTE_PTYPE_L3_IPV4;
+		break;
+	case NETA_INQ_L3_TYPE_IPV6:
+		packet_type |= RTE_PTYPE_L3_IPV6;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l3 packet type\n");
+		break;
+	}
+
+	switch (l4_type) {
+	case NETA_INQ_L4_TYPE_TCP:
+		packet_type |= RTE_PTYPE_L4_TCP;
+		break;
+	case NETA_INQ_L4_TYPE_UDP:
+		packet_type |= RTE_PTYPE_L4_UDP;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l4 packet type\n");
+		break;
+	}
+
+	return packet_type;
+}
+
+/**
+ * Prepare offload information.
+ *
+ * @param ol_flags
+ *   Offload flags.
+ * @param packet_type
+ *   Packet type bitfield.
+ * @param l3_type
+ *   Pointer to the neta_ouq_l3_type structure.
+ * @param l4_type
+ *   Pointer to the neta_outq_l4_type structure.
+ * @param gen_l3_cksum
+ *   Will be set to 1 in case l3 checksum is computed.
+ * @param l4_cksum
+ *   Will be set to 1 in case l4 checksum is computed.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_prepare_proto_info(uint64_t ol_flags, uint32_t packet_type,
+			enum neta_outq_l3_type *l3_type,
+			enum neta_outq_l4_type *l4_type,
+			int *gen_l3_cksum,
+			int *gen_l4_cksum)
+{
+	/*
+	 * Based on ol_flags prepare information
+	 * for neta_ppio_outq_desc_set_proto_info() which setups descriptor
+	 * for offloading.
+	 */
+	if (ol_flags & PKT_TX_IPV4) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV4;
+		*gen_l3_cksum = ol_flags & PKT_TX_IP_CKSUM ? 1 : 0;
+	} else if (ol_flags & PKT_TX_IPV6) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV6;
+		/* no checksum for ipv6 header */
+		*gen_l3_cksum = 0;
+	} else {
+		/* if something different then stop processing */
+		return -1;
+	}
+
+	ol_flags &= PKT_TX_L4_MASK;
+	if ((packet_type & RTE_PTYPE_L4_TCP) &&
+	    ol_flags == PKT_TX_TCP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_TCP;
+		*gen_l4_cksum = 1;
+	} else if ((packet_type & RTE_PTYPE_L4_UDP) &&
+		   ol_flags == PKT_TX_UDP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_UDP;
+		*gen_l4_cksum = 1;
+	} else {
+		*l4_type = NETA_OUTQ_L4_TYPE_OTHER;
+		/* no checksum for other type */
+		*gen_l4_cksum = 0;
+	}
+
+	return 0;
+}
+
+/**
+ * Get offload information from the received packet descriptor.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ *
+ * @return
+ *   Mbuf offload flags.
+ */
+static inline uint64_t
+mvneta_desc_to_ol_flags(struct neta_ppio_desc *desc)
+{
+	uint64_t flags;
+	enum neta_inq_desc_status status;
+
+	status = neta_ppio_inq_desc_get_l3_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags = PKT_RX_IP_CKSUM_BAD;
+	else
+		flags = PKT_RX_IP_CKSUM_GOOD;
+
+	status = neta_ppio_inq_desc_get_l4_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags |= PKT_RX_L4_CKSUM_BAD;
+	else
+		flags |= PKT_RX_L4_CKSUM_GOOD;
+
+	return flags;
+}
+
+/**
+ * DPDK callback for transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts];
+
+	int i, ret, bytes_sent = 0;
+	uint16_t num, sq_free_size;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	if (unlikely(!nb_pkts || !q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+	if (unlikely(nb_pkts > sq_free_size)) {
+		MVNETA_LOG(DEBUG,
+			"No room in shadow queue for %d packets! %d packets will be sent.\n",
+			nb_pkts, sq_free_size);
+		nb_pkts = sq_free_size;
+	}
+
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		/* Fill first mbuf info in shadow queue */
+		mvneta_fill_shadowq(sq, mbuf);
+		mvneta_fill_desc(&descs[i], mbuf);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[i], l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = nb_pkts;
+	neta_ppio_send(q->priv->ppio, q->queue_id, descs, &nb_pkts);
+
+
+	/* number of packets that were not sent */
+	if (unlikely(num > nb_pkts)) {
+		for (i = nb_pkts; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE + sq->head - 1) &
+				MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = cookie_addr_high | sq->ent[sq->head].cookie;
+			bytes_sent -=
+				rte_pktmbuf_pkt_len((struct rte_mbuf *)addr);
+		}
+		sq->size -= num - nb_pkts;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/** DPDK callback for S/G transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_sg_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts * NETA_PPIO_DESC_NUM_FRAGS];
+	struct neta_ppio_sg_pkts pkts;
+	uint8_t frags[nb_pkts];
+	int i, j, ret, bytes_sent = 0;
+	int tail, tail_first;
+	uint16_t num, sq_free_size;
+	uint16_t nb_segs, total_descs = 0;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	pkts.frags = frags;
+	pkts.num = 0;
+
+	if (unlikely(!q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+	/* Save shadow queue free size */
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+
+	tail = 0;
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		struct rte_mbuf *seg = NULL;
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		nb_segs = mbuf->nb_segs;
+		total_descs += nb_segs;
+
+		/*
+		 * Check if total_descs does not exceed
+		 * shadow queue free size
+		 */
+		if (unlikely(total_descs > sq_free_size)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(DEBUG,
+				"No room in shadow queue for %d packets! "
+				"%d packets will be sent.\n",
+				nb_pkts, i);
+			break;
+		}
+
+
+		/* Check if nb_segs does not exceed the max nb of desc per
+		 * fragmented packet
+		 */
+		if (unlikely(nb_segs > NETA_PPIO_DESC_NUM_FRAGS)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(ERR,
+				"Too many segments. Packet won't be sent.\n");
+			break;
+		}
+
+		pkts.frags[pkts.num] = nb_segs;
+		pkts.num++;
+		tail_first = tail;
+
+		seg = mbuf;
+		for (j = 0; j < nb_segs - 1; j++) {
+			/* For the subsequent segments, set shadow queue
+			 * buffer to NULL
+			 */
+			mvneta_fill_shadowq(sq, NULL);
+			mvneta_fill_desc(&descs[tail], seg);
+
+			tail++;
+			seg = seg->next;
+		}
+		/* Put first mbuf info in last shadow queue entry */
+		mvneta_fill_shadowq(sq, mbuf);
+		/* Update descriptor with last segment */
+		mvneta_fill_desc(&descs[tail++], seg);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[tail_first],
+						   l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = total_descs;
+	neta_ppio_send_sg(q->priv->ppio, q->queue_id, descs, &total_descs,
+			  &pkts);
+
+	/* number of packets that were not sent */
+	if (unlikely(num > total_descs)) {
+		for (i = total_descs; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE +
+					sq->head - 1) &
+					MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = sq->ent[sq->head].cookie;
+			if (addr)
+				bytes_sent -= rte_pktmbuf_pkt_len(
+					(struct rte_mbuf *)
+					(cookie_addr_high | addr));
+		}
+		sq->size -= num - total_descs;
+		nb_pkts = pkts.num;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/**
+ * DPDK callback for receive.
+ *
+ * @param rxq
+ *   Generic pointer to the receive queue.
+ * @param rx_pkts
+ *   Array to store received packets.
+ * @param nb_pkts
+ *   Maximum number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully received.
+ */
+static uint16_t
+mvneta_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_rxq *q = rxq;
+	struct neta_ppio_desc descs[nb_pkts];
+	int i, ret, rx_done = 0, rx_dropped = 0;
+
+	if (unlikely(!q || !q->priv->ppio))
+		return 0;
+
+	ret = neta_ppio_recv(q->priv->ppio, q->queue_id,
+			descs, &nb_pkts);
+
+	if (unlikely(ret < 0)) {
+		MVNETA_LOG(ERR, "Failed to receive packets\n");
+		return 0;
+	}
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf;
+		uint8_t l3_offset, l4_offset;
+		enum neta_inq_desc_status status;
+		uint64_t addr;
+
+		addr = cookie_addr_high |
+			neta_ppio_inq_desc_get_cookie(&descs[i]);
+		mbuf = (struct rte_mbuf *)addr;
+
+		rte_pktmbuf_reset(mbuf);
+
+		/* drop packet in case of mac, overrun or resource error */
+		status = neta_ppio_inq_desc_get_l2_pkt_error(&descs[i]);
+		if (unlikely(status != NETA_DESC_ERR_OK)) {
+			/* Release the mbuf to the mempool since
+			 * it won't be transferred to tx path
+			 */
+			rte_pktmbuf_free(mbuf);
+			q->drop_mac++;
+			rx_dropped++;
+			continue;
+		}
+
+		mbuf->data_off += MVNETA_PKT_EFFEC_OFFS;
+		mbuf->pkt_len = neta_ppio_inq_desc_get_pkt_len(&descs[i]);
+		mbuf->data_len = mbuf->pkt_len;
+		mbuf->port = q->port_id;
+		mbuf->packet_type =
+			mvneta_desc_to_packet_type_and_offset(&descs[i],
+								&l3_offset,
+								&l4_offset);
+		mbuf->l2_len = l3_offset;
+		mbuf->l3_len = l4_offset - l3_offset;
+
+		if (likely(q->cksum_enabled))
+			mbuf->ol_flags = mvneta_desc_to_ol_flags(&descs[i]);
+
+		rx_pkts[rx_done++] = mbuf;
+		q->bytes_recv += mbuf->pkt_len;
+	}
+	q->pkts_processed += rx_done + rx_dropped;
+
+	if (q->pkts_processed > rx_desc_free_thresh) {
+		int buf_to_refill = rx_desc_free_thresh;
+
+		ret = mvneta_buffs_alloc(q->priv, q, &buf_to_refill);
+		if (ret)
+			MVNETA_LOG(ERR, "Refill failed\n");
+		q->pkts_processed -= buf_to_refill;
+	}
+
+	return rx_done;
+}
+
+/**
  * Ethernet device configuration.
  *
  * Prepare the driver for a given number of TX and RX queues and
@@ -394,6 +1130,7 @@ mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 	rxq->queue_id = idx;
 	rxq->port_id = dev->data->port_id;
 	rxq->size = desc;
+	rx_desc_free_thresh = RTE_MIN(rx_desc_free_thresh, (desc / 2));
 	priv->ppio_params.inqs_params.tcs_params[MRVL_NETA_DEFAULT_TC].size =
 		desc;
 
@@ -416,6 +1153,14 @@ mvneta_rx_queue_release(void *rxq)
 	if (!q)
 		return;
 
+	/* If dev_stop was called already, mbufs are already
+	 * returned to mempool and ppio is deinitialized.
+	 * Skip this step.
+	 */
+
+	if (q->priv->ppio)
+		mvneta_rx_queue_flush(q);
+
 	rte_free(rxq);
 }
 
@@ -481,6 +1226,26 @@ mvneta_tx_queue_release(void *txq)
 	rte_free(q);
 }
 
+/**
+ * Set tx burst function according to offload flag
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_set_tx_function(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	/* Use a simple Tx queue (no offloads, no multi segs) if possible */
+	if (priv->multiseg) {
+		MVNETA_LOG(INFO, "Using multi-segment tx callback\n");
+		dev->tx_pkt_burst = mvneta_tx_sg_pkt_burst;
+	} else {
+		MVNETA_LOG(INFO, "Using single-segment tx callback\n");
+		dev->tx_pkt_burst = mvneta_tx_pkt_burst;
+	}
+}
 
 /**
  * DPDK callback to start the device.
@@ -528,6 +1293,18 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 		priv->uc_mc_flushed = 1;
 	}
 
+	/* Allocate buffers */
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+		int num = rxq->size;
+
+		ret = mvneta_buffs_alloc(priv, rxq, &num);
+		if (ret || (num != rxq->size)) {
+			rte_free(rxq);
+			return ret;
+		}
+	}
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up\n");
@@ -538,6 +1315,8 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 	for (i = 0; i < dev->data->nb_tx_queues; i++)
 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
 
+	mvneta_set_tx_function(dev);
+
 	return 0;
 
 out:
@@ -556,11 +1335,25 @@ static void
 mvneta_dev_stop(struct rte_eth_dev *dev)
 {
 	struct mvneta_priv *priv = dev->data->dev_private;
+	int i;
 
 	if (!priv->ppio)
 		return;
 
 	mvneta_dev_set_link_down(dev);
+	MVNETA_LOG(INFO, "Flushing rx queues\n");
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+
+		mvneta_rx_queue_flush(rxq);
+	}
+
+	MVNETA_LOG(INFO, "Flushing tx queues\n");
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		struct mvneta_txq *txq = dev->data->tx_queues[i];
+
+		mvneta_tx_queue_flush(txq);
+	}
 
 	neta_ppio_deinit(priv->ppio);
 
@@ -707,6 +1500,8 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
 	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
+	eth_dev->rx_pkt_burst = mvneta_rx_pkt_burst;
+	mvneta_set_tx_function(eth_dev);
 ;	eth_dev->dev_ops = &mvneta_ops;
 
 	return 0;
diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h
index 8957034..a05566d 100644
--- a/drivers/net/mvneta/mvneta_ethdev.h
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -43,6 +43,17 @@
 
 #define MRVL_NETA_DEFAULT_TC 0
 
+/** Maximum number of descriptors in shadow queue. Must be power of 2 */
+#define MRVL_NETA_TX_SHADOWQ_SIZE MRVL_NETA_TXD_MAX
+
+/** Shadow queue size mask (since shadow queue size is power of 2) */
+#define MRVL_NETA_TX_SHADOWQ_MASK (MRVL_NETA_TX_SHADOWQ_SIZE - 1)
+
+/** Minimum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN	16
+
+/** Maximum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX	64
 
 #define MRVL_NETA_VLAN_TAG_LEN		4
 #define MRVL_NETA_ETH_HDRS_LEN		(ETHER_HDR_LEN + ETHER_CRC_LEN + \
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH 3/8] net/mvneta: support for setting of MTU
  2018-08-28 15:10 [dpdk-dev] [PATCH 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
@ 2018-08-28 15:10 ` Andrzej Ostruszka
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 4/8] net/mvneta: add link update Andrzej Ostruszka
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-28 15:10 UTC (permalink / raw)
  To: dev; +Cc: nsamsono

From: Natalie Samsonov <nsamsono@marvell.com>

Add callback for setting of MTU.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 78 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index a480b14..eded4eb 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1032,6 +1032,77 @@ static void mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
 }
 
 /**
+ * DPDK callback to change the MTU.
+ *
+ * Setting the MTU affects hardware MRU (packets larger than the MRU
+ * will be dropped).
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param mtu
+ *   New MTU.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	uint16_t mbuf_data_size = 0; /* SW buffer size */
+	uint16_t mru;
+	int ret;
+
+	mru = MRVL_NETA_MTU_TO_MRU(mtu);
+	/*
+	 * min_rx_buf_size is equal to mbuf data size
+	 * if pmd didn't set it differently
+	 */
+	mbuf_data_size = dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM;
+	/* Prevent PMD from:
+	 * - setting mru greater than the mbuf size resulting in
+	 * hw and sw buffer size mismatch
+	 * - setting mtu that requires the support of scattered packets
+	 * when this feature has not been enabled/supported so far.
+	 */
+	if (!dev->data->scattered_rx &&
+	    (mru + MRVL_NETA_PKT_OFFS > mbuf_data_size)) {
+		mru = mbuf_data_size - MRVL_NETA_PKT_OFFS;
+		mtu = MRVL_NETA_MRU_TO_MTU(mru);
+		MVNETA_LOG(WARNING, "MTU too big, max MTU possible limitted by"
+			" current mbuf size: %u. Set MTU to %u, MRU to %u\n",
+			mbuf_data_size, mtu, mru);
+	}
+
+	if (mtu < ETHER_MIN_MTU || mru > MVNETA_PKT_SIZE_MAX) {
+		MVNETA_LOG(ERR, "Invalid MTU [%u] or MRU [%u]\n", mtu, mru);
+		return -EINVAL;
+	}
+
+	dev->data->mtu = mtu;
+	dev->data->dev_conf.rxmode.max_rx_pkt_len = mru - MV_MH_SIZE;
+
+	if (!priv->ppio)
+		/* It is OK. New MTU will be set later on mvneta_dev_start */
+		return 0;
+
+	ret = neta_ppio_set_mru(priv->ppio, mru);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MRU\n");
+		return ret;
+	}
+
+	ret = neta_ppio_set_mtu(priv->ppio, mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MTU\n");
+		return ret;
+	}
+	MVNETA_LOG(INFO, "MTU changed to %u, MRU = %u\n", mtu, mru);
+
+	return 0;
+}
+
+/**
  * DPDK callback to bring the link up.
  *
  * @param dev
@@ -1305,6 +1376,12 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 		}
 	}
 
+	ret = mvneta_mtu_set(dev, dev->data->mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to set MTU %d\n", dev->data->mtu);
+		goto out;
+	}
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up\n");
@@ -1420,6 +1497,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
 	.mac_addr_set = mvneta_mac_addr_set,
+	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH 4/8] net/mvneta: add link update
  2018-08-28 15:10 [dpdk-dev] [PATCH 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                   ` (2 preceding siblings ...)
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
@ 2018-08-28 15:10 ` Andrzej Ostruszka
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-28 15:10 UTC (permalink / raw)
  To: dev; +Cc: nsamsono

From: Natalie Samsonov <nsamsono@marvell.com>

Add callback for updating information about link status/info.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 71 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index eded4eb..d1c180c 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1464,6 +1464,76 @@ mvneta_dev_close(struct rte_eth_dev *dev)
 }
 
 /**
+ * DPDK callback to retrieve physical link information.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param wait_to_complete
+ *   Wait for request completion (ignored).
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
+{
+	/*
+	 * TODO
+	 * once MUSDK provides necessary API use it here
+	 */
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct ethtool_cmd edata;
+	struct ifreq req;
+	int ret, fd, link_up;
+
+	if (!priv->ppio)
+		return -EPERM;
+
+	edata.cmd = ETHTOOL_GSET;
+
+	strcpy(req.ifr_name, dev->data->name);
+	req.ifr_data = (void *)&edata;
+
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd == -1)
+		return -EFAULT;
+	ret = ioctl(fd, SIOCETHTOOL, &req);
+	if (ret == -1) {
+		close(fd);
+		return -EFAULT;
+	}
+
+	close(fd);
+
+	switch (ethtool_cmd_speed(&edata)) {
+	case SPEED_10:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_10M;
+		break;
+	case SPEED_100:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_100M;
+		break;
+	case SPEED_1000:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_1G;
+		break;
+	case SPEED_2500:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_2_5G;
+		break;
+	default:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE;
+	}
+
+	dev->data->dev_link.link_duplex = edata.duplex ? ETH_LINK_FULL_DUPLEX :
+							 ETH_LINK_HALF_DUPLEX;
+	dev->data->dev_link.link_autoneg = edata.autoneg ? ETH_LINK_AUTONEG :
+							   ETH_LINK_FIXED;
+
+	neta_ppio_get_link_state(priv->ppio, &link_up);
+	dev->data->dev_link.link_status = link_up ? ETH_LINK_UP : ETH_LINK_DOWN;
+
+	return 0;
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -1496,6 +1566,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_up = mvneta_dev_set_link_up,
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
+	.link_update = mvneta_link_update,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH 5/8] net/mvneta: support for promiscuous
  2018-08-28 15:10 [dpdk-dev] [PATCH 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                   ` (3 preceding siblings ...)
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 4/8] net/mvneta: add link update Andrzej Ostruszka
@ 2018-08-28 15:10 ` Andrzej Ostruszka
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-28 15:10 UTC (permalink / raw)
  To: dev; +Cc: nsamsono

From: Yelena Krivosheev <yelena@marvell.com>

Add callbacks for enabling/disabling of promiscuous mode.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 54 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index d1c180c..3236e93 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1534,6 +1534,58 @@ mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
 }
 
 /**
+ * DPDK callback to enable promiscuous mode.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_promiscuous_enable(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	int ret, en;
+
+	if (!priv->ppio)
+		return;
+
+	neta_ppio_get_promisc(priv->ppio, &en);
+	if (en) {
+		MVNETA_LOG(INFO, "Promiscuous already enabled\n");
+		return;
+	}
+
+	ret = neta_ppio_set_promisc(priv->ppio, 1);
+	if (ret)
+		MVNETA_LOG(ERR, "Failed to enable promiscuous mode\n");
+}
+
+/**
+ * DPDK callback to disable allmulticast mode.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_promiscuous_disable(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	int ret, en;
+
+	if (!priv->ppio)
+		return;
+
+	neta_ppio_get_promisc(priv->ppio, &en);
+	if (!en) {
+		MVNETA_LOG(INFO, "Promiscuous already disabled\n");
+		return;
+	}
+
+	ret = neta_ppio_set_promisc(priv->ppio, 0);
+	if (ret)
+		MVNETA_LOG(ERR, "Failed to disable promiscuous mode\n");
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -1567,6 +1619,8 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
 	.link_update = mvneta_link_update,
+	.promiscuous_enable = mvneta_promiscuous_enable,
+	.promiscuous_disable = mvneta_promiscuous_disable,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH 6/8] net/mvneta: add MAC filtering
  2018-08-28 15:10 [dpdk-dev] [PATCH 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                   ` (4 preceding siblings ...)
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
@ 2018-08-28 15:10 ` Andrzej Ostruszka
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-28 15:10 UTC (permalink / raw)
  To: dev; +Cc: nsamsono

From: Yelena Krivosheev <yelena@marvell.com>

Add callbacks for adding/removing MAC addresses.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 69 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 3236e93..f19d2ea 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1586,6 +1586,73 @@ mvneta_promiscuous_disable(struct rte_eth_dev *dev)
 }
 
 /**
+ * DPDK callback to remove a MAC address.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param index
+ *   MAC address index.
+ */
+static void
+mvneta_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	char buf[ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	if (!priv->ppio)
+		return;
+
+	ret = neta_ppio_remove_mac_addr(priv->ppio,
+				       dev->data->mac_addrs[index].addr_bytes);
+	if (ret) {
+		ether_format_addr(buf, sizeof(buf),
+				  &dev->data->mac_addrs[index]);
+		MVNETA_LOG(ERR, "Failed to remove mac %s\n", buf);
+	}
+}
+
+/**
+ * DPDK callback to add a MAC address.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param mac_addr
+ *   MAC address to register.
+ * @param index
+ *   MAC address index.
+ * @param vmdq
+ *   VMDq pool index to associate address with (unused).
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
+		  uint32_t index, uint32_t vmdq __rte_unused)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	char buf[ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	if (index == 0)
+		/* For setting index 0, mrvl_mac_addr_set() should be used.*/
+		return -1;
+
+	if (!priv->ppio)
+		return 0;
+
+	ret = neta_ppio_add_mac_addr(priv->ppio, mac_addr->addr_bytes);
+	if (ret) {
+		ether_format_addr(buf, sizeof(buf), mac_addr);
+		MVNETA_LOG(ERR, "Failed to add mac %s\n", buf);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -1621,6 +1688,8 @@ static const struct eth_dev_ops mvneta_ops = {
 	.link_update = mvneta_link_update,
 	.promiscuous_enable = mvneta_promiscuous_enable,
 	.promiscuous_disable = mvneta_promiscuous_disable,
+	.mac_addr_remove = mvneta_mac_addr_remove,
+	.mac_addr_add = mvneta_mac_addr_add,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH 7/8] net/mvneta: add support for basic stats
  2018-08-28 15:10 [dpdk-dev] [PATCH 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                   ` (5 preceding siblings ...)
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
@ 2018-08-28 15:10 ` Andrzej Ostruszka
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
  2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-28 15:10 UTC (permalink / raw)
  To: dev; +Cc: nsamsono

From: Yelena Krivosheev <yelena@marvell.com>

Add support for getting of basic statistics for the driver.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 47 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index f19d2ea..9bff6c3 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1678,6 +1678,52 @@ mvneta_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
 	return 0;
 }
 
+/**
+ * DPDK callback to get device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param stats
+ *   Stats structure output buffer.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct neta_ppio_statistics ppio_stats;
+	unsigned int ret;
+
+	if (!priv->ppio)
+		return -EPERM;
+
+	ret = neta_ppio_get_statistics(priv->ppio, &ppio_stats);
+	if (unlikely(ret)) {
+		MVNETA_LOG(ERR, "Failed to update port statistics\n");
+		return ret;
+	}
+
+	stats->ipackets += ppio_stats.rx_packets +
+			ppio_stats.rx_broadcast_packets +
+			ppio_stats.rx_multicast_packets;
+	stats->opackets += ppio_stats.tx_packets +
+			ppio_stats.tx_broadcast_packets +
+			ppio_stats.tx_multicast_packets;
+	stats->ibytes += ppio_stats.rx_bytes;
+	stats->obytes += ppio_stats.tx_bytes;
+	stats->imissed += ppio_stats.rx_discard +
+			  ppio_stats.rx_overrun;
+
+	stats->ierrors = ppio_stats.rx_packets_err +
+			ppio_stats.rx_errors +
+			ppio_stats.rx_crc_error;
+	stats->oerrors = ppio_stats.tx_errors;
+
+	return 0;
+}
+
 static const struct eth_dev_ops mvneta_ops = {
 	.dev_configure = mvneta_dev_configure,
 	.dev_start = mvneta_dev_start,
@@ -1692,6 +1738,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_add = mvneta_mac_addr_add,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
+	.stats_get = mvneta_stats_get,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH 8/8] net/mvneta: add reset statistics callback
  2018-08-28 15:10 [dpdk-dev] [PATCH 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                   ` (6 preceding siblings ...)
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
@ 2018-08-28 15:10 ` Andrzej Ostruszka
  2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-28 15:10 UTC (permalink / raw)
  To: dev; +Cc: nsamsono

From: Natalie Samsonov <nsamsono@marvell.com>

Add support for reseting of driver statistics.

Singed-off-by: Natalie Samsonov <nsamsono@marvell.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 40 +++++++++++++++++++++++++++++++-------
 drivers/net/mvneta/mvneta_ethdev.h |  1 +
 2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 9bff6c3..9bad2e3 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1707,23 +1707,48 @@ mvneta_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 
 	stats->ipackets += ppio_stats.rx_packets +
 			ppio_stats.rx_broadcast_packets +
-			ppio_stats.rx_multicast_packets;
+			ppio_stats.rx_multicast_packets -
+			priv->prev_stats.ipackets;
 	stats->opackets += ppio_stats.tx_packets +
 			ppio_stats.tx_broadcast_packets +
-			ppio_stats.tx_multicast_packets;
-	stats->ibytes += ppio_stats.rx_bytes;
-	stats->obytes += ppio_stats.tx_bytes;
+			ppio_stats.tx_multicast_packets -
+			priv->prev_stats.opackets;
+	stats->ibytes += ppio_stats.rx_bytes - priv->prev_stats.ibytes;
+	stats->obytes += ppio_stats.tx_bytes - priv->prev_stats.obytes;
 	stats->imissed += ppio_stats.rx_discard +
-			  ppio_stats.rx_overrun;
+			  ppio_stats.rx_overrun -
+			  priv->prev_stats.imissed;
 
 	stats->ierrors = ppio_stats.rx_packets_err +
 			ppio_stats.rx_errors +
-			ppio_stats.rx_crc_error;
-	stats->oerrors = ppio_stats.tx_errors;
+			ppio_stats.rx_crc_error -
+			priv->prev_stats.ierrors;
+	stats->oerrors = ppio_stats.tx_errors - priv->prev_stats.oerrors;
 
 	return 0;
 }
 
+/**
+ * DPDK callback to clear device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_stats_reset(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	unsigned int ret;
+
+	if (!priv->ppio)
+		return;
+
+	ret = mvneta_stats_get(dev, &priv->prev_stats);
+	if (unlikely(ret))
+		RTE_LOG(ERR, PMD, "Failed to reset port statistics\n");
+}
+
+
 static const struct eth_dev_ops mvneta_ops = {
 	.dev_configure = mvneta_dev_configure,
 	.dev_start = mvneta_dev_start,
@@ -1739,6 +1764,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.stats_get = mvneta_stats_get,
+	.stats_reset = mvneta_stats_reset,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h
index a05566d..6aed170 100644
--- a/drivers/net/mvneta/mvneta_ethdev.h
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -77,6 +77,7 @@ struct mvneta_priv {
 	uint16_t nb_rx_queues;
 
 	uint64_t rate_max;
+	struct rte_eth_stats prev_stats;
 };
 
 /** Current log type. */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH 1/8] net/mvneta: add neta PMD skeleton
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
@ 2018-08-30  8:42   ` Hemant
  2018-08-30  9:54     ` Andrzej Ostruszka
  0 siblings, 1 reply; 96+ messages in thread
From: Hemant @ 2018-08-30  8:42 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev; +Cc: nsamsono

Hi,

On 8/28/2018 8:40 PM, Andrzej Ostruszka wrote:
> diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
> new file mode 100644
> index 0000000..6e9f511
> --- /dev/null
> +++ b/doc/guides/nics/mvneta.rst
> @@ -0,0 +1,182 @@
> +..  SPDX-License-Identifier: BSD-3-Clause
> +    Copyright(c) 2018 Marvell International Ltd.
> +    Copyright(c) 2018 Semihalf.
> +    All rights reserved.
> +
> +    Redistribution and use in source and binary forms, with or without
> +    modification, are permitted provided that the following conditions
> +    are met:
> +
> +      * Redistributions of source code must retain the above copyright
> +        notice, this list of conditions and the following disclaimer.
> +      * Redistributions in binary form must reproduce the above copyright
> +        notice, this list of conditions and the following disclaimer in
> +        the documentation and/or other materials provided with the
> +        distribution.
> +      * Neither the name of the copyright holder nor the names of its
> +        contributors may be used to endorse or promote products derived
> +        from this software without specific prior written permission.
> +
> +    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> +    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> +    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> +    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> +    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> +    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> +    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> +    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> +    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> +    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> +    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Since you are already providing the SPDX license identifier, you should 
avoid copying the full BSD text again in the files.

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH 1/8] net/mvneta: add neta PMD skeleton
  2018-08-30  8:42   ` Hemant
@ 2018-08-30  9:54     ` Andrzej Ostruszka
  0 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-30  9:54 UTC (permalink / raw)
  To: dev

On 30.08.2018 10:42, Hemant wrote:
[...]
> Since you are already providing the SPDX license identifier, you should 
> avoid copying the full BSD text again in the files.

Thank you Hemant for taking a look.  Will remove.

Best regards
Andrzej

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD
  2018-08-28 15:10 [dpdk-dev] [PATCH 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                   ` (7 preceding siblings ...)
  2018-08-28 15:10 ` [dpdk-dev] [PATCH 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
@ 2018-08-31 12:25 ` Andrzej Ostruszka
  2018-08-31 12:25   ` [dpdk-dev] [PATCH v2 1/8] net/bonding: fix buf corruption in packets Andrzej Ostruszka
                     ` (12 more replies)
  8 siblings, 13 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:25 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

This patch series introduces new PMD for Marvell NETA adapters (MVNETA).
See the documentation for more info.

It is split for easier reviewing.

v2:
  * fixed couple of checkpatch warnings
  * removed '\n' from MVNETA_LOG invocations (appended by the macro)
  * removed unused MVNETA_MUSDK_DMA_MEMSIZE define
  * changed one printf into MVNETA_LOG
  * removed __func__ from one MVNETA_LOG invocation (inserted
    automatically by the macro)
  * minor grammar/spelling correction in comments
  * removed license text from file with SPDX tag (mvneta.rst)
  * removed misleading part of comment for mvneta_shadow_txq
  * changed authorship of the patches to the original author

Natalie Samsonov (1):
  net/mvneta: add reset statistics callback

Zyta Szpak (7):
  net/mvneta: add neta PMD skeleton
  net/mvneta: add Rx/Tx support
  net/mvneta: support for setting of MTU
  net/mvneta: add link update
  net/mvneta: support for promiscuous
  net/mvneta: add MAC filtering
  net/mvneta: add support for basic stats

 MAINTAINERS                                   |    8 +
 config/common_base                            |    5 +
 devtools/test-build.sh                        |    2 +
 doc/guides/nics/features/mvneta.ini           |   18 +
 doc/guides/nics/mvneta.rst                    |  154 ++
 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            | 2016 +++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h            |   90 ++
 drivers/net/mvneta/rte_pmd_mvneta_version.map |    3 +
 mk/rte.app.mk                                 |    7 +-
 16 files changed, 2380 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

-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v2 1/8] net/bonding: fix buf corruption in packets
  2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
@ 2018-08-31 12:25   ` Andrzej Ostruszka
  2018-08-31 12:33     ` Andrzej Ostruszka
  2018-08-31 12:25   ` [dpdk-dev] [PATCH v2 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
                     ` (11 subsequent siblings)
  12 siblings, 1 reply; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:25 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono, Jia Yu, stable

From: Jia Yu <jyu@vmware.com>

When bond slave devices cannot transmit all packets in bufs array,
tx_burst callback shall merge the un-transmitted packets back to
bufs array. Recent merge logic introduced a bug which causes
invalid mbuf addresses being written to bufs array.
When caller frees the un-transmitted packets, due to invalid addresses,
application will crash.

The fix is avoid shifting mbufs, and directly write un-transmitted
packets back to bufs array.

Fixes: 09150784a776 ("net/bonding: burst mode hash calculation")
Cc: stable@dpdk.org

Signed-off-by: Jia Yu <jyu@vmware.com>
Acked-by: Chas Williams <chas3@att.com>
---
 drivers/net/bonding/rte_eth_bond_pmd.c | 116 +++++++--------------------------
 1 file changed, 23 insertions(+), 93 deletions(-)

diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index 4417422..b84f322 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -301,10 +301,10 @@ bond_ethdev_tx_burst_8023ad_fast_queue(void *queue, struct rte_mbuf **bufs,
 	/* Mapping array generated by hash function to map mbufs to slaves */
 	uint16_t bufs_slave_port_idxs[RTE_MAX_ETHPORTS] = { 0 };
 
-	uint16_t slave_tx_count, slave_tx_fail_count[RTE_MAX_ETHPORTS] = { 0 };
+	uint16_t slave_tx_count;
 	uint16_t total_tx_count = 0, total_tx_fail_count = 0;
 
-	uint16_t i, j;
+	uint16_t i;
 
 	if (unlikely(nb_bufs == 0))
 		return 0;
@@ -359,34 +359,12 @@ bond_ethdev_tx_burst_8023ad_fast_queue(void *queue, struct rte_mbuf **bufs,
 
 		/* If tx burst fails move packets to end of bufs */
 		if (unlikely(slave_tx_count < slave_nb_bufs[i])) {
-			slave_tx_fail_count[i] = slave_nb_bufs[i] -
+			int slave_tx_fail_count = slave_nb_bufs[i] -
 					slave_tx_count;
-			total_tx_fail_count += slave_tx_fail_count[i];
-
-			/*
-			 * Shift bufs to beginning of array to allow reordering
-			 * later
-			 */
-			for (j = 0; j < slave_tx_fail_count[i]; j++) {
-				slave_bufs[i][j] =
-					slave_bufs[i][(slave_tx_count - 1) + j];
-			}
-		}
-	}
-
-	/*
-	 * If there are tx burst failures we move packets to end of bufs to
-	 * preserve expected PMD behaviour of all failed transmitted being
-	 * at the end of the input mbuf array
-	 */
-	if (unlikely(total_tx_fail_count > 0)) {
-		int bufs_idx = nb_bufs - total_tx_fail_count - 1;
-
-		for (i = 0; i < slave_count; i++) {
-			if (slave_tx_fail_count[i] > 0) {
-				for (j = 0; j < slave_tx_fail_count[i]; j++)
-					bufs[bufs_idx++] = slave_bufs[i][j];
-			}
+			total_tx_fail_count += slave_tx_fail_count;
+			memcpy(&bufs[nb_bufs - total_tx_fail_count],
+			       &slave_bufs[i][slave_tx_count],
+			       slave_tx_fail_count * sizeof(bufs[0]));
 		}
 	}
 
@@ -716,8 +694,8 @@ bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,
 				tx_fail_total += tx_fail_slave;
 
 				memcpy(&bufs[nb_pkts - tx_fail_total],
-						&slave_bufs[i][num_tx_slave],
-						tx_fail_slave * sizeof(bufs[0]));
+				       &slave_bufs[i][num_tx_slave],
+				       tx_fail_slave * sizeof(bufs[0]));
 			}
 			num_tx_total += num_tx_slave;
 		}
@@ -1222,10 +1200,10 @@ bond_ethdev_tx_burst_balance(void *queue, struct rte_mbuf **bufs,
 	/* Mapping array generated by hash function to map mbufs to slaves */
 	uint16_t bufs_slave_port_idxs[nb_bufs];
 
-	uint16_t slave_tx_count, slave_tx_fail_count[RTE_MAX_ETHPORTS] = { 0 };
+	uint16_t slave_tx_count;
 	uint16_t total_tx_count = 0, total_tx_fail_count = 0;
 
-	uint16_t i, j;
+	uint16_t i;
 
 	if (unlikely(nb_bufs == 0))
 		return 0;
@@ -1266,34 +1244,12 @@ bond_ethdev_tx_burst_balance(void *queue, struct rte_mbuf **bufs,
 
 		/* If tx burst fails move packets to end of bufs */
 		if (unlikely(slave_tx_count < slave_nb_bufs[i])) {
-			slave_tx_fail_count[i] = slave_nb_bufs[i] -
+			int slave_tx_fail_count = slave_nb_bufs[i] -
 					slave_tx_count;
-			total_tx_fail_count += slave_tx_fail_count[i];
-
-			/*
-			 * Shift bufs to beginning of array to allow reordering
-			 * later
-			 */
-			for (j = 0; j < slave_tx_fail_count[i]; j++) {
-				slave_bufs[i][j] =
-					slave_bufs[i][(slave_tx_count - 1) + j];
-			}
-		}
-	}
-
-	/*
-	 * If there are tx burst failures we move packets to end of bufs to
-	 * preserve expected PMD behaviour of all failed transmitted being
-	 * at the end of the input mbuf array
-	 */
-	if (unlikely(total_tx_fail_count > 0)) {
-		int bufs_idx = nb_bufs - total_tx_fail_count - 1;
-
-		for (i = 0; i < slave_count; i++) {
-			if (slave_tx_fail_count[i] > 0) {
-				for (j = 0; j < slave_tx_fail_count[i]; j++)
-					bufs[bufs_idx++] = slave_bufs[i][j];
-			}
+			total_tx_fail_count += slave_tx_fail_count;
+			memcpy(&bufs[nb_bufs - total_tx_fail_count],
+			       &slave_bufs[i][slave_tx_count],
+			       slave_tx_fail_count * sizeof(bufs[0]));
 		}
 	}
 
@@ -1320,10 +1276,10 @@ bond_ethdev_tx_burst_8023ad(void *queue, struct rte_mbuf **bufs,
 	/* Mapping array generated by hash function to map mbufs to slaves */
 	uint16_t bufs_slave_port_idxs[RTE_MAX_ETHPORTS] = { 0 };
 
-	uint16_t slave_tx_count, slave_tx_fail_count[RTE_MAX_ETHPORTS] = { 0 };
+	uint16_t slave_tx_count;
 	uint16_t total_tx_count = 0, total_tx_fail_count = 0;
 
-	uint16_t i, j;
+	uint16_t i;
 
 	if (unlikely(nb_bufs == 0))
 		return 0;
@@ -1381,39 +1337,13 @@ bond_ethdev_tx_burst_8023ad(void *queue, struct rte_mbuf **bufs,
 
 			/* If tx burst fails move packets to end of bufs */
 			if (unlikely(slave_tx_count < slave_nb_bufs[i])) {
-				slave_tx_fail_count[i] = slave_nb_bufs[i] -
+				int slave_tx_fail_count = slave_nb_bufs[i] -
 						slave_tx_count;
-				total_tx_fail_count += slave_tx_fail_count[i];
-
-				/*
-				 * Shift bufs to beginning of array to allow
-				 * reordering later
-				 */
-				for (j = 0; j < slave_tx_fail_count[i]; j++)
-					slave_bufs[i][j] =
-						slave_bufs[i]
-							[(slave_tx_count - 1)
-							+ j];
-			}
-		}
+				total_tx_fail_count += slave_tx_fail_count;
 
-		/*
-		 * If there are tx burst failures we move packets to end of
-		 * bufs to preserve expected PMD behaviour of all failed
-		 * transmitted being at the end of the input mbuf array
-		 */
-		if (unlikely(total_tx_fail_count > 0)) {
-			int bufs_idx = nb_bufs - total_tx_fail_count - 1;
-
-			for (i = 0; i < slave_count; i++) {
-				if (slave_tx_fail_count[i] > 0) {
-					for (j = 0;
-						j < slave_tx_fail_count[i];
-						j++) {
-						bufs[bufs_idx++] =
-							slave_bufs[i][j];
-					}
-				}
+				memcpy(&bufs[nb_bufs - total_tx_fail_count],
+				       &slave_bufs[i][slave_tx_count],
+				       slave_tx_fail_count * sizeof(bufs[0]));
 			}
 		}
 	}
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v2 1/8] net/mvneta: add neta PMD skeleton
  2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  2018-08-31 12:25   ` [dpdk-dev] [PATCH v2 1/8] net/bonding: fix buf corruption in packets Andrzej Ostruszka
@ 2018-08-31 12:25   ` Andrzej Ostruszka
  2018-08-31 12:25   ` [dpdk-dev] [PATCH v2 2/8] " Andrzej Ostruszka
                     ` (10 subsequent siblings)
  12 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:25 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add neta pmd driver skeleton providing base for the further
development.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
Signed-off-by: Andrzej Ostruszka <amo@semihalf.com>
---
 MAINTAINERS                                   |   8 +
 config/common_base                            |   5 +
 devtools/test-build.sh                        |   2 +
 doc/guides/nics/features/mvneta.ini           |  18 +
 doc/guides/nics/mvneta.rst                    | 154 +++++
 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            | 880 ++++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h            |  78 +++
 drivers/net/mvneta/rte_pmd_mvneta_version.map |   3 +
 mk/rte.app.mk                                 |   7 +-
 16 files changed, 1232 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 9fd258f..18858b9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -585,6 +585,14 @@ F: drivers/net/mvpp2/
 F: doc/guides/nics/mvpp2.rst
 F: doc/guides/nics/features/mvpp2.ini
 
+Marvell mvneta
+M: Zyta Szpak <zr@semihalf.com>
+M: Dmitri Epshtein <dima@marvell.com>
+M: Natalie Samsonov <nsamsono@marvell.com>
+F: drivers/net/mvneta/
+F: doc/guides/nics/mvneta.rst
+F: doc/guides/nics/features/mvneta.ini
+
 Mellanox mlx4
 M: Matan Azrad <matan@mellanox.com>
 M: Shahaf Shuler <shahafs@mellanox.com>
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 () # <directory> <target> <options>
 		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..3f02f84
--- /dev/null
+++ b/doc/guides/nics/features/mvneta.ini
@@ -0,0 +1,18 @@
+;
+; 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
+Link status          = Y
+MTU update           = Y
+Jumbo frame          = Y
+Promiscuous mode     = Y
+CRC offload          = Y
+L3 checksum offload  = Y
+L4 checksum offload  = Y
+Packet type parsing  = Y
+Basic stats          = 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..8d4b9e4
--- /dev/null
+++ b/doc/guides/nics/mvneta.rst
@@ -0,0 +1,154 @@
+..  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
+- tx/rx_burst
+- Speed capabilities
+- Link status
+- CRC offload
+- Packet type parsing
+
+
+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 <https://extranet.marvell.com>`_. 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 <linux_gsg>` 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=eth_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=<toolchain>/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=<musdk>/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=eth_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=eth_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 24204e6..0586715 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -54,6 +54,10 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **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..621f38a
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -0,0 +1,880 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Marvell International Ltd.
+ * Copyright(c) 2018 Semihalf.
+ * All rights reserved.
+ */
+
+#include <rte_ethdev_driver.h>
+#include <rte_kvargs.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_bus_vdev.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <rte_mvep_common.h>
+#include "mvneta_ethdev.h"
+
+
+#define MVNETA_IFACE_NAME_ARG "iface"
+
+#define MVNETA_RX_OFFLOADS (DEV_RX_OFFLOAD_JUMBO_FRAME | \
+			  DEV_RX_OFFLOAD_CRC_STRIP | \
+			  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
+
+#define MVNETA_PKT_EFFEC_OFFS (MRVL_NETA_PKT_OFFS + MV_MH_SIZE)
+
+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;
+};
+
+
+struct mvneta_rxq {
+	struct mvneta_priv *priv;
+	struct rte_mempool *mp;
+	int queue_id;
+	int port_id;
+	int size;
+	int cksum_enabled;
+	uint64_t bytes_recv;
+	uint64_t drop_mac;
+	uint64_t pkts_processed;
+};
+
+
+struct mvneta_txq {
+	struct mvneta_priv *priv;
+	int queue_id;
+	int port_id;
+	uint64_t bytes_sent;
+	int tx_deferred_start;
+};
+
+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.offloads & DEV_RX_OFFLOAD_CRC_STRIP)) {
+		MVNETA_LOG(INFO,
+			"L2 CRC stripping is always enabled in hw");
+		dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CRC_STRIP;
+	}
+
+	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;
+	info->default_rxconf.offloads = DEV_RX_OFFLOAD_CRC_STRIP;
+	/* 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 get information about specific receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param rx_queue_id
+ *   Receive queue index.
+ * @param qinfo
+ *   Receive queue information structure.
+ */
+static void mvneta_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+			      struct rte_eth_rxq_info *qinfo)
+{
+	struct mvneta_rxq *q = dev->data->rx_queues[rx_queue_id];
+
+	qinfo->mp = q->mp;
+	qinfo->nb_desc = q->size;
+}
+
+/**
+ * DPDK callback to get information about specific transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param tx_queue_id
+ *   Transmit queue index.
+ * @param qinfo
+ *   Transmit queue information structure.
+ */
+static void mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+			      struct rte_eth_txq_info *qinfo)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	qinfo->nb_desc =
+		priv->ppio_params.outqs_params.outqs_params[tx_queue_id].size;
+}
+
+/**
+ * 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 configure the receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   RX queue index.
+ * @param desc
+ *   Number of descriptors to configure in queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Thresholds parameters (unused_).
+ * @param mp
+ *   Memory pool for buffer allocations.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		    unsigned int socket,
+		    const struct rte_eth_rxconf *conf __rte_unused,
+		    struct rte_mempool *mp)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_rxq *rxq;
+	uint32_t frame_size, buf_size = rte_pktmbuf_data_room_size(mp);
+	uint32_t max_rx_pkt_len = dev->data->dev_conf.rxmode.max_rx_pkt_len;
+
+	frame_size = buf_size - RTE_PKTMBUF_HEADROOM - MVNETA_PKT_EFFEC_OFFS;
+
+	if (frame_size < max_rx_pkt_len) {
+		MVNETA_LOG(ERR,
+			"Mbuf size must be increased to %u bytes to hold up "
+			"to %u bytes of data.",
+			buf_size + max_rx_pkt_len - frame_size,
+			max_rx_pkt_len);
+		dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
+		MVNETA_LOG(INFO, "Setting max rx pkt len to %u",
+			dev->data->dev_conf.rxmode.max_rx_pkt_len);
+	}
+
+	if (dev->data->rx_queues[idx]) {
+		rte_free(dev->data->rx_queues[idx]);
+		dev->data->rx_queues[idx] = NULL;
+	}
+
+	rxq = rte_zmalloc_socket("rxq", sizeof(*rxq), 0, socket);
+	if (!rxq)
+		return -ENOMEM;
+
+	rxq->priv = priv;
+	rxq->mp = mp;
+	rxq->cksum_enabled = dev->data->dev_conf.rxmode.offloads &
+			     DEV_RX_OFFLOAD_IPV4_CKSUM;
+	rxq->queue_id = idx;
+	rxq->port_id = dev->data->port_id;
+	rxq->size = desc;
+	priv->ppio_params.inqs_params.tcs_params[MRVL_NETA_DEFAULT_TC].size =
+		desc;
+
+	dev->data->rx_queues[idx] = rxq;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to release the receive queue.
+ *
+ * @param rxq
+ *   Generic receive queue pointer.
+ */
+static void
+mvneta_rx_queue_release(void *rxq)
+{
+	struct mvneta_rxq *q = rxq;
+
+	if (!q)
+		return;
+
+	rte_free(rxq);
+}
+
+/**
+ * DPDK callback to configure the transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   Transmit queue index.
+ * @param desc
+ *   Number of descriptors to configure in the queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Tx queue configuration parameters.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		    unsigned int socket, const struct rte_eth_txconf *conf)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_txq *txq;
+
+	if (dev->data->tx_queues[idx]) {
+		rte_free(dev->data->tx_queues[idx]);
+		dev->data->tx_queues[idx] = NULL;
+	}
+
+	txq = rte_zmalloc_socket("txq", sizeof(*txq), 0, socket);
+	if (!txq)
+		return -ENOMEM;
+
+	txq->priv = priv;
+	txq->queue_id = idx;
+	txq->port_id = dev->data->port_id;
+	txq->tx_deferred_start = conf->tx_deferred_start;
+	dev->data->tx_queues[idx] = txq;
+
+	priv->ppio_params.outqs_params.outqs_params[idx].size = desc;
+	priv->ppio_params.outqs_params.outqs_params[idx].weight = 1;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to release the transmit queue.
+ *
+ * @param txq
+ *   Generic transmit queue pointer.
+ */
+static void
+mvneta_tx_queue_release(void *txq)
+{
+	struct mvneta_txq *q = txq;
+
+	if (!q)
+		return;
+
+	rte_free(q);
+}
+
+
+/**
+ * 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;
+	int i;
+
+	if (priv->ppio)
+		mvneta_dev_stop(dev);
+
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		mvneta_rx_queue_release(dev->data->rx_queues[i]);
+		dev->data->rx_queues[i] = NULL;
+	}
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		mvneta_tx_queue_release(dev->data->tx_queues[i]);
+		dev->data->tx_queues[i] = NULL;
+	}
+}
+
+/**
+ * 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,
+	.rxq_info_get = mvneta_rxq_info_get,
+	.txq_info_get = mvneta_txq_info_get,
+	.rx_queue_setup = mvneta_rx_queue_setup,
+	.rx_queue_release = mvneta_rx_queue_release,
+	.tx_queue_setup = mvneta_tx_queue_setup,
+	.tx_queue_release = mvneta_tx_queue_release,
+};
+
+/**
+ * Create private device structure.
+ *
+ * @param dev_name
+ *   Pointer to the port name passed in the initialization parameters.
+ *
+ * @return
+ *   Pointer to the newly allocated private device structure.
+ */
+static struct mvneta_priv *
+mvneta_priv_create(const char *dev_name)
+{
+	struct mvneta_priv *priv;
+
+	priv = rte_zmalloc_socket(dev_name, sizeof(*priv), 0, rte_socket_id());
+	if (!priv)
+		return NULL;
+
+	return priv;
+}
+
+/**
+ * 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 = mvneta_priv_create(name);
+
+	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_dev:
+	rte_eth_dev_release_port(eth_dev);
+out_free_priv:
+	rte_free(priv);
+
+	return ret;
+}
+
+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_PMD_REGISTER_ALIAS(net_mvneta, eth_mvneta);
+
+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..8957034
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -0,0 +1,78 @@
+/* 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 <drivers/mv_neta.h>
+#include <drivers/mv_neta_ppio.h>
+
+/** 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 TODO is it? */
+#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 TODO is it? */
+#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_DEFAULT_TC 0
+
+
+#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
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v2 2/8] net/mvneta: add neta PMD skeleton
  2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  2018-08-31 12:25   ` [dpdk-dev] [PATCH v2 1/8] net/bonding: fix buf corruption in packets Andrzej Ostruszka
  2018-08-31 12:25   ` [dpdk-dev] [PATCH v2 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
@ 2018-08-31 12:25   ` Andrzej Ostruszka
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
                     ` (9 subsequent siblings)
  12 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:25 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add neta pmd driver skeleton providing base for the further
development.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
Signed-off-by: Andrzej Ostruszka <amo@semihalf.com>
---
 MAINTAINERS                                   |   8 +
 config/common_base                            |   5 +
 devtools/test-build.sh                        |   2 +
 doc/guides/nics/features/mvneta.ini           |  18 +
 doc/guides/nics/mvneta.rst                    | 154 +++++
 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            | 880 ++++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h            |  78 +++
 drivers/net/mvneta/rte_pmd_mvneta_version.map |   3 +
 mk/rte.app.mk                                 |   7 +-
 16 files changed, 1232 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 9fd258f..18858b9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -585,6 +585,14 @@ F: drivers/net/mvpp2/
 F: doc/guides/nics/mvpp2.rst
 F: doc/guides/nics/features/mvpp2.ini
 
+Marvell mvneta
+M: Zyta Szpak <zr@semihalf.com>
+M: Dmitri Epshtein <dima@marvell.com>
+M: Natalie Samsonov <nsamsono@marvell.com>
+F: drivers/net/mvneta/
+F: doc/guides/nics/mvneta.rst
+F: doc/guides/nics/features/mvneta.ini
+
 Mellanox mlx4
 M: Matan Azrad <matan@mellanox.com>
 M: Shahaf Shuler <shahafs@mellanox.com>
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 () # <directory> <target> <options>
 		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..3f02f84
--- /dev/null
+++ b/doc/guides/nics/features/mvneta.ini
@@ -0,0 +1,18 @@
+;
+; 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
+Link status          = Y
+MTU update           = Y
+Jumbo frame          = Y
+Promiscuous mode     = Y
+CRC offload          = Y
+L3 checksum offload  = Y
+L4 checksum offload  = Y
+Packet type parsing  = Y
+Basic stats          = 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..8d4b9e4
--- /dev/null
+++ b/doc/guides/nics/mvneta.rst
@@ -0,0 +1,154 @@
+..  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
+- tx/rx_burst
+- Speed capabilities
+- Link status
+- CRC offload
+- Packet type parsing
+
+
+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 <https://extranet.marvell.com>`_. 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 <linux_gsg>` 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=eth_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=<toolchain>/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=<musdk>/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=eth_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=eth_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 24204e6..0586715 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -54,6 +54,10 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **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..621f38a
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -0,0 +1,880 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Marvell International Ltd.
+ * Copyright(c) 2018 Semihalf.
+ * All rights reserved.
+ */
+
+#include <rte_ethdev_driver.h>
+#include <rte_kvargs.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_bus_vdev.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <rte_mvep_common.h>
+#include "mvneta_ethdev.h"
+
+
+#define MVNETA_IFACE_NAME_ARG "iface"
+
+#define MVNETA_RX_OFFLOADS (DEV_RX_OFFLOAD_JUMBO_FRAME | \
+			  DEV_RX_OFFLOAD_CRC_STRIP | \
+			  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
+
+#define MVNETA_PKT_EFFEC_OFFS (MRVL_NETA_PKT_OFFS + MV_MH_SIZE)
+
+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;
+};
+
+
+struct mvneta_rxq {
+	struct mvneta_priv *priv;
+	struct rte_mempool *mp;
+	int queue_id;
+	int port_id;
+	int size;
+	int cksum_enabled;
+	uint64_t bytes_recv;
+	uint64_t drop_mac;
+	uint64_t pkts_processed;
+};
+
+
+struct mvneta_txq {
+	struct mvneta_priv *priv;
+	int queue_id;
+	int port_id;
+	uint64_t bytes_sent;
+	int tx_deferred_start;
+};
+
+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.offloads & DEV_RX_OFFLOAD_CRC_STRIP)) {
+		MVNETA_LOG(INFO,
+			"L2 CRC stripping is always enabled in hw");
+		dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CRC_STRIP;
+	}
+
+	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;
+	info->default_rxconf.offloads = DEV_RX_OFFLOAD_CRC_STRIP;
+	/* 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 get information about specific receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param rx_queue_id
+ *   Receive queue index.
+ * @param qinfo
+ *   Receive queue information structure.
+ */
+static void mvneta_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+			      struct rte_eth_rxq_info *qinfo)
+{
+	struct mvneta_rxq *q = dev->data->rx_queues[rx_queue_id];
+
+	qinfo->mp = q->mp;
+	qinfo->nb_desc = q->size;
+}
+
+/**
+ * DPDK callback to get information about specific transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param tx_queue_id
+ *   Transmit queue index.
+ * @param qinfo
+ *   Transmit queue information structure.
+ */
+static void mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+			      struct rte_eth_txq_info *qinfo)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	qinfo->nb_desc =
+		priv->ppio_params.outqs_params.outqs_params[tx_queue_id].size;
+}
+
+/**
+ * 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 configure the receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   RX queue index.
+ * @param desc
+ *   Number of descriptors to configure in queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Thresholds parameters (unused_).
+ * @param mp
+ *   Memory pool for buffer allocations.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		    unsigned int socket,
+		    const struct rte_eth_rxconf *conf __rte_unused,
+		    struct rte_mempool *mp)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_rxq *rxq;
+	uint32_t frame_size, buf_size = rte_pktmbuf_data_room_size(mp);
+	uint32_t max_rx_pkt_len = dev->data->dev_conf.rxmode.max_rx_pkt_len;
+
+	frame_size = buf_size - RTE_PKTMBUF_HEADROOM - MVNETA_PKT_EFFEC_OFFS;
+
+	if (frame_size < max_rx_pkt_len) {
+		MVNETA_LOG(ERR,
+			"Mbuf size must be increased to %u bytes to hold up "
+			"to %u bytes of data.",
+			buf_size + max_rx_pkt_len - frame_size,
+			max_rx_pkt_len);
+		dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
+		MVNETA_LOG(INFO, "Setting max rx pkt len to %u",
+			dev->data->dev_conf.rxmode.max_rx_pkt_len);
+	}
+
+	if (dev->data->rx_queues[idx]) {
+		rte_free(dev->data->rx_queues[idx]);
+		dev->data->rx_queues[idx] = NULL;
+	}
+
+	rxq = rte_zmalloc_socket("rxq", sizeof(*rxq), 0, socket);
+	if (!rxq)
+		return -ENOMEM;
+
+	rxq->priv = priv;
+	rxq->mp = mp;
+	rxq->cksum_enabled = dev->data->dev_conf.rxmode.offloads &
+			     DEV_RX_OFFLOAD_IPV4_CKSUM;
+	rxq->queue_id = idx;
+	rxq->port_id = dev->data->port_id;
+	rxq->size = desc;
+	priv->ppio_params.inqs_params.tcs_params[MRVL_NETA_DEFAULT_TC].size =
+		desc;
+
+	dev->data->rx_queues[idx] = rxq;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to release the receive queue.
+ *
+ * @param rxq
+ *   Generic receive queue pointer.
+ */
+static void
+mvneta_rx_queue_release(void *rxq)
+{
+	struct mvneta_rxq *q = rxq;
+
+	if (!q)
+		return;
+
+	rte_free(rxq);
+}
+
+/**
+ * DPDK callback to configure the transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   Transmit queue index.
+ * @param desc
+ *   Number of descriptors to configure in the queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Tx queue configuration parameters.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		    unsigned int socket, const struct rte_eth_txconf *conf)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_txq *txq;
+
+	if (dev->data->tx_queues[idx]) {
+		rte_free(dev->data->tx_queues[idx]);
+		dev->data->tx_queues[idx] = NULL;
+	}
+
+	txq = rte_zmalloc_socket("txq", sizeof(*txq), 0, socket);
+	if (!txq)
+		return -ENOMEM;
+
+	txq->priv = priv;
+	txq->queue_id = idx;
+	txq->port_id = dev->data->port_id;
+	txq->tx_deferred_start = conf->tx_deferred_start;
+	dev->data->tx_queues[idx] = txq;
+
+	priv->ppio_params.outqs_params.outqs_params[idx].size = desc;
+	priv->ppio_params.outqs_params.outqs_params[idx].weight = 1;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to release the transmit queue.
+ *
+ * @param txq
+ *   Generic transmit queue pointer.
+ */
+static void
+mvneta_tx_queue_release(void *txq)
+{
+	struct mvneta_txq *q = txq;
+
+	if (!q)
+		return;
+
+	rte_free(q);
+}
+
+
+/**
+ * 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;
+	int i;
+
+	if (priv->ppio)
+		mvneta_dev_stop(dev);
+
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		mvneta_rx_queue_release(dev->data->rx_queues[i]);
+		dev->data->rx_queues[i] = NULL;
+	}
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		mvneta_tx_queue_release(dev->data->tx_queues[i]);
+		dev->data->tx_queues[i] = NULL;
+	}
+}
+
+/**
+ * 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,
+	.rxq_info_get = mvneta_rxq_info_get,
+	.txq_info_get = mvneta_txq_info_get,
+	.rx_queue_setup = mvneta_rx_queue_setup,
+	.rx_queue_release = mvneta_rx_queue_release,
+	.tx_queue_setup = mvneta_tx_queue_setup,
+	.tx_queue_release = mvneta_tx_queue_release,
+};
+
+/**
+ * Create private device structure.
+ *
+ * @param dev_name
+ *   Pointer to the port name passed in the initialization parameters.
+ *
+ * @return
+ *   Pointer to the newly allocated private device structure.
+ */
+static struct mvneta_priv *
+mvneta_priv_create(const char *dev_name)
+{
+	struct mvneta_priv *priv;
+
+	priv = rte_zmalloc_socket(dev_name, sizeof(*priv), 0, rte_socket_id());
+	if (!priv)
+		return NULL;
+
+	return priv;
+}
+
+/**
+ * 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 = mvneta_priv_create(name);
+
+	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_dev:
+	rte_eth_dev_release_port(eth_dev);
+out_free_priv:
+	rte_free(priv);
+
+	return ret;
+}
+
+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_PMD_REGISTER_ALIAS(net_mvneta, eth_mvneta);
+
+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..8957034
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -0,0 +1,78 @@
+/* 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 <drivers/mv_neta.h>
+#include <drivers/mv_neta_ppio.h>
+
+/** 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 TODO is it? */
+#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 TODO is it? */
+#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_DEFAULT_TC 0
+
+
+#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
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v2 2/8] net/mvneta: add Rx/Tx support
  2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                     ` (2 preceding siblings ...)
  2018-08-31 12:25   ` [dpdk-dev] [PATCH v2 2/8] " Andrzej Ostruszka
@ 2018-08-31 12:26   ` Andrzej Ostruszka
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 3/8] " Andrzej Ostruszka
                     ` (8 subsequent siblings)
  12 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:26 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add part of PMD for actual reception/transmission.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 791 +++++++++++++++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h |  11 +
 2 files changed, 802 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 621f38a..968f920 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -27,6 +27,11 @@
 
 #define MVNETA_IFACE_NAME_ARG "iface"
 
+#define MVNETA_COOKIE_ADDR_INVALID ~0ULL
+
+#define MVNETA_COOKIE_HIGH_ADDR_SHIFT	(sizeof(neta_cookie_t) * 8)
+#define MVNETA_COOKIE_HIGH_ADDR_MASK	(~0ULL << MVNETA_COOKIE_HIGH_ADDR_SHIFT)
+
 #define MVNETA_RX_OFFLOADS (DEV_RX_OFFLOAD_JUMBO_FRAME | \
 			  DEV_RX_OFFLOAD_CRC_STRIP | \
 			  DEV_RX_OFFLOAD_CHECKSUM)
@@ -46,6 +51,19 @@
 
 #define MVNETA_PKT_EFFEC_OFFS (MRVL_NETA_PKT_OFFS + MV_MH_SIZE)
 
+static uint64_t cookie_addr_high = MVNETA_COOKIE_ADDR_INVALID;
+static uint16_t rx_desc_free_thresh = MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN;
+
+#define MVNETA_SET_COOKIE_HIGH_ADDR(addr) {				\
+	if (unlikely(cookie_addr_high == MVNETA_COOKIE_ADDR_INVALID))	\
+		cookie_addr_high =					\
+			(uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK;\
+}
+
+#define MVNETA_CHECK_COOKIE_HIGH_ADDR(addr)			\
+	((likely(cookie_addr_high ==				\
+	((uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK))) ? 1 : 0)
+
 int mvneta_logtype;
 
 static const char * const valid_args[] = {
@@ -58,6 +76,17 @@ struct mvneta_ifnames {
 	int idx;
 };
 
+/*
+ * To use buffer harvesting based on loopback port shadow queue structure
+ * was introduced for buffers information bookkeeping.
+ */
+struct mvneta_shadow_txq {
+	int head;           /* write index - used when sending buffers */
+	int tail;           /* read index - used when releasing buffers */
+	u16 size;           /* queue occupied size */
+	struct neta_buff_inf ent[MRVL_NETA_TX_SHADOWQ_SIZE]; /* q entries */
+};
+
 
 struct mvneta_rxq {
 	struct mvneta_priv *priv;
@@ -77,6 +106,7 @@ struct mvneta_txq {
 	int queue_id;
 	int port_id;
 	uint64_t bytes_sent;
+	struct mvneta_shadow_txq shadow_txq;
 	int tx_deferred_start;
 };
 
@@ -84,6 +114,247 @@ static int mvneta_dev_num;
 static int mvneta_lcore_first;
 static int mvneta_lcore_last;
 
+static inline void
+mvneta_fill_shadowq(struct mvneta_shadow_txq *sq, struct rte_mbuf *buf)
+{
+	sq->ent[sq->head].cookie = (uint64_t)buf;
+	sq->ent[sq->head].addr = buf ?
+		rte_mbuf_data_iova_default(buf) : 0;
+
+	sq->head = (sq->head + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	sq->size++;
+}
+
+static inline void
+mvneta_fill_desc(struct neta_ppio_desc *desc, struct rte_mbuf *buf)
+{
+	neta_ppio_outq_desc_reset(desc);
+	neta_ppio_outq_desc_set_phys_addr(desc, rte_pktmbuf_iova(buf));
+	neta_ppio_outq_desc_set_pkt_offset(desc, 0);
+	neta_ppio_outq_desc_set_pkt_len(desc, rte_pktmbuf_data_len(buf));
+}
+
+static inline int
+mvneta_buffs_refill(struct mvneta_priv *priv, struct mvneta_rxq *rxq, u16 *num)
+{
+	struct rte_mbuf *mbufs[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	struct neta_buff_inf entries[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	int i, ret;
+	uint16_t nb_desc = *num;
+
+	ret = rte_pktmbuf_alloc_bulk(rxq->mp, mbufs, nb_desc);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to allocate %u mbufs.", nb_desc);
+		*num = 0;
+		return -1;
+	}
+
+	MVNETA_SET_COOKIE_HIGH_ADDR(mbufs[0]);
+
+	for (i = 0; i < nb_desc; i++) {
+		if (unlikely(!MVNETA_CHECK_COOKIE_HIGH_ADDR(mbufs[i]))) {
+			MVNETA_LOG(ERR,
+				"mbuf virt high addr 0x%lx out of range 0x%lx",
+				(uint64_t)mbufs[i] >> 32,
+				cookie_addr_high >> 32);
+			*num = 0;
+			goto out;
+		}
+		entries[i].addr = rte_mbuf_data_iova_default(mbufs[i]);
+		entries[i].cookie = (neta_cookie_t)(uint64_t)mbufs[i];
+	}
+	neta_ppio_inq_put_buffs(priv->ppio, rxq->queue_id, entries, num);
+
+out:
+	for (i = *num; i < nb_desc; i++)
+		rte_pktmbuf_free(mbufs[i]);
+
+	return 0;
+}
+
+
+/**
+ * Allocate buffers from mempool
+ * and store addresses in rx descriptors.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_buffs_alloc(struct mvneta_priv *priv, struct mvneta_rxq *rxq, int *num)
+{
+	uint16_t nb_desc, nb_desc_burst, sent = 0;
+	int ret = 0;
+
+	nb_desc = *num;
+
+	do {
+		nb_desc_burst =
+			(nb_desc < MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX) ?
+			nb_desc : MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX;
+
+		ret = mvneta_buffs_refill(priv, rxq, &nb_desc_burst);
+		if (unlikely(ret || !nb_desc_burst))
+			break;
+
+		sent += nb_desc_burst;
+		nb_desc -= nb_desc_burst;
+
+	} while (nb_desc);
+
+	*num = sent;
+
+	return ret;
+}
+
+/**
+ * Return mbufs to mempool.
+ *
+ * @param rxq
+ *    Pointer to rx queue structure
+ * @param desc
+ *    Array of rx descriptors
+ */
+static void
+mvneta_recv_buffs_free(struct neta_ppio_desc *desc, uint16_t num)
+{
+	uint64_t addr;
+	uint8_t i;
+
+	for (i = 0; i < num; i++) {
+		if (desc) {
+			addr = cookie_addr_high |
+					neta_ppio_inq_desc_get_cookie(desc);
+			if (addr)
+				rte_pktmbuf_free((struct rte_mbuf *)addr);
+			desc++;
+		}
+	}
+}
+
+/**
+ * Release already sent buffers to mempool.
+ *
+ * @param ppio
+ *   Pointer to the port structure.
+ * @param sq
+ *   Pointer to the shadow queue.
+ * @param qid
+ *   Queue id number.
+ * @param force
+ *   Force releasing packets.
+ */
+static inline void
+mvneta_sent_buffers_free(struct neta_ppio *ppio,
+			 struct mvneta_shadow_txq *sq, int qid)
+{
+	struct neta_buff_inf *entry;
+	uint16_t nb_done = 0;
+	int i;
+	int tail = sq->tail;
+
+	neta_ppio_get_num_outq_done(ppio, qid, &nb_done);
+
+	if (nb_done > sq->size) {
+		MVNETA_LOG(ERR, "nb_done: %d, sq->size %d",
+			   nb_done, sq->size);
+		return;
+	}
+
+	for (i = 0; i < nb_done; i++) {
+		entry = &sq->ent[tail];
+
+		if (unlikely(!entry->addr)) {
+			MVNETA_LOG(DEBUG,
+				"Shadow memory @%d: cookie(%lx), pa(%lx)!",
+				tail, (u64)entry->cookie,
+				(u64)entry->addr);
+			tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+			continue;
+		}
+
+		struct rte_mbuf *mbuf;
+
+		mbuf = (struct rte_mbuf *)
+			   (cookie_addr_high | entry->cookie);
+		rte_pktmbuf_free(mbuf);
+		tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+
+	sq->tail = tail;
+	sq->size -= nb_done;
+}
+
+/**
+ * Flush single receive queue.
+ *
+ * @param rxq
+ *   Pointer to rx queue structure.
+ * @param descs
+ *   Array of rx descriptors
+ */
+static void
+mvneta_rx_queue_flush(struct mvneta_rxq *rxq)
+{
+	struct neta_ppio_desc *descs;
+	struct neta_buff_inf *bufs;
+	uint16_t num;
+	int ret, i;
+
+	descs = rte_malloc("rxdesc", MRVL_NETA_RXD_MAX * sizeof(*descs), 0);
+	bufs = rte_malloc("buffs", MRVL_NETA_RXD_MAX * sizeof(*bufs), 0);
+
+	do {
+		num = MRVL_NETA_RXD_MAX;
+		ret = neta_ppio_recv(rxq->priv->ppio,
+				     rxq->queue_id,
+				     descs, &num);
+		mvneta_recv_buffs_free(descs, num);
+	} while (ret == 0 && num);
+
+	rxq->pkts_processed = 0;
+
+	num = MRVL_NETA_RXD_MAX;
+
+	neta_ppio_inq_get_all_buffs(rxq->priv->ppio, rxq->queue_id, bufs, &num);
+	MVNETA_LOG(INFO, "freeing %u unused bufs.", num);
+
+	for (i = 0; i < num; i++) {
+		uint64_t addr;
+		if (bufs[i].cookie) {
+			addr = cookie_addr_high | bufs[i].cookie;
+			rte_pktmbuf_free((struct rte_mbuf *)addr);
+		}
+	}
+
+	rte_free(descs);
+	rte_free(bufs);
+}
+
+/**
+ * Flush single transmit queue.
+ *
+ * @param txq
+ *     Pointer to tx queue structure
+ */
+static void
+mvneta_tx_queue_flush(struct mvneta_txq *txq)
+{
+	struct mvneta_shadow_txq *sq = &txq->shadow_txq;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(txq->priv->ppio, sq,
+					 txq->queue_id);
+
+	/* free the rest of them */
+	while (sq->tail != sq->head) {
+		uint64_t addr = cookie_addr_high |
+			sq->ent[sq->tail].cookie;
+		rte_pktmbuf_free((struct rte_mbuf *)addr);
+		sq->tail = (sq->tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+	memset(sq, 0, sizeof(*sq));
+}
 
 /**
  * Deinitialize packet processor.
@@ -132,6 +403,467 @@ mvneta_ifnames_get(const char *key __rte_unused, const char *value,
 }
 
 /**
+ * Return packet type information and l3/l4 offsets.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ * @param l3_offset
+ *   l3 packet offset.
+ * @param l4_offset
+ *   l4 packet offset.
+ *
+ * @return
+ *   Packet type information.
+ */
+static inline uint64_t
+mvneta_desc_to_packet_type_and_offset(struct neta_ppio_desc *desc,
+				    uint8_t *l3_offset, uint8_t *l4_offset)
+{
+	enum neta_inq_l3_type l3_type;
+	enum neta_inq_l4_type l4_type;
+	uint64_t packet_type;
+
+	neta_ppio_inq_desc_get_l3_info(desc, &l3_type, l3_offset);
+	neta_ppio_inq_desc_get_l4_info(desc, &l4_type, l4_offset);
+
+	packet_type = RTE_PTYPE_L2_ETHER;
+
+	if (NETA_RXD_GET_VLAN_INFO(desc))
+		packet_type |= RTE_PTYPE_L2_ETHER_VLAN;
+
+	switch (l3_type) {
+	case NETA_INQ_L3_TYPE_IPV4_BAD:
+	case NETA_INQ_L3_TYPE_IPV4_OK:
+		packet_type |= RTE_PTYPE_L3_IPV4;
+		break;
+	case NETA_INQ_L3_TYPE_IPV6:
+		packet_type |= RTE_PTYPE_L3_IPV6;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l3 packet type");
+		break;
+	}
+
+	switch (l4_type) {
+	case NETA_INQ_L4_TYPE_TCP:
+		packet_type |= RTE_PTYPE_L4_TCP;
+		break;
+	case NETA_INQ_L4_TYPE_UDP:
+		packet_type |= RTE_PTYPE_L4_UDP;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l4 packet type");
+		break;
+	}
+
+	return packet_type;
+}
+
+/**
+ * Prepare offload information.
+ *
+ * @param ol_flags
+ *   Offload flags.
+ * @param packet_type
+ *   Packet type bitfield.
+ * @param l3_type
+ *   Pointer to the neta_ouq_l3_type structure.
+ * @param l4_type
+ *   Pointer to the neta_outq_l4_type structure.
+ * @param gen_l3_cksum
+ *   Will be set to 1 in case l3 checksum is computed.
+ * @param l4_cksum
+ *   Will be set to 1 in case l4 checksum is computed.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_prepare_proto_info(uint64_t ol_flags, uint32_t packet_type,
+			enum neta_outq_l3_type *l3_type,
+			enum neta_outq_l4_type *l4_type,
+			int *gen_l3_cksum,
+			int *gen_l4_cksum)
+{
+	/*
+	 * Based on ol_flags prepare information
+	 * for neta_ppio_outq_desc_set_proto_info() which setups descriptor
+	 * for offloading.
+	 */
+	if (ol_flags & PKT_TX_IPV4) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV4;
+		*gen_l3_cksum = ol_flags & PKT_TX_IP_CKSUM ? 1 : 0;
+	} else if (ol_flags & PKT_TX_IPV6) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV6;
+		/* no checksum for ipv6 header */
+		*gen_l3_cksum = 0;
+	} else {
+		/* if something different then stop processing */
+		return -1;
+	}
+
+	ol_flags &= PKT_TX_L4_MASK;
+	if ((packet_type & RTE_PTYPE_L4_TCP) &&
+	    ol_flags == PKT_TX_TCP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_TCP;
+		*gen_l4_cksum = 1;
+	} else if ((packet_type & RTE_PTYPE_L4_UDP) &&
+		   ol_flags == PKT_TX_UDP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_UDP;
+		*gen_l4_cksum = 1;
+	} else {
+		*l4_type = NETA_OUTQ_L4_TYPE_OTHER;
+		/* no checksum for other type */
+		*gen_l4_cksum = 0;
+	}
+
+	return 0;
+}
+
+/**
+ * Get offload information from the received packet descriptor.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ *
+ * @return
+ *   Mbuf offload flags.
+ */
+static inline uint64_t
+mvneta_desc_to_ol_flags(struct neta_ppio_desc *desc)
+{
+	uint64_t flags;
+	enum neta_inq_desc_status status;
+
+	status = neta_ppio_inq_desc_get_l3_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags = PKT_RX_IP_CKSUM_BAD;
+	else
+		flags = PKT_RX_IP_CKSUM_GOOD;
+
+	status = neta_ppio_inq_desc_get_l4_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags |= PKT_RX_L4_CKSUM_BAD;
+	else
+		flags |= PKT_RX_L4_CKSUM_GOOD;
+
+	return flags;
+}
+
+/**
+ * DPDK callback for transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts];
+
+	int i, ret, bytes_sent = 0;
+	uint16_t num, sq_free_size;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	if (unlikely(!nb_pkts || !q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+	if (unlikely(nb_pkts > sq_free_size)) {
+		MVNETA_LOG(DEBUG,
+			"No room in shadow queue for %d packets! %d packets will be sent.",
+			nb_pkts, sq_free_size);
+		nb_pkts = sq_free_size;
+	}
+
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		/* Fill first mbuf info in shadow queue */
+		mvneta_fill_shadowq(sq, mbuf);
+		mvneta_fill_desc(&descs[i], mbuf);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[i], l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = nb_pkts;
+	neta_ppio_send(q->priv->ppio, q->queue_id, descs, &nb_pkts);
+
+
+	/* number of packets that were not sent */
+	if (unlikely(num > nb_pkts)) {
+		for (i = nb_pkts; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE + sq->head - 1) &
+				MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = cookie_addr_high | sq->ent[sq->head].cookie;
+			bytes_sent -=
+				rte_pktmbuf_pkt_len((struct rte_mbuf *)addr);
+		}
+		sq->size -= num - nb_pkts;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/** DPDK callback for S/G transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_sg_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts * NETA_PPIO_DESC_NUM_FRAGS];
+	struct neta_ppio_sg_pkts pkts;
+	uint8_t frags[nb_pkts];
+	int i, j, ret, bytes_sent = 0;
+	int tail, tail_first;
+	uint16_t num, sq_free_size;
+	uint16_t nb_segs, total_descs = 0;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	pkts.frags = frags;
+	pkts.num = 0;
+
+	if (unlikely(!q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+	/* Save shadow queue free size */
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+
+	tail = 0;
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		struct rte_mbuf *seg = NULL;
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		nb_segs = mbuf->nb_segs;
+		total_descs += nb_segs;
+
+		/*
+		 * Check if total_descs does not exceed
+		 * shadow queue free size
+		 */
+		if (unlikely(total_descs > sq_free_size)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(DEBUG,
+				"No room in shadow queue for %d packets! "
+				"%d packets will be sent.",
+				nb_pkts, i);
+			break;
+		}
+
+
+		/* Check if nb_segs does not exceed the max nb of desc per
+		 * fragmented packet
+		 */
+		if (unlikely(nb_segs > NETA_PPIO_DESC_NUM_FRAGS)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(ERR,
+				"Too many segments. Packet won't be sent.");
+			break;
+		}
+
+		pkts.frags[pkts.num] = nb_segs;
+		pkts.num++;
+		tail_first = tail;
+
+		seg = mbuf;
+		for (j = 0; j < nb_segs - 1; j++) {
+			/* For the subsequent segments, set shadow queue
+			 * buffer to NULL
+			 */
+			mvneta_fill_shadowq(sq, NULL);
+			mvneta_fill_desc(&descs[tail], seg);
+
+			tail++;
+			seg = seg->next;
+		}
+		/* Put first mbuf info in last shadow queue entry */
+		mvneta_fill_shadowq(sq, mbuf);
+		/* Update descriptor with last segment */
+		mvneta_fill_desc(&descs[tail++], seg);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[tail_first],
+						   l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = total_descs;
+	neta_ppio_send_sg(q->priv->ppio, q->queue_id, descs, &total_descs,
+			  &pkts);
+
+	/* number of packets that were not sent */
+	if (unlikely(num > total_descs)) {
+		for (i = total_descs; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE +
+					sq->head - 1) &
+					MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = sq->ent[sq->head].cookie;
+			if (addr) {
+				struct rte_mbuf *mbuf;
+
+				mbuf = (struct rte_mbuf *)
+						(cookie_addr_high | addr);
+				bytes_sent -= rte_pktmbuf_pkt_len(mbuf);
+			}
+		}
+		sq->size -= num - total_descs;
+		nb_pkts = pkts.num;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/**
+ * DPDK callback for receive.
+ *
+ * @param rxq
+ *   Generic pointer to the receive queue.
+ * @param rx_pkts
+ *   Array to store received packets.
+ * @param nb_pkts
+ *   Maximum number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully received.
+ */
+static uint16_t
+mvneta_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_rxq *q = rxq;
+	struct neta_ppio_desc descs[nb_pkts];
+	int i, ret, rx_done = 0, rx_dropped = 0;
+
+	if (unlikely(!q || !q->priv->ppio))
+		return 0;
+
+	ret = neta_ppio_recv(q->priv->ppio, q->queue_id,
+			descs, &nb_pkts);
+
+	if (unlikely(ret < 0)) {
+		MVNETA_LOG(ERR, "Failed to receive packets");
+		return 0;
+	}
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf;
+		uint8_t l3_offset, l4_offset;
+		enum neta_inq_desc_status status;
+		uint64_t addr;
+
+		addr = cookie_addr_high |
+			neta_ppio_inq_desc_get_cookie(&descs[i]);
+		mbuf = (struct rte_mbuf *)addr;
+
+		rte_pktmbuf_reset(mbuf);
+
+		/* drop packet in case of mac, overrun or resource error */
+		status = neta_ppio_inq_desc_get_l2_pkt_error(&descs[i]);
+		if (unlikely(status != NETA_DESC_ERR_OK)) {
+			/* Release the mbuf to the mempool since
+			 * it won't be transferred to tx path
+			 */
+			rte_pktmbuf_free(mbuf);
+			q->drop_mac++;
+			rx_dropped++;
+			continue;
+		}
+
+		mbuf->data_off += MVNETA_PKT_EFFEC_OFFS;
+		mbuf->pkt_len = neta_ppio_inq_desc_get_pkt_len(&descs[i]);
+		mbuf->data_len = mbuf->pkt_len;
+		mbuf->port = q->port_id;
+		mbuf->packet_type =
+			mvneta_desc_to_packet_type_and_offset(&descs[i],
+								&l3_offset,
+								&l4_offset);
+		mbuf->l2_len = l3_offset;
+		mbuf->l3_len = l4_offset - l3_offset;
+
+		if (likely(q->cksum_enabled))
+			mbuf->ol_flags = mvneta_desc_to_ol_flags(&descs[i]);
+
+		rx_pkts[rx_done++] = mbuf;
+		q->bytes_recv += mbuf->pkt_len;
+	}
+	q->pkts_processed += rx_done + rx_dropped;
+
+	if (q->pkts_processed > rx_desc_free_thresh) {
+		int buf_to_refill = rx_desc_free_thresh;
+
+		ret = mvneta_buffs_alloc(q->priv, q, &buf_to_refill);
+		if (ret)
+			MVNETA_LOG(ERR, "Refill failed");
+		q->pkts_processed -= buf_to_refill;
+	}
+
+	return rx_done;
+}
+
+/**
  * Ethernet device configuration.
  *
  * Prepare the driver for a given number of TX and RX queues and
@@ -391,6 +1123,7 @@ mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 	rxq->queue_id = idx;
 	rxq->port_id = dev->data->port_id;
 	rxq->size = desc;
+	rx_desc_free_thresh = RTE_MIN(rx_desc_free_thresh, (desc / 2));
 	priv->ppio_params.inqs_params.tcs_params[MRVL_NETA_DEFAULT_TC].size =
 		desc;
 
@@ -413,6 +1146,14 @@ mvneta_rx_queue_release(void *rxq)
 	if (!q)
 		return;
 
+	/* If dev_stop was called already, mbufs are already
+	 * returned to mempool and ppio is deinitialized.
+	 * Skip this step.
+	 */
+
+	if (q->priv->ppio)
+		mvneta_rx_queue_flush(q);
+
 	rte_free(rxq);
 }
 
@@ -478,6 +1219,26 @@ mvneta_tx_queue_release(void *txq)
 	rte_free(q);
 }
 
+/**
+ * Set tx burst function according to offload flag
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_set_tx_function(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	/* Use a simple Tx queue (no offloads, no multi segs) if possible */
+	if (priv->multiseg) {
+		MVNETA_LOG(INFO, "Using multi-segment tx callback");
+		dev->tx_pkt_burst = mvneta_tx_sg_pkt_burst;
+	} else {
+		MVNETA_LOG(INFO, "Using single-segment tx callback");
+		dev->tx_pkt_burst = mvneta_tx_pkt_burst;
+	}
+}
 
 /**
  * DPDK callback to start the device.
@@ -525,6 +1286,18 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 		priv->uc_mc_flushed = 1;
 	}
 
+	/* Allocate buffers */
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+		int num = rxq->size;
+
+		ret = mvneta_buffs_alloc(priv, rxq, &num);
+		if (ret || num != rxq->size) {
+			rte_free(rxq);
+			return ret;
+		}
+	}
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up");
@@ -535,6 +1308,8 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 	for (i = 0; i < dev->data->nb_tx_queues; i++)
 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
 
+	mvneta_set_tx_function(dev);
+
 	return 0;
 
 out:
@@ -553,11 +1328,25 @@ static void
 mvneta_dev_stop(struct rte_eth_dev *dev)
 {
 	struct mvneta_priv *priv = dev->data->dev_private;
+	int i;
 
 	if (!priv->ppio)
 		return;
 
 	mvneta_dev_set_link_down(dev);
+	MVNETA_LOG(INFO, "Flushing rx queues");
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+
+		mvneta_rx_queue_flush(rxq);
+	}
+
+	MVNETA_LOG(INFO, "Flushing tx queues");
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		struct mvneta_txq *txq = dev->data->tx_queues[i];
+
+		mvneta_tx_queue_flush(txq);
+	}
 
 	neta_ppio_deinit(priv->ppio);
 
@@ -704,6 +1493,8 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
 	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
+	eth_dev->rx_pkt_burst = mvneta_rx_pkt_burst;
+	mvneta_set_tx_function(eth_dev);
 ;	eth_dev->dev_ops = &mvneta_ops;
 
 	return 0;
diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h
index 8957034..a05566d 100644
--- a/drivers/net/mvneta/mvneta_ethdev.h
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -43,6 +43,17 @@
 
 #define MRVL_NETA_DEFAULT_TC 0
 
+/** Maximum number of descriptors in shadow queue. Must be power of 2 */
+#define MRVL_NETA_TX_SHADOWQ_SIZE MRVL_NETA_TXD_MAX
+
+/** Shadow queue size mask (since shadow queue size is power of 2) */
+#define MRVL_NETA_TX_SHADOWQ_MASK (MRVL_NETA_TX_SHADOWQ_SIZE - 1)
+
+/** Minimum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN	16
+
+/** Maximum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX	64
 
 #define MRVL_NETA_VLAN_TAG_LEN		4
 #define MRVL_NETA_ETH_HDRS_LEN		(ETHER_HDR_LEN + ETHER_CRC_LEN + \
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v2 3/8] net/mvneta: add Rx/Tx support
  2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                     ` (3 preceding siblings ...)
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
@ 2018-08-31 12:26   ` Andrzej Ostruszka
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
                     ` (7 subsequent siblings)
  12 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:26 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add part of PMD for actual reception/transmission.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 791 +++++++++++++++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h |  11 +
 2 files changed, 802 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 621f38a..968f920 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -27,6 +27,11 @@
 
 #define MVNETA_IFACE_NAME_ARG "iface"
 
+#define MVNETA_COOKIE_ADDR_INVALID ~0ULL
+
+#define MVNETA_COOKIE_HIGH_ADDR_SHIFT	(sizeof(neta_cookie_t) * 8)
+#define MVNETA_COOKIE_HIGH_ADDR_MASK	(~0ULL << MVNETA_COOKIE_HIGH_ADDR_SHIFT)
+
 #define MVNETA_RX_OFFLOADS (DEV_RX_OFFLOAD_JUMBO_FRAME | \
 			  DEV_RX_OFFLOAD_CRC_STRIP | \
 			  DEV_RX_OFFLOAD_CHECKSUM)
@@ -46,6 +51,19 @@
 
 #define MVNETA_PKT_EFFEC_OFFS (MRVL_NETA_PKT_OFFS + MV_MH_SIZE)
 
+static uint64_t cookie_addr_high = MVNETA_COOKIE_ADDR_INVALID;
+static uint16_t rx_desc_free_thresh = MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN;
+
+#define MVNETA_SET_COOKIE_HIGH_ADDR(addr) {				\
+	if (unlikely(cookie_addr_high == MVNETA_COOKIE_ADDR_INVALID))	\
+		cookie_addr_high =					\
+			(uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK;\
+}
+
+#define MVNETA_CHECK_COOKIE_HIGH_ADDR(addr)			\
+	((likely(cookie_addr_high ==				\
+	((uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK))) ? 1 : 0)
+
 int mvneta_logtype;
 
 static const char * const valid_args[] = {
@@ -58,6 +76,17 @@ struct mvneta_ifnames {
 	int idx;
 };
 
+/*
+ * To use buffer harvesting based on loopback port shadow queue structure
+ * was introduced for buffers information bookkeeping.
+ */
+struct mvneta_shadow_txq {
+	int head;           /* write index - used when sending buffers */
+	int tail;           /* read index - used when releasing buffers */
+	u16 size;           /* queue occupied size */
+	struct neta_buff_inf ent[MRVL_NETA_TX_SHADOWQ_SIZE]; /* q entries */
+};
+
 
 struct mvneta_rxq {
 	struct mvneta_priv *priv;
@@ -77,6 +106,7 @@ struct mvneta_txq {
 	int queue_id;
 	int port_id;
 	uint64_t bytes_sent;
+	struct mvneta_shadow_txq shadow_txq;
 	int tx_deferred_start;
 };
 
@@ -84,6 +114,247 @@ static int mvneta_dev_num;
 static int mvneta_lcore_first;
 static int mvneta_lcore_last;
 
+static inline void
+mvneta_fill_shadowq(struct mvneta_shadow_txq *sq, struct rte_mbuf *buf)
+{
+	sq->ent[sq->head].cookie = (uint64_t)buf;
+	sq->ent[sq->head].addr = buf ?
+		rte_mbuf_data_iova_default(buf) : 0;
+
+	sq->head = (sq->head + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	sq->size++;
+}
+
+static inline void
+mvneta_fill_desc(struct neta_ppio_desc *desc, struct rte_mbuf *buf)
+{
+	neta_ppio_outq_desc_reset(desc);
+	neta_ppio_outq_desc_set_phys_addr(desc, rte_pktmbuf_iova(buf));
+	neta_ppio_outq_desc_set_pkt_offset(desc, 0);
+	neta_ppio_outq_desc_set_pkt_len(desc, rte_pktmbuf_data_len(buf));
+}
+
+static inline int
+mvneta_buffs_refill(struct mvneta_priv *priv, struct mvneta_rxq *rxq, u16 *num)
+{
+	struct rte_mbuf *mbufs[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	struct neta_buff_inf entries[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	int i, ret;
+	uint16_t nb_desc = *num;
+
+	ret = rte_pktmbuf_alloc_bulk(rxq->mp, mbufs, nb_desc);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to allocate %u mbufs.", nb_desc);
+		*num = 0;
+		return -1;
+	}
+
+	MVNETA_SET_COOKIE_HIGH_ADDR(mbufs[0]);
+
+	for (i = 0; i < nb_desc; i++) {
+		if (unlikely(!MVNETA_CHECK_COOKIE_HIGH_ADDR(mbufs[i]))) {
+			MVNETA_LOG(ERR,
+				"mbuf virt high addr 0x%lx out of range 0x%lx",
+				(uint64_t)mbufs[i] >> 32,
+				cookie_addr_high >> 32);
+			*num = 0;
+			goto out;
+		}
+		entries[i].addr = rte_mbuf_data_iova_default(mbufs[i]);
+		entries[i].cookie = (neta_cookie_t)(uint64_t)mbufs[i];
+	}
+	neta_ppio_inq_put_buffs(priv->ppio, rxq->queue_id, entries, num);
+
+out:
+	for (i = *num; i < nb_desc; i++)
+		rte_pktmbuf_free(mbufs[i]);
+
+	return 0;
+}
+
+
+/**
+ * Allocate buffers from mempool
+ * and store addresses in rx descriptors.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_buffs_alloc(struct mvneta_priv *priv, struct mvneta_rxq *rxq, int *num)
+{
+	uint16_t nb_desc, nb_desc_burst, sent = 0;
+	int ret = 0;
+
+	nb_desc = *num;
+
+	do {
+		nb_desc_burst =
+			(nb_desc < MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX) ?
+			nb_desc : MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX;
+
+		ret = mvneta_buffs_refill(priv, rxq, &nb_desc_burst);
+		if (unlikely(ret || !nb_desc_burst))
+			break;
+
+		sent += nb_desc_burst;
+		nb_desc -= nb_desc_burst;
+
+	} while (nb_desc);
+
+	*num = sent;
+
+	return ret;
+}
+
+/**
+ * Return mbufs to mempool.
+ *
+ * @param rxq
+ *    Pointer to rx queue structure
+ * @param desc
+ *    Array of rx descriptors
+ */
+static void
+mvneta_recv_buffs_free(struct neta_ppio_desc *desc, uint16_t num)
+{
+	uint64_t addr;
+	uint8_t i;
+
+	for (i = 0; i < num; i++) {
+		if (desc) {
+			addr = cookie_addr_high |
+					neta_ppio_inq_desc_get_cookie(desc);
+			if (addr)
+				rte_pktmbuf_free((struct rte_mbuf *)addr);
+			desc++;
+		}
+	}
+}
+
+/**
+ * Release already sent buffers to mempool.
+ *
+ * @param ppio
+ *   Pointer to the port structure.
+ * @param sq
+ *   Pointer to the shadow queue.
+ * @param qid
+ *   Queue id number.
+ * @param force
+ *   Force releasing packets.
+ */
+static inline void
+mvneta_sent_buffers_free(struct neta_ppio *ppio,
+			 struct mvneta_shadow_txq *sq, int qid)
+{
+	struct neta_buff_inf *entry;
+	uint16_t nb_done = 0;
+	int i;
+	int tail = sq->tail;
+
+	neta_ppio_get_num_outq_done(ppio, qid, &nb_done);
+
+	if (nb_done > sq->size) {
+		MVNETA_LOG(ERR, "nb_done: %d, sq->size %d",
+			   nb_done, sq->size);
+		return;
+	}
+
+	for (i = 0; i < nb_done; i++) {
+		entry = &sq->ent[tail];
+
+		if (unlikely(!entry->addr)) {
+			MVNETA_LOG(DEBUG,
+				"Shadow memory @%d: cookie(%lx), pa(%lx)!",
+				tail, (u64)entry->cookie,
+				(u64)entry->addr);
+			tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+			continue;
+		}
+
+		struct rte_mbuf *mbuf;
+
+		mbuf = (struct rte_mbuf *)
+			   (cookie_addr_high | entry->cookie);
+		rte_pktmbuf_free(mbuf);
+		tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+
+	sq->tail = tail;
+	sq->size -= nb_done;
+}
+
+/**
+ * Flush single receive queue.
+ *
+ * @param rxq
+ *   Pointer to rx queue structure.
+ * @param descs
+ *   Array of rx descriptors
+ */
+static void
+mvneta_rx_queue_flush(struct mvneta_rxq *rxq)
+{
+	struct neta_ppio_desc *descs;
+	struct neta_buff_inf *bufs;
+	uint16_t num;
+	int ret, i;
+
+	descs = rte_malloc("rxdesc", MRVL_NETA_RXD_MAX * sizeof(*descs), 0);
+	bufs = rte_malloc("buffs", MRVL_NETA_RXD_MAX * sizeof(*bufs), 0);
+
+	do {
+		num = MRVL_NETA_RXD_MAX;
+		ret = neta_ppio_recv(rxq->priv->ppio,
+				     rxq->queue_id,
+				     descs, &num);
+		mvneta_recv_buffs_free(descs, num);
+	} while (ret == 0 && num);
+
+	rxq->pkts_processed = 0;
+
+	num = MRVL_NETA_RXD_MAX;
+
+	neta_ppio_inq_get_all_buffs(rxq->priv->ppio, rxq->queue_id, bufs, &num);
+	MVNETA_LOG(INFO, "freeing %u unused bufs.", num);
+
+	for (i = 0; i < num; i++) {
+		uint64_t addr;
+		if (bufs[i].cookie) {
+			addr = cookie_addr_high | bufs[i].cookie;
+			rte_pktmbuf_free((struct rte_mbuf *)addr);
+		}
+	}
+
+	rte_free(descs);
+	rte_free(bufs);
+}
+
+/**
+ * Flush single transmit queue.
+ *
+ * @param txq
+ *     Pointer to tx queue structure
+ */
+static void
+mvneta_tx_queue_flush(struct mvneta_txq *txq)
+{
+	struct mvneta_shadow_txq *sq = &txq->shadow_txq;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(txq->priv->ppio, sq,
+					 txq->queue_id);
+
+	/* free the rest of them */
+	while (sq->tail != sq->head) {
+		uint64_t addr = cookie_addr_high |
+			sq->ent[sq->tail].cookie;
+		rte_pktmbuf_free((struct rte_mbuf *)addr);
+		sq->tail = (sq->tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+	memset(sq, 0, sizeof(*sq));
+}
 
 /**
  * Deinitialize packet processor.
@@ -132,6 +403,467 @@ mvneta_ifnames_get(const char *key __rte_unused, const char *value,
 }
 
 /**
+ * Return packet type information and l3/l4 offsets.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ * @param l3_offset
+ *   l3 packet offset.
+ * @param l4_offset
+ *   l4 packet offset.
+ *
+ * @return
+ *   Packet type information.
+ */
+static inline uint64_t
+mvneta_desc_to_packet_type_and_offset(struct neta_ppio_desc *desc,
+				    uint8_t *l3_offset, uint8_t *l4_offset)
+{
+	enum neta_inq_l3_type l3_type;
+	enum neta_inq_l4_type l4_type;
+	uint64_t packet_type;
+
+	neta_ppio_inq_desc_get_l3_info(desc, &l3_type, l3_offset);
+	neta_ppio_inq_desc_get_l4_info(desc, &l4_type, l4_offset);
+
+	packet_type = RTE_PTYPE_L2_ETHER;
+
+	if (NETA_RXD_GET_VLAN_INFO(desc))
+		packet_type |= RTE_PTYPE_L2_ETHER_VLAN;
+
+	switch (l3_type) {
+	case NETA_INQ_L3_TYPE_IPV4_BAD:
+	case NETA_INQ_L3_TYPE_IPV4_OK:
+		packet_type |= RTE_PTYPE_L3_IPV4;
+		break;
+	case NETA_INQ_L3_TYPE_IPV6:
+		packet_type |= RTE_PTYPE_L3_IPV6;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l3 packet type");
+		break;
+	}
+
+	switch (l4_type) {
+	case NETA_INQ_L4_TYPE_TCP:
+		packet_type |= RTE_PTYPE_L4_TCP;
+		break;
+	case NETA_INQ_L4_TYPE_UDP:
+		packet_type |= RTE_PTYPE_L4_UDP;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l4 packet type");
+		break;
+	}
+
+	return packet_type;
+}
+
+/**
+ * Prepare offload information.
+ *
+ * @param ol_flags
+ *   Offload flags.
+ * @param packet_type
+ *   Packet type bitfield.
+ * @param l3_type
+ *   Pointer to the neta_ouq_l3_type structure.
+ * @param l4_type
+ *   Pointer to the neta_outq_l4_type structure.
+ * @param gen_l3_cksum
+ *   Will be set to 1 in case l3 checksum is computed.
+ * @param l4_cksum
+ *   Will be set to 1 in case l4 checksum is computed.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_prepare_proto_info(uint64_t ol_flags, uint32_t packet_type,
+			enum neta_outq_l3_type *l3_type,
+			enum neta_outq_l4_type *l4_type,
+			int *gen_l3_cksum,
+			int *gen_l4_cksum)
+{
+	/*
+	 * Based on ol_flags prepare information
+	 * for neta_ppio_outq_desc_set_proto_info() which setups descriptor
+	 * for offloading.
+	 */
+	if (ol_flags & PKT_TX_IPV4) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV4;
+		*gen_l3_cksum = ol_flags & PKT_TX_IP_CKSUM ? 1 : 0;
+	} else if (ol_flags & PKT_TX_IPV6) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV6;
+		/* no checksum for ipv6 header */
+		*gen_l3_cksum = 0;
+	} else {
+		/* if something different then stop processing */
+		return -1;
+	}
+
+	ol_flags &= PKT_TX_L4_MASK;
+	if ((packet_type & RTE_PTYPE_L4_TCP) &&
+	    ol_flags == PKT_TX_TCP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_TCP;
+		*gen_l4_cksum = 1;
+	} else if ((packet_type & RTE_PTYPE_L4_UDP) &&
+		   ol_flags == PKT_TX_UDP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_UDP;
+		*gen_l4_cksum = 1;
+	} else {
+		*l4_type = NETA_OUTQ_L4_TYPE_OTHER;
+		/* no checksum for other type */
+		*gen_l4_cksum = 0;
+	}
+
+	return 0;
+}
+
+/**
+ * Get offload information from the received packet descriptor.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ *
+ * @return
+ *   Mbuf offload flags.
+ */
+static inline uint64_t
+mvneta_desc_to_ol_flags(struct neta_ppio_desc *desc)
+{
+	uint64_t flags;
+	enum neta_inq_desc_status status;
+
+	status = neta_ppio_inq_desc_get_l3_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags = PKT_RX_IP_CKSUM_BAD;
+	else
+		flags = PKT_RX_IP_CKSUM_GOOD;
+
+	status = neta_ppio_inq_desc_get_l4_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags |= PKT_RX_L4_CKSUM_BAD;
+	else
+		flags |= PKT_RX_L4_CKSUM_GOOD;
+
+	return flags;
+}
+
+/**
+ * DPDK callback for transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts];
+
+	int i, ret, bytes_sent = 0;
+	uint16_t num, sq_free_size;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	if (unlikely(!nb_pkts || !q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+	if (unlikely(nb_pkts > sq_free_size)) {
+		MVNETA_LOG(DEBUG,
+			"No room in shadow queue for %d packets! %d packets will be sent.",
+			nb_pkts, sq_free_size);
+		nb_pkts = sq_free_size;
+	}
+
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		/* Fill first mbuf info in shadow queue */
+		mvneta_fill_shadowq(sq, mbuf);
+		mvneta_fill_desc(&descs[i], mbuf);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[i], l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = nb_pkts;
+	neta_ppio_send(q->priv->ppio, q->queue_id, descs, &nb_pkts);
+
+
+	/* number of packets that were not sent */
+	if (unlikely(num > nb_pkts)) {
+		for (i = nb_pkts; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE + sq->head - 1) &
+				MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = cookie_addr_high | sq->ent[sq->head].cookie;
+			bytes_sent -=
+				rte_pktmbuf_pkt_len((struct rte_mbuf *)addr);
+		}
+		sq->size -= num - nb_pkts;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/** DPDK callback for S/G transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_sg_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts * NETA_PPIO_DESC_NUM_FRAGS];
+	struct neta_ppio_sg_pkts pkts;
+	uint8_t frags[nb_pkts];
+	int i, j, ret, bytes_sent = 0;
+	int tail, tail_first;
+	uint16_t num, sq_free_size;
+	uint16_t nb_segs, total_descs = 0;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	pkts.frags = frags;
+	pkts.num = 0;
+
+	if (unlikely(!q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+	/* Save shadow queue free size */
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+
+	tail = 0;
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		struct rte_mbuf *seg = NULL;
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		nb_segs = mbuf->nb_segs;
+		total_descs += nb_segs;
+
+		/*
+		 * Check if total_descs does not exceed
+		 * shadow queue free size
+		 */
+		if (unlikely(total_descs > sq_free_size)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(DEBUG,
+				"No room in shadow queue for %d packets! "
+				"%d packets will be sent.",
+				nb_pkts, i);
+			break;
+		}
+
+
+		/* Check if nb_segs does not exceed the max nb of desc per
+		 * fragmented packet
+		 */
+		if (unlikely(nb_segs > NETA_PPIO_DESC_NUM_FRAGS)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(ERR,
+				"Too many segments. Packet won't be sent.");
+			break;
+		}
+
+		pkts.frags[pkts.num] = nb_segs;
+		pkts.num++;
+		tail_first = tail;
+
+		seg = mbuf;
+		for (j = 0; j < nb_segs - 1; j++) {
+			/* For the subsequent segments, set shadow queue
+			 * buffer to NULL
+			 */
+			mvneta_fill_shadowq(sq, NULL);
+			mvneta_fill_desc(&descs[tail], seg);
+
+			tail++;
+			seg = seg->next;
+		}
+		/* Put first mbuf info in last shadow queue entry */
+		mvneta_fill_shadowq(sq, mbuf);
+		/* Update descriptor with last segment */
+		mvneta_fill_desc(&descs[tail++], seg);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[tail_first],
+						   l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = total_descs;
+	neta_ppio_send_sg(q->priv->ppio, q->queue_id, descs, &total_descs,
+			  &pkts);
+
+	/* number of packets that were not sent */
+	if (unlikely(num > total_descs)) {
+		for (i = total_descs; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE +
+					sq->head - 1) &
+					MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = sq->ent[sq->head].cookie;
+			if (addr) {
+				struct rte_mbuf *mbuf;
+
+				mbuf = (struct rte_mbuf *)
+						(cookie_addr_high | addr);
+				bytes_sent -= rte_pktmbuf_pkt_len(mbuf);
+			}
+		}
+		sq->size -= num - total_descs;
+		nb_pkts = pkts.num;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/**
+ * DPDK callback for receive.
+ *
+ * @param rxq
+ *   Generic pointer to the receive queue.
+ * @param rx_pkts
+ *   Array to store received packets.
+ * @param nb_pkts
+ *   Maximum number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully received.
+ */
+static uint16_t
+mvneta_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_rxq *q = rxq;
+	struct neta_ppio_desc descs[nb_pkts];
+	int i, ret, rx_done = 0, rx_dropped = 0;
+
+	if (unlikely(!q || !q->priv->ppio))
+		return 0;
+
+	ret = neta_ppio_recv(q->priv->ppio, q->queue_id,
+			descs, &nb_pkts);
+
+	if (unlikely(ret < 0)) {
+		MVNETA_LOG(ERR, "Failed to receive packets");
+		return 0;
+	}
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf;
+		uint8_t l3_offset, l4_offset;
+		enum neta_inq_desc_status status;
+		uint64_t addr;
+
+		addr = cookie_addr_high |
+			neta_ppio_inq_desc_get_cookie(&descs[i]);
+		mbuf = (struct rte_mbuf *)addr;
+
+		rte_pktmbuf_reset(mbuf);
+
+		/* drop packet in case of mac, overrun or resource error */
+		status = neta_ppio_inq_desc_get_l2_pkt_error(&descs[i]);
+		if (unlikely(status != NETA_DESC_ERR_OK)) {
+			/* Release the mbuf to the mempool since
+			 * it won't be transferred to tx path
+			 */
+			rte_pktmbuf_free(mbuf);
+			q->drop_mac++;
+			rx_dropped++;
+			continue;
+		}
+
+		mbuf->data_off += MVNETA_PKT_EFFEC_OFFS;
+		mbuf->pkt_len = neta_ppio_inq_desc_get_pkt_len(&descs[i]);
+		mbuf->data_len = mbuf->pkt_len;
+		mbuf->port = q->port_id;
+		mbuf->packet_type =
+			mvneta_desc_to_packet_type_and_offset(&descs[i],
+								&l3_offset,
+								&l4_offset);
+		mbuf->l2_len = l3_offset;
+		mbuf->l3_len = l4_offset - l3_offset;
+
+		if (likely(q->cksum_enabled))
+			mbuf->ol_flags = mvneta_desc_to_ol_flags(&descs[i]);
+
+		rx_pkts[rx_done++] = mbuf;
+		q->bytes_recv += mbuf->pkt_len;
+	}
+	q->pkts_processed += rx_done + rx_dropped;
+
+	if (q->pkts_processed > rx_desc_free_thresh) {
+		int buf_to_refill = rx_desc_free_thresh;
+
+		ret = mvneta_buffs_alloc(q->priv, q, &buf_to_refill);
+		if (ret)
+			MVNETA_LOG(ERR, "Refill failed");
+		q->pkts_processed -= buf_to_refill;
+	}
+
+	return rx_done;
+}
+
+/**
  * Ethernet device configuration.
  *
  * Prepare the driver for a given number of TX and RX queues and
@@ -391,6 +1123,7 @@ mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 	rxq->queue_id = idx;
 	rxq->port_id = dev->data->port_id;
 	rxq->size = desc;
+	rx_desc_free_thresh = RTE_MIN(rx_desc_free_thresh, (desc / 2));
 	priv->ppio_params.inqs_params.tcs_params[MRVL_NETA_DEFAULT_TC].size =
 		desc;
 
@@ -413,6 +1146,14 @@ mvneta_rx_queue_release(void *rxq)
 	if (!q)
 		return;
 
+	/* If dev_stop was called already, mbufs are already
+	 * returned to mempool and ppio is deinitialized.
+	 * Skip this step.
+	 */
+
+	if (q->priv->ppio)
+		mvneta_rx_queue_flush(q);
+
 	rte_free(rxq);
 }
 
@@ -478,6 +1219,26 @@ mvneta_tx_queue_release(void *txq)
 	rte_free(q);
 }
 
+/**
+ * Set tx burst function according to offload flag
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_set_tx_function(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	/* Use a simple Tx queue (no offloads, no multi segs) if possible */
+	if (priv->multiseg) {
+		MVNETA_LOG(INFO, "Using multi-segment tx callback");
+		dev->tx_pkt_burst = mvneta_tx_sg_pkt_burst;
+	} else {
+		MVNETA_LOG(INFO, "Using single-segment tx callback");
+		dev->tx_pkt_burst = mvneta_tx_pkt_burst;
+	}
+}
 
 /**
  * DPDK callback to start the device.
@@ -525,6 +1286,18 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 		priv->uc_mc_flushed = 1;
 	}
 
+	/* Allocate buffers */
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+		int num = rxq->size;
+
+		ret = mvneta_buffs_alloc(priv, rxq, &num);
+		if (ret || num != rxq->size) {
+			rte_free(rxq);
+			return ret;
+		}
+	}
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up");
@@ -535,6 +1308,8 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 	for (i = 0; i < dev->data->nb_tx_queues; i++)
 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
 
+	mvneta_set_tx_function(dev);
+
 	return 0;
 
 out:
@@ -553,11 +1328,25 @@ static void
 mvneta_dev_stop(struct rte_eth_dev *dev)
 {
 	struct mvneta_priv *priv = dev->data->dev_private;
+	int i;
 
 	if (!priv->ppio)
 		return;
 
 	mvneta_dev_set_link_down(dev);
+	MVNETA_LOG(INFO, "Flushing rx queues");
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+
+		mvneta_rx_queue_flush(rxq);
+	}
+
+	MVNETA_LOG(INFO, "Flushing tx queues");
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		struct mvneta_txq *txq = dev->data->tx_queues[i];
+
+		mvneta_tx_queue_flush(txq);
+	}
 
 	neta_ppio_deinit(priv->ppio);
 
@@ -704,6 +1493,8 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
 	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
+	eth_dev->rx_pkt_burst = mvneta_rx_pkt_burst;
+	mvneta_set_tx_function(eth_dev);
 ;	eth_dev->dev_ops = &mvneta_ops;
 
 	return 0;
diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h
index 8957034..a05566d 100644
--- a/drivers/net/mvneta/mvneta_ethdev.h
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -43,6 +43,17 @@
 
 #define MRVL_NETA_DEFAULT_TC 0
 
+/** Maximum number of descriptors in shadow queue. Must be power of 2 */
+#define MRVL_NETA_TX_SHADOWQ_SIZE MRVL_NETA_TXD_MAX
+
+/** Shadow queue size mask (since shadow queue size is power of 2) */
+#define MRVL_NETA_TX_SHADOWQ_MASK (MRVL_NETA_TX_SHADOWQ_SIZE - 1)
+
+/** Minimum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN	16
+
+/** Maximum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX	64
 
 #define MRVL_NETA_VLAN_TAG_LEN		4
 #define MRVL_NETA_ETH_HDRS_LEN		(ETHER_HDR_LEN + ETHER_CRC_LEN + \
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v2 3/8] net/mvneta: support for setting of MTU
  2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                     ` (4 preceding siblings ...)
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 3/8] " Andrzej Ostruszka
@ 2018-08-31 12:26   ` Andrzej Ostruszka
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 4/8] net/mvneta: add link update Andrzej Ostruszka
                     ` (6 subsequent siblings)
  12 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:26 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add callback for setting of MTU.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 78 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 968f920..88d28f2 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1025,6 +1025,77 @@ static void mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
 }
 
 /**
+ * DPDK callback to change the MTU.
+ *
+ * Setting the MTU affects hardware MRU (packets larger than the MRU
+ * will be dropped).
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param mtu
+ *   New MTU.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	uint16_t mbuf_data_size = 0; /* SW buffer size */
+	uint16_t mru;
+	int ret;
+
+	mru = MRVL_NETA_MTU_TO_MRU(mtu);
+	/*
+	 * min_rx_buf_size is equal to mbuf data size
+	 * if pmd didn't set it differently
+	 */
+	mbuf_data_size = dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM;
+	/* Prevent PMD from:
+	 * - setting mru greater than the mbuf size resulting in
+	 * hw and sw buffer size mismatch
+	 * - setting mtu that requires the support of scattered packets
+	 * when this feature has not been enabled/supported so far.
+	 */
+	if (!dev->data->scattered_rx &&
+	    (mru + MRVL_NETA_PKT_OFFS > mbuf_data_size)) {
+		mru = mbuf_data_size - MRVL_NETA_PKT_OFFS;
+		mtu = MRVL_NETA_MRU_TO_MTU(mru);
+		MVNETA_LOG(WARNING, "MTU too big, max MTU possible limitted by"
+			" current mbuf size: %u. Set MTU to %u, MRU to %u",
+			mbuf_data_size, mtu, mru);
+	}
+
+	if (mtu < ETHER_MIN_MTU || mru > MVNETA_PKT_SIZE_MAX) {
+		MVNETA_LOG(ERR, "Invalid MTU [%u] or MRU [%u]", mtu, mru);
+		return -EINVAL;
+	}
+
+	dev->data->mtu = mtu;
+	dev->data->dev_conf.rxmode.max_rx_pkt_len = mru - MV_MH_SIZE;
+
+	if (!priv->ppio)
+		/* It is OK. New MTU will be set later on mvneta_dev_start */
+		return 0;
+
+	ret = neta_ppio_set_mru(priv->ppio, mru);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MRU");
+		return ret;
+	}
+
+	ret = neta_ppio_set_mtu(priv->ppio, mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MTU");
+		return ret;
+	}
+	MVNETA_LOG(INFO, "MTU changed to %u, MRU = %u", mtu, mru);
+
+	return 0;
+}
+
+/**
  * DPDK callback to bring the link up.
  *
  * @param dev
@@ -1298,6 +1369,12 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 		}
 	}
 
+	ret = mvneta_mtu_set(dev, dev->data->mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to set MTU %d", dev->data->mtu);
+		goto out;
+	}
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up");
@@ -1413,6 +1490,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
 	.mac_addr_set = mvneta_mac_addr_set,
+	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v2 4/8] net/mvneta: add link update
  2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                     ` (5 preceding siblings ...)
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
@ 2018-08-31 12:26   ` Andrzej Ostruszka
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 4/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
                     ` (5 subsequent siblings)
  12 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:26 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add callback for updating information about link status/info.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 71 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 88d28f2..a7e79ea 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1457,6 +1457,76 @@ mvneta_dev_close(struct rte_eth_dev *dev)
 }
 
 /**
+ * DPDK callback to retrieve physical link information.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param wait_to_complete
+ *   Wait for request completion (ignored).
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
+{
+	/*
+	 * TODO
+	 * once MUSDK provides necessary API use it here
+	 */
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct ethtool_cmd edata;
+	struct ifreq req;
+	int ret, fd, link_up;
+
+	if (!priv->ppio)
+		return -EPERM;
+
+	edata.cmd = ETHTOOL_GSET;
+
+	strcpy(req.ifr_name, dev->data->name);
+	req.ifr_data = (void *)&edata;
+
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd == -1)
+		return -EFAULT;
+	ret = ioctl(fd, SIOCETHTOOL, &req);
+	if (ret == -1) {
+		close(fd);
+		return -EFAULT;
+	}
+
+	close(fd);
+
+	switch (ethtool_cmd_speed(&edata)) {
+	case SPEED_10:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_10M;
+		break;
+	case SPEED_100:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_100M;
+		break;
+	case SPEED_1000:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_1G;
+		break;
+	case SPEED_2500:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_2_5G;
+		break;
+	default:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE;
+	}
+
+	dev->data->dev_link.link_duplex = edata.duplex ? ETH_LINK_FULL_DUPLEX :
+							 ETH_LINK_HALF_DUPLEX;
+	dev->data->dev_link.link_autoneg = edata.autoneg ? ETH_LINK_AUTONEG :
+							   ETH_LINK_FIXED;
+
+	neta_ppio_get_link_state(priv->ppio, &link_up);
+	dev->data->dev_link.link_status = link_up ? ETH_LINK_UP : ETH_LINK_DOWN;
+
+	return 0;
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -1489,6 +1559,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_up = mvneta_dev_set_link_up,
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
+	.link_update = mvneta_link_update,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v2 4/8] net/mvneta: support for setting of MTU
  2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                     ` (6 preceding siblings ...)
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 4/8] net/mvneta: add link update Andrzej Ostruszka
@ 2018-08-31 12:26   ` Andrzej Ostruszka
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
                     ` (4 subsequent siblings)
  12 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:26 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add callback for setting of MTU.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 149 +++++++++++++++++++++++++++++++++++++
 1 file changed, 149 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 968f920..a7e79ea 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1025,6 +1025,77 @@ static void mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
 }
 
 /**
+ * DPDK callback to change the MTU.
+ *
+ * Setting the MTU affects hardware MRU (packets larger than the MRU
+ * will be dropped).
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param mtu
+ *   New MTU.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	uint16_t mbuf_data_size = 0; /* SW buffer size */
+	uint16_t mru;
+	int ret;
+
+	mru = MRVL_NETA_MTU_TO_MRU(mtu);
+	/*
+	 * min_rx_buf_size is equal to mbuf data size
+	 * if pmd didn't set it differently
+	 */
+	mbuf_data_size = dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM;
+	/* Prevent PMD from:
+	 * - setting mru greater than the mbuf size resulting in
+	 * hw and sw buffer size mismatch
+	 * - setting mtu that requires the support of scattered packets
+	 * when this feature has not been enabled/supported so far.
+	 */
+	if (!dev->data->scattered_rx &&
+	    (mru + MRVL_NETA_PKT_OFFS > mbuf_data_size)) {
+		mru = mbuf_data_size - MRVL_NETA_PKT_OFFS;
+		mtu = MRVL_NETA_MRU_TO_MTU(mru);
+		MVNETA_LOG(WARNING, "MTU too big, max MTU possible limitted by"
+			" current mbuf size: %u. Set MTU to %u, MRU to %u",
+			mbuf_data_size, mtu, mru);
+	}
+
+	if (mtu < ETHER_MIN_MTU || mru > MVNETA_PKT_SIZE_MAX) {
+		MVNETA_LOG(ERR, "Invalid MTU [%u] or MRU [%u]", mtu, mru);
+		return -EINVAL;
+	}
+
+	dev->data->mtu = mtu;
+	dev->data->dev_conf.rxmode.max_rx_pkt_len = mru - MV_MH_SIZE;
+
+	if (!priv->ppio)
+		/* It is OK. New MTU will be set later on mvneta_dev_start */
+		return 0;
+
+	ret = neta_ppio_set_mru(priv->ppio, mru);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MRU");
+		return ret;
+	}
+
+	ret = neta_ppio_set_mtu(priv->ppio, mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MTU");
+		return ret;
+	}
+	MVNETA_LOG(INFO, "MTU changed to %u, MRU = %u", mtu, mru);
+
+	return 0;
+}
+
+/**
  * DPDK callback to bring the link up.
  *
  * @param dev
@@ -1298,6 +1369,12 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 		}
 	}
 
+	ret = mvneta_mtu_set(dev, dev->data->mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to set MTU %d", dev->data->mtu);
+		goto out;
+	}
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up");
@@ -1380,6 +1457,76 @@ mvneta_dev_close(struct rte_eth_dev *dev)
 }
 
 /**
+ * DPDK callback to retrieve physical link information.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param wait_to_complete
+ *   Wait for request completion (ignored).
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
+{
+	/*
+	 * TODO
+	 * once MUSDK provides necessary API use it here
+	 */
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct ethtool_cmd edata;
+	struct ifreq req;
+	int ret, fd, link_up;
+
+	if (!priv->ppio)
+		return -EPERM;
+
+	edata.cmd = ETHTOOL_GSET;
+
+	strcpy(req.ifr_name, dev->data->name);
+	req.ifr_data = (void *)&edata;
+
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd == -1)
+		return -EFAULT;
+	ret = ioctl(fd, SIOCETHTOOL, &req);
+	if (ret == -1) {
+		close(fd);
+		return -EFAULT;
+	}
+
+	close(fd);
+
+	switch (ethtool_cmd_speed(&edata)) {
+	case SPEED_10:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_10M;
+		break;
+	case SPEED_100:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_100M;
+		break;
+	case SPEED_1000:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_1G;
+		break;
+	case SPEED_2500:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_2_5G;
+		break;
+	default:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE;
+	}
+
+	dev->data->dev_link.link_duplex = edata.duplex ? ETH_LINK_FULL_DUPLEX :
+							 ETH_LINK_HALF_DUPLEX;
+	dev->data->dev_link.link_autoneg = edata.autoneg ? ETH_LINK_AUTONEG :
+							   ETH_LINK_FIXED;
+
+	neta_ppio_get_link_state(priv->ppio, &link_up);
+	dev->data->dev_link.link_status = link_up ? ETH_LINK_UP : ETH_LINK_DOWN;
+
+	return 0;
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -1412,7 +1559,9 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_up = mvneta_dev_set_link_up,
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
+	.link_update = mvneta_link_update,
 	.mac_addr_set = mvneta_mac_addr_set,
+	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v2 5/8] net/mvneta: support for promiscuous
  2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                     ` (7 preceding siblings ...)
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 4/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
@ 2018-08-31 12:26   ` Andrzej Ostruszka
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
                     ` (3 subsequent siblings)
  12 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:26 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add callbacks for enabling/disabling of promiscuous mode.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 54 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index a7e79ea..68d363e 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1527,6 +1527,58 @@ mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
 }
 
 /**
+ * DPDK callback to enable promiscuous mode.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_promiscuous_enable(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	int ret, en;
+
+	if (!priv->ppio)
+		return;
+
+	neta_ppio_get_promisc(priv->ppio, &en);
+	if (en) {
+		MVNETA_LOG(INFO, "Promiscuous already enabled");
+		return;
+	}
+
+	ret = neta_ppio_set_promisc(priv->ppio, 1);
+	if (ret)
+		MVNETA_LOG(ERR, "Failed to enable promiscuous mode");
+}
+
+/**
+ * DPDK callback to disable allmulticast mode.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_promiscuous_disable(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	int ret, en;
+
+	if (!priv->ppio)
+		return;
+
+	neta_ppio_get_promisc(priv->ppio, &en);
+	if (!en) {
+		MVNETA_LOG(INFO, "Promiscuous already disabled");
+		return;
+	}
+
+	ret = neta_ppio_set_promisc(priv->ppio, 0);
+	if (ret)
+		MVNETA_LOG(ERR, "Failed to disable promiscuous mode");
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -1560,6 +1612,8 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
 	.link_update = mvneta_link_update,
+	.promiscuous_enable = mvneta_promiscuous_enable,
+	.promiscuous_disable = mvneta_promiscuous_disable,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v2 6/8] net/mvneta: add MAC filtering
  2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                     ` (8 preceding siblings ...)
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
@ 2018-08-31 12:26   ` Andrzej Ostruszka
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
                     ` (2 subsequent siblings)
  12 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:26 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add callbacks for adding/removing MAC addresses.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 69 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 68d363e..975375e 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1579,6 +1579,73 @@ mvneta_promiscuous_disable(struct rte_eth_dev *dev)
 }
 
 /**
+ * DPDK callback to remove a MAC address.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param index
+ *   MAC address index.
+ */
+static void
+mvneta_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	char buf[ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	if (!priv->ppio)
+		return;
+
+	ret = neta_ppio_remove_mac_addr(priv->ppio,
+				       dev->data->mac_addrs[index].addr_bytes);
+	if (ret) {
+		ether_format_addr(buf, sizeof(buf),
+				  &dev->data->mac_addrs[index]);
+		MVNETA_LOG(ERR, "Failed to remove mac %s", buf);
+	}
+}
+
+/**
+ * DPDK callback to add a MAC address.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param mac_addr
+ *   MAC address to register.
+ * @param index
+ *   MAC address index.
+ * @param vmdq
+ *   VMDq pool index to associate address with (unused).
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
+		  uint32_t index, uint32_t vmdq __rte_unused)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	char buf[ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	if (index == 0)
+		/* For setting index 0, mrvl_mac_addr_set() should be used.*/
+		return -1;
+
+	if (!priv->ppio)
+		return 0;
+
+	ret = neta_ppio_add_mac_addr(priv->ppio, mac_addr->addr_bytes);
+	if (ret) {
+		ether_format_addr(buf, sizeof(buf), mac_addr);
+		MVNETA_LOG(ERR, "Failed to add mac %s", buf);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -1614,6 +1681,8 @@ static const struct eth_dev_ops mvneta_ops = {
 	.link_update = mvneta_link_update,
 	.promiscuous_enable = mvneta_promiscuous_enable,
 	.promiscuous_disable = mvneta_promiscuous_disable,
+	.mac_addr_remove = mvneta_mac_addr_remove,
+	.mac_addr_add = mvneta_mac_addr_add,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v2 7/8] net/mvneta: add support for basic stats
  2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                     ` (9 preceding siblings ...)
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
@ 2018-08-31 12:26   ` Andrzej Ostruszka
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
  2018-08-31 12:59   ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  12 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:26 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add support for getting of basic statistics for the driver.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 47 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 975375e..2bf2e2e 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1671,6 +1671,52 @@ mvneta_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
 	return 0;
 }
 
+/**
+ * DPDK callback to get device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param stats
+ *   Stats structure output buffer.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct neta_ppio_statistics ppio_stats;
+	unsigned int ret;
+
+	if (!priv->ppio)
+		return -EPERM;
+
+	ret = neta_ppio_get_statistics(priv->ppio, &ppio_stats);
+	if (unlikely(ret)) {
+		MVNETA_LOG(ERR, "Failed to update port statistics");
+		return ret;
+	}
+
+	stats->ipackets += ppio_stats.rx_packets +
+			ppio_stats.rx_broadcast_packets +
+			ppio_stats.rx_multicast_packets;
+	stats->opackets += ppio_stats.tx_packets +
+			ppio_stats.tx_broadcast_packets +
+			ppio_stats.tx_multicast_packets;
+	stats->ibytes += ppio_stats.rx_bytes;
+	stats->obytes += ppio_stats.tx_bytes;
+	stats->imissed += ppio_stats.rx_discard +
+			  ppio_stats.rx_overrun;
+
+	stats->ierrors = ppio_stats.rx_packets_err +
+			ppio_stats.rx_errors +
+			ppio_stats.rx_crc_error;
+	stats->oerrors = ppio_stats.tx_errors;
+
+	return 0;
+}
+
 static const struct eth_dev_ops mvneta_ops = {
 	.dev_configure = mvneta_dev_configure,
 	.dev_start = mvneta_dev_start,
@@ -1685,6 +1731,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_add = mvneta_mac_addr_add,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
+	.stats_get = mvneta_stats_get,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v2 8/8] net/mvneta: add reset statistics callback
  2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                     ` (10 preceding siblings ...)
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
@ 2018-08-31 12:26   ` Andrzej Ostruszka
  2018-08-31 12:59   ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  12 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:26 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Natalie Samsonov <nsamsono@marvell.com>

Add support for resetting of driver statistics.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 40 +++++++++++++++++++++++++++++++-------
 drivers/net/mvneta/mvneta_ethdev.h |  1 +
 2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 2bf2e2e..1bcfc68 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1700,23 +1700,48 @@ mvneta_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 
 	stats->ipackets += ppio_stats.rx_packets +
 			ppio_stats.rx_broadcast_packets +
-			ppio_stats.rx_multicast_packets;
+			ppio_stats.rx_multicast_packets -
+			priv->prev_stats.ipackets;
 	stats->opackets += ppio_stats.tx_packets +
 			ppio_stats.tx_broadcast_packets +
-			ppio_stats.tx_multicast_packets;
-	stats->ibytes += ppio_stats.rx_bytes;
-	stats->obytes += ppio_stats.tx_bytes;
+			ppio_stats.tx_multicast_packets -
+			priv->prev_stats.opackets;
+	stats->ibytes += ppio_stats.rx_bytes - priv->prev_stats.ibytes;
+	stats->obytes += ppio_stats.tx_bytes - priv->prev_stats.obytes;
 	stats->imissed += ppio_stats.rx_discard +
-			  ppio_stats.rx_overrun;
+			  ppio_stats.rx_overrun -
+			  priv->prev_stats.imissed;
 
 	stats->ierrors = ppio_stats.rx_packets_err +
 			ppio_stats.rx_errors +
-			ppio_stats.rx_crc_error;
-	stats->oerrors = ppio_stats.tx_errors;
+			ppio_stats.rx_crc_error -
+			priv->prev_stats.ierrors;
+	stats->oerrors = ppio_stats.tx_errors - priv->prev_stats.oerrors;
 
 	return 0;
 }
 
+/**
+ * DPDK callback to clear device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_stats_reset(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	unsigned int ret;
+
+	if (!priv->ppio)
+		return;
+
+	ret = mvneta_stats_get(dev, &priv->prev_stats);
+	if (unlikely(ret))
+		RTE_LOG(ERR, PMD, "Failed to reset port statistics");
+}
+
+
 static const struct eth_dev_ops mvneta_ops = {
 	.dev_configure = mvneta_dev_configure,
 	.dev_start = mvneta_dev_start,
@@ -1732,6 +1757,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.stats_get = mvneta_stats_get,
+	.stats_reset = mvneta_stats_reset,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h
index a05566d..6aed170 100644
--- a/drivers/net/mvneta/mvneta_ethdev.h
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -77,6 +77,7 @@ struct mvneta_priv {
 	uint16_t nb_rx_queues;
 
 	uint64_t rate_max;
+	struct rte_eth_stats prev_stats;
 };
 
 /** Current log type. */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/8] net/bonding: fix buf corruption in packets
  2018-08-31 12:25   ` [dpdk-dev] [PATCH v2 1/8] net/bonding: fix buf corruption in packets Andrzej Ostruszka
@ 2018-08-31 12:33     ` Andrzej Ostruszka
  0 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:33 UTC (permalink / raw)
  To: dev; +Cc: stable

Please forgive me this particular patch - that was my mistake when
sending.  That was leftover from wrong format-patch that was picked by
shell wildcard.

Apologies for the noise.

Best regards
Andrzej

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD
  2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                     ` (11 preceding siblings ...)
  2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
@ 2018-08-31 12:59   ` Andrzej Ostruszka
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
                       ` (10 more replies)
  12 siblings, 11 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:59 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

This patch series introduces new PMD for Marvell NETA adapters (MVNETA).
See the documentation for more info.

It is split for easier reviewing.

v3:
    No changes against v2, just resubmitting again to have clean patch
    set after my faulty format-patch.  My apologies for the noise.

v2:
  * fixed couple of checkpatch warnings
  * removed '\n' from MVNETA_LOG invocations (appended by the macro)
  * removed unused MVNETA_MUSDK_DMA_MEMSIZE define
  * changed one printf into MVNETA_LOG
  * removed __func__ from one MVNETA_LOG invocation (inserted
    automatically by the macro)
  * minor grammar/spelling correction in comments
  * removed license text from file with SPDX tag (mvneta.rst)
  * removed misleading part of comment for mvneta_shadow_txq
  * changed authorship of the patches to the original author

Natalie Samsonov (1):
  net/mvneta: add reset statistics callback

Zyta Szpak (7):
  net/mvneta: add neta PMD skeleton
  net/mvneta: add Rx/Tx support
  net/mvneta: support for setting of MTU
  net/mvneta: add link update
  net/mvneta: support for promiscuous
  net/mvneta: add MAC filtering
  net/mvneta: add support for basic stats

 MAINTAINERS                                   |    8 +
 config/common_base                            |    5 +
 devtools/test-build.sh                        |    2 +
 doc/guides/nics/features/mvneta.ini           |   18 +
 doc/guides/nics/mvneta.rst                    |  154 ++
 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            | 2016 +++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h            |   90 ++
 drivers/net/mvneta/rte_pmd_mvneta_version.map |    3 +
 mk/rte.app.mk                                 |    7 +-
 16 files changed, 2380 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

-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v3 1/8] net/mvneta: add neta PMD skeleton
  2018-08-31 12:59   ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
@ 2018-08-31 12:59     ` Andrzej Ostruszka
  2018-09-14 16:23       ` Ferruh Yigit
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
                       ` (9 subsequent siblings)
  10 siblings, 1 reply; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:59 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add neta pmd driver skeleton providing base for the further
development.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
Signed-off-by: Andrzej Ostruszka <amo@semihalf.com>
---
 MAINTAINERS                                   |   8 +
 config/common_base                            |   5 +
 devtools/test-build.sh                        |   2 +
 doc/guides/nics/features/mvneta.ini           |  18 +
 doc/guides/nics/mvneta.rst                    | 154 +++++
 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            | 880 ++++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h            |  78 +++
 drivers/net/mvneta/rte_pmd_mvneta_version.map |   3 +
 mk/rte.app.mk                                 |   7 +-
 16 files changed, 1232 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 9fd258f..18858b9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -585,6 +585,14 @@ F: drivers/net/mvpp2/
 F: doc/guides/nics/mvpp2.rst
 F: doc/guides/nics/features/mvpp2.ini
 
+Marvell mvneta
+M: Zyta Szpak <zr@semihalf.com>
+M: Dmitri Epshtein <dima@marvell.com>
+M: Natalie Samsonov <nsamsono@marvell.com>
+F: drivers/net/mvneta/
+F: doc/guides/nics/mvneta.rst
+F: doc/guides/nics/features/mvneta.ini
+
 Mellanox mlx4
 M: Matan Azrad <matan@mellanox.com>
 M: Shahaf Shuler <shahafs@mellanox.com>
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 () # <directory> <target> <options>
 		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..3f02f84
--- /dev/null
+++ b/doc/guides/nics/features/mvneta.ini
@@ -0,0 +1,18 @@
+;
+; 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
+Link status          = Y
+MTU update           = Y
+Jumbo frame          = Y
+Promiscuous mode     = Y
+CRC offload          = Y
+L3 checksum offload  = Y
+L4 checksum offload  = Y
+Packet type parsing  = Y
+Basic stats          = 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..8d4b9e4
--- /dev/null
+++ b/doc/guides/nics/mvneta.rst
@@ -0,0 +1,154 @@
+..  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
+- tx/rx_burst
+- Speed capabilities
+- Link status
+- CRC offload
+- Packet type parsing
+
+
+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 <https://extranet.marvell.com>`_. 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 <linux_gsg>` 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=eth_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=<toolchain>/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=<musdk>/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=eth_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=eth_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 24204e6..0586715 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -54,6 +54,10 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **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..621f38a
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -0,0 +1,880 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Marvell International Ltd.
+ * Copyright(c) 2018 Semihalf.
+ * All rights reserved.
+ */
+
+#include <rte_ethdev_driver.h>
+#include <rte_kvargs.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_bus_vdev.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <rte_mvep_common.h>
+#include "mvneta_ethdev.h"
+
+
+#define MVNETA_IFACE_NAME_ARG "iface"
+
+#define MVNETA_RX_OFFLOADS (DEV_RX_OFFLOAD_JUMBO_FRAME | \
+			  DEV_RX_OFFLOAD_CRC_STRIP | \
+			  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
+
+#define MVNETA_PKT_EFFEC_OFFS (MRVL_NETA_PKT_OFFS + MV_MH_SIZE)
+
+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;
+};
+
+
+struct mvneta_rxq {
+	struct mvneta_priv *priv;
+	struct rte_mempool *mp;
+	int queue_id;
+	int port_id;
+	int size;
+	int cksum_enabled;
+	uint64_t bytes_recv;
+	uint64_t drop_mac;
+	uint64_t pkts_processed;
+};
+
+
+struct mvneta_txq {
+	struct mvneta_priv *priv;
+	int queue_id;
+	int port_id;
+	uint64_t bytes_sent;
+	int tx_deferred_start;
+};
+
+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.offloads & DEV_RX_OFFLOAD_CRC_STRIP)) {
+		MVNETA_LOG(INFO,
+			"L2 CRC stripping is always enabled in hw");
+		dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CRC_STRIP;
+	}
+
+	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;
+	info->default_rxconf.offloads = DEV_RX_OFFLOAD_CRC_STRIP;
+	/* 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 get information about specific receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param rx_queue_id
+ *   Receive queue index.
+ * @param qinfo
+ *   Receive queue information structure.
+ */
+static void mvneta_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+			      struct rte_eth_rxq_info *qinfo)
+{
+	struct mvneta_rxq *q = dev->data->rx_queues[rx_queue_id];
+
+	qinfo->mp = q->mp;
+	qinfo->nb_desc = q->size;
+}
+
+/**
+ * DPDK callback to get information about specific transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param tx_queue_id
+ *   Transmit queue index.
+ * @param qinfo
+ *   Transmit queue information structure.
+ */
+static void mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+			      struct rte_eth_txq_info *qinfo)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	qinfo->nb_desc =
+		priv->ppio_params.outqs_params.outqs_params[tx_queue_id].size;
+}
+
+/**
+ * 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 configure the receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   RX queue index.
+ * @param desc
+ *   Number of descriptors to configure in queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Thresholds parameters (unused_).
+ * @param mp
+ *   Memory pool for buffer allocations.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		    unsigned int socket,
+		    const struct rte_eth_rxconf *conf __rte_unused,
+		    struct rte_mempool *mp)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_rxq *rxq;
+	uint32_t frame_size, buf_size = rte_pktmbuf_data_room_size(mp);
+	uint32_t max_rx_pkt_len = dev->data->dev_conf.rxmode.max_rx_pkt_len;
+
+	frame_size = buf_size - RTE_PKTMBUF_HEADROOM - MVNETA_PKT_EFFEC_OFFS;
+
+	if (frame_size < max_rx_pkt_len) {
+		MVNETA_LOG(ERR,
+			"Mbuf size must be increased to %u bytes to hold up "
+			"to %u bytes of data.",
+			buf_size + max_rx_pkt_len - frame_size,
+			max_rx_pkt_len);
+		dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
+		MVNETA_LOG(INFO, "Setting max rx pkt len to %u",
+			dev->data->dev_conf.rxmode.max_rx_pkt_len);
+	}
+
+	if (dev->data->rx_queues[idx]) {
+		rte_free(dev->data->rx_queues[idx]);
+		dev->data->rx_queues[idx] = NULL;
+	}
+
+	rxq = rte_zmalloc_socket("rxq", sizeof(*rxq), 0, socket);
+	if (!rxq)
+		return -ENOMEM;
+
+	rxq->priv = priv;
+	rxq->mp = mp;
+	rxq->cksum_enabled = dev->data->dev_conf.rxmode.offloads &
+			     DEV_RX_OFFLOAD_IPV4_CKSUM;
+	rxq->queue_id = idx;
+	rxq->port_id = dev->data->port_id;
+	rxq->size = desc;
+	priv->ppio_params.inqs_params.tcs_params[MRVL_NETA_DEFAULT_TC].size =
+		desc;
+
+	dev->data->rx_queues[idx] = rxq;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to release the receive queue.
+ *
+ * @param rxq
+ *   Generic receive queue pointer.
+ */
+static void
+mvneta_rx_queue_release(void *rxq)
+{
+	struct mvneta_rxq *q = rxq;
+
+	if (!q)
+		return;
+
+	rte_free(rxq);
+}
+
+/**
+ * DPDK callback to configure the transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   Transmit queue index.
+ * @param desc
+ *   Number of descriptors to configure in the queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Tx queue configuration parameters.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		    unsigned int socket, const struct rte_eth_txconf *conf)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_txq *txq;
+
+	if (dev->data->tx_queues[idx]) {
+		rte_free(dev->data->tx_queues[idx]);
+		dev->data->tx_queues[idx] = NULL;
+	}
+
+	txq = rte_zmalloc_socket("txq", sizeof(*txq), 0, socket);
+	if (!txq)
+		return -ENOMEM;
+
+	txq->priv = priv;
+	txq->queue_id = idx;
+	txq->port_id = dev->data->port_id;
+	txq->tx_deferred_start = conf->tx_deferred_start;
+	dev->data->tx_queues[idx] = txq;
+
+	priv->ppio_params.outqs_params.outqs_params[idx].size = desc;
+	priv->ppio_params.outqs_params.outqs_params[idx].weight = 1;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to release the transmit queue.
+ *
+ * @param txq
+ *   Generic transmit queue pointer.
+ */
+static void
+mvneta_tx_queue_release(void *txq)
+{
+	struct mvneta_txq *q = txq;
+
+	if (!q)
+		return;
+
+	rte_free(q);
+}
+
+
+/**
+ * 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;
+	int i;
+
+	if (priv->ppio)
+		mvneta_dev_stop(dev);
+
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		mvneta_rx_queue_release(dev->data->rx_queues[i]);
+		dev->data->rx_queues[i] = NULL;
+	}
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		mvneta_tx_queue_release(dev->data->tx_queues[i]);
+		dev->data->tx_queues[i] = NULL;
+	}
+}
+
+/**
+ * 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,
+	.rxq_info_get = mvneta_rxq_info_get,
+	.txq_info_get = mvneta_txq_info_get,
+	.rx_queue_setup = mvneta_rx_queue_setup,
+	.rx_queue_release = mvneta_rx_queue_release,
+	.tx_queue_setup = mvneta_tx_queue_setup,
+	.tx_queue_release = mvneta_tx_queue_release,
+};
+
+/**
+ * Create private device structure.
+ *
+ * @param dev_name
+ *   Pointer to the port name passed in the initialization parameters.
+ *
+ * @return
+ *   Pointer to the newly allocated private device structure.
+ */
+static struct mvneta_priv *
+mvneta_priv_create(const char *dev_name)
+{
+	struct mvneta_priv *priv;
+
+	priv = rte_zmalloc_socket(dev_name, sizeof(*priv), 0, rte_socket_id());
+	if (!priv)
+		return NULL;
+
+	return priv;
+}
+
+/**
+ * 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 = mvneta_priv_create(name);
+
+	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_dev:
+	rte_eth_dev_release_port(eth_dev);
+out_free_priv:
+	rte_free(priv);
+
+	return ret;
+}
+
+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_PMD_REGISTER_ALIAS(net_mvneta, eth_mvneta);
+
+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..8957034
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -0,0 +1,78 @@
+/* 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 <drivers/mv_neta.h>
+#include <drivers/mv_neta_ppio.h>
+
+/** 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 TODO is it? */
+#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 TODO is it? */
+#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_DEFAULT_TC 0
+
+
+#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
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v3 2/8] net/mvneta: add Rx/Tx support
  2018-08-31 12:59   ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
@ 2018-08-31 12:59     ` Andrzej Ostruszka
  2018-09-14 16:24       ` Ferruh Yigit
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
                       ` (8 subsequent siblings)
  10 siblings, 1 reply; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:59 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add part of PMD for actual reception/transmission.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 791 +++++++++++++++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h |  11 +
 2 files changed, 802 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 621f38a..968f920 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -27,6 +27,11 @@
 
 #define MVNETA_IFACE_NAME_ARG "iface"
 
+#define MVNETA_COOKIE_ADDR_INVALID ~0ULL
+
+#define MVNETA_COOKIE_HIGH_ADDR_SHIFT	(sizeof(neta_cookie_t) * 8)
+#define MVNETA_COOKIE_HIGH_ADDR_MASK	(~0ULL << MVNETA_COOKIE_HIGH_ADDR_SHIFT)
+
 #define MVNETA_RX_OFFLOADS (DEV_RX_OFFLOAD_JUMBO_FRAME | \
 			  DEV_RX_OFFLOAD_CRC_STRIP | \
 			  DEV_RX_OFFLOAD_CHECKSUM)
@@ -46,6 +51,19 @@
 
 #define MVNETA_PKT_EFFEC_OFFS (MRVL_NETA_PKT_OFFS + MV_MH_SIZE)
 
+static uint64_t cookie_addr_high = MVNETA_COOKIE_ADDR_INVALID;
+static uint16_t rx_desc_free_thresh = MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN;
+
+#define MVNETA_SET_COOKIE_HIGH_ADDR(addr) {				\
+	if (unlikely(cookie_addr_high == MVNETA_COOKIE_ADDR_INVALID))	\
+		cookie_addr_high =					\
+			(uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK;\
+}
+
+#define MVNETA_CHECK_COOKIE_HIGH_ADDR(addr)			\
+	((likely(cookie_addr_high ==				\
+	((uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK))) ? 1 : 0)
+
 int mvneta_logtype;
 
 static const char * const valid_args[] = {
@@ -58,6 +76,17 @@ struct mvneta_ifnames {
 	int idx;
 };
 
+/*
+ * To use buffer harvesting based on loopback port shadow queue structure
+ * was introduced for buffers information bookkeeping.
+ */
+struct mvneta_shadow_txq {
+	int head;           /* write index - used when sending buffers */
+	int tail;           /* read index - used when releasing buffers */
+	u16 size;           /* queue occupied size */
+	struct neta_buff_inf ent[MRVL_NETA_TX_SHADOWQ_SIZE]; /* q entries */
+};
+
 
 struct mvneta_rxq {
 	struct mvneta_priv *priv;
@@ -77,6 +106,7 @@ struct mvneta_txq {
 	int queue_id;
 	int port_id;
 	uint64_t bytes_sent;
+	struct mvneta_shadow_txq shadow_txq;
 	int tx_deferred_start;
 };
 
@@ -84,6 +114,247 @@ static int mvneta_dev_num;
 static int mvneta_lcore_first;
 static int mvneta_lcore_last;
 
+static inline void
+mvneta_fill_shadowq(struct mvneta_shadow_txq *sq, struct rte_mbuf *buf)
+{
+	sq->ent[sq->head].cookie = (uint64_t)buf;
+	sq->ent[sq->head].addr = buf ?
+		rte_mbuf_data_iova_default(buf) : 0;
+
+	sq->head = (sq->head + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	sq->size++;
+}
+
+static inline void
+mvneta_fill_desc(struct neta_ppio_desc *desc, struct rte_mbuf *buf)
+{
+	neta_ppio_outq_desc_reset(desc);
+	neta_ppio_outq_desc_set_phys_addr(desc, rte_pktmbuf_iova(buf));
+	neta_ppio_outq_desc_set_pkt_offset(desc, 0);
+	neta_ppio_outq_desc_set_pkt_len(desc, rte_pktmbuf_data_len(buf));
+}
+
+static inline int
+mvneta_buffs_refill(struct mvneta_priv *priv, struct mvneta_rxq *rxq, u16 *num)
+{
+	struct rte_mbuf *mbufs[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	struct neta_buff_inf entries[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	int i, ret;
+	uint16_t nb_desc = *num;
+
+	ret = rte_pktmbuf_alloc_bulk(rxq->mp, mbufs, nb_desc);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to allocate %u mbufs.", nb_desc);
+		*num = 0;
+		return -1;
+	}
+
+	MVNETA_SET_COOKIE_HIGH_ADDR(mbufs[0]);
+
+	for (i = 0; i < nb_desc; i++) {
+		if (unlikely(!MVNETA_CHECK_COOKIE_HIGH_ADDR(mbufs[i]))) {
+			MVNETA_LOG(ERR,
+				"mbuf virt high addr 0x%lx out of range 0x%lx",
+				(uint64_t)mbufs[i] >> 32,
+				cookie_addr_high >> 32);
+			*num = 0;
+			goto out;
+		}
+		entries[i].addr = rte_mbuf_data_iova_default(mbufs[i]);
+		entries[i].cookie = (neta_cookie_t)(uint64_t)mbufs[i];
+	}
+	neta_ppio_inq_put_buffs(priv->ppio, rxq->queue_id, entries, num);
+
+out:
+	for (i = *num; i < nb_desc; i++)
+		rte_pktmbuf_free(mbufs[i]);
+
+	return 0;
+}
+
+
+/**
+ * Allocate buffers from mempool
+ * and store addresses in rx descriptors.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_buffs_alloc(struct mvneta_priv *priv, struct mvneta_rxq *rxq, int *num)
+{
+	uint16_t nb_desc, nb_desc_burst, sent = 0;
+	int ret = 0;
+
+	nb_desc = *num;
+
+	do {
+		nb_desc_burst =
+			(nb_desc < MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX) ?
+			nb_desc : MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX;
+
+		ret = mvneta_buffs_refill(priv, rxq, &nb_desc_burst);
+		if (unlikely(ret || !nb_desc_burst))
+			break;
+
+		sent += nb_desc_burst;
+		nb_desc -= nb_desc_burst;
+
+	} while (nb_desc);
+
+	*num = sent;
+
+	return ret;
+}
+
+/**
+ * Return mbufs to mempool.
+ *
+ * @param rxq
+ *    Pointer to rx queue structure
+ * @param desc
+ *    Array of rx descriptors
+ */
+static void
+mvneta_recv_buffs_free(struct neta_ppio_desc *desc, uint16_t num)
+{
+	uint64_t addr;
+	uint8_t i;
+
+	for (i = 0; i < num; i++) {
+		if (desc) {
+			addr = cookie_addr_high |
+					neta_ppio_inq_desc_get_cookie(desc);
+			if (addr)
+				rte_pktmbuf_free((struct rte_mbuf *)addr);
+			desc++;
+		}
+	}
+}
+
+/**
+ * Release already sent buffers to mempool.
+ *
+ * @param ppio
+ *   Pointer to the port structure.
+ * @param sq
+ *   Pointer to the shadow queue.
+ * @param qid
+ *   Queue id number.
+ * @param force
+ *   Force releasing packets.
+ */
+static inline void
+mvneta_sent_buffers_free(struct neta_ppio *ppio,
+			 struct mvneta_shadow_txq *sq, int qid)
+{
+	struct neta_buff_inf *entry;
+	uint16_t nb_done = 0;
+	int i;
+	int tail = sq->tail;
+
+	neta_ppio_get_num_outq_done(ppio, qid, &nb_done);
+
+	if (nb_done > sq->size) {
+		MVNETA_LOG(ERR, "nb_done: %d, sq->size %d",
+			   nb_done, sq->size);
+		return;
+	}
+
+	for (i = 0; i < nb_done; i++) {
+		entry = &sq->ent[tail];
+
+		if (unlikely(!entry->addr)) {
+			MVNETA_LOG(DEBUG,
+				"Shadow memory @%d: cookie(%lx), pa(%lx)!",
+				tail, (u64)entry->cookie,
+				(u64)entry->addr);
+			tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+			continue;
+		}
+
+		struct rte_mbuf *mbuf;
+
+		mbuf = (struct rte_mbuf *)
+			   (cookie_addr_high | entry->cookie);
+		rte_pktmbuf_free(mbuf);
+		tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+
+	sq->tail = tail;
+	sq->size -= nb_done;
+}
+
+/**
+ * Flush single receive queue.
+ *
+ * @param rxq
+ *   Pointer to rx queue structure.
+ * @param descs
+ *   Array of rx descriptors
+ */
+static void
+mvneta_rx_queue_flush(struct mvneta_rxq *rxq)
+{
+	struct neta_ppio_desc *descs;
+	struct neta_buff_inf *bufs;
+	uint16_t num;
+	int ret, i;
+
+	descs = rte_malloc("rxdesc", MRVL_NETA_RXD_MAX * sizeof(*descs), 0);
+	bufs = rte_malloc("buffs", MRVL_NETA_RXD_MAX * sizeof(*bufs), 0);
+
+	do {
+		num = MRVL_NETA_RXD_MAX;
+		ret = neta_ppio_recv(rxq->priv->ppio,
+				     rxq->queue_id,
+				     descs, &num);
+		mvneta_recv_buffs_free(descs, num);
+	} while (ret == 0 && num);
+
+	rxq->pkts_processed = 0;
+
+	num = MRVL_NETA_RXD_MAX;
+
+	neta_ppio_inq_get_all_buffs(rxq->priv->ppio, rxq->queue_id, bufs, &num);
+	MVNETA_LOG(INFO, "freeing %u unused bufs.", num);
+
+	for (i = 0; i < num; i++) {
+		uint64_t addr;
+		if (bufs[i].cookie) {
+			addr = cookie_addr_high | bufs[i].cookie;
+			rte_pktmbuf_free((struct rte_mbuf *)addr);
+		}
+	}
+
+	rte_free(descs);
+	rte_free(bufs);
+}
+
+/**
+ * Flush single transmit queue.
+ *
+ * @param txq
+ *     Pointer to tx queue structure
+ */
+static void
+mvneta_tx_queue_flush(struct mvneta_txq *txq)
+{
+	struct mvneta_shadow_txq *sq = &txq->shadow_txq;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(txq->priv->ppio, sq,
+					 txq->queue_id);
+
+	/* free the rest of them */
+	while (sq->tail != sq->head) {
+		uint64_t addr = cookie_addr_high |
+			sq->ent[sq->tail].cookie;
+		rte_pktmbuf_free((struct rte_mbuf *)addr);
+		sq->tail = (sq->tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+	memset(sq, 0, sizeof(*sq));
+}
 
 /**
  * Deinitialize packet processor.
@@ -132,6 +403,467 @@ mvneta_ifnames_get(const char *key __rte_unused, const char *value,
 }
 
 /**
+ * Return packet type information and l3/l4 offsets.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ * @param l3_offset
+ *   l3 packet offset.
+ * @param l4_offset
+ *   l4 packet offset.
+ *
+ * @return
+ *   Packet type information.
+ */
+static inline uint64_t
+mvneta_desc_to_packet_type_and_offset(struct neta_ppio_desc *desc,
+				    uint8_t *l3_offset, uint8_t *l4_offset)
+{
+	enum neta_inq_l3_type l3_type;
+	enum neta_inq_l4_type l4_type;
+	uint64_t packet_type;
+
+	neta_ppio_inq_desc_get_l3_info(desc, &l3_type, l3_offset);
+	neta_ppio_inq_desc_get_l4_info(desc, &l4_type, l4_offset);
+
+	packet_type = RTE_PTYPE_L2_ETHER;
+
+	if (NETA_RXD_GET_VLAN_INFO(desc))
+		packet_type |= RTE_PTYPE_L2_ETHER_VLAN;
+
+	switch (l3_type) {
+	case NETA_INQ_L3_TYPE_IPV4_BAD:
+	case NETA_INQ_L3_TYPE_IPV4_OK:
+		packet_type |= RTE_PTYPE_L3_IPV4;
+		break;
+	case NETA_INQ_L3_TYPE_IPV6:
+		packet_type |= RTE_PTYPE_L3_IPV6;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l3 packet type");
+		break;
+	}
+
+	switch (l4_type) {
+	case NETA_INQ_L4_TYPE_TCP:
+		packet_type |= RTE_PTYPE_L4_TCP;
+		break;
+	case NETA_INQ_L4_TYPE_UDP:
+		packet_type |= RTE_PTYPE_L4_UDP;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l4 packet type");
+		break;
+	}
+
+	return packet_type;
+}
+
+/**
+ * Prepare offload information.
+ *
+ * @param ol_flags
+ *   Offload flags.
+ * @param packet_type
+ *   Packet type bitfield.
+ * @param l3_type
+ *   Pointer to the neta_ouq_l3_type structure.
+ * @param l4_type
+ *   Pointer to the neta_outq_l4_type structure.
+ * @param gen_l3_cksum
+ *   Will be set to 1 in case l3 checksum is computed.
+ * @param l4_cksum
+ *   Will be set to 1 in case l4 checksum is computed.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_prepare_proto_info(uint64_t ol_flags, uint32_t packet_type,
+			enum neta_outq_l3_type *l3_type,
+			enum neta_outq_l4_type *l4_type,
+			int *gen_l3_cksum,
+			int *gen_l4_cksum)
+{
+	/*
+	 * Based on ol_flags prepare information
+	 * for neta_ppio_outq_desc_set_proto_info() which setups descriptor
+	 * for offloading.
+	 */
+	if (ol_flags & PKT_TX_IPV4) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV4;
+		*gen_l3_cksum = ol_flags & PKT_TX_IP_CKSUM ? 1 : 0;
+	} else if (ol_flags & PKT_TX_IPV6) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV6;
+		/* no checksum for ipv6 header */
+		*gen_l3_cksum = 0;
+	} else {
+		/* if something different then stop processing */
+		return -1;
+	}
+
+	ol_flags &= PKT_TX_L4_MASK;
+	if ((packet_type & RTE_PTYPE_L4_TCP) &&
+	    ol_flags == PKT_TX_TCP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_TCP;
+		*gen_l4_cksum = 1;
+	} else if ((packet_type & RTE_PTYPE_L4_UDP) &&
+		   ol_flags == PKT_TX_UDP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_UDP;
+		*gen_l4_cksum = 1;
+	} else {
+		*l4_type = NETA_OUTQ_L4_TYPE_OTHER;
+		/* no checksum for other type */
+		*gen_l4_cksum = 0;
+	}
+
+	return 0;
+}
+
+/**
+ * Get offload information from the received packet descriptor.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ *
+ * @return
+ *   Mbuf offload flags.
+ */
+static inline uint64_t
+mvneta_desc_to_ol_flags(struct neta_ppio_desc *desc)
+{
+	uint64_t flags;
+	enum neta_inq_desc_status status;
+
+	status = neta_ppio_inq_desc_get_l3_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags = PKT_RX_IP_CKSUM_BAD;
+	else
+		flags = PKT_RX_IP_CKSUM_GOOD;
+
+	status = neta_ppio_inq_desc_get_l4_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags |= PKT_RX_L4_CKSUM_BAD;
+	else
+		flags |= PKT_RX_L4_CKSUM_GOOD;
+
+	return flags;
+}
+
+/**
+ * DPDK callback for transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts];
+
+	int i, ret, bytes_sent = 0;
+	uint16_t num, sq_free_size;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	if (unlikely(!nb_pkts || !q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+	if (unlikely(nb_pkts > sq_free_size)) {
+		MVNETA_LOG(DEBUG,
+			"No room in shadow queue for %d packets! %d packets will be sent.",
+			nb_pkts, sq_free_size);
+		nb_pkts = sq_free_size;
+	}
+
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		/* Fill first mbuf info in shadow queue */
+		mvneta_fill_shadowq(sq, mbuf);
+		mvneta_fill_desc(&descs[i], mbuf);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[i], l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = nb_pkts;
+	neta_ppio_send(q->priv->ppio, q->queue_id, descs, &nb_pkts);
+
+
+	/* number of packets that were not sent */
+	if (unlikely(num > nb_pkts)) {
+		for (i = nb_pkts; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE + sq->head - 1) &
+				MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = cookie_addr_high | sq->ent[sq->head].cookie;
+			bytes_sent -=
+				rte_pktmbuf_pkt_len((struct rte_mbuf *)addr);
+		}
+		sq->size -= num - nb_pkts;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/** DPDK callback for S/G transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_sg_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts * NETA_PPIO_DESC_NUM_FRAGS];
+	struct neta_ppio_sg_pkts pkts;
+	uint8_t frags[nb_pkts];
+	int i, j, ret, bytes_sent = 0;
+	int tail, tail_first;
+	uint16_t num, sq_free_size;
+	uint16_t nb_segs, total_descs = 0;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	pkts.frags = frags;
+	pkts.num = 0;
+
+	if (unlikely(!q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+	/* Save shadow queue free size */
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+
+	tail = 0;
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		struct rte_mbuf *seg = NULL;
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		nb_segs = mbuf->nb_segs;
+		total_descs += nb_segs;
+
+		/*
+		 * Check if total_descs does not exceed
+		 * shadow queue free size
+		 */
+		if (unlikely(total_descs > sq_free_size)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(DEBUG,
+				"No room in shadow queue for %d packets! "
+				"%d packets will be sent.",
+				nb_pkts, i);
+			break;
+		}
+
+
+		/* Check if nb_segs does not exceed the max nb of desc per
+		 * fragmented packet
+		 */
+		if (unlikely(nb_segs > NETA_PPIO_DESC_NUM_FRAGS)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(ERR,
+				"Too many segments. Packet won't be sent.");
+			break;
+		}
+
+		pkts.frags[pkts.num] = nb_segs;
+		pkts.num++;
+		tail_first = tail;
+
+		seg = mbuf;
+		for (j = 0; j < nb_segs - 1; j++) {
+			/* For the subsequent segments, set shadow queue
+			 * buffer to NULL
+			 */
+			mvneta_fill_shadowq(sq, NULL);
+			mvneta_fill_desc(&descs[tail], seg);
+
+			tail++;
+			seg = seg->next;
+		}
+		/* Put first mbuf info in last shadow queue entry */
+		mvneta_fill_shadowq(sq, mbuf);
+		/* Update descriptor with last segment */
+		mvneta_fill_desc(&descs[tail++], seg);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[tail_first],
+						   l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = total_descs;
+	neta_ppio_send_sg(q->priv->ppio, q->queue_id, descs, &total_descs,
+			  &pkts);
+
+	/* number of packets that were not sent */
+	if (unlikely(num > total_descs)) {
+		for (i = total_descs; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE +
+					sq->head - 1) &
+					MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = sq->ent[sq->head].cookie;
+			if (addr) {
+				struct rte_mbuf *mbuf;
+
+				mbuf = (struct rte_mbuf *)
+						(cookie_addr_high | addr);
+				bytes_sent -= rte_pktmbuf_pkt_len(mbuf);
+			}
+		}
+		sq->size -= num - total_descs;
+		nb_pkts = pkts.num;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/**
+ * DPDK callback for receive.
+ *
+ * @param rxq
+ *   Generic pointer to the receive queue.
+ * @param rx_pkts
+ *   Array to store received packets.
+ * @param nb_pkts
+ *   Maximum number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully received.
+ */
+static uint16_t
+mvneta_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_rxq *q = rxq;
+	struct neta_ppio_desc descs[nb_pkts];
+	int i, ret, rx_done = 0, rx_dropped = 0;
+
+	if (unlikely(!q || !q->priv->ppio))
+		return 0;
+
+	ret = neta_ppio_recv(q->priv->ppio, q->queue_id,
+			descs, &nb_pkts);
+
+	if (unlikely(ret < 0)) {
+		MVNETA_LOG(ERR, "Failed to receive packets");
+		return 0;
+	}
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf;
+		uint8_t l3_offset, l4_offset;
+		enum neta_inq_desc_status status;
+		uint64_t addr;
+
+		addr = cookie_addr_high |
+			neta_ppio_inq_desc_get_cookie(&descs[i]);
+		mbuf = (struct rte_mbuf *)addr;
+
+		rte_pktmbuf_reset(mbuf);
+
+		/* drop packet in case of mac, overrun or resource error */
+		status = neta_ppio_inq_desc_get_l2_pkt_error(&descs[i]);
+		if (unlikely(status != NETA_DESC_ERR_OK)) {
+			/* Release the mbuf to the mempool since
+			 * it won't be transferred to tx path
+			 */
+			rte_pktmbuf_free(mbuf);
+			q->drop_mac++;
+			rx_dropped++;
+			continue;
+		}
+
+		mbuf->data_off += MVNETA_PKT_EFFEC_OFFS;
+		mbuf->pkt_len = neta_ppio_inq_desc_get_pkt_len(&descs[i]);
+		mbuf->data_len = mbuf->pkt_len;
+		mbuf->port = q->port_id;
+		mbuf->packet_type =
+			mvneta_desc_to_packet_type_and_offset(&descs[i],
+								&l3_offset,
+								&l4_offset);
+		mbuf->l2_len = l3_offset;
+		mbuf->l3_len = l4_offset - l3_offset;
+
+		if (likely(q->cksum_enabled))
+			mbuf->ol_flags = mvneta_desc_to_ol_flags(&descs[i]);
+
+		rx_pkts[rx_done++] = mbuf;
+		q->bytes_recv += mbuf->pkt_len;
+	}
+	q->pkts_processed += rx_done + rx_dropped;
+
+	if (q->pkts_processed > rx_desc_free_thresh) {
+		int buf_to_refill = rx_desc_free_thresh;
+
+		ret = mvneta_buffs_alloc(q->priv, q, &buf_to_refill);
+		if (ret)
+			MVNETA_LOG(ERR, "Refill failed");
+		q->pkts_processed -= buf_to_refill;
+	}
+
+	return rx_done;
+}
+
+/**
  * Ethernet device configuration.
  *
  * Prepare the driver for a given number of TX and RX queues and
@@ -391,6 +1123,7 @@ mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 	rxq->queue_id = idx;
 	rxq->port_id = dev->data->port_id;
 	rxq->size = desc;
+	rx_desc_free_thresh = RTE_MIN(rx_desc_free_thresh, (desc / 2));
 	priv->ppio_params.inqs_params.tcs_params[MRVL_NETA_DEFAULT_TC].size =
 		desc;
 
@@ -413,6 +1146,14 @@ mvneta_rx_queue_release(void *rxq)
 	if (!q)
 		return;
 
+	/* If dev_stop was called already, mbufs are already
+	 * returned to mempool and ppio is deinitialized.
+	 * Skip this step.
+	 */
+
+	if (q->priv->ppio)
+		mvneta_rx_queue_flush(q);
+
 	rte_free(rxq);
 }
 
@@ -478,6 +1219,26 @@ mvneta_tx_queue_release(void *txq)
 	rte_free(q);
 }
 
+/**
+ * Set tx burst function according to offload flag
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_set_tx_function(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	/* Use a simple Tx queue (no offloads, no multi segs) if possible */
+	if (priv->multiseg) {
+		MVNETA_LOG(INFO, "Using multi-segment tx callback");
+		dev->tx_pkt_burst = mvneta_tx_sg_pkt_burst;
+	} else {
+		MVNETA_LOG(INFO, "Using single-segment tx callback");
+		dev->tx_pkt_burst = mvneta_tx_pkt_burst;
+	}
+}
 
 /**
  * DPDK callback to start the device.
@@ -525,6 +1286,18 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 		priv->uc_mc_flushed = 1;
 	}
 
+	/* Allocate buffers */
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+		int num = rxq->size;
+
+		ret = mvneta_buffs_alloc(priv, rxq, &num);
+		if (ret || num != rxq->size) {
+			rte_free(rxq);
+			return ret;
+		}
+	}
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up");
@@ -535,6 +1308,8 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 	for (i = 0; i < dev->data->nb_tx_queues; i++)
 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
 
+	mvneta_set_tx_function(dev);
+
 	return 0;
 
 out:
@@ -553,11 +1328,25 @@ static void
 mvneta_dev_stop(struct rte_eth_dev *dev)
 {
 	struct mvneta_priv *priv = dev->data->dev_private;
+	int i;
 
 	if (!priv->ppio)
 		return;
 
 	mvneta_dev_set_link_down(dev);
+	MVNETA_LOG(INFO, "Flushing rx queues");
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+
+		mvneta_rx_queue_flush(rxq);
+	}
+
+	MVNETA_LOG(INFO, "Flushing tx queues");
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		struct mvneta_txq *txq = dev->data->tx_queues[i];
+
+		mvneta_tx_queue_flush(txq);
+	}
 
 	neta_ppio_deinit(priv->ppio);
 
@@ -704,6 +1493,8 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
 	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
+	eth_dev->rx_pkt_burst = mvneta_rx_pkt_burst;
+	mvneta_set_tx_function(eth_dev);
 ;	eth_dev->dev_ops = &mvneta_ops;
 
 	return 0;
diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h
index 8957034..a05566d 100644
--- a/drivers/net/mvneta/mvneta_ethdev.h
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -43,6 +43,17 @@
 
 #define MRVL_NETA_DEFAULT_TC 0
 
+/** Maximum number of descriptors in shadow queue. Must be power of 2 */
+#define MRVL_NETA_TX_SHADOWQ_SIZE MRVL_NETA_TXD_MAX
+
+/** Shadow queue size mask (since shadow queue size is power of 2) */
+#define MRVL_NETA_TX_SHADOWQ_MASK (MRVL_NETA_TX_SHADOWQ_SIZE - 1)
+
+/** Minimum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN	16
+
+/** Maximum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX	64
 
 #define MRVL_NETA_VLAN_TAG_LEN		4
 #define MRVL_NETA_ETH_HDRS_LEN		(ETHER_HDR_LEN + ETHER_CRC_LEN + \
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v3 3/8] net/mvneta: support for setting of MTU
  2018-08-31 12:59   ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
@ 2018-08-31 12:59     ` Andrzej Ostruszka
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 4/8] net/mvneta: add link update Andrzej Ostruszka
                       ` (7 subsequent siblings)
  10 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:59 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add callback for setting of MTU.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 78 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 968f920..88d28f2 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1025,6 +1025,77 @@ static void mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
 }
 
 /**
+ * DPDK callback to change the MTU.
+ *
+ * Setting the MTU affects hardware MRU (packets larger than the MRU
+ * will be dropped).
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param mtu
+ *   New MTU.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	uint16_t mbuf_data_size = 0; /* SW buffer size */
+	uint16_t mru;
+	int ret;
+
+	mru = MRVL_NETA_MTU_TO_MRU(mtu);
+	/*
+	 * min_rx_buf_size is equal to mbuf data size
+	 * if pmd didn't set it differently
+	 */
+	mbuf_data_size = dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM;
+	/* Prevent PMD from:
+	 * - setting mru greater than the mbuf size resulting in
+	 * hw and sw buffer size mismatch
+	 * - setting mtu that requires the support of scattered packets
+	 * when this feature has not been enabled/supported so far.
+	 */
+	if (!dev->data->scattered_rx &&
+	    (mru + MRVL_NETA_PKT_OFFS > mbuf_data_size)) {
+		mru = mbuf_data_size - MRVL_NETA_PKT_OFFS;
+		mtu = MRVL_NETA_MRU_TO_MTU(mru);
+		MVNETA_LOG(WARNING, "MTU too big, max MTU possible limitted by"
+			" current mbuf size: %u. Set MTU to %u, MRU to %u",
+			mbuf_data_size, mtu, mru);
+	}
+
+	if (mtu < ETHER_MIN_MTU || mru > MVNETA_PKT_SIZE_MAX) {
+		MVNETA_LOG(ERR, "Invalid MTU [%u] or MRU [%u]", mtu, mru);
+		return -EINVAL;
+	}
+
+	dev->data->mtu = mtu;
+	dev->data->dev_conf.rxmode.max_rx_pkt_len = mru - MV_MH_SIZE;
+
+	if (!priv->ppio)
+		/* It is OK. New MTU will be set later on mvneta_dev_start */
+		return 0;
+
+	ret = neta_ppio_set_mru(priv->ppio, mru);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MRU");
+		return ret;
+	}
+
+	ret = neta_ppio_set_mtu(priv->ppio, mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MTU");
+		return ret;
+	}
+	MVNETA_LOG(INFO, "MTU changed to %u, MRU = %u", mtu, mru);
+
+	return 0;
+}
+
+/**
  * DPDK callback to bring the link up.
  *
  * @param dev
@@ -1298,6 +1369,12 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 		}
 	}
 
+	ret = mvneta_mtu_set(dev, dev->data->mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to set MTU %d", dev->data->mtu);
+		goto out;
+	}
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up");
@@ -1413,6 +1490,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
 	.mac_addr_set = mvneta_mac_addr_set,
+	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v3 4/8] net/mvneta: add link update
  2018-08-31 12:59   ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                       ` (2 preceding siblings ...)
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
@ 2018-08-31 12:59     ` Andrzej Ostruszka
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
                       ` (6 subsequent siblings)
  10 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:59 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add callback for updating information about link status/info.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 71 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 88d28f2..a7e79ea 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1457,6 +1457,76 @@ mvneta_dev_close(struct rte_eth_dev *dev)
 }
 
 /**
+ * DPDK callback to retrieve physical link information.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param wait_to_complete
+ *   Wait for request completion (ignored).
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
+{
+	/*
+	 * TODO
+	 * once MUSDK provides necessary API use it here
+	 */
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct ethtool_cmd edata;
+	struct ifreq req;
+	int ret, fd, link_up;
+
+	if (!priv->ppio)
+		return -EPERM;
+
+	edata.cmd = ETHTOOL_GSET;
+
+	strcpy(req.ifr_name, dev->data->name);
+	req.ifr_data = (void *)&edata;
+
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd == -1)
+		return -EFAULT;
+	ret = ioctl(fd, SIOCETHTOOL, &req);
+	if (ret == -1) {
+		close(fd);
+		return -EFAULT;
+	}
+
+	close(fd);
+
+	switch (ethtool_cmd_speed(&edata)) {
+	case SPEED_10:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_10M;
+		break;
+	case SPEED_100:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_100M;
+		break;
+	case SPEED_1000:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_1G;
+		break;
+	case SPEED_2500:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_2_5G;
+		break;
+	default:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE;
+	}
+
+	dev->data->dev_link.link_duplex = edata.duplex ? ETH_LINK_FULL_DUPLEX :
+							 ETH_LINK_HALF_DUPLEX;
+	dev->data->dev_link.link_autoneg = edata.autoneg ? ETH_LINK_AUTONEG :
+							   ETH_LINK_FIXED;
+
+	neta_ppio_get_link_state(priv->ppio, &link_up);
+	dev->data->dev_link.link_status = link_up ? ETH_LINK_UP : ETH_LINK_DOWN;
+
+	return 0;
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -1489,6 +1559,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_up = mvneta_dev_set_link_up,
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
+	.link_update = mvneta_link_update,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v3 5/8] net/mvneta: support for promiscuous
  2018-08-31 12:59   ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                       ` (3 preceding siblings ...)
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 4/8] net/mvneta: add link update Andrzej Ostruszka
@ 2018-08-31 12:59     ` Andrzej Ostruszka
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
                       ` (5 subsequent siblings)
  10 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:59 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add callbacks for enabling/disabling of promiscuous mode.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 54 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index a7e79ea..68d363e 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1527,6 +1527,58 @@ mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
 }
 
 /**
+ * DPDK callback to enable promiscuous mode.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_promiscuous_enable(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	int ret, en;
+
+	if (!priv->ppio)
+		return;
+
+	neta_ppio_get_promisc(priv->ppio, &en);
+	if (en) {
+		MVNETA_LOG(INFO, "Promiscuous already enabled");
+		return;
+	}
+
+	ret = neta_ppio_set_promisc(priv->ppio, 1);
+	if (ret)
+		MVNETA_LOG(ERR, "Failed to enable promiscuous mode");
+}
+
+/**
+ * DPDK callback to disable allmulticast mode.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_promiscuous_disable(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	int ret, en;
+
+	if (!priv->ppio)
+		return;
+
+	neta_ppio_get_promisc(priv->ppio, &en);
+	if (!en) {
+		MVNETA_LOG(INFO, "Promiscuous already disabled");
+		return;
+	}
+
+	ret = neta_ppio_set_promisc(priv->ppio, 0);
+	if (ret)
+		MVNETA_LOG(ERR, "Failed to disable promiscuous mode");
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -1560,6 +1612,8 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
 	.link_update = mvneta_link_update,
+	.promiscuous_enable = mvneta_promiscuous_enable,
+	.promiscuous_disable = mvneta_promiscuous_disable,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v3 6/8] net/mvneta: add MAC filtering
  2018-08-31 12:59   ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                       ` (4 preceding siblings ...)
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
@ 2018-08-31 12:59     ` Andrzej Ostruszka
  2018-09-14 16:24       ` Ferruh Yigit
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
                       ` (4 subsequent siblings)
  10 siblings, 1 reply; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:59 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add callbacks for adding/removing MAC addresses.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 69 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 68d363e..975375e 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1579,6 +1579,73 @@ mvneta_promiscuous_disable(struct rte_eth_dev *dev)
 }
 
 /**
+ * DPDK callback to remove a MAC address.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param index
+ *   MAC address index.
+ */
+static void
+mvneta_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	char buf[ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	if (!priv->ppio)
+		return;
+
+	ret = neta_ppio_remove_mac_addr(priv->ppio,
+				       dev->data->mac_addrs[index].addr_bytes);
+	if (ret) {
+		ether_format_addr(buf, sizeof(buf),
+				  &dev->data->mac_addrs[index]);
+		MVNETA_LOG(ERR, "Failed to remove mac %s", buf);
+	}
+}
+
+/**
+ * DPDK callback to add a MAC address.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param mac_addr
+ *   MAC address to register.
+ * @param index
+ *   MAC address index.
+ * @param vmdq
+ *   VMDq pool index to associate address with (unused).
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
+		  uint32_t index, uint32_t vmdq __rte_unused)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	char buf[ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	if (index == 0)
+		/* For setting index 0, mrvl_mac_addr_set() should be used.*/
+		return -1;
+
+	if (!priv->ppio)
+		return 0;
+
+	ret = neta_ppio_add_mac_addr(priv->ppio, mac_addr->addr_bytes);
+	if (ret) {
+		ether_format_addr(buf, sizeof(buf), mac_addr);
+		MVNETA_LOG(ERR, "Failed to add mac %s", buf);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -1614,6 +1681,8 @@ static const struct eth_dev_ops mvneta_ops = {
 	.link_update = mvneta_link_update,
 	.promiscuous_enable = mvneta_promiscuous_enable,
 	.promiscuous_disable = mvneta_promiscuous_disable,
+	.mac_addr_remove = mvneta_mac_addr_remove,
+	.mac_addr_add = mvneta_mac_addr_add,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v3 7/8] net/mvneta: add support for basic stats
  2018-08-31 12:59   ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                       ` (5 preceding siblings ...)
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
@ 2018-08-31 12:59     ` Andrzej Ostruszka
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
                       ` (3 subsequent siblings)
  10 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:59 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Zyta Szpak <zr@semihalf.com>

Add support for getting of basic statistics for the driver.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 47 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 975375e..2bf2e2e 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1671,6 +1671,52 @@ mvneta_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
 	return 0;
 }
 
+/**
+ * DPDK callback to get device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param stats
+ *   Stats structure output buffer.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct neta_ppio_statistics ppio_stats;
+	unsigned int ret;
+
+	if (!priv->ppio)
+		return -EPERM;
+
+	ret = neta_ppio_get_statistics(priv->ppio, &ppio_stats);
+	if (unlikely(ret)) {
+		MVNETA_LOG(ERR, "Failed to update port statistics");
+		return ret;
+	}
+
+	stats->ipackets += ppio_stats.rx_packets +
+			ppio_stats.rx_broadcast_packets +
+			ppio_stats.rx_multicast_packets;
+	stats->opackets += ppio_stats.tx_packets +
+			ppio_stats.tx_broadcast_packets +
+			ppio_stats.tx_multicast_packets;
+	stats->ibytes += ppio_stats.rx_bytes;
+	stats->obytes += ppio_stats.tx_bytes;
+	stats->imissed += ppio_stats.rx_discard +
+			  ppio_stats.rx_overrun;
+
+	stats->ierrors = ppio_stats.rx_packets_err +
+			ppio_stats.rx_errors +
+			ppio_stats.rx_crc_error;
+	stats->oerrors = ppio_stats.tx_errors;
+
+	return 0;
+}
+
 static const struct eth_dev_ops mvneta_ops = {
 	.dev_configure = mvneta_dev_configure,
 	.dev_start = mvneta_dev_start,
@@ -1685,6 +1731,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_add = mvneta_mac_addr_add,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
+	.stats_get = mvneta_stats_get,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v3 8/8] net/mvneta: add reset statistics callback
  2018-08-31 12:59   ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                       ` (6 preceding siblings ...)
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
@ 2018-08-31 12:59     ` Andrzej Ostruszka
  2018-09-10  6:11     ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                       ` (2 subsequent siblings)
  10 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-08-31 12:59 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono

From: Natalie Samsonov <nsamsono@marvell.com>

Add support for resetting of driver statistics.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 40 +++++++++++++++++++++++++++++++-------
 drivers/net/mvneta/mvneta_ethdev.h |  1 +
 2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 2bf2e2e..1bcfc68 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -1700,23 +1700,48 @@ mvneta_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 
 	stats->ipackets += ppio_stats.rx_packets +
 			ppio_stats.rx_broadcast_packets +
-			ppio_stats.rx_multicast_packets;
+			ppio_stats.rx_multicast_packets -
+			priv->prev_stats.ipackets;
 	stats->opackets += ppio_stats.tx_packets +
 			ppio_stats.tx_broadcast_packets +
-			ppio_stats.tx_multicast_packets;
-	stats->ibytes += ppio_stats.rx_bytes;
-	stats->obytes += ppio_stats.tx_bytes;
+			ppio_stats.tx_multicast_packets -
+			priv->prev_stats.opackets;
+	stats->ibytes += ppio_stats.rx_bytes - priv->prev_stats.ibytes;
+	stats->obytes += ppio_stats.tx_bytes - priv->prev_stats.obytes;
 	stats->imissed += ppio_stats.rx_discard +
-			  ppio_stats.rx_overrun;
+			  ppio_stats.rx_overrun -
+			  priv->prev_stats.imissed;
 
 	stats->ierrors = ppio_stats.rx_packets_err +
 			ppio_stats.rx_errors +
-			ppio_stats.rx_crc_error;
-	stats->oerrors = ppio_stats.tx_errors;
+			ppio_stats.rx_crc_error -
+			priv->prev_stats.ierrors;
+	stats->oerrors = ppio_stats.tx_errors - priv->prev_stats.oerrors;
 
 	return 0;
 }
 
+/**
+ * DPDK callback to clear device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_stats_reset(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	unsigned int ret;
+
+	if (!priv->ppio)
+		return;
+
+	ret = mvneta_stats_get(dev, &priv->prev_stats);
+	if (unlikely(ret))
+		RTE_LOG(ERR, PMD, "Failed to reset port statistics");
+}
+
+
 static const struct eth_dev_ops mvneta_ops = {
 	.dev_configure = mvneta_dev_configure,
 	.dev_start = mvneta_dev_start,
@@ -1732,6 +1757,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.stats_get = mvneta_stats_get,
+	.stats_reset = mvneta_stats_reset,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h
index a05566d..6aed170 100644
--- a/drivers/net/mvneta/mvneta_ethdev.h
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -77,6 +77,7 @@ struct mvneta_priv {
 	uint16_t nb_rx_queues;
 
 	uint64_t rate_max;
+	struct rte_eth_stats prev_stats;
 };
 
 /** Current log type. */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD
  2018-08-31 12:59   ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                       ` (7 preceding siblings ...)
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
@ 2018-09-10  6:11     ` Andrzej Ostruszka
  2018-09-14 16:20     ` Ferruh Yigit
  2018-09-19 15:01     ` [dpdk-dev] [PATCH v4 " Andrzej Ostruszka
  10 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-10  6:11 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nsamsono, Ferruh Yigit

On 31.08.2018 14:59, Andrzej Ostruszka wrote:
> This patch series introduces new PMD for Marvell NETA adapters (MVNETA).
> See the documentation for more info.
[...]

Hello all

I'd appreciate comments on this patch series.  So far I have received
one comment for the redundant license text when SPDX tag is present
(which is fixed already in the latest version together with a number of
other minor fixes).

Thank you in advance
Best regards
Andrzej Ostruszka

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD
  2018-08-31 12:59   ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                       ` (8 preceding siblings ...)
  2018-09-10  6:11     ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
@ 2018-09-14 16:20     ` Ferruh Yigit
  2018-09-19 15:07       ` Andrzej Ostruszka
  2018-09-19 15:01     ` [dpdk-dev] [PATCH v4 " Andrzej Ostruszka
  10 siblings, 1 reply; 96+ messages in thread
From: Ferruh Yigit @ 2018-09-14 16:20 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev; +Cc: mw, zr, tdu, nsamsono

On 8/31/2018 1:59 PM, Andrzej Ostruszka wrote:
> This patch series introduces new PMD for Marvell NETA adapters (MVNETA).
> See the documentation for more info.
> 
> It is split for easier reviewing.
> 
> v3:
>     No changes against v2, just resubmitting again to have clean patch
>     set after my faulty format-patch.  My apologies for the noise.
> 
> v2:
>   * fixed couple of checkpatch warnings
>   * removed '\n' from MVNETA_LOG invocations (appended by the macro)
>   * removed unused MVNETA_MUSDK_DMA_MEMSIZE define
>   * changed one printf into MVNETA_LOG
>   * removed __func__ from one MVNETA_LOG invocation (inserted
>     automatically by the macro)
>   * minor grammar/spelling correction in comments
>   * removed license text from file with SPDX tag (mvneta.rst)
>   * removed misleading part of comment for mvneta_shadow_txq
>   * changed authorship of the patches to the original author
> 
> Natalie Samsonov (1):
>   net/mvneta: add reset statistics callback
> 
> Zyta Szpak (7):
>   net/mvneta: add neta PMD skeleton
>   net/mvneta: add Rx/Tx support
>   net/mvneta: support for setting of MTU
>   net/mvneta: add link update
>   net/mvneta: support for promiscuous
>   net/mvneta: add MAC filtering
>   net/mvneta: add support for basic stats

Hi Andrzej,

Patchset is mostly looks good to me, there is no major issue but I have
commented on some minor issues.

Can you also set a web page patch to add new hardware to supported hw list:
http://core.dpdk.org/supported/
https://git.dpdk.org/tools/dpdk-web/

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/8] net/mvneta: add neta PMD skeleton
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
@ 2018-09-14 16:23       ` Ferruh Yigit
  2018-09-19 15:14         ` Andrzej Ostruszka
  0 siblings, 1 reply; 96+ messages in thread
From: Ferruh Yigit @ 2018-09-14 16:23 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev; +Cc: mw, zr, tdu, nsamsono

On 8/31/2018 1:59 PM, Andrzej Ostruszka wrote:
> From: Zyta Szpak <zr@semihalf.com>
> 
> Add neta pmd driver skeleton providing base for the further
> development.
> 
> Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
> Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
> Signed-off-by: Dmitri Epshtein <dima@marvell.com>
> Signed-off-by: Zyta Szpak <zr@semihalf.com>
> Signed-off-by: Andrzej Ostruszka <amo@semihalf.com>
<...>

> --- /dev/null
> +++ b/doc/guides/nics/features/mvneta.ini
> @@ -0,0 +1,18 @@
> +;
> +; 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
> +Link status          = Y
For link status feature "link_update" eth_dev_ops needs to be implemented,
please either implement it or remove feature. (I saw this done later,  please
add this on relevant patch)

> +MTU update           = Y

For mtu update feature "mtu_set" eth_dev_ops needs to be implemented,
please either implement it or remove feature.  (I saw this done later,  please
add this on relevant patch)

> +Jumbo frame          = Y
> +Promiscuous mode     = Y

Promiscuous mode support is not enabled. (I saw this done later,  please add
this on relevant patch)

> +CRC offload          = Y
> +L3 checksum offload  = Y
> +L4 checksum offload  = Y

Claiming L3 & L4 cksum offload also requires data path implementation to take
care mbuf.ol_flags flags. (I saw this is done in next patch, please add this
line in next patch)
Also I can see these are presented as capabilities but shouldn't this
information passed to musdk somehow? Are they always enabled?

> +Packet type parsing  = Y

Similar to above, dev_supported_ptypes_get() is implemented but this also
requires data path implementation that fills mbuf->packet_type.  (I saw this is
done in next patch, please add this line in next patch)

> +Basic stats          = Y

Basic stats collection is not implemented in this patch.  (I saw this done
later,  please add this on relevant patch)

<...>

> +Usage example
> +^^^^^^^^^^^^^
> +
> +.. code-block:: console
> +
> +   ./testpmd --vdev=eth_mvneta,iface=eth0,iface=eth1 \

There is a limit to number of "iface" in code, does it make sense to document it?

<...>

> +#define MVNETA_RX_OFFLOADS (DEV_RX_OFFLOAD_JUMBO_FRAME | \
> +			  DEV_RX_OFFLOAD_CRC_STRIP | \

CRC_STRIP flag removed in next-net

<...>

> +
> +	if (!(dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_CRC_STRIP)) {
> +		MVNETA_LOG(INFO,
> +			"L2 CRC stripping is always enabled in hw");
> +		dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CRC_STRIP;
> +	}

DEV_RX_OFFLOAD_CRC_STRIP is removed from next-net, you can remove it from
capabilities and remove above block.

<...>

> +
> +	eth_dev->data->kdrv = RTE_KDRV_NONE;
> +	eth_dev->data->dev_private = priv;
> +	eth_dev->device = &vdev->device;
> +;	eth_dev->dev_ops = &mvneta_ops;

extra ";" at the beginning of the line

<...>

> +RTE_PMD_REGISTER_VDEV(net_mvneta, pmd_mvneta_drv);
> +RTE_PMD_REGISTER_ALIAS(net_mvneta, eth_mvneta);

No need to provide alias for new PMDs

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v3 2/8] net/mvneta: add Rx/Tx support
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
@ 2018-09-14 16:24       ` Ferruh Yigit
  0 siblings, 0 replies; 96+ messages in thread
From: Ferruh Yigit @ 2018-09-14 16:24 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev; +Cc: mw, zr, tdu, nsamsono

On 8/31/2018 1:59 PM, Andrzej Ostruszka wrote:
> From: Zyta Szpak <zr@semihalf.com>
> 
> Add part of PMD for actual reception/transmission.
> 
> Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
> Signed-off-by: Dmitri Epshtein <dima@marvell.com>
> Signed-off-by: Zyta Szpak <zr@semihalf.com>
> ---
>  drivers/net/mvneta/mvneta_ethdev.c | 791 +++++++++++++++++++++++++++++++++++++
>  drivers/net/mvneta/mvneta_ethdev.h |  11 +
>  2 files changed, 802 insertions(+)

It is common in DPDK to move Rx/Tx related functions to its own file, like
mvneta_rxtx.c, that is a good logical separation which I suggest to do, but it
is up to you to have all in same file or not.

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v3 6/8] net/mvneta: add MAC filtering
  2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
@ 2018-09-14 16:24       ` Ferruh Yigit
  0 siblings, 0 replies; 96+ messages in thread
From: Ferruh Yigit @ 2018-09-14 16:24 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev; +Cc: mw, zr, tdu, nsamsono

On 8/31/2018 1:59 PM, Andrzej Ostruszka wrote:
> From: Zyta Szpak <zr@semihalf.com>
> 
> Add callbacks for adding/removing MAC addresses.
> 
> Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
> Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
> Signed-off-by: Zyta Szpak <zr@semihalf.com>

<...>

> @@ -1614,6 +1681,8 @@ static const struct eth_dev_ops mvneta_ops = {
>  	.link_update = mvneta_link_update,
>  	.promiscuous_enable = mvneta_promiscuous_enable,
>  	.promiscuous_disable = mvneta_promiscuous_disable,
> +	.mac_addr_remove = mvneta_mac_addr_remove,
> +	.mac_addr_add = mvneta_mac_addr_add,

Please announce "Unicast MAC filter" support in .ini file

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v4 0/8] Add Marvell NETA PMD
  2018-08-31 12:59   ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                       ` (9 preceding siblings ...)
  2018-09-14 16:20     ` Ferruh Yigit
@ 2018-09-19 15:01     ` Andrzej Ostruszka
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
                         ` (8 more replies)
  10 siblings, 9 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-19 15:01 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

This patch series introduces new PMD for Marvell NETA adapters (MVNETA).
See the documentation for more info.

It is split for easier reviewing.

v4:
  * rebased on top of next-net (DEV_RX_OFFLOAD_CRC_STRIP removed)
  * Rx/Tx functionality moved to new mvneta_rxtx.c file
  * removed eth_mvneta alias (and docs updated accordingly)
  * fixed additional review comments

v3:
    No changes against v2, just resubmitting again to have clean patch
    set after faulty format-patch.  My apologies for the noise.

v2:
  * fixed couple of checkpatch warnings
  * removed '\n' from MVNETA_LOG invocations (appended by the macro)
  * removed unused MVNETA_MUSDK_DMA_MEMSIZE define
  * changed one printf into MVNETA_LOG
  * removed __func__ from one MVNETA_LOG invocation (inserted
    automatically by the macro)
  * minor grammar/spelling correction in comments
  * removed license text from file with SPDX tag (mvneta.rst)
  * removed misleading part of comment for mvneta_shadow_txq
  * changed authorship of the patches to the original author

Natalie Samsonov (1):
  net/mvneta: add reset statistics callback

Zyta Szpak (7):
  net/mvneta: add neta PMD skeleton
  net/mvneta: add Rx/Tx support
  net/mvneta: support for setting of MTU
  net/mvneta: add link update
  net/mvneta: support for promiscuous
  net/mvneta: add MAC filtering
  net/mvneta: add support for basic stats

 MAINTAINERS                                   |    8 +
 config/common_base                            |    5 +
 devtools/test-build.sh                        |    2 +
 doc/guides/nics/features/mvneta.ini           |   19 +
 doc/guides/nics/mvneta.rst                    |  161 ++++
 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                |   28 +
 drivers/net/mvneta/mvneta_ethdev.c            | 1041 +++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h            |   80 ++
 drivers/net/mvneta/mvneta_rxtx.c              |  850 ++++++++++++++++++++
 drivers/net/mvneta/mvneta_rxtx.h              |  168 ++++
 drivers/net/mvneta/rte_pmd_mvneta_version.map |    3 +
 mk/rte.app.mk                                 |    7 +-
 18 files changed, 2422 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/mvneta_rxtx.c
 create mode 100644 drivers/net/mvneta/mvneta_rxtx.h
 create mode 100644 drivers/net/mvneta/rte_pmd_mvneta_version.map

-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v4 1/8] net/mvneta: add neta PMD skeleton
  2018-09-19 15:01     ` [dpdk-dev] [PATCH v4 " Andrzej Ostruszka
@ 2018-09-19 15:01       ` Andrzej Ostruszka
  2018-09-19 16:19         ` Stephen Hemminger
  2018-09-19 16:28         ` Stephen Hemminger
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
                         ` (7 subsequent siblings)
  8 siblings, 2 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-19 15:01 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

From: Zyta Szpak <zr@semihalf.com>

Add neta pmd driver skeleton providing base for the further
development.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
Signed-off-by: Andrzej Ostruszka <amo@semihalf.com>
---
 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            | 651 ++++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h            |  75 +++
 drivers/net/mvneta/rte_pmd_mvneta_version.map |   3 +
 mk/rte.app.mk                                 |   7 +-
 16 files changed, 991 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 <zr@semihalf.com>
+M: Dmitri Epshtein <dima@marvell.com>
+M: Natalie Samsonov <nsamsono@marvell.com>
+F: drivers/net/mvneta/
+F: doc/guides/nics/mvneta.rst
+F: doc/guides/nics/features/mvneta.ini
+
 Mellanox mlx4
 M: Matan Azrad <matan@mellanox.com>
 M: Shahaf Shuler <shahafs@mellanox.com>
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 () # <directory> <target> <options>
 		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 <https://extranet.marvell.com>`_. 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 <linux_gsg>` 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=<toolchain>/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=<musdk>/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..2dd684b
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -0,0 +1,651 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Marvell International Ltd.
+ * Copyright(c) 2018 Semihalf.
+ * All rights reserved.
+ */
+
+#include <rte_ethdev_driver.h>
+#include <rte_kvargs.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_bus_vdev.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <rte_mvep_common.h>
+
+#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 private device structure.
+ *
+ * @param dev_name
+ *   Pointer to the port name passed in the initialization parameters.
+ *
+ * @return
+ *   Pointer to the newly allocated private device structure.
+ */
+static struct mvneta_priv *
+mvneta_priv_create(const char *dev_name)
+{
+	struct mvneta_priv *priv;
+
+	priv = rte_zmalloc_socket(dev_name, sizeof(*priv), 0, rte_socket_id());
+	if (!priv)
+		return NULL;
+
+	return priv;
+}
+
+/**
+ * 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 = mvneta_priv_create(name);
+
+	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_dev:
+	rte_eth_dev_release_port(eth_dev);
+out_free_priv:
+	rte_free(priv);
+
+	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 <drivers/mv_neta.h>
+#include <drivers/mv_neta_ppio.h>
+
+/** 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
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v4 2/8] net/mvneta: add Rx/Tx support
  2018-09-19 15:01     ` [dpdk-dev] [PATCH v4 " Andrzej Ostruszka
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
@ 2018-09-19 15:01       ` Andrzej Ostruszka
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
                         ` (6 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-19 15:01 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

From: Zyta Szpak <zr@semihalf.com>

Add part of PMD for actual reception/transmission.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |   3 +
 doc/guides/nics/mvneta.rst          |   4 +
 drivers/net/mvneta/Makefile         |   2 +-
 drivers/net/mvneta/meson.build      |   3 +-
 drivers/net/mvneta/mvneta_ethdev.c  |  51 ++-
 drivers/net/mvneta/mvneta_ethdev.h  |   4 +
 drivers/net/mvneta/mvneta_rxtx.c    | 850 ++++++++++++++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_rxtx.h    | 168 +++++++
 8 files changed, 1080 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/mvneta/mvneta_rxtx.c
 create mode 100644 drivers/net/mvneta/mvneta_rxtx.h

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index ba6fe4b..0a89e2f 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -7,5 +7,8 @@
 Speed capabilities   = Y
 Jumbo frame          = Y
 CRC offload          = Y
+L3 checksum offload  = Y
+L4 checksum offload  = Y
+Packet type parsing  = Y
 ARMv8                = Y
 Usage doc            = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index bf08417..9d25c40 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -27,9 +27,13 @@ Features of the MVNETA PMD are:
 
 - Start/stop
 - tx/rx_queue_setup
+- tx/rx_burst
 - Speed capabilities
 - Jumbo frame
 - CRC offload
+- L3 checksum offload
+- L4 checksum offload
+- Packet type parsing
 
 
 Limitations
diff --git a/drivers/net/mvneta/Makefile b/drivers/net/mvneta/Makefile
index 149992e..349f550 100644
--- a/drivers/net/mvneta/Makefile
+++ b/drivers/net/mvneta/Makefile
@@ -37,6 +37,6 @@ 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
+SRCS-$(CONFIG_RTE_LIBRTE_MVNETA_PMD) += mvneta_ethdev.c mvneta_rxtx.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/mvneta/meson.build b/drivers/net/mvneta/meson.build
index 2f31954..c0b1bce 100644
--- a/drivers/net/mvneta/meson.build
+++ b/drivers/net/mvneta/meson.build
@@ -21,7 +21,8 @@ else
 endif
 
 sources = files(
-	'mvneta_ethdev.c'
+	'mvneta_ethdev.c',
+	'mvneta_rxtx.c'
 )
 
 deps += ['cfgfile', 'common_mvep']
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 2dd684b..3d6f97b 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -6,8 +6,6 @@
 
 #include <rte_ethdev_driver.h>
 #include <rte_kvargs.h>
-#include <rte_log.h>
-#include <rte_malloc.h>
 #include <rte_bus_vdev.h>
 
 #include <stdio.h>
@@ -23,7 +21,7 @@
 
 #include <rte_mvep_common.h>
 
-#include "mvneta_ethdev.h"
+#include "mvneta_rxtx.h"
 
 
 #define MVNETA_IFACE_NAME_ARG "iface"
@@ -308,6 +306,18 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 		priv->uc_mc_flushed = 1;
 	}
 
+	/* Allocate buffers */
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+		int num = rxq->size;
+
+		ret = mvneta_buffs_alloc(priv, rxq, &num);
+		if (ret || num != rxq->size) {
+			rte_free(rxq);
+			return ret;
+		}
+	}
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up");
@@ -318,6 +328,8 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 	for (i = 0; i < dev->data->nb_tx_queues; i++)
 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
 
+	mvneta_set_tx_function(dev);
+
 	return 0;
 
 out:
@@ -336,11 +348,25 @@ static void
 mvneta_dev_stop(struct rte_eth_dev *dev)
 {
 	struct mvneta_priv *priv = dev->data->dev_private;
+	int i;
 
 	if (!priv->ppio)
 		return;
 
 	mvneta_dev_set_link_down(dev);
+	MVNETA_LOG(INFO, "Flushing rx queues");
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+
+		mvneta_rx_queue_flush(rxq);
+	}
+
+	MVNETA_LOG(INFO, "Flushing tx queues");
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		struct mvneta_txq *txq = dev->data->tx_queues[i];
+
+		mvneta_tx_queue_flush(txq);
+	}
 
 	neta_ppio_deinit(priv->ppio);
 
@@ -357,9 +383,20 @@ static void
 mvneta_dev_close(struct rte_eth_dev *dev)
 {
 	struct mvneta_priv *priv = dev->data->dev_private;
+	int i;
 
 	if (priv->ppio)
 		mvneta_dev_stop(dev);
+
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		mvneta_rx_queue_release(dev->data->rx_queues[i]);
+		dev->data->rx_queues[i] = NULL;
+	}
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		mvneta_tx_queue_release(dev->data->tx_queues[i]);
+		dev->data->tx_queues[i] = NULL;
+	}
 }
 
 /**
@@ -398,6 +435,12 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_set = mvneta_mac_addr_set,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
+	.rxq_info_get = mvneta_rxq_info_get,
+	.txq_info_get = mvneta_txq_info_get,
+	.rx_queue_setup = mvneta_rx_queue_setup,
+	.rx_queue_release = mvneta_rx_queue_release,
+	.tx_queue_setup = mvneta_tx_queue_setup,
+	.tx_queue_release = mvneta_tx_queue_release,
 };
 
 /**
@@ -470,6 +513,8 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
 	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
+	eth_dev->rx_pkt_burst = mvneta_rx_pkt_burst;
+	mvneta_set_tx_function(eth_dev);
 	eth_dev->dev_ops = &mvneta_ops;
 
 	return 0;
diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h
index 8b8d726..1a78a41 100644
--- a/drivers/net/mvneta/mvneta_ethdev.h
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -7,6 +7,10 @@
 #ifndef _MVNETA_ETHDEV_H_
 #define _MVNETA_ETHDEV_H_
 
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_log.h>
+
 /*
  * container_of is defined by both DPDK and MUSDK,
  * we'll declare only one version.
diff --git a/drivers/net/mvneta/mvneta_rxtx.c b/drivers/net/mvneta/mvneta_rxtx.c
new file mode 100644
index 0000000..d5ea5a8
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_rxtx.c
@@ -0,0 +1,850 @@
+#include "mvneta_rxtx.h"
+
+uint64_t cookie_addr_high = MVNETA_COOKIE_ADDR_INVALID;
+uint16_t rx_desc_free_thresh = MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN;
+
+static inline void
+mvneta_fill_shadowq(struct mvneta_shadow_txq *sq, struct rte_mbuf *buf)
+{
+	sq->ent[sq->head].cookie = (uint64_t)buf;
+	sq->ent[sq->head].addr = buf ?
+		rte_mbuf_data_iova_default(buf) : 0;
+
+	sq->head = (sq->head + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	sq->size++;
+}
+
+static inline void
+mvneta_fill_desc(struct neta_ppio_desc *desc, struct rte_mbuf *buf)
+{
+	neta_ppio_outq_desc_reset(desc);
+	neta_ppio_outq_desc_set_phys_addr(desc, rte_pktmbuf_iova(buf));
+	neta_ppio_outq_desc_set_pkt_offset(desc, 0);
+	neta_ppio_outq_desc_set_pkt_len(desc, rte_pktmbuf_data_len(buf));
+}
+
+/**
+ * Release already sent buffers to mempool.
+ *
+ * @param ppio
+ *   Pointer to the port structure.
+ * @param sq
+ *   Pointer to the shadow queue.
+ * @param qid
+ *   Queue id number.
+ * @param force
+ *   Force releasing packets.
+ */
+static inline void
+mvneta_sent_buffers_free(struct neta_ppio *ppio,
+			 struct mvneta_shadow_txq *sq, int qid)
+{
+	struct neta_buff_inf *entry;
+	uint16_t nb_done = 0;
+	int i;
+	int tail = sq->tail;
+
+	neta_ppio_get_num_outq_done(ppio, qid, &nb_done);
+
+	if (nb_done > sq->size) {
+		MVNETA_LOG(ERR, "nb_done: %d, sq->size %d",
+			   nb_done, sq->size);
+		return;
+	}
+
+	for (i = 0; i < nb_done; i++) {
+		entry = &sq->ent[tail];
+
+		if (unlikely(!entry->addr)) {
+			MVNETA_LOG(DEBUG,
+				"Shadow memory @%d: cookie(%lx), pa(%lx)!",
+				tail, (u64)entry->cookie,
+				(u64)entry->addr);
+			tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+			continue;
+		}
+
+		struct rte_mbuf *mbuf;
+
+		mbuf = (struct rte_mbuf *)
+			   (cookie_addr_high | entry->cookie);
+		rte_pktmbuf_free(mbuf);
+		tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+
+	sq->tail = tail;
+	sq->size -= nb_done;
+}
+
+/**
+ * Return packet type information and l3/l4 offsets.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ * @param l3_offset
+ *   l3 packet offset.
+ * @param l4_offset
+ *   l4 packet offset.
+ *
+ * @return
+ *   Packet type information.
+ */
+static inline uint64_t
+mvneta_desc_to_packet_type_and_offset(struct neta_ppio_desc *desc,
+				    uint8_t *l3_offset, uint8_t *l4_offset)
+{
+	enum neta_inq_l3_type l3_type;
+	enum neta_inq_l4_type l4_type;
+	uint64_t packet_type;
+
+	neta_ppio_inq_desc_get_l3_info(desc, &l3_type, l3_offset);
+	neta_ppio_inq_desc_get_l4_info(desc, &l4_type, l4_offset);
+
+	packet_type = RTE_PTYPE_L2_ETHER;
+
+	if (NETA_RXD_GET_VLAN_INFO(desc))
+		packet_type |= RTE_PTYPE_L2_ETHER_VLAN;
+
+	switch (l3_type) {
+	case NETA_INQ_L3_TYPE_IPV4_BAD:
+	case NETA_INQ_L3_TYPE_IPV4_OK:
+		packet_type |= RTE_PTYPE_L3_IPV4;
+		break;
+	case NETA_INQ_L3_TYPE_IPV6:
+		packet_type |= RTE_PTYPE_L3_IPV6;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l3 packet type");
+		break;
+	}
+
+	switch (l4_type) {
+	case NETA_INQ_L4_TYPE_TCP:
+		packet_type |= RTE_PTYPE_L4_TCP;
+		break;
+	case NETA_INQ_L4_TYPE_UDP:
+		packet_type |= RTE_PTYPE_L4_UDP;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l4 packet type");
+		break;
+	}
+
+	return packet_type;
+}
+
+/**
+ * Prepare offload information.
+ *
+ * @param ol_flags
+ *   Offload flags.
+ * @param packet_type
+ *   Packet type bitfield.
+ * @param l3_type
+ *   Pointer to the neta_ouq_l3_type structure.
+ * @param l4_type
+ *   Pointer to the neta_outq_l4_type structure.
+ * @param gen_l3_cksum
+ *   Will be set to 1 in case l3 checksum is computed.
+ * @param l4_cksum
+ *   Will be set to 1 in case l4 checksum is computed.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_prepare_proto_info(uint64_t ol_flags, uint32_t packet_type,
+			enum neta_outq_l3_type *l3_type,
+			enum neta_outq_l4_type *l4_type,
+			int *gen_l3_cksum,
+			int *gen_l4_cksum)
+{
+	/*
+	 * Based on ol_flags prepare information
+	 * for neta_ppio_outq_desc_set_proto_info() which setups descriptor
+	 * for offloading.
+	 */
+	if (ol_flags & PKT_TX_IPV4) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV4;
+		*gen_l3_cksum = ol_flags & PKT_TX_IP_CKSUM ? 1 : 0;
+	} else if (ol_flags & PKT_TX_IPV6) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV6;
+		/* no checksum for ipv6 header */
+		*gen_l3_cksum = 0;
+	} else {
+		/* if something different then stop processing */
+		return -1;
+	}
+
+	ol_flags &= PKT_TX_L4_MASK;
+	if ((packet_type & RTE_PTYPE_L4_TCP) &&
+	    ol_flags == PKT_TX_TCP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_TCP;
+		*gen_l4_cksum = 1;
+	} else if ((packet_type & RTE_PTYPE_L4_UDP) &&
+		   ol_flags == PKT_TX_UDP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_UDP;
+		*gen_l4_cksum = 1;
+	} else {
+		*l4_type = NETA_OUTQ_L4_TYPE_OTHER;
+		/* no checksum for other type */
+		*gen_l4_cksum = 0;
+	}
+
+	return 0;
+}
+
+/**
+ * Get offload information from the received packet descriptor.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ *
+ * @return
+ *   Mbuf offload flags.
+ */
+static inline uint64_t
+mvneta_desc_to_ol_flags(struct neta_ppio_desc *desc)
+{
+	uint64_t flags;
+	enum neta_inq_desc_status status;
+
+	status = neta_ppio_inq_desc_get_l3_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags = PKT_RX_IP_CKSUM_BAD;
+	else
+		flags = PKT_RX_IP_CKSUM_GOOD;
+
+	status = neta_ppio_inq_desc_get_l4_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags |= PKT_RX_L4_CKSUM_BAD;
+	else
+		flags |= PKT_RX_L4_CKSUM_GOOD;
+
+	return flags;
+}
+
+/**
+ * DPDK callback for transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts];
+
+	int i, ret, bytes_sent = 0;
+	uint16_t num, sq_free_size;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	if (unlikely(!nb_pkts || !q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+	if (unlikely(nb_pkts > sq_free_size)) {
+		MVNETA_LOG(DEBUG,
+			"No room in shadow queue for %d packets! %d packets will be sent.",
+			nb_pkts, sq_free_size);
+		nb_pkts = sq_free_size;
+	}
+
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		/* Fill first mbuf info in shadow queue */
+		mvneta_fill_shadowq(sq, mbuf);
+		mvneta_fill_desc(&descs[i], mbuf);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[i], l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = nb_pkts;
+	neta_ppio_send(q->priv->ppio, q->queue_id, descs, &nb_pkts);
+
+
+	/* number of packets that were not sent */
+	if (unlikely(num > nb_pkts)) {
+		for (i = nb_pkts; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE + sq->head - 1) &
+				MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = cookie_addr_high | sq->ent[sq->head].cookie;
+			bytes_sent -=
+				rte_pktmbuf_pkt_len((struct rte_mbuf *)addr);
+		}
+		sq->size -= num - nb_pkts;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/** DPDK callback for S/G transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_sg_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts * NETA_PPIO_DESC_NUM_FRAGS];
+	struct neta_ppio_sg_pkts pkts;
+	uint8_t frags[nb_pkts];
+	int i, j, ret, bytes_sent = 0;
+	int tail, tail_first;
+	uint16_t num, sq_free_size;
+	uint16_t nb_segs, total_descs = 0;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	pkts.frags = frags;
+	pkts.num = 0;
+
+	if (unlikely(!q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+	/* Save shadow queue free size */
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+
+	tail = 0;
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		struct rte_mbuf *seg = NULL;
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		nb_segs = mbuf->nb_segs;
+		total_descs += nb_segs;
+
+		/*
+		 * Check if total_descs does not exceed
+		 * shadow queue free size
+		 */
+		if (unlikely(total_descs > sq_free_size)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(DEBUG,
+				"No room in shadow queue for %d packets! "
+				"%d packets will be sent.",
+				nb_pkts, i);
+			break;
+		}
+
+
+		/* Check if nb_segs does not exceed the max nb of desc per
+		 * fragmented packet
+		 */
+		if (unlikely(nb_segs > NETA_PPIO_DESC_NUM_FRAGS)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(ERR,
+				"Too many segments. Packet won't be sent.");
+			break;
+		}
+
+		pkts.frags[pkts.num] = nb_segs;
+		pkts.num++;
+		tail_first = tail;
+
+		seg = mbuf;
+		for (j = 0; j < nb_segs - 1; j++) {
+			/* For the subsequent segments, set shadow queue
+			 * buffer to NULL
+			 */
+			mvneta_fill_shadowq(sq, NULL);
+			mvneta_fill_desc(&descs[tail], seg);
+
+			tail++;
+			seg = seg->next;
+		}
+		/* Put first mbuf info in last shadow queue entry */
+		mvneta_fill_shadowq(sq, mbuf);
+		/* Update descriptor with last segment */
+		mvneta_fill_desc(&descs[tail++], seg);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[tail_first],
+						   l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = total_descs;
+	neta_ppio_send_sg(q->priv->ppio, q->queue_id, descs, &total_descs,
+			  &pkts);
+
+	/* number of packets that were not sent */
+	if (unlikely(num > total_descs)) {
+		for (i = total_descs; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE +
+					sq->head - 1) &
+					MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = sq->ent[sq->head].cookie;
+			if (addr) {
+				struct rte_mbuf *mbuf;
+
+				mbuf = (struct rte_mbuf *)
+						(cookie_addr_high | addr);
+				bytes_sent -= rte_pktmbuf_pkt_len(mbuf);
+			}
+		}
+		sq->size -= num - total_descs;
+		nb_pkts = pkts.num;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/**
+ * Set tx burst function according to offload flag
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+void
+mvneta_set_tx_function(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	/* Use a simple Tx queue (no offloads, no multi segs) if possible */
+	if (priv->multiseg) {
+		MVNETA_LOG(INFO, "Using multi-segment tx callback");
+		dev->tx_pkt_burst = mvneta_tx_sg_pkt_burst;
+	} else {
+		MVNETA_LOG(INFO, "Using single-segment tx callback");
+		dev->tx_pkt_burst = mvneta_tx_pkt_burst;
+	}
+}
+
+/**
+ * DPDK callback for receive.
+ *
+ * @param rxq
+ *   Generic pointer to the receive queue.
+ * @param rx_pkts
+ *   Array to store received packets.
+ * @param nb_pkts
+ *   Maximum number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully received.
+ */
+uint16_t
+mvneta_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_rxq *q = rxq;
+	struct neta_ppio_desc descs[nb_pkts];
+	int i, ret, rx_done = 0, rx_dropped = 0;
+
+	if (unlikely(!q || !q->priv->ppio))
+		return 0;
+
+	ret = neta_ppio_recv(q->priv->ppio, q->queue_id,
+			descs, &nb_pkts);
+
+	if (unlikely(ret < 0)) {
+		MVNETA_LOG(ERR, "Failed to receive packets");
+		return 0;
+	}
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf;
+		uint8_t l3_offset, l4_offset;
+		enum neta_inq_desc_status status;
+		uint64_t addr;
+
+		addr = cookie_addr_high |
+			neta_ppio_inq_desc_get_cookie(&descs[i]);
+		mbuf = (struct rte_mbuf *)addr;
+
+		rte_pktmbuf_reset(mbuf);
+
+		/* drop packet in case of mac, overrun or resource error */
+		status = neta_ppio_inq_desc_get_l2_pkt_error(&descs[i]);
+		if (unlikely(status != NETA_DESC_ERR_OK)) {
+			/* Release the mbuf to the mempool since
+			 * it won't be transferred to tx path
+			 */
+			rte_pktmbuf_free(mbuf);
+			q->drop_mac++;
+			rx_dropped++;
+			continue;
+		}
+
+		mbuf->data_off += MVNETA_PKT_EFFEC_OFFS;
+		mbuf->pkt_len = neta_ppio_inq_desc_get_pkt_len(&descs[i]);
+		mbuf->data_len = mbuf->pkt_len;
+		mbuf->port = q->port_id;
+		mbuf->packet_type =
+			mvneta_desc_to_packet_type_and_offset(&descs[i],
+								&l3_offset,
+								&l4_offset);
+		mbuf->l2_len = l3_offset;
+		mbuf->l3_len = l4_offset - l3_offset;
+
+		if (likely(q->cksum_enabled))
+			mbuf->ol_flags = mvneta_desc_to_ol_flags(&descs[i]);
+
+		rx_pkts[rx_done++] = mbuf;
+		q->bytes_recv += mbuf->pkt_len;
+	}
+	q->pkts_processed += rx_done + rx_dropped;
+
+	if (q->pkts_processed > rx_desc_free_thresh) {
+		int buf_to_refill = rx_desc_free_thresh;
+
+		ret = mvneta_buffs_alloc(q->priv, q, &buf_to_refill);
+		if (ret)
+			MVNETA_LOG(ERR, "Refill failed");
+		q->pkts_processed -= buf_to_refill;
+	}
+
+	return rx_done;
+}
+
+/**
+ * DPDK callback to configure the receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   RX queue index.
+ * @param desc
+ *   Number of descriptors to configure in queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Thresholds parameters (unused_).
+ * @param mp
+ *   Memory pool for buffer allocations.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+int
+mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket,
+		      const struct rte_eth_rxconf *conf __rte_unused,
+		      struct rte_mempool *mp)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_rxq *rxq;
+	uint32_t frame_size, buf_size = rte_pktmbuf_data_room_size(mp);
+	uint32_t max_rx_pkt_len = dev->data->dev_conf.rxmode.max_rx_pkt_len;
+
+	frame_size = buf_size - RTE_PKTMBUF_HEADROOM - MVNETA_PKT_EFFEC_OFFS;
+
+	if (frame_size < max_rx_pkt_len) {
+		MVNETA_LOG(ERR,
+			"Mbuf size must be increased to %u bytes to hold up "
+			"to %u bytes of data.",
+			buf_size + max_rx_pkt_len - frame_size,
+			max_rx_pkt_len);
+		dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
+		MVNETA_LOG(INFO, "Setting max rx pkt len to %u",
+			dev->data->dev_conf.rxmode.max_rx_pkt_len);
+	}
+
+	if (dev->data->rx_queues[idx]) {
+		rte_free(dev->data->rx_queues[idx]);
+		dev->data->rx_queues[idx] = NULL;
+	}
+
+	rxq = rte_zmalloc_socket("rxq", sizeof(*rxq), 0, socket);
+	if (!rxq)
+		return -ENOMEM;
+
+	rxq->priv = priv;
+	rxq->mp = mp;
+	rxq->cksum_enabled = dev->data->dev_conf.rxmode.offloads &
+			     DEV_RX_OFFLOAD_IPV4_CKSUM;
+	rxq->queue_id = idx;
+	rxq->port_id = dev->data->port_id;
+	rxq->size = desc;
+	rx_desc_free_thresh = RTE_MIN(rx_desc_free_thresh, (desc / 2));
+	priv->ppio_params.inqs_params.tcs_params[MRVL_NETA_DEFAULT_TC].size =
+		desc;
+
+	dev->data->rx_queues[idx] = rxq;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to release the receive queue.
+ *
+ * @param rxq
+ *   Generic receive queue pointer.
+ */
+void
+mvneta_rx_queue_release(void *rxq)
+{
+	struct mvneta_rxq *q = rxq;
+
+	if (!q)
+		return;
+
+	/* If dev_stop was called already, mbufs are already
+	 * returned to mempool and ppio is deinitialized.
+	 * Skip this step.
+	 */
+
+	if (q->priv->ppio)
+		mvneta_rx_queue_flush(q);
+
+	rte_free(rxq);
+}
+
+/**
+ * DPDK callback to configure the transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   Transmit queue index.
+ * @param desc
+ *   Number of descriptors to configure in the queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Tx queue configuration parameters.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+int
+mvneta_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket, const struct rte_eth_txconf *conf)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_txq *txq;
+
+	if (dev->data->tx_queues[idx]) {
+		rte_free(dev->data->tx_queues[idx]);
+		dev->data->tx_queues[idx] = NULL;
+	}
+
+	txq = rte_zmalloc_socket("txq", sizeof(*txq), 0, socket);
+	if (!txq)
+		return -ENOMEM;
+
+	txq->priv = priv;
+	txq->queue_id = idx;
+	txq->port_id = dev->data->port_id;
+	txq->tx_deferred_start = conf->tx_deferred_start;
+	dev->data->tx_queues[idx] = txq;
+
+	priv->ppio_params.outqs_params.outqs_params[idx].size = desc;
+	priv->ppio_params.outqs_params.outqs_params[idx].weight = 1;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to release the transmit queue.
+ *
+ * @param txq
+ *   Generic transmit queue pointer.
+ */
+void
+mvneta_tx_queue_release(void *txq)
+{
+	struct mvneta_txq *q = txq;
+
+	if (!q)
+		return;
+
+	rte_free(q);
+}
+
+/**
+ * Return mbufs to mempool.
+ *
+ * @param rxq
+ *    Pointer to rx queue structure
+ * @param desc
+ *    Array of rx descriptors
+ */
+static void
+mvneta_recv_buffs_free(struct neta_ppio_desc *desc, uint16_t num)
+{
+	uint64_t addr;
+	uint8_t i;
+
+	for (i = 0; i < num; i++) {
+		if (desc) {
+			addr = cookie_addr_high |
+					neta_ppio_inq_desc_get_cookie(desc);
+			if (addr)
+				rte_pktmbuf_free((struct rte_mbuf *)addr);
+			desc++;
+		}
+	}
+}
+
+/**
+ * Flush single receive queue.
+ *
+ * @param rxq
+ *   Pointer to rx queue structure.
+ * @param descs
+ *   Array of rx descriptors
+ */
+void
+mvneta_rx_queue_flush(struct mvneta_rxq *rxq)
+{
+	struct neta_ppio_desc *descs;
+	struct neta_buff_inf *bufs;
+	uint16_t num;
+	int ret, i;
+
+	descs = rte_malloc("rxdesc", MRVL_NETA_RXD_MAX * sizeof(*descs), 0);
+	bufs = rte_malloc("buffs", MRVL_NETA_RXD_MAX * sizeof(*bufs), 0);
+
+	do {
+		num = MRVL_NETA_RXD_MAX;
+		ret = neta_ppio_recv(rxq->priv->ppio,
+				     rxq->queue_id,
+				     descs, &num);
+		mvneta_recv_buffs_free(descs, num);
+	} while (ret == 0 && num);
+
+	rxq->pkts_processed = 0;
+
+	num = MRVL_NETA_RXD_MAX;
+
+	neta_ppio_inq_get_all_buffs(rxq->priv->ppio, rxq->queue_id, bufs, &num);
+	MVNETA_LOG(INFO, "freeing %u unused bufs.", num);
+
+	for (i = 0; i < num; i++) {
+		uint64_t addr;
+		if (bufs[i].cookie) {
+			addr = cookie_addr_high | bufs[i].cookie;
+			rte_pktmbuf_free((struct rte_mbuf *)addr);
+		}
+	}
+
+	rte_free(descs);
+	rte_free(bufs);
+}
+
+/**
+ * Flush single transmit queue.
+ *
+ * @param txq
+ *     Pointer to tx queue structure
+ */
+void
+mvneta_tx_queue_flush(struct mvneta_txq *txq)
+{
+	struct mvneta_shadow_txq *sq = &txq->shadow_txq;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(txq->priv->ppio, sq,
+					 txq->queue_id);
+
+	/* free the rest of them */
+	while (sq->tail != sq->head) {
+		uint64_t addr = cookie_addr_high |
+			sq->ent[sq->tail].cookie;
+		rte_pktmbuf_free((struct rte_mbuf *)addr);
+		sq->tail = (sq->tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+	memset(sq, 0, sizeof(*sq));
+}
+
+/**
+ * DPDK callback to get information about specific receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param rx_queue_id
+ *   Receive queue index.
+ * @param qinfo
+ *   Receive queue information structure.
+ */
+void
+mvneta_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		    struct rte_eth_rxq_info *qinfo)
+{
+	struct mvneta_rxq *q = dev->data->rx_queues[rx_queue_id];
+
+	qinfo->mp = q->mp;
+	qinfo->nb_desc = q->size;
+}
+
+/**
+ * DPDK callback to get information about specific transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param tx_queue_id
+ *   Transmit queue index.
+ * @param qinfo
+ *   Transmit queue information structure.
+ */
+void
+mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		    struct rte_eth_txq_info *qinfo)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	qinfo->nb_desc =
+		priv->ppio_params.outqs_params.outqs_params[tx_queue_id].size;
+}
diff --git a/drivers/net/mvneta/mvneta_rxtx.h b/drivers/net/mvneta/mvneta_rxtx.h
new file mode 100644
index 0000000..7867c18
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_rxtx.h
@@ -0,0 +1,168 @@
+#ifndef _MVNETA_RXTX_H_
+#define _MVNETA_RXTX_H_
+
+#include "mvneta_ethdev.h"
+
+#define MVNETA_PKT_EFFEC_OFFS (MRVL_NETA_PKT_OFFS + MV_MH_SIZE)
+
+#define MRVL_NETA_DEFAULT_TC 0
+
+/** Maximum number of descriptors in shadow queue. Must be power of 2 */
+#define MRVL_NETA_TX_SHADOWQ_SIZE MRVL_NETA_TXD_MAX
+
+/** Shadow queue size mask (since shadow queue size is power of 2) */
+#define MRVL_NETA_TX_SHADOWQ_MASK (MRVL_NETA_TX_SHADOWQ_SIZE - 1)
+
+/** Minimum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN	16
+
+/** Maximum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX	64
+
+#define MVNETA_COOKIE_ADDR_INVALID ~0ULL
+#define MVNETA_COOKIE_HIGH_ADDR_SHIFT	(sizeof(neta_cookie_t) * 8)
+#define MVNETA_COOKIE_HIGH_ADDR_MASK	(~0ULL << MVNETA_COOKIE_HIGH_ADDR_SHIFT)
+
+#define MVNETA_SET_COOKIE_HIGH_ADDR(addr) {				\
+	if (unlikely(cookie_addr_high == MVNETA_COOKIE_ADDR_INVALID))	\
+		cookie_addr_high =					\
+			(uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK;\
+}
+
+#define MVNETA_CHECK_COOKIE_HIGH_ADDR(addr)			\
+	((likely(cookie_addr_high ==				\
+	((uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK))) ? 1 : 0)
+
+/*
+ * To use buffer harvesting based on loopback port shadow queue structure
+ * was introduced for buffers information bookkeeping.
+ */
+struct mvneta_shadow_txq {
+	int head;           /* write index - used when sending buffers */
+	int tail;           /* read index - used when releasing buffers */
+	u16 size;           /* queue occupied size */
+	struct neta_buff_inf ent[MRVL_NETA_TX_SHADOWQ_SIZE]; /* q entries */
+};
+
+struct mvneta_rxq {
+	struct mvneta_priv *priv;
+	struct rte_mempool *mp;
+	int queue_id;
+	int port_id;
+	int size;
+	int cksum_enabled;
+	uint64_t bytes_recv;
+	uint64_t drop_mac;
+	uint64_t pkts_processed;
+};
+
+
+struct mvneta_txq {
+	struct mvneta_priv *priv;
+	int queue_id;
+	int port_id;
+	uint64_t bytes_sent;
+	struct mvneta_shadow_txq shadow_txq;
+	int tx_deferred_start;
+};
+
+extern uint64_t cookie_addr_high;
+extern uint16_t rx_desc_free_thresh;
+
+static inline int
+mvneta_buffs_refill(struct mvneta_priv *priv, struct mvneta_rxq *rxq, u16 *num)
+{
+	struct rte_mbuf *mbufs[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	struct neta_buff_inf entries[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	int i, ret;
+	uint16_t nb_desc = *num;
+
+	ret = rte_pktmbuf_alloc_bulk(rxq->mp, mbufs, nb_desc);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to allocate %u mbufs.", nb_desc);
+		*num = 0;
+		return -1;
+	}
+
+	MVNETA_SET_COOKIE_HIGH_ADDR(mbufs[0]);
+
+	for (i = 0; i < nb_desc; i++) {
+		if (unlikely(!MVNETA_CHECK_COOKIE_HIGH_ADDR(mbufs[i]))) {
+			MVNETA_LOG(ERR,
+				"mbuf virt high addr 0x%lx out of range 0x%lx",
+				(uint64_t)mbufs[i] >> 32,
+				cookie_addr_high >> 32);
+			*num = 0;
+			goto out;
+		}
+		entries[i].addr = rte_mbuf_data_iova_default(mbufs[i]);
+		entries[i].cookie = (neta_cookie_t)(uint64_t)mbufs[i];
+	}
+	neta_ppio_inq_put_buffs(priv->ppio, rxq->queue_id, entries, num);
+
+out:
+	for (i = *num; i < nb_desc; i++)
+		rte_pktmbuf_free(mbufs[i]);
+
+	return 0;
+}
+
+/**
+ * Allocate buffers from mempool
+ * and store addresses in rx descriptors.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_buffs_alloc(struct mvneta_priv *priv, struct mvneta_rxq *rxq, int *num)
+{
+	uint16_t nb_desc, nb_desc_burst, sent = 0;
+	int ret = 0;
+
+	nb_desc = *num;
+
+	do {
+		nb_desc_burst =
+			(nb_desc < MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX) ?
+			nb_desc : MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX;
+
+		ret = mvneta_buffs_refill(priv, rxq, &nb_desc_burst);
+		if (unlikely(ret || !nb_desc_burst))
+			break;
+
+		sent += nb_desc_burst;
+		nb_desc -= nb_desc_burst;
+
+	} while (nb_desc);
+
+	*num = sent;
+
+	return ret;
+}
+
+void mvneta_rx_queue_flush(struct mvneta_rxq *rxq);
+void mvneta_tx_queue_flush(struct mvneta_txq *txq);
+
+void mvneta_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+			 struct rte_eth_rxq_info *qinfo);
+void mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+			 struct rte_eth_txq_info *qinfo);
+
+void mvneta_set_tx_function(struct rte_eth_dev *dev);
+uint16_t
+mvneta_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
+
+int
+mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket,
+		      const struct rte_eth_rxconf *conf __rte_unused,
+		      struct rte_mempool *mp);
+int
+mvneta_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket, const struct rte_eth_txconf *conf);
+
+void mvneta_rx_queue_release(void *rxq);
+void mvneta_tx_queue_release(void *txq);
+
+#endif /* _MVNETA_RXTX_H_ */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v4 3/8] net/mvneta: support for setting of MTU
  2018-09-19 15:01     ` [dpdk-dev] [PATCH v4 " Andrzej Ostruszka
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
@ 2018-09-19 15:01       ` Andrzej Ostruszka
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 4/8] net/mvneta: add link update Andrzej Ostruszka
                         ` (5 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-19 15:01 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

From: Zyta Szpak <zr@semihalf.com>

Add callback for setting of MTU.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 78 +++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 0a89e2f..bc4e400 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -5,6 +5,7 @@
 ;
 [Features]
 Speed capabilities   = Y
+MTU update           = Y
 Jumbo frame          = Y
 CRC offload          = Y
 L3 checksum offload  = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index 9d25c40..55ffe57 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -30,6 +30,7 @@ Features of the MVNETA PMD are:
 - tx/rx_burst
 - Speed capabilities
 - Jumbo frame
+- MTU update
 - CRC offload
 - L3 checksum offload
 - L4 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 3d6f97b..80ab9ba 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -221,6 +221,77 @@ mvneta_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
 }
 
 /**
+ * DPDK callback to change the MTU.
+ *
+ * Setting the MTU affects hardware MRU (packets larger than the MRU
+ * will be dropped).
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param mtu
+ *   New MTU.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	uint16_t mbuf_data_size = 0; /* SW buffer size */
+	uint16_t mru;
+	int ret;
+
+	mru = MRVL_NETA_MTU_TO_MRU(mtu);
+	/*
+	 * min_rx_buf_size is equal to mbuf data size
+	 * if pmd didn't set it differently
+	 */
+	mbuf_data_size = dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM;
+	/* Prevent PMD from:
+	 * - setting mru greater than the mbuf size resulting in
+	 * hw and sw buffer size mismatch
+	 * - setting mtu that requires the support of scattered packets
+	 * when this feature has not been enabled/supported so far.
+	 */
+	if (!dev->data->scattered_rx &&
+	    (mru + MRVL_NETA_PKT_OFFS > mbuf_data_size)) {
+		mru = mbuf_data_size - MRVL_NETA_PKT_OFFS;
+		mtu = MRVL_NETA_MRU_TO_MTU(mru);
+		MVNETA_LOG(WARNING, "MTU too big, max MTU possible limitted by"
+			" current mbuf size: %u. Set MTU to %u, MRU to %u",
+			mbuf_data_size, mtu, mru);
+	}
+
+	if (mtu < ETHER_MIN_MTU || mru > MVNETA_PKT_SIZE_MAX) {
+		MVNETA_LOG(ERR, "Invalid MTU [%u] or MRU [%u]", mtu, mru);
+		return -EINVAL;
+	}
+
+	dev->data->mtu = mtu;
+	dev->data->dev_conf.rxmode.max_rx_pkt_len = mru - MV_MH_SIZE;
+
+	if (!priv->ppio)
+		/* It is OK. New MTU will be set later on mvneta_dev_start */
+		return 0;
+
+	ret = neta_ppio_set_mru(priv->ppio, mru);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MRU");
+		return ret;
+	}
+
+	ret = neta_ppio_set_mtu(priv->ppio, mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MTU");
+		return ret;
+	}
+	MVNETA_LOG(INFO, "MTU changed to %u, MRU = %u", mtu, mru);
+
+	return 0;
+}
+
+/**
  * DPDK callback to bring the link up.
  *
  * @param dev
@@ -318,6 +389,12 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 		}
 	}
 
+	ret = mvneta_mtu_set(dev, dev->data->mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to set MTU %d", dev->data->mtu);
+		goto out;
+	}
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up");
@@ -433,6 +510,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
 	.mac_addr_set = mvneta_mac_addr_set,
+	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v4 4/8] net/mvneta: add link update
  2018-09-19 15:01     ` [dpdk-dev] [PATCH v4 " Andrzej Ostruszka
                         ` (2 preceding siblings ...)
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
@ 2018-09-19 15:01       ` Andrzej Ostruszka
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
                         ` (4 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-19 15:01 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

From: Zyta Szpak <zr@semihalf.com>

Add callback for updating information about link status/info.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 71 +++++++++++++++++++++++++++++++++++++
 3 files changed, 73 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index bc4e400..581ed31 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -5,6 +5,7 @@
 ;
 [Features]
 Speed capabilities   = Y
+Link status          = Y
 MTU update           = Y
 Jumbo frame          = Y
 CRC offload          = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index 55ffe57..85cdd1d 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -31,6 +31,7 @@ Features of the MVNETA PMD are:
 - Speed capabilities
 - Jumbo frame
 - MTU update
+- Link status
 - CRC offload
 - L3 checksum offload
 - L4 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 80ab9ba..e40437f 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -477,6 +477,76 @@ mvneta_dev_close(struct rte_eth_dev *dev)
 }
 
 /**
+ * DPDK callback to retrieve physical link information.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param wait_to_complete
+ *   Wait for request completion (ignored).
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
+{
+	/*
+	 * TODO
+	 * once MUSDK provides necessary API use it here
+	 */
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct ethtool_cmd edata;
+	struct ifreq req;
+	int ret, fd, link_up;
+
+	if (!priv->ppio)
+		return -EPERM;
+
+	edata.cmd = ETHTOOL_GSET;
+
+	strcpy(req.ifr_name, dev->data->name);
+	req.ifr_data = (void *)&edata;
+
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd == -1)
+		return -EFAULT;
+	ret = ioctl(fd, SIOCETHTOOL, &req);
+	if (ret == -1) {
+		close(fd);
+		return -EFAULT;
+	}
+
+	close(fd);
+
+	switch (ethtool_cmd_speed(&edata)) {
+	case SPEED_10:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_10M;
+		break;
+	case SPEED_100:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_100M;
+		break;
+	case SPEED_1000:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_1G;
+		break;
+	case SPEED_2500:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_2_5G;
+		break;
+	default:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE;
+	}
+
+	dev->data->dev_link.link_duplex = edata.duplex ? ETH_LINK_FULL_DUPLEX :
+							 ETH_LINK_HALF_DUPLEX;
+	dev->data->dev_link.link_autoneg = edata.autoneg ? ETH_LINK_AUTONEG :
+							   ETH_LINK_FIXED;
+
+	neta_ppio_get_link_state(priv->ppio, &link_up);
+	dev->data->dev_link.link_status = link_up ? ETH_LINK_UP : ETH_LINK_DOWN;
+
+	return 0;
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -509,6 +579,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_up = mvneta_dev_set_link_up,
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
+	.link_update = mvneta_link_update,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v4 5/8] net/mvneta: support for promiscuous
  2018-09-19 15:01     ` [dpdk-dev] [PATCH v4 " Andrzej Ostruszka
                         ` (3 preceding siblings ...)
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 4/8] net/mvneta: add link update Andrzej Ostruszka
@ 2018-09-19 15:01       ` Andrzej Ostruszka
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
                         ` (3 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-19 15:01 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

From: Zyta Szpak <zr@semihalf.com>

Add callbacks for enabling/disabling of promiscuous mode.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 54 +++++++++++++++++++++++++++++++++++++
 3 files changed, 56 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 581ed31..6a140a3 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -8,6 +8,7 @@ Speed capabilities   = Y
 Link status          = Y
 MTU update           = Y
 Jumbo frame          = Y
+Promiscuous mode     = Y
 CRC offload          = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index 85cdd1d..1912c3e 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -31,6 +31,7 @@ Features of the MVNETA PMD are:
 - Speed capabilities
 - Jumbo frame
 - MTU update
+- Promiscuous mode
 - Link status
 - CRC offload
 - L3 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index e40437f..0f4dece 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -547,6 +547,58 @@ mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
 }
 
 /**
+ * DPDK callback to enable promiscuous mode.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_promiscuous_enable(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	int ret, en;
+
+	if (!priv->ppio)
+		return;
+
+	neta_ppio_get_promisc(priv->ppio, &en);
+	if (en) {
+		MVNETA_LOG(INFO, "Promiscuous already enabled");
+		return;
+	}
+
+	ret = neta_ppio_set_promisc(priv->ppio, 1);
+	if (ret)
+		MVNETA_LOG(ERR, "Failed to enable promiscuous mode");
+}
+
+/**
+ * DPDK callback to disable allmulticast mode.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_promiscuous_disable(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	int ret, en;
+
+	if (!priv->ppio)
+		return;
+
+	neta_ppio_get_promisc(priv->ppio, &en);
+	if (!en) {
+		MVNETA_LOG(INFO, "Promiscuous already disabled");
+		return;
+	}
+
+	ret = neta_ppio_set_promisc(priv->ppio, 0);
+	if (ret)
+		MVNETA_LOG(ERR, "Failed to disable promiscuous mode");
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -580,6 +632,8 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
 	.link_update = mvneta_link_update,
+	.promiscuous_enable = mvneta_promiscuous_enable,
+	.promiscuous_disable = mvneta_promiscuous_disable,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v4 6/8] net/mvneta: add MAC filtering
  2018-09-19 15:01     ` [dpdk-dev] [PATCH v4 " Andrzej Ostruszka
                         ` (4 preceding siblings ...)
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
@ 2018-09-19 15:01       ` Andrzej Ostruszka
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
                         ` (2 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-19 15:01 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

From: Zyta Szpak <zr@semihalf.com>

Add callbacks for adding/removing MAC addresses.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 69 +++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 6a140a3..59c9c36 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -9,6 +9,7 @@ Link status          = Y
 MTU update           = Y
 Jumbo frame          = Y
 Promiscuous mode     = Y
+Unicast MAC filter   = Y
 CRC offload          = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index 1912c3e..b21581b 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -32,6 +32,7 @@ Features of the MVNETA PMD are:
 - Jumbo frame
 - MTU update
 - Promiscuous mode
+- Unicast MAC filter
 - Link status
 - CRC offload
 - L3 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 0f4dece..fdd6eb0 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -599,6 +599,73 @@ mvneta_promiscuous_disable(struct rte_eth_dev *dev)
 }
 
 /**
+ * DPDK callback to remove a MAC address.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param index
+ *   MAC address index.
+ */
+static void
+mvneta_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	char buf[ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	if (!priv->ppio)
+		return;
+
+	ret = neta_ppio_remove_mac_addr(priv->ppio,
+				       dev->data->mac_addrs[index].addr_bytes);
+	if (ret) {
+		ether_format_addr(buf, sizeof(buf),
+				  &dev->data->mac_addrs[index]);
+		MVNETA_LOG(ERR, "Failed to remove mac %s", buf);
+	}
+}
+
+/**
+ * DPDK callback to add a MAC address.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param mac_addr
+ *   MAC address to register.
+ * @param index
+ *   MAC address index.
+ * @param vmdq
+ *   VMDq pool index to associate address with (unused).
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
+		  uint32_t index, uint32_t vmdq __rte_unused)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	char buf[ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	if (index == 0)
+		/* For setting index 0, mrvl_mac_addr_set() should be used.*/
+		return -1;
+
+	if (!priv->ppio)
+		return 0;
+
+	ret = neta_ppio_add_mac_addr(priv->ppio, mac_addr->addr_bytes);
+	if (ret) {
+		ether_format_addr(buf, sizeof(buf), mac_addr);
+		MVNETA_LOG(ERR, "Failed to add mac %s", buf);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -634,6 +701,8 @@ static const struct eth_dev_ops mvneta_ops = {
 	.link_update = mvneta_link_update,
 	.promiscuous_enable = mvneta_promiscuous_enable,
 	.promiscuous_disable = mvneta_promiscuous_disable,
+	.mac_addr_remove = mvneta_mac_addr_remove,
+	.mac_addr_add = mvneta_mac_addr_add,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v4 7/8] net/mvneta: add support for basic stats
  2018-09-19 15:01     ` [dpdk-dev] [PATCH v4 " Andrzej Ostruszka
                         ` (5 preceding siblings ...)
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
@ 2018-09-19 15:01       ` Andrzej Ostruszka
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
  2018-09-20  9:05       ` [dpdk-dev] [PATCH v5 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-19 15:01 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

From: Zyta Szpak <zr@semihalf.com>

Add support for getting of basic statistics for the driver.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 47 +++++++++++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 59c9c36..701eb03 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -14,5 +14,6 @@ CRC offload          = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
 Packet type parsing  = Y
+Basic stats          = Y
 ARMv8                = Y
 Usage doc            = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index b21581b..5bcf3b6 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -38,6 +38,7 @@ Features of the MVNETA PMD are:
 - L3 checksum offload
 - L4 checksum offload
 - Packet type parsing
+- Basic stats
 
 
 Limitations
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index fdd6eb0..3ea1dba 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -691,6 +691,52 @@ mvneta_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
 	return 0;
 }
 
+/**
+ * DPDK callback to get device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param stats
+ *   Stats structure output buffer.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct neta_ppio_statistics ppio_stats;
+	unsigned int ret;
+
+	if (!priv->ppio)
+		return -EPERM;
+
+	ret = neta_ppio_get_statistics(priv->ppio, &ppio_stats);
+	if (unlikely(ret)) {
+		MVNETA_LOG(ERR, "Failed to update port statistics");
+		return ret;
+	}
+
+	stats->ipackets += ppio_stats.rx_packets +
+			ppio_stats.rx_broadcast_packets +
+			ppio_stats.rx_multicast_packets;
+	stats->opackets += ppio_stats.tx_packets +
+			ppio_stats.tx_broadcast_packets +
+			ppio_stats.tx_multicast_packets;
+	stats->ibytes += ppio_stats.rx_bytes;
+	stats->obytes += ppio_stats.tx_bytes;
+	stats->imissed += ppio_stats.rx_discard +
+			  ppio_stats.rx_overrun;
+
+	stats->ierrors = ppio_stats.rx_packets_err +
+			ppio_stats.rx_errors +
+			ppio_stats.rx_crc_error;
+	stats->oerrors = ppio_stats.tx_errors;
+
+	return 0;
+}
+
 static const struct eth_dev_ops mvneta_ops = {
 	.dev_configure = mvneta_dev_configure,
 	.dev_start = mvneta_dev_start,
@@ -705,6 +751,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_add = mvneta_mac_addr_add,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
+	.stats_get = mvneta_stats_get,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v4 8/8] net/mvneta: add reset statistics callback
  2018-09-19 15:01     ` [dpdk-dev] [PATCH v4 " Andrzej Ostruszka
                         ` (6 preceding siblings ...)
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
@ 2018-09-19 15:01       ` Andrzej Ostruszka
  2018-09-20  9:05       ` [dpdk-dev] [PATCH v5 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-19 15:01 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh, Natalie Samsonov

From: Natalie Samsonov <nsamsono@marvell.com>

Add support for resetting of driver statistics.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 40 +++++++++++++++++++++++++++++++-------
 drivers/net/mvneta/mvneta_ethdev.h |  1 +
 2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 3ea1dba..40c33cd 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -720,23 +720,48 @@ mvneta_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 
 	stats->ipackets += ppio_stats.rx_packets +
 			ppio_stats.rx_broadcast_packets +
-			ppio_stats.rx_multicast_packets;
+			ppio_stats.rx_multicast_packets -
+			priv->prev_stats.ipackets;
 	stats->opackets += ppio_stats.tx_packets +
 			ppio_stats.tx_broadcast_packets +
-			ppio_stats.tx_multicast_packets;
-	stats->ibytes += ppio_stats.rx_bytes;
-	stats->obytes += ppio_stats.tx_bytes;
+			ppio_stats.tx_multicast_packets -
+			priv->prev_stats.opackets;
+	stats->ibytes += ppio_stats.rx_bytes - priv->prev_stats.ibytes;
+	stats->obytes += ppio_stats.tx_bytes - priv->prev_stats.obytes;
 	stats->imissed += ppio_stats.rx_discard +
-			  ppio_stats.rx_overrun;
+			  ppio_stats.rx_overrun -
+			  priv->prev_stats.imissed;
 
 	stats->ierrors = ppio_stats.rx_packets_err +
 			ppio_stats.rx_errors +
-			ppio_stats.rx_crc_error;
-	stats->oerrors = ppio_stats.tx_errors;
+			ppio_stats.rx_crc_error -
+			priv->prev_stats.ierrors;
+	stats->oerrors = ppio_stats.tx_errors - priv->prev_stats.oerrors;
 
 	return 0;
 }
 
+/**
+ * DPDK callback to clear device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_stats_reset(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	unsigned int ret;
+
+	if (!priv->ppio)
+		return;
+
+	ret = mvneta_stats_get(dev, &priv->prev_stats);
+	if (unlikely(ret))
+		RTE_LOG(ERR, PMD, "Failed to reset port statistics");
+}
+
+
 static const struct eth_dev_ops mvneta_ops = {
 	.dev_configure = mvneta_dev_configure,
 	.dev_start = mvneta_dev_start,
@@ -752,6 +777,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.stats_get = mvneta_stats_get,
+	.stats_reset = mvneta_stats_reset,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h
index 1a78a41..eeea31a 100644
--- a/drivers/net/mvneta/mvneta_ethdev.h
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -67,6 +67,7 @@ struct mvneta_priv {
 	uint16_t nb_rx_queues;
 
 	uint64_t rate_max;
+	struct rte_eth_stats prev_stats;
 };
 
 /** Current log type. */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD
  2018-09-14 16:20     ` Ferruh Yigit
@ 2018-09-19 15:07       ` Andrzej Ostruszka
  2018-09-19 17:39         ` Ferruh Yigit
  0 siblings, 1 reply; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-19 15:07 UTC (permalink / raw)
  To: dev

On 14.09.2018 18:20, Ferruh Yigit wrote:
> On 8/31/2018 1:59 PM, Andrzej Ostruszka wrote:
>> This patch series introduces new PMD for Marvell NETA adapters (MVNETA).
>> See the documentation for more info.
[...]
> Hi Andrzej,
> 
> Patchset is mostly looks good to me, there is no major issue but I have
> commented on some minor issues.

Thank you Ferruh for taking time to review it.  I have just pushed out
new version incorporating your suggestions.

> Can you also set a web page patch to add new hardware to supported hw list:
> http://core.dpdk.org/supported/
> https://git.dpdk.org/tools/dpdk-web/

Could you tell me what is the procedure for submitting web page patches?
 Same as for code (sending via e-mail to dev)?

Best regards
Andrzej

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/8] net/mvneta: add neta PMD skeleton
  2018-09-14 16:23       ` Ferruh Yigit
@ 2018-09-19 15:14         ` Andrzej Ostruszka
  2018-09-19 17:38           ` Ferruh Yigit
  0 siblings, 1 reply; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-19 15:14 UTC (permalink / raw)
  To: dev

On 14.09.2018 18:23, Ferruh Yigit wrote:
> On 8/31/2018 1:59 PM, Andrzej Ostruszka wrote:
[...]
> For link status feature "link_update" eth_dev_ops needs to be implemented,
> please either implement it or remove feature. (I saw this done later,  please
> add this on relevant patch)
> 
>> +MTU update           = Y
> 
> For mtu update feature "mtu_set" eth_dev_ops needs to be implemented,
> please either implement it or remove feature.  (I saw this done later,  please
> add this on relevant patch)
> 
>> +Jumbo frame          = Y
>> +Promiscuous mode     = Y
> 
> Promiscuous mode support is not enabled. (I saw this done later,  please add
> this on relevant patch)
> 
>> +CRC offload          = Y
>> +L3 checksum offload  = Y
>> +L4 checksum offload  = Y
> 
> Claiming L3 & L4 cksum offload also requires data path implementation to take
> care mbuf.ol_flags flags. (I saw this is done in next patch, please add this
> line in next patch)
> Also I can see these are presented as capabilities but shouldn't this
> information passed to musdk somehow? Are they always enabled?
> 
>> +Packet type parsing  = Y
> 
> Similar to above, dev_supported_ptypes_get() is implemented but this also
> requires data path implementation that fills mbuf->packet_type.  (I saw this is
> done in next patch, please add this line in next patch)
> 
>> +Basic stats          = Y
> 
> Basic stats collection is not implemented in this patch.  (I saw this done
> later,  please add this on relevant patch)

I have moved documentation of features to relevant patches.

> There is a limit to number of "iface" in code, does it make sense to document it?

I don't think so - there won't be a board supporting more than 4 ports.

>> +RTE_PMD_REGISTER_VDEV(net_mvneta, pmd_mvneta_drv);
>> +RTE_PMD_REGISTER_ALIAS(net_mvneta, eth_mvneta);
> 
> No need to provide alias for new PMDs

Removed.  So "eth_XXX" naming is just legacy - I see it in many drivers
that they are available both as "net_XXX" and "eth_XXX".

Best regards
Andrzej

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v4 1/8] net/mvneta: add neta PMD skeleton
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
@ 2018-09-19 16:19         ` Stephen Hemminger
  2018-09-20  7:45           ` Andrzej Ostruszka
  2018-09-19 16:28         ` Stephen Hemminger
  1 sibling, 1 reply; 96+ messages in thread
From: Stephen Hemminger @ 2018-09-19 16:19 UTC (permalink / raw)
  To: Andrzej Ostruszka; +Cc: dev, mw, zr, tdu, nadavh

On Wed, 19 Sep 2018 17:01:27 +0200
Andrzej Ostruszka <amo@semihalf.com> wrote:

> +
> +- Custom Linux Kernel sources
> +
> +  .. code-block:: console
> +
> +     git clone https://github.com/MarvellEmbeddedProcessors/linux-marvell.git -b linux-4.4.52-armada-17.10
> +

In general the rule for DPDK is that drivers in upstream DPDK must have their OS support
components upstream. You are relying on an old Linux kernel which is maybe the way embedded
works, but it really needs to be upstream first.

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v4 1/8] net/mvneta: add neta PMD skeleton
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
  2018-09-19 16:19         ` Stephen Hemminger
@ 2018-09-19 16:28         ` Stephen Hemminger
  2018-09-20  7:57           ` Andrzej Ostruszka
  1 sibling, 1 reply; 96+ messages in thread
From: Stephen Hemminger @ 2018-09-19 16:28 UTC (permalink / raw)
  To: Andrzej Ostruszka; +Cc: dev, mw, zr, tdu, nadavh

On Wed, 19 Sep 2018 17:01:27 +0200
Andrzej Ostruszka <amo@semihalf.com> wrote:

> +/**
> + * Create private device structure.
> + *
> + * @param dev_name
> + *   Pointer to the port name passed in the initialization parameters.
> + *
> + * @return
> + *   Pointer to the newly allocated private device structure.
> + */
> +static struct mvneta_priv *
> +mvneta_priv_create(const char *dev_name)
> +{
> +	struct mvneta_priv *priv;
> +
> +	priv = rte_zmalloc_socket(dev_name, sizeof(*priv), 0, rte_socket_id());
> +	if (!priv)
> +		return NULL;
> +
> +	return priv;
> +}

Why make this a function, it really doesn't add anything over just doing it inline.


> +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 = mvneta_priv_create(name);
> +
> +	if (!priv) {

nit: no blank line needed.

> +		ret = -ENOMEM;
> +		goto out_free_dev;

You have error goto's backwards.

> +	}
> +
> +	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);



> +out_free_mac:
> +	rte_free(eth_dev->data->mac_addrs);
> +out_free_dev:
> +	rte_eth_dev_release_port(eth_dev);
> +out_free_priv:
> +	rte_free(priv);

These are backwards: out_free_priv is called if ioctl fails and will
leak eth_dev port.

> +	return ret;
> +}

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/8] net/mvneta: add neta PMD skeleton
  2018-09-19 15:14         ` Andrzej Ostruszka
@ 2018-09-19 17:38           ` Ferruh Yigit
  0 siblings, 0 replies; 96+ messages in thread
From: Ferruh Yigit @ 2018-09-19 17:38 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev

On 9/19/2018 4:14 PM, Andrzej Ostruszka wrote:
> On 14.09.2018 18:23, Ferruh Yigit wrote:
>> On 8/31/2018 1:59 PM, Andrzej Ostruszka wrote:
> [...]
>> For link status feature "link_update" eth_dev_ops needs to be implemented,
>> please either implement it or remove feature. (I saw this done later,  please
>> add this on relevant patch)
>>
>>> +MTU update           = Y
>>
>> For mtu update feature "mtu_set" eth_dev_ops needs to be implemented,
>> please either implement it or remove feature.  (I saw this done later,  please
>> add this on relevant patch)
>>
>>> +Jumbo frame          = Y
>>> +Promiscuous mode     = Y
>>
>> Promiscuous mode support is not enabled. (I saw this done later,  please add
>> this on relevant patch)
>>
>>> +CRC offload          = Y
>>> +L3 checksum offload  = Y
>>> +L4 checksum offload  = Y
>>
>> Claiming L3 & L4 cksum offload also requires data path implementation to take
>> care mbuf.ol_flags flags. (I saw this is done in next patch, please add this
>> line in next patch)
>> Also I can see these are presented as capabilities but shouldn't this
>> information passed to musdk somehow? Are they always enabled?
>>
>>> +Packet type parsing  = Y
>>
>> Similar to above, dev_supported_ptypes_get() is implemented but this also
>> requires data path implementation that fills mbuf->packet_type.  (I saw this is
>> done in next patch, please add this line in next patch)
>>
>>> +Basic stats          = Y
>>
>> Basic stats collection is not implemented in this patch.  (I saw this done
>> later,  please add this on relevant patch)
> 
> I have moved documentation of features to relevant patches.
> 
>> There is a limit to number of "iface" in code, does it make sense to document it?
> 
> I don't think so - there won't be a board supporting more than 4 ports.
> 
>>> +RTE_PMD_REGISTER_VDEV(net_mvneta, pmd_mvneta_drv);
>>> +RTE_PMD_REGISTER_ALIAS(net_mvneta, eth_mvneta);
>>
>> No need to provide alias for new PMDs
> 
> Removed.  So "eth_XXX" naming is just legacy - I see it in many drivers
> that they are available both as "net_XXX" and "eth_XXX".

It was eth_xxx in the past, renamed to net_xxx and added and alias for eth_xxx
for backward compatibility. Since no one uses eth_mvneta no need to keep it.

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD
  2018-09-19 15:07       ` Andrzej Ostruszka
@ 2018-09-19 17:39         ` Ferruh Yigit
  2018-09-21 11:59           ` Andrzej Ostruszka
  0 siblings, 1 reply; 96+ messages in thread
From: Ferruh Yigit @ 2018-09-19 17:39 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev, dpdk-web

On 9/19/2018 4:07 PM, Andrzej Ostruszka wrote:
> On 14.09.2018 18:20, Ferruh Yigit wrote:
>> On 8/31/2018 1:59 PM, Andrzej Ostruszka wrote:
>>> This patch series introduces new PMD for Marvell NETA adapters (MVNETA).
>>> See the documentation for more info.
> [...]
>> Hi Andrzej,
>>
>> Patchset is mostly looks good to me, there is no major issue but I have
>> commented on some minor issues.
> 
> Thank you Ferruh for taking time to review it.  I have just pushed out
> new version incorporating your suggestions.
> 
>> Can you also set a web page patch to add new hardware to supported hw list:
>> http://core.dpdk.org/supported/
>> https://git.dpdk.org/tools/dpdk-web/
> 
> Could you tell me what is the procedure for submitting web page patches?
>  Same as for code (sending via e-mail to dev)?

Same process but different mail list: web@dpdk.org

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v4 1/8] net/mvneta: add neta PMD skeleton
  2018-09-19 16:19         ` Stephen Hemminger
@ 2018-09-20  7:45           ` Andrzej Ostruszka
  0 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-20  7:45 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev, mw, zr, tdu, nadavh

Thank you Stephen for taking a look at these patches.

On 19.09.2018 18:19, Stephen Hemminger wrote:
> On Wed, 19 Sep 2018 17:01:27 +0200
> Andrzej Ostruszka <amo@semihalf.com> wrote:
[...]
>> +     git clone https://github.com/MarvellEmbeddedProcessors/linux-marvell.git -b linux-4.4.52-armada-17.10
>> +
> 
> In general the rule for DPDK is that drivers in upstream DPDK must have their OS support
> components upstream. You are relying on an old Linux kernel which is maybe the way embedded
> works, but it really needs to be upstream first.

If this rule holds then there are some exceptions e.g. mvpp2 (in current
release using the same version of kernel) so accepting this driver will
not brake this rule any more than it is now.

AFAIK Marvell is using some parts that are not upstreamable so it will
be always a custom kernel - but I'm not competent enough to claim that
authoritatively.  In mvpp2 we have just recently switched to newer
kernel (just applied to next-net) and with enough of testing mvneta will
switch to it too.

So I hope this is not a blocker.

Best regards
Andrzej

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v4 1/8] net/mvneta: add neta PMD skeleton
  2018-09-19 16:28         ` Stephen Hemminger
@ 2018-09-20  7:57           ` Andrzej Ostruszka
  0 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-20  7:57 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev, mw, zr, tdu, nadavh

On 19.09.2018 18:28, Stephen Hemminger wrote:
> On Wed, 19 Sep 2018 17:01:27 +0200
> Andrzej Ostruszka <amo@semihalf.com> wrote:
> 
>> +/**
>> + * Create private device structure.
>> + *
>> + * @param dev_name
>> + *   Pointer to the port name passed in the initialization parameters.
>> + *
>> + * @return
>> + *   Pointer to the newly allocated private device structure.
>> + */
>> +static struct mvneta_priv *
>> +mvneta_priv_create(const char *dev_name)
>> +{
>> +	struct mvneta_priv *priv;
>> +
>> +	priv = rte_zmalloc_socket(dev_name, sizeof(*priv), 0, rte_socket_id());
>> +	if (!priv)
>> +		return NULL;
>> +
>> +	return priv;
>> +}
> 
> Why make this a function, it really doesn't add anything over just doing it inline.

True.  Removed it.

>> +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 = mvneta_priv_create(name);
>> +
>> +	if (!priv) {
> 
> nit: no blank line needed.
> 
>> +		ret = -ENOMEM;
>> +		goto out_free_dev;
> 
> You have error goto's backwards.
> 
>> +	}
>> +
>> +	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);
> 
> 
> 
>> +out_free_mac:
>> +	rte_free(eth_dev->data->mac_addrs);
>> +out_free_dev:
>> +	rte_eth_dev_release_port(eth_dev);
>> +out_free_priv:
>> +	rte_free(priv);
> 
> These are backwards: out_free_priv is called if ioctl fails and will
> leak eth_dev port.

Good catch - 'out_free_priv' should go before 'out_free_dev'!  Thank
you.  The problem is not for the case of ioctl failure but I guess that
is just a wording lapsus.

Best regards
Andrzej

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v5 0/8] Add Marvell NETA PMD
  2018-09-19 15:01     ` [dpdk-dev] [PATCH v4 " Andrzej Ostruszka
                         ` (7 preceding siblings ...)
  2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
@ 2018-09-20  9:05       ` Andrzej Ostruszka
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
                           ` (8 more replies)
  8 siblings, 9 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-20  9:05 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

This patch series introduces new PMD for Marvell NETA adapters (MVNETA).
See the documentation for more info.

It is split for easier reviewing.

v5:
  * fixed wrong order of clenup in mvneta_eth_dev_create()
  * inlined one auxilary function (mvneta_priv_create())

v4:
  * rebased on top of next-net (DEV_RX_OFFLOAD_CRC_STRIP removed)
  * Rx/Tx functionality moved to new mvneta_rxtx.c file
  * removed eth_mvneta alias (and docs updated accordingly)
  * fixed additional review comments

v3:
    No changes against v2, just resubmitting again to have clean patch
    set after faulty format-patch.  My apologies for the noise.

v2:
  * fixed couple of checkpatch warnings
  * removed '\n' from MVNETA_LOG invocations (appended by the macro)
  * removed unused MVNETA_MUSDK_DMA_MEMSIZE define
  * changed one printf into MVNETA_LOG
  * removed __func__ from one MVNETA_LOG invocation (inserted
    automatically by the macro)
  * minor grammar/spelling correction in comments
  * removed license text from file with SPDX tag (mvneta.rst)
  * removed misleading part of comment for mvneta_shadow_txq
  * changed authorship of the patches to the original author

Natalie Samsonov (1):
  net/mvneta: add reset statistics callback

Zyta Szpak (7):
  net/mvneta: add neta PMD skeleton
  net/mvneta: add Rx/Tx support
  net/mvneta: support for setting of MTU
  net/mvneta: add link update
  net/mvneta: support for promiscuous
  net/mvneta: add MAC filtering
  net/mvneta: add support for basic stats

 MAINTAINERS                                   |    8 +
 config/common_base                            |    5 +
 devtools/test-build.sh                        |    2 +
 doc/guides/nics/features/mvneta.ini           |   19 +
 doc/guides/nics/mvneta.rst                    |  161 ++++
 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                |   28 +
 drivers/net/mvneta/mvneta_ethdev.c            | 1019 +++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h            |   80 ++
 drivers/net/mvneta/mvneta_rxtx.c              |  850 +++++++++++++++++++++
 drivers/net/mvneta/mvneta_rxtx.h              |  168 ++++
 drivers/net/mvneta/rte_pmd_mvneta_version.map |    3 +
 mk/rte.app.mk                                 |    7 +-
 18 files changed, 2400 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/mvneta_rxtx.c
 create mode 100644 drivers/net/mvneta/mvneta_rxtx.h
 create mode 100644 drivers/net/mvneta/rte_pmd_mvneta_version.map

-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton
  2018-09-20  9:05       ` [dpdk-dev] [PATCH v5 0/8] Add Marvell NETA PMD Andrzej Ostruszka
@ 2018-09-20  9:05         ` Andrzej Ostruszka
  2018-09-24  9:21           ` Ferruh Yigit
                             ` (2 more replies)
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
                           ` (7 subsequent siblings)
  8 siblings, 3 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-20  9:05 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

From: Zyta Szpak <zr@semihalf.com>

Add neta pmd driver skeleton providing base for the further
development.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
Signed-off-by: Andrzej Ostruszka <amo@semihalf.com>
---
 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 <zr@semihalf.com>
+M: Dmitri Epshtein <dima@marvell.com>
+M: Natalie Samsonov <nsamsono@marvell.com>
+F: drivers/net/mvneta/
+F: doc/guides/nics/mvneta.rst
+F: doc/guides/nics/features/mvneta.ini
+
 Mellanox mlx4
 M: Matan Azrad <matan@mellanox.com>
 M: Shahaf Shuler <shahafs@mellanox.com>
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 () # <directory> <target> <options>
 		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 <https://extranet.marvell.com>`_. 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 <linux_gsg>` 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=<toolchain>/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=<musdk>/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 <rte_ethdev_driver.h>
+#include <rte_kvargs.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_bus_vdev.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <rte_mvep_common.h>
+
+#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 <drivers/mv_neta.h>
+#include <drivers/mv_neta_ppio.h>
+
+/** 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
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v5 2/8] net/mvneta: add Rx/Tx support
  2018-09-20  9:05       ` [dpdk-dev] [PATCH v5 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
@ 2018-09-20  9:05         ` Andrzej Ostruszka
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
                           ` (6 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-20  9:05 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

From: Zyta Szpak <zr@semihalf.com>

Add part of PMD for actual reception/transmission.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |   3 +
 doc/guides/nics/mvneta.rst          |   4 +
 drivers/net/mvneta/Makefile         |   2 +-
 drivers/net/mvneta/meson.build      |   3 +-
 drivers/net/mvneta/mvneta_ethdev.c  |  51 ++-
 drivers/net/mvneta/mvneta_ethdev.h  |   4 +
 drivers/net/mvneta/mvneta_rxtx.c    | 850 ++++++++++++++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_rxtx.h    | 168 +++++++
 8 files changed, 1080 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/mvneta/mvneta_rxtx.c
 create mode 100644 drivers/net/mvneta/mvneta_rxtx.h

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index ba6fe4b..0a89e2f 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -7,5 +7,8 @@
 Speed capabilities   = Y
 Jumbo frame          = Y
 CRC offload          = Y
+L3 checksum offload  = Y
+L4 checksum offload  = Y
+Packet type parsing  = Y
 ARMv8                = Y
 Usage doc            = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index bf08417..9d25c40 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -27,9 +27,13 @@ Features of the MVNETA PMD are:
 
 - Start/stop
 - tx/rx_queue_setup
+- tx/rx_burst
 - Speed capabilities
 - Jumbo frame
 - CRC offload
+- L3 checksum offload
+- L4 checksum offload
+- Packet type parsing
 
 
 Limitations
diff --git a/drivers/net/mvneta/Makefile b/drivers/net/mvneta/Makefile
index 149992e..349f550 100644
--- a/drivers/net/mvneta/Makefile
+++ b/drivers/net/mvneta/Makefile
@@ -37,6 +37,6 @@ 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
+SRCS-$(CONFIG_RTE_LIBRTE_MVNETA_PMD) += mvneta_ethdev.c mvneta_rxtx.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/mvneta/meson.build b/drivers/net/mvneta/meson.build
index 2f31954..c0b1bce 100644
--- a/drivers/net/mvneta/meson.build
+++ b/drivers/net/mvneta/meson.build
@@ -21,7 +21,8 @@ else
 endif
 
 sources = files(
-	'mvneta_ethdev.c'
+	'mvneta_ethdev.c',
+	'mvneta_rxtx.c'
 )
 
 deps += ['cfgfile', 'common_mvep']
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 9ee197a..331cd1d 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -6,8 +6,6 @@
 
 #include <rte_ethdev_driver.h>
 #include <rte_kvargs.h>
-#include <rte_log.h>
-#include <rte_malloc.h>
 #include <rte_bus_vdev.h>
 
 #include <stdio.h>
@@ -23,7 +21,7 @@
 
 #include <rte_mvep_common.h>
 
-#include "mvneta_ethdev.h"
+#include "mvneta_rxtx.h"
 
 
 #define MVNETA_IFACE_NAME_ARG "iface"
@@ -308,6 +306,18 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 		priv->uc_mc_flushed = 1;
 	}
 
+	/* Allocate buffers */
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+		int num = rxq->size;
+
+		ret = mvneta_buffs_alloc(priv, rxq, &num);
+		if (ret || num != rxq->size) {
+			rte_free(rxq);
+			return ret;
+		}
+	}
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up");
@@ -318,6 +328,8 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 	for (i = 0; i < dev->data->nb_tx_queues; i++)
 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
 
+	mvneta_set_tx_function(dev);
+
 	return 0;
 
 out:
@@ -336,11 +348,25 @@ static void
 mvneta_dev_stop(struct rte_eth_dev *dev)
 {
 	struct mvneta_priv *priv = dev->data->dev_private;
+	int i;
 
 	if (!priv->ppio)
 		return;
 
 	mvneta_dev_set_link_down(dev);
+	MVNETA_LOG(INFO, "Flushing rx queues");
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+
+		mvneta_rx_queue_flush(rxq);
+	}
+
+	MVNETA_LOG(INFO, "Flushing tx queues");
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		struct mvneta_txq *txq = dev->data->tx_queues[i];
+
+		mvneta_tx_queue_flush(txq);
+	}
 
 	neta_ppio_deinit(priv->ppio);
 
@@ -357,9 +383,20 @@ static void
 mvneta_dev_close(struct rte_eth_dev *dev)
 {
 	struct mvneta_priv *priv = dev->data->dev_private;
+	int i;
 
 	if (priv->ppio)
 		mvneta_dev_stop(dev);
+
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		mvneta_rx_queue_release(dev->data->rx_queues[i]);
+		dev->data->rx_queues[i] = NULL;
+	}
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		mvneta_tx_queue_release(dev->data->tx_queues[i]);
+		dev->data->tx_queues[i] = NULL;
+	}
 }
 
 /**
@@ -398,6 +435,12 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_set = mvneta_mac_addr_set,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
+	.rxq_info_get = mvneta_rxq_info_get,
+	.txq_info_get = mvneta_txq_info_get,
+	.rx_queue_setup = mvneta_rx_queue_setup,
+	.rx_queue_release = mvneta_rx_queue_release,
+	.tx_queue_setup = mvneta_tx_queue_setup,
+	.tx_queue_release = mvneta_tx_queue_release,
 };
 
 /**
@@ -448,6 +491,8 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
 	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
+	eth_dev->rx_pkt_burst = mvneta_rx_pkt_burst;
+	mvneta_set_tx_function(eth_dev);
 	eth_dev->dev_ops = &mvneta_ops;
 
 	return 0;
diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h
index 8b8d726..1a78a41 100644
--- a/drivers/net/mvneta/mvneta_ethdev.h
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -7,6 +7,10 @@
 #ifndef _MVNETA_ETHDEV_H_
 #define _MVNETA_ETHDEV_H_
 
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_log.h>
+
 /*
  * container_of is defined by both DPDK and MUSDK,
  * we'll declare only one version.
diff --git a/drivers/net/mvneta/mvneta_rxtx.c b/drivers/net/mvneta/mvneta_rxtx.c
new file mode 100644
index 0000000..d5ea5a8
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_rxtx.c
@@ -0,0 +1,850 @@
+#include "mvneta_rxtx.h"
+
+uint64_t cookie_addr_high = MVNETA_COOKIE_ADDR_INVALID;
+uint16_t rx_desc_free_thresh = MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN;
+
+static inline void
+mvneta_fill_shadowq(struct mvneta_shadow_txq *sq, struct rte_mbuf *buf)
+{
+	sq->ent[sq->head].cookie = (uint64_t)buf;
+	sq->ent[sq->head].addr = buf ?
+		rte_mbuf_data_iova_default(buf) : 0;
+
+	sq->head = (sq->head + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	sq->size++;
+}
+
+static inline void
+mvneta_fill_desc(struct neta_ppio_desc *desc, struct rte_mbuf *buf)
+{
+	neta_ppio_outq_desc_reset(desc);
+	neta_ppio_outq_desc_set_phys_addr(desc, rte_pktmbuf_iova(buf));
+	neta_ppio_outq_desc_set_pkt_offset(desc, 0);
+	neta_ppio_outq_desc_set_pkt_len(desc, rte_pktmbuf_data_len(buf));
+}
+
+/**
+ * Release already sent buffers to mempool.
+ *
+ * @param ppio
+ *   Pointer to the port structure.
+ * @param sq
+ *   Pointer to the shadow queue.
+ * @param qid
+ *   Queue id number.
+ * @param force
+ *   Force releasing packets.
+ */
+static inline void
+mvneta_sent_buffers_free(struct neta_ppio *ppio,
+			 struct mvneta_shadow_txq *sq, int qid)
+{
+	struct neta_buff_inf *entry;
+	uint16_t nb_done = 0;
+	int i;
+	int tail = sq->tail;
+
+	neta_ppio_get_num_outq_done(ppio, qid, &nb_done);
+
+	if (nb_done > sq->size) {
+		MVNETA_LOG(ERR, "nb_done: %d, sq->size %d",
+			   nb_done, sq->size);
+		return;
+	}
+
+	for (i = 0; i < nb_done; i++) {
+		entry = &sq->ent[tail];
+
+		if (unlikely(!entry->addr)) {
+			MVNETA_LOG(DEBUG,
+				"Shadow memory @%d: cookie(%lx), pa(%lx)!",
+				tail, (u64)entry->cookie,
+				(u64)entry->addr);
+			tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+			continue;
+		}
+
+		struct rte_mbuf *mbuf;
+
+		mbuf = (struct rte_mbuf *)
+			   (cookie_addr_high | entry->cookie);
+		rte_pktmbuf_free(mbuf);
+		tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+
+	sq->tail = tail;
+	sq->size -= nb_done;
+}
+
+/**
+ * Return packet type information and l3/l4 offsets.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ * @param l3_offset
+ *   l3 packet offset.
+ * @param l4_offset
+ *   l4 packet offset.
+ *
+ * @return
+ *   Packet type information.
+ */
+static inline uint64_t
+mvneta_desc_to_packet_type_and_offset(struct neta_ppio_desc *desc,
+				    uint8_t *l3_offset, uint8_t *l4_offset)
+{
+	enum neta_inq_l3_type l3_type;
+	enum neta_inq_l4_type l4_type;
+	uint64_t packet_type;
+
+	neta_ppio_inq_desc_get_l3_info(desc, &l3_type, l3_offset);
+	neta_ppio_inq_desc_get_l4_info(desc, &l4_type, l4_offset);
+
+	packet_type = RTE_PTYPE_L2_ETHER;
+
+	if (NETA_RXD_GET_VLAN_INFO(desc))
+		packet_type |= RTE_PTYPE_L2_ETHER_VLAN;
+
+	switch (l3_type) {
+	case NETA_INQ_L3_TYPE_IPV4_BAD:
+	case NETA_INQ_L3_TYPE_IPV4_OK:
+		packet_type |= RTE_PTYPE_L3_IPV4;
+		break;
+	case NETA_INQ_L3_TYPE_IPV6:
+		packet_type |= RTE_PTYPE_L3_IPV6;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l3 packet type");
+		break;
+	}
+
+	switch (l4_type) {
+	case NETA_INQ_L4_TYPE_TCP:
+		packet_type |= RTE_PTYPE_L4_TCP;
+		break;
+	case NETA_INQ_L4_TYPE_UDP:
+		packet_type |= RTE_PTYPE_L4_UDP;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l4 packet type");
+		break;
+	}
+
+	return packet_type;
+}
+
+/**
+ * Prepare offload information.
+ *
+ * @param ol_flags
+ *   Offload flags.
+ * @param packet_type
+ *   Packet type bitfield.
+ * @param l3_type
+ *   Pointer to the neta_ouq_l3_type structure.
+ * @param l4_type
+ *   Pointer to the neta_outq_l4_type structure.
+ * @param gen_l3_cksum
+ *   Will be set to 1 in case l3 checksum is computed.
+ * @param l4_cksum
+ *   Will be set to 1 in case l4 checksum is computed.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_prepare_proto_info(uint64_t ol_flags, uint32_t packet_type,
+			enum neta_outq_l3_type *l3_type,
+			enum neta_outq_l4_type *l4_type,
+			int *gen_l3_cksum,
+			int *gen_l4_cksum)
+{
+	/*
+	 * Based on ol_flags prepare information
+	 * for neta_ppio_outq_desc_set_proto_info() which setups descriptor
+	 * for offloading.
+	 */
+	if (ol_flags & PKT_TX_IPV4) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV4;
+		*gen_l3_cksum = ol_flags & PKT_TX_IP_CKSUM ? 1 : 0;
+	} else if (ol_flags & PKT_TX_IPV6) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV6;
+		/* no checksum for ipv6 header */
+		*gen_l3_cksum = 0;
+	} else {
+		/* if something different then stop processing */
+		return -1;
+	}
+
+	ol_flags &= PKT_TX_L4_MASK;
+	if ((packet_type & RTE_PTYPE_L4_TCP) &&
+	    ol_flags == PKT_TX_TCP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_TCP;
+		*gen_l4_cksum = 1;
+	} else if ((packet_type & RTE_PTYPE_L4_UDP) &&
+		   ol_flags == PKT_TX_UDP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_UDP;
+		*gen_l4_cksum = 1;
+	} else {
+		*l4_type = NETA_OUTQ_L4_TYPE_OTHER;
+		/* no checksum for other type */
+		*gen_l4_cksum = 0;
+	}
+
+	return 0;
+}
+
+/**
+ * Get offload information from the received packet descriptor.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ *
+ * @return
+ *   Mbuf offload flags.
+ */
+static inline uint64_t
+mvneta_desc_to_ol_flags(struct neta_ppio_desc *desc)
+{
+	uint64_t flags;
+	enum neta_inq_desc_status status;
+
+	status = neta_ppio_inq_desc_get_l3_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags = PKT_RX_IP_CKSUM_BAD;
+	else
+		flags = PKT_RX_IP_CKSUM_GOOD;
+
+	status = neta_ppio_inq_desc_get_l4_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags |= PKT_RX_L4_CKSUM_BAD;
+	else
+		flags |= PKT_RX_L4_CKSUM_GOOD;
+
+	return flags;
+}
+
+/**
+ * DPDK callback for transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts];
+
+	int i, ret, bytes_sent = 0;
+	uint16_t num, sq_free_size;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	if (unlikely(!nb_pkts || !q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+	if (unlikely(nb_pkts > sq_free_size)) {
+		MVNETA_LOG(DEBUG,
+			"No room in shadow queue for %d packets! %d packets will be sent.",
+			nb_pkts, sq_free_size);
+		nb_pkts = sq_free_size;
+	}
+
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		/* Fill first mbuf info in shadow queue */
+		mvneta_fill_shadowq(sq, mbuf);
+		mvneta_fill_desc(&descs[i], mbuf);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[i], l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = nb_pkts;
+	neta_ppio_send(q->priv->ppio, q->queue_id, descs, &nb_pkts);
+
+
+	/* number of packets that were not sent */
+	if (unlikely(num > nb_pkts)) {
+		for (i = nb_pkts; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE + sq->head - 1) &
+				MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = cookie_addr_high | sq->ent[sq->head].cookie;
+			bytes_sent -=
+				rte_pktmbuf_pkt_len((struct rte_mbuf *)addr);
+		}
+		sq->size -= num - nb_pkts;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/** DPDK callback for S/G transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_sg_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts * NETA_PPIO_DESC_NUM_FRAGS];
+	struct neta_ppio_sg_pkts pkts;
+	uint8_t frags[nb_pkts];
+	int i, j, ret, bytes_sent = 0;
+	int tail, tail_first;
+	uint16_t num, sq_free_size;
+	uint16_t nb_segs, total_descs = 0;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	pkts.frags = frags;
+	pkts.num = 0;
+
+	if (unlikely(!q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+	/* Save shadow queue free size */
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+
+	tail = 0;
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		struct rte_mbuf *seg = NULL;
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		nb_segs = mbuf->nb_segs;
+		total_descs += nb_segs;
+
+		/*
+		 * Check if total_descs does not exceed
+		 * shadow queue free size
+		 */
+		if (unlikely(total_descs > sq_free_size)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(DEBUG,
+				"No room in shadow queue for %d packets! "
+				"%d packets will be sent.",
+				nb_pkts, i);
+			break;
+		}
+
+
+		/* Check if nb_segs does not exceed the max nb of desc per
+		 * fragmented packet
+		 */
+		if (unlikely(nb_segs > NETA_PPIO_DESC_NUM_FRAGS)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(ERR,
+				"Too many segments. Packet won't be sent.");
+			break;
+		}
+
+		pkts.frags[pkts.num] = nb_segs;
+		pkts.num++;
+		tail_first = tail;
+
+		seg = mbuf;
+		for (j = 0; j < nb_segs - 1; j++) {
+			/* For the subsequent segments, set shadow queue
+			 * buffer to NULL
+			 */
+			mvneta_fill_shadowq(sq, NULL);
+			mvneta_fill_desc(&descs[tail], seg);
+
+			tail++;
+			seg = seg->next;
+		}
+		/* Put first mbuf info in last shadow queue entry */
+		mvneta_fill_shadowq(sq, mbuf);
+		/* Update descriptor with last segment */
+		mvneta_fill_desc(&descs[tail++], seg);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[tail_first],
+						   l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = total_descs;
+	neta_ppio_send_sg(q->priv->ppio, q->queue_id, descs, &total_descs,
+			  &pkts);
+
+	/* number of packets that were not sent */
+	if (unlikely(num > total_descs)) {
+		for (i = total_descs; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE +
+					sq->head - 1) &
+					MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = sq->ent[sq->head].cookie;
+			if (addr) {
+				struct rte_mbuf *mbuf;
+
+				mbuf = (struct rte_mbuf *)
+						(cookie_addr_high | addr);
+				bytes_sent -= rte_pktmbuf_pkt_len(mbuf);
+			}
+		}
+		sq->size -= num - total_descs;
+		nb_pkts = pkts.num;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/**
+ * Set tx burst function according to offload flag
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+void
+mvneta_set_tx_function(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	/* Use a simple Tx queue (no offloads, no multi segs) if possible */
+	if (priv->multiseg) {
+		MVNETA_LOG(INFO, "Using multi-segment tx callback");
+		dev->tx_pkt_burst = mvneta_tx_sg_pkt_burst;
+	} else {
+		MVNETA_LOG(INFO, "Using single-segment tx callback");
+		dev->tx_pkt_burst = mvneta_tx_pkt_burst;
+	}
+}
+
+/**
+ * DPDK callback for receive.
+ *
+ * @param rxq
+ *   Generic pointer to the receive queue.
+ * @param rx_pkts
+ *   Array to store received packets.
+ * @param nb_pkts
+ *   Maximum number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully received.
+ */
+uint16_t
+mvneta_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_rxq *q = rxq;
+	struct neta_ppio_desc descs[nb_pkts];
+	int i, ret, rx_done = 0, rx_dropped = 0;
+
+	if (unlikely(!q || !q->priv->ppio))
+		return 0;
+
+	ret = neta_ppio_recv(q->priv->ppio, q->queue_id,
+			descs, &nb_pkts);
+
+	if (unlikely(ret < 0)) {
+		MVNETA_LOG(ERR, "Failed to receive packets");
+		return 0;
+	}
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf;
+		uint8_t l3_offset, l4_offset;
+		enum neta_inq_desc_status status;
+		uint64_t addr;
+
+		addr = cookie_addr_high |
+			neta_ppio_inq_desc_get_cookie(&descs[i]);
+		mbuf = (struct rte_mbuf *)addr;
+
+		rte_pktmbuf_reset(mbuf);
+
+		/* drop packet in case of mac, overrun or resource error */
+		status = neta_ppio_inq_desc_get_l2_pkt_error(&descs[i]);
+		if (unlikely(status != NETA_DESC_ERR_OK)) {
+			/* Release the mbuf to the mempool since
+			 * it won't be transferred to tx path
+			 */
+			rte_pktmbuf_free(mbuf);
+			q->drop_mac++;
+			rx_dropped++;
+			continue;
+		}
+
+		mbuf->data_off += MVNETA_PKT_EFFEC_OFFS;
+		mbuf->pkt_len = neta_ppio_inq_desc_get_pkt_len(&descs[i]);
+		mbuf->data_len = mbuf->pkt_len;
+		mbuf->port = q->port_id;
+		mbuf->packet_type =
+			mvneta_desc_to_packet_type_and_offset(&descs[i],
+								&l3_offset,
+								&l4_offset);
+		mbuf->l2_len = l3_offset;
+		mbuf->l3_len = l4_offset - l3_offset;
+
+		if (likely(q->cksum_enabled))
+			mbuf->ol_flags = mvneta_desc_to_ol_flags(&descs[i]);
+
+		rx_pkts[rx_done++] = mbuf;
+		q->bytes_recv += mbuf->pkt_len;
+	}
+	q->pkts_processed += rx_done + rx_dropped;
+
+	if (q->pkts_processed > rx_desc_free_thresh) {
+		int buf_to_refill = rx_desc_free_thresh;
+
+		ret = mvneta_buffs_alloc(q->priv, q, &buf_to_refill);
+		if (ret)
+			MVNETA_LOG(ERR, "Refill failed");
+		q->pkts_processed -= buf_to_refill;
+	}
+
+	return rx_done;
+}
+
+/**
+ * DPDK callback to configure the receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   RX queue index.
+ * @param desc
+ *   Number of descriptors to configure in queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Thresholds parameters (unused_).
+ * @param mp
+ *   Memory pool for buffer allocations.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+int
+mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket,
+		      const struct rte_eth_rxconf *conf __rte_unused,
+		      struct rte_mempool *mp)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_rxq *rxq;
+	uint32_t frame_size, buf_size = rte_pktmbuf_data_room_size(mp);
+	uint32_t max_rx_pkt_len = dev->data->dev_conf.rxmode.max_rx_pkt_len;
+
+	frame_size = buf_size - RTE_PKTMBUF_HEADROOM - MVNETA_PKT_EFFEC_OFFS;
+
+	if (frame_size < max_rx_pkt_len) {
+		MVNETA_LOG(ERR,
+			"Mbuf size must be increased to %u bytes to hold up "
+			"to %u bytes of data.",
+			buf_size + max_rx_pkt_len - frame_size,
+			max_rx_pkt_len);
+		dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
+		MVNETA_LOG(INFO, "Setting max rx pkt len to %u",
+			dev->data->dev_conf.rxmode.max_rx_pkt_len);
+	}
+
+	if (dev->data->rx_queues[idx]) {
+		rte_free(dev->data->rx_queues[idx]);
+		dev->data->rx_queues[idx] = NULL;
+	}
+
+	rxq = rte_zmalloc_socket("rxq", sizeof(*rxq), 0, socket);
+	if (!rxq)
+		return -ENOMEM;
+
+	rxq->priv = priv;
+	rxq->mp = mp;
+	rxq->cksum_enabled = dev->data->dev_conf.rxmode.offloads &
+			     DEV_RX_OFFLOAD_IPV4_CKSUM;
+	rxq->queue_id = idx;
+	rxq->port_id = dev->data->port_id;
+	rxq->size = desc;
+	rx_desc_free_thresh = RTE_MIN(rx_desc_free_thresh, (desc / 2));
+	priv->ppio_params.inqs_params.tcs_params[MRVL_NETA_DEFAULT_TC].size =
+		desc;
+
+	dev->data->rx_queues[idx] = rxq;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to release the receive queue.
+ *
+ * @param rxq
+ *   Generic receive queue pointer.
+ */
+void
+mvneta_rx_queue_release(void *rxq)
+{
+	struct mvneta_rxq *q = rxq;
+
+	if (!q)
+		return;
+
+	/* If dev_stop was called already, mbufs are already
+	 * returned to mempool and ppio is deinitialized.
+	 * Skip this step.
+	 */
+
+	if (q->priv->ppio)
+		mvneta_rx_queue_flush(q);
+
+	rte_free(rxq);
+}
+
+/**
+ * DPDK callback to configure the transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   Transmit queue index.
+ * @param desc
+ *   Number of descriptors to configure in the queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Tx queue configuration parameters.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+int
+mvneta_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket, const struct rte_eth_txconf *conf)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_txq *txq;
+
+	if (dev->data->tx_queues[idx]) {
+		rte_free(dev->data->tx_queues[idx]);
+		dev->data->tx_queues[idx] = NULL;
+	}
+
+	txq = rte_zmalloc_socket("txq", sizeof(*txq), 0, socket);
+	if (!txq)
+		return -ENOMEM;
+
+	txq->priv = priv;
+	txq->queue_id = idx;
+	txq->port_id = dev->data->port_id;
+	txq->tx_deferred_start = conf->tx_deferred_start;
+	dev->data->tx_queues[idx] = txq;
+
+	priv->ppio_params.outqs_params.outqs_params[idx].size = desc;
+	priv->ppio_params.outqs_params.outqs_params[idx].weight = 1;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to release the transmit queue.
+ *
+ * @param txq
+ *   Generic transmit queue pointer.
+ */
+void
+mvneta_tx_queue_release(void *txq)
+{
+	struct mvneta_txq *q = txq;
+
+	if (!q)
+		return;
+
+	rte_free(q);
+}
+
+/**
+ * Return mbufs to mempool.
+ *
+ * @param rxq
+ *    Pointer to rx queue structure
+ * @param desc
+ *    Array of rx descriptors
+ */
+static void
+mvneta_recv_buffs_free(struct neta_ppio_desc *desc, uint16_t num)
+{
+	uint64_t addr;
+	uint8_t i;
+
+	for (i = 0; i < num; i++) {
+		if (desc) {
+			addr = cookie_addr_high |
+					neta_ppio_inq_desc_get_cookie(desc);
+			if (addr)
+				rte_pktmbuf_free((struct rte_mbuf *)addr);
+			desc++;
+		}
+	}
+}
+
+/**
+ * Flush single receive queue.
+ *
+ * @param rxq
+ *   Pointer to rx queue structure.
+ * @param descs
+ *   Array of rx descriptors
+ */
+void
+mvneta_rx_queue_flush(struct mvneta_rxq *rxq)
+{
+	struct neta_ppio_desc *descs;
+	struct neta_buff_inf *bufs;
+	uint16_t num;
+	int ret, i;
+
+	descs = rte_malloc("rxdesc", MRVL_NETA_RXD_MAX * sizeof(*descs), 0);
+	bufs = rte_malloc("buffs", MRVL_NETA_RXD_MAX * sizeof(*bufs), 0);
+
+	do {
+		num = MRVL_NETA_RXD_MAX;
+		ret = neta_ppio_recv(rxq->priv->ppio,
+				     rxq->queue_id,
+				     descs, &num);
+		mvneta_recv_buffs_free(descs, num);
+	} while (ret == 0 && num);
+
+	rxq->pkts_processed = 0;
+
+	num = MRVL_NETA_RXD_MAX;
+
+	neta_ppio_inq_get_all_buffs(rxq->priv->ppio, rxq->queue_id, bufs, &num);
+	MVNETA_LOG(INFO, "freeing %u unused bufs.", num);
+
+	for (i = 0; i < num; i++) {
+		uint64_t addr;
+		if (bufs[i].cookie) {
+			addr = cookie_addr_high | bufs[i].cookie;
+			rte_pktmbuf_free((struct rte_mbuf *)addr);
+		}
+	}
+
+	rte_free(descs);
+	rte_free(bufs);
+}
+
+/**
+ * Flush single transmit queue.
+ *
+ * @param txq
+ *     Pointer to tx queue structure
+ */
+void
+mvneta_tx_queue_flush(struct mvneta_txq *txq)
+{
+	struct mvneta_shadow_txq *sq = &txq->shadow_txq;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(txq->priv->ppio, sq,
+					 txq->queue_id);
+
+	/* free the rest of them */
+	while (sq->tail != sq->head) {
+		uint64_t addr = cookie_addr_high |
+			sq->ent[sq->tail].cookie;
+		rte_pktmbuf_free((struct rte_mbuf *)addr);
+		sq->tail = (sq->tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+	memset(sq, 0, sizeof(*sq));
+}
+
+/**
+ * DPDK callback to get information about specific receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param rx_queue_id
+ *   Receive queue index.
+ * @param qinfo
+ *   Receive queue information structure.
+ */
+void
+mvneta_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		    struct rte_eth_rxq_info *qinfo)
+{
+	struct mvneta_rxq *q = dev->data->rx_queues[rx_queue_id];
+
+	qinfo->mp = q->mp;
+	qinfo->nb_desc = q->size;
+}
+
+/**
+ * DPDK callback to get information about specific transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param tx_queue_id
+ *   Transmit queue index.
+ * @param qinfo
+ *   Transmit queue information structure.
+ */
+void
+mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		    struct rte_eth_txq_info *qinfo)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	qinfo->nb_desc =
+		priv->ppio_params.outqs_params.outqs_params[tx_queue_id].size;
+}
diff --git a/drivers/net/mvneta/mvneta_rxtx.h b/drivers/net/mvneta/mvneta_rxtx.h
new file mode 100644
index 0000000..7867c18
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_rxtx.h
@@ -0,0 +1,168 @@
+#ifndef _MVNETA_RXTX_H_
+#define _MVNETA_RXTX_H_
+
+#include "mvneta_ethdev.h"
+
+#define MVNETA_PKT_EFFEC_OFFS (MRVL_NETA_PKT_OFFS + MV_MH_SIZE)
+
+#define MRVL_NETA_DEFAULT_TC 0
+
+/** Maximum number of descriptors in shadow queue. Must be power of 2 */
+#define MRVL_NETA_TX_SHADOWQ_SIZE MRVL_NETA_TXD_MAX
+
+/** Shadow queue size mask (since shadow queue size is power of 2) */
+#define MRVL_NETA_TX_SHADOWQ_MASK (MRVL_NETA_TX_SHADOWQ_SIZE - 1)
+
+/** Minimum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN	16
+
+/** Maximum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX	64
+
+#define MVNETA_COOKIE_ADDR_INVALID ~0ULL
+#define MVNETA_COOKIE_HIGH_ADDR_SHIFT	(sizeof(neta_cookie_t) * 8)
+#define MVNETA_COOKIE_HIGH_ADDR_MASK	(~0ULL << MVNETA_COOKIE_HIGH_ADDR_SHIFT)
+
+#define MVNETA_SET_COOKIE_HIGH_ADDR(addr) {				\
+	if (unlikely(cookie_addr_high == MVNETA_COOKIE_ADDR_INVALID))	\
+		cookie_addr_high =					\
+			(uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK;\
+}
+
+#define MVNETA_CHECK_COOKIE_HIGH_ADDR(addr)			\
+	((likely(cookie_addr_high ==				\
+	((uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK))) ? 1 : 0)
+
+/*
+ * To use buffer harvesting based on loopback port shadow queue structure
+ * was introduced for buffers information bookkeeping.
+ */
+struct mvneta_shadow_txq {
+	int head;           /* write index - used when sending buffers */
+	int tail;           /* read index - used when releasing buffers */
+	u16 size;           /* queue occupied size */
+	struct neta_buff_inf ent[MRVL_NETA_TX_SHADOWQ_SIZE]; /* q entries */
+};
+
+struct mvneta_rxq {
+	struct mvneta_priv *priv;
+	struct rte_mempool *mp;
+	int queue_id;
+	int port_id;
+	int size;
+	int cksum_enabled;
+	uint64_t bytes_recv;
+	uint64_t drop_mac;
+	uint64_t pkts_processed;
+};
+
+
+struct mvneta_txq {
+	struct mvneta_priv *priv;
+	int queue_id;
+	int port_id;
+	uint64_t bytes_sent;
+	struct mvneta_shadow_txq shadow_txq;
+	int tx_deferred_start;
+};
+
+extern uint64_t cookie_addr_high;
+extern uint16_t rx_desc_free_thresh;
+
+static inline int
+mvneta_buffs_refill(struct mvneta_priv *priv, struct mvneta_rxq *rxq, u16 *num)
+{
+	struct rte_mbuf *mbufs[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	struct neta_buff_inf entries[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	int i, ret;
+	uint16_t nb_desc = *num;
+
+	ret = rte_pktmbuf_alloc_bulk(rxq->mp, mbufs, nb_desc);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to allocate %u mbufs.", nb_desc);
+		*num = 0;
+		return -1;
+	}
+
+	MVNETA_SET_COOKIE_HIGH_ADDR(mbufs[0]);
+
+	for (i = 0; i < nb_desc; i++) {
+		if (unlikely(!MVNETA_CHECK_COOKIE_HIGH_ADDR(mbufs[i]))) {
+			MVNETA_LOG(ERR,
+				"mbuf virt high addr 0x%lx out of range 0x%lx",
+				(uint64_t)mbufs[i] >> 32,
+				cookie_addr_high >> 32);
+			*num = 0;
+			goto out;
+		}
+		entries[i].addr = rte_mbuf_data_iova_default(mbufs[i]);
+		entries[i].cookie = (neta_cookie_t)(uint64_t)mbufs[i];
+	}
+	neta_ppio_inq_put_buffs(priv->ppio, rxq->queue_id, entries, num);
+
+out:
+	for (i = *num; i < nb_desc; i++)
+		rte_pktmbuf_free(mbufs[i]);
+
+	return 0;
+}
+
+/**
+ * Allocate buffers from mempool
+ * and store addresses in rx descriptors.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_buffs_alloc(struct mvneta_priv *priv, struct mvneta_rxq *rxq, int *num)
+{
+	uint16_t nb_desc, nb_desc_burst, sent = 0;
+	int ret = 0;
+
+	nb_desc = *num;
+
+	do {
+		nb_desc_burst =
+			(nb_desc < MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX) ?
+			nb_desc : MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX;
+
+		ret = mvneta_buffs_refill(priv, rxq, &nb_desc_burst);
+		if (unlikely(ret || !nb_desc_burst))
+			break;
+
+		sent += nb_desc_burst;
+		nb_desc -= nb_desc_burst;
+
+	} while (nb_desc);
+
+	*num = sent;
+
+	return ret;
+}
+
+void mvneta_rx_queue_flush(struct mvneta_rxq *rxq);
+void mvneta_tx_queue_flush(struct mvneta_txq *txq);
+
+void mvneta_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+			 struct rte_eth_rxq_info *qinfo);
+void mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+			 struct rte_eth_txq_info *qinfo);
+
+void mvneta_set_tx_function(struct rte_eth_dev *dev);
+uint16_t
+mvneta_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
+
+int
+mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket,
+		      const struct rte_eth_rxconf *conf __rte_unused,
+		      struct rte_mempool *mp);
+int
+mvneta_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket, const struct rte_eth_txconf *conf);
+
+void mvneta_rx_queue_release(void *rxq);
+void mvneta_tx_queue_release(void *txq);
+
+#endif /* _MVNETA_RXTX_H_ */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v5 3/8] net/mvneta: support for setting of MTU
  2018-09-20  9:05       ` [dpdk-dev] [PATCH v5 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
@ 2018-09-20  9:05         ` Andrzej Ostruszka
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 4/8] net/mvneta: add link update Andrzej Ostruszka
                           ` (5 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-20  9:05 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

From: Zyta Szpak <zr@semihalf.com>

Add callback for setting of MTU.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 78 +++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 0a89e2f..bc4e400 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -5,6 +5,7 @@
 ;
 [Features]
 Speed capabilities   = Y
+MTU update           = Y
 Jumbo frame          = Y
 CRC offload          = Y
 L3 checksum offload  = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index 9d25c40..55ffe57 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -30,6 +30,7 @@ Features of the MVNETA PMD are:
 - tx/rx_burst
 - Speed capabilities
 - Jumbo frame
+- MTU update
 - CRC offload
 - L3 checksum offload
 - L4 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 331cd1d..1b26c87 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -221,6 +221,77 @@ mvneta_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
 }
 
 /**
+ * DPDK callback to change the MTU.
+ *
+ * Setting the MTU affects hardware MRU (packets larger than the MRU
+ * will be dropped).
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param mtu
+ *   New MTU.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	uint16_t mbuf_data_size = 0; /* SW buffer size */
+	uint16_t mru;
+	int ret;
+
+	mru = MRVL_NETA_MTU_TO_MRU(mtu);
+	/*
+	 * min_rx_buf_size is equal to mbuf data size
+	 * if pmd didn't set it differently
+	 */
+	mbuf_data_size = dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM;
+	/* Prevent PMD from:
+	 * - setting mru greater than the mbuf size resulting in
+	 * hw and sw buffer size mismatch
+	 * - setting mtu that requires the support of scattered packets
+	 * when this feature has not been enabled/supported so far.
+	 */
+	if (!dev->data->scattered_rx &&
+	    (mru + MRVL_NETA_PKT_OFFS > mbuf_data_size)) {
+		mru = mbuf_data_size - MRVL_NETA_PKT_OFFS;
+		mtu = MRVL_NETA_MRU_TO_MTU(mru);
+		MVNETA_LOG(WARNING, "MTU too big, max MTU possible limitted by"
+			" current mbuf size: %u. Set MTU to %u, MRU to %u",
+			mbuf_data_size, mtu, mru);
+	}
+
+	if (mtu < ETHER_MIN_MTU || mru > MVNETA_PKT_SIZE_MAX) {
+		MVNETA_LOG(ERR, "Invalid MTU [%u] or MRU [%u]", mtu, mru);
+		return -EINVAL;
+	}
+
+	dev->data->mtu = mtu;
+	dev->data->dev_conf.rxmode.max_rx_pkt_len = mru - MV_MH_SIZE;
+
+	if (!priv->ppio)
+		/* It is OK. New MTU will be set later on mvneta_dev_start */
+		return 0;
+
+	ret = neta_ppio_set_mru(priv->ppio, mru);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MRU");
+		return ret;
+	}
+
+	ret = neta_ppio_set_mtu(priv->ppio, mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MTU");
+		return ret;
+	}
+	MVNETA_LOG(INFO, "MTU changed to %u, MRU = %u", mtu, mru);
+
+	return 0;
+}
+
+/**
  * DPDK callback to bring the link up.
  *
  * @param dev
@@ -318,6 +389,12 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 		}
 	}
 
+	ret = mvneta_mtu_set(dev, dev->data->mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to set MTU %d", dev->data->mtu);
+		goto out;
+	}
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up");
@@ -433,6 +510,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
 	.mac_addr_set = mvneta_mac_addr_set,
+	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v5 4/8] net/mvneta: add link update
  2018-09-20  9:05       ` [dpdk-dev] [PATCH v5 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                           ` (2 preceding siblings ...)
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
@ 2018-09-20  9:05         ` Andrzej Ostruszka
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
                           ` (4 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-20  9:05 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

From: Zyta Szpak <zr@semihalf.com>

Add callback for updating information about link status/info.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 71 +++++++++++++++++++++++++++++++++++++
 3 files changed, 73 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index bc4e400..581ed31 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -5,6 +5,7 @@
 ;
 [Features]
 Speed capabilities   = Y
+Link status          = Y
 MTU update           = Y
 Jumbo frame          = Y
 CRC offload          = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index 55ffe57..85cdd1d 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -31,6 +31,7 @@ Features of the MVNETA PMD are:
 - Speed capabilities
 - Jumbo frame
 - MTU update
+- Link status
 - CRC offload
 - L3 checksum offload
 - L4 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 1b26c87..e9cbff7 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -477,6 +477,76 @@ mvneta_dev_close(struct rte_eth_dev *dev)
 }
 
 /**
+ * DPDK callback to retrieve physical link information.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param wait_to_complete
+ *   Wait for request completion (ignored).
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
+{
+	/*
+	 * TODO
+	 * once MUSDK provides necessary API use it here
+	 */
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct ethtool_cmd edata;
+	struct ifreq req;
+	int ret, fd, link_up;
+
+	if (!priv->ppio)
+		return -EPERM;
+
+	edata.cmd = ETHTOOL_GSET;
+
+	strcpy(req.ifr_name, dev->data->name);
+	req.ifr_data = (void *)&edata;
+
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd == -1)
+		return -EFAULT;
+	ret = ioctl(fd, SIOCETHTOOL, &req);
+	if (ret == -1) {
+		close(fd);
+		return -EFAULT;
+	}
+
+	close(fd);
+
+	switch (ethtool_cmd_speed(&edata)) {
+	case SPEED_10:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_10M;
+		break;
+	case SPEED_100:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_100M;
+		break;
+	case SPEED_1000:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_1G;
+		break;
+	case SPEED_2500:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_2_5G;
+		break;
+	default:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE;
+	}
+
+	dev->data->dev_link.link_duplex = edata.duplex ? ETH_LINK_FULL_DUPLEX :
+							 ETH_LINK_HALF_DUPLEX;
+	dev->data->dev_link.link_autoneg = edata.autoneg ? ETH_LINK_AUTONEG :
+							   ETH_LINK_FIXED;
+
+	neta_ppio_get_link_state(priv->ppio, &link_up);
+	dev->data->dev_link.link_status = link_up ? ETH_LINK_UP : ETH_LINK_DOWN;
+
+	return 0;
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -509,6 +579,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_up = mvneta_dev_set_link_up,
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
+	.link_update = mvneta_link_update,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v5 5/8] net/mvneta: support for promiscuous
  2018-09-20  9:05       ` [dpdk-dev] [PATCH v5 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                           ` (3 preceding siblings ...)
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 4/8] net/mvneta: add link update Andrzej Ostruszka
@ 2018-09-20  9:05         ` Andrzej Ostruszka
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
                           ` (3 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-20  9:05 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

From: Zyta Szpak <zr@semihalf.com>

Add callbacks for enabling/disabling of promiscuous mode.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 54 +++++++++++++++++++++++++++++++++++++
 3 files changed, 56 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 581ed31..6a140a3 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -8,6 +8,7 @@ Speed capabilities   = Y
 Link status          = Y
 MTU update           = Y
 Jumbo frame          = Y
+Promiscuous mode     = Y
 CRC offload          = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index 85cdd1d..1912c3e 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -31,6 +31,7 @@ Features of the MVNETA PMD are:
 - Speed capabilities
 - Jumbo frame
 - MTU update
+- Promiscuous mode
 - Link status
 - CRC offload
 - L3 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index e9cbff7..04881d5 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -547,6 +547,58 @@ mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
 }
 
 /**
+ * DPDK callback to enable promiscuous mode.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_promiscuous_enable(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	int ret, en;
+
+	if (!priv->ppio)
+		return;
+
+	neta_ppio_get_promisc(priv->ppio, &en);
+	if (en) {
+		MVNETA_LOG(INFO, "Promiscuous already enabled");
+		return;
+	}
+
+	ret = neta_ppio_set_promisc(priv->ppio, 1);
+	if (ret)
+		MVNETA_LOG(ERR, "Failed to enable promiscuous mode");
+}
+
+/**
+ * DPDK callback to disable allmulticast mode.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_promiscuous_disable(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	int ret, en;
+
+	if (!priv->ppio)
+		return;
+
+	neta_ppio_get_promisc(priv->ppio, &en);
+	if (!en) {
+		MVNETA_LOG(INFO, "Promiscuous already disabled");
+		return;
+	}
+
+	ret = neta_ppio_set_promisc(priv->ppio, 0);
+	if (ret)
+		MVNETA_LOG(ERR, "Failed to disable promiscuous mode");
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -580,6 +632,8 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
 	.link_update = mvneta_link_update,
+	.promiscuous_enable = mvneta_promiscuous_enable,
+	.promiscuous_disable = mvneta_promiscuous_disable,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v5 6/8] net/mvneta: add MAC filtering
  2018-09-20  9:05       ` [dpdk-dev] [PATCH v5 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                           ` (4 preceding siblings ...)
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
@ 2018-09-20  9:05         ` Andrzej Ostruszka
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
                           ` (2 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-20  9:05 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

From: Zyta Szpak <zr@semihalf.com>

Add callbacks for adding/removing MAC addresses.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 69 +++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 6a140a3..59c9c36 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -9,6 +9,7 @@ Link status          = Y
 MTU update           = Y
 Jumbo frame          = Y
 Promiscuous mode     = Y
+Unicast MAC filter   = Y
 CRC offload          = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index 1912c3e..b21581b 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -32,6 +32,7 @@ Features of the MVNETA PMD are:
 - Jumbo frame
 - MTU update
 - Promiscuous mode
+- Unicast MAC filter
 - Link status
 - CRC offload
 - L3 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 04881d5..09b98de 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -599,6 +599,73 @@ mvneta_promiscuous_disable(struct rte_eth_dev *dev)
 }
 
 /**
+ * DPDK callback to remove a MAC address.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param index
+ *   MAC address index.
+ */
+static void
+mvneta_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	char buf[ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	if (!priv->ppio)
+		return;
+
+	ret = neta_ppio_remove_mac_addr(priv->ppio,
+				       dev->data->mac_addrs[index].addr_bytes);
+	if (ret) {
+		ether_format_addr(buf, sizeof(buf),
+				  &dev->data->mac_addrs[index]);
+		MVNETA_LOG(ERR, "Failed to remove mac %s", buf);
+	}
+}
+
+/**
+ * DPDK callback to add a MAC address.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param mac_addr
+ *   MAC address to register.
+ * @param index
+ *   MAC address index.
+ * @param vmdq
+ *   VMDq pool index to associate address with (unused).
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
+		  uint32_t index, uint32_t vmdq __rte_unused)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	char buf[ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	if (index == 0)
+		/* For setting index 0, mrvl_mac_addr_set() should be used.*/
+		return -1;
+
+	if (!priv->ppio)
+		return 0;
+
+	ret = neta_ppio_add_mac_addr(priv->ppio, mac_addr->addr_bytes);
+	if (ret) {
+		ether_format_addr(buf, sizeof(buf), mac_addr);
+		MVNETA_LOG(ERR, "Failed to add mac %s", buf);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -634,6 +701,8 @@ static const struct eth_dev_ops mvneta_ops = {
 	.link_update = mvneta_link_update,
 	.promiscuous_enable = mvneta_promiscuous_enable,
 	.promiscuous_disable = mvneta_promiscuous_disable,
+	.mac_addr_remove = mvneta_mac_addr_remove,
+	.mac_addr_add = mvneta_mac_addr_add,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v5 7/8] net/mvneta: add support for basic stats
  2018-09-20  9:05       ` [dpdk-dev] [PATCH v5 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                           ` (5 preceding siblings ...)
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
@ 2018-09-20  9:05         ` Andrzej Ostruszka
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
  2018-10-01  9:26         ` [dpdk-dev] [PATCH v6 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-20  9:05 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh

From: Zyta Szpak <zr@semihalf.com>

Add support for getting of basic statistics for the driver.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 47 +++++++++++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 59c9c36..701eb03 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -14,5 +14,6 @@ CRC offload          = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
 Packet type parsing  = Y
+Basic stats          = Y
 ARMv8                = Y
 Usage doc            = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index b21581b..5bcf3b6 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -38,6 +38,7 @@ Features of the MVNETA PMD are:
 - L3 checksum offload
 - L4 checksum offload
 - Packet type parsing
+- Basic stats
 
 
 Limitations
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 09b98de..c4ba42b 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -691,6 +691,52 @@ mvneta_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
 	return 0;
 }
 
+/**
+ * DPDK callback to get device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param stats
+ *   Stats structure output buffer.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct neta_ppio_statistics ppio_stats;
+	unsigned int ret;
+
+	if (!priv->ppio)
+		return -EPERM;
+
+	ret = neta_ppio_get_statistics(priv->ppio, &ppio_stats);
+	if (unlikely(ret)) {
+		MVNETA_LOG(ERR, "Failed to update port statistics");
+		return ret;
+	}
+
+	stats->ipackets += ppio_stats.rx_packets +
+			ppio_stats.rx_broadcast_packets +
+			ppio_stats.rx_multicast_packets;
+	stats->opackets += ppio_stats.tx_packets +
+			ppio_stats.tx_broadcast_packets +
+			ppio_stats.tx_multicast_packets;
+	stats->ibytes += ppio_stats.rx_bytes;
+	stats->obytes += ppio_stats.tx_bytes;
+	stats->imissed += ppio_stats.rx_discard +
+			  ppio_stats.rx_overrun;
+
+	stats->ierrors = ppio_stats.rx_packets_err +
+			ppio_stats.rx_errors +
+			ppio_stats.rx_crc_error;
+	stats->oerrors = ppio_stats.tx_errors;
+
+	return 0;
+}
+
 static const struct eth_dev_ops mvneta_ops = {
 	.dev_configure = mvneta_dev_configure,
 	.dev_start = mvneta_dev_start,
@@ -705,6 +751,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_add = mvneta_mac_addr_add,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
+	.stats_get = mvneta_stats_get,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v5 8/8] net/mvneta: add reset statistics callback
  2018-09-20  9:05       ` [dpdk-dev] [PATCH v5 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                           ` (6 preceding siblings ...)
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
@ 2018-09-20  9:05         ` Andrzej Ostruszka
  2018-10-01  9:26         ` [dpdk-dev] [PATCH v6 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-20  9:05 UTC (permalink / raw)
  To: dev; +Cc: mw, zr, tdu, nadavh, Natalie Samsonov

From: Natalie Samsonov <nsamsono@marvell.com>

Add support for resetting of driver statistics.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 40 +++++++++++++++++++++++++++++++-------
 drivers/net/mvneta/mvneta_ethdev.h |  1 +
 2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index c4ba42b..c5d190d 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -720,23 +720,48 @@ mvneta_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 
 	stats->ipackets += ppio_stats.rx_packets +
 			ppio_stats.rx_broadcast_packets +
-			ppio_stats.rx_multicast_packets;
+			ppio_stats.rx_multicast_packets -
+			priv->prev_stats.ipackets;
 	stats->opackets += ppio_stats.tx_packets +
 			ppio_stats.tx_broadcast_packets +
-			ppio_stats.tx_multicast_packets;
-	stats->ibytes += ppio_stats.rx_bytes;
-	stats->obytes += ppio_stats.tx_bytes;
+			ppio_stats.tx_multicast_packets -
+			priv->prev_stats.opackets;
+	stats->ibytes += ppio_stats.rx_bytes - priv->prev_stats.ibytes;
+	stats->obytes += ppio_stats.tx_bytes - priv->prev_stats.obytes;
 	stats->imissed += ppio_stats.rx_discard +
-			  ppio_stats.rx_overrun;
+			  ppio_stats.rx_overrun -
+			  priv->prev_stats.imissed;
 
 	stats->ierrors = ppio_stats.rx_packets_err +
 			ppio_stats.rx_errors +
-			ppio_stats.rx_crc_error;
-	stats->oerrors = ppio_stats.tx_errors;
+			ppio_stats.rx_crc_error -
+			priv->prev_stats.ierrors;
+	stats->oerrors = ppio_stats.tx_errors - priv->prev_stats.oerrors;
 
 	return 0;
 }
 
+/**
+ * DPDK callback to clear device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_stats_reset(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	unsigned int ret;
+
+	if (!priv->ppio)
+		return;
+
+	ret = mvneta_stats_get(dev, &priv->prev_stats);
+	if (unlikely(ret))
+		RTE_LOG(ERR, PMD, "Failed to reset port statistics");
+}
+
+
 static const struct eth_dev_ops mvneta_ops = {
 	.dev_configure = mvneta_dev_configure,
 	.dev_start = mvneta_dev_start,
@@ -752,6 +777,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.stats_get = mvneta_stats_get,
+	.stats_reset = mvneta_stats_reset,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h
index 1a78a41..eeea31a 100644
--- a/drivers/net/mvneta/mvneta_ethdev.h
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -67,6 +67,7 @@ struct mvneta_priv {
 	uint16_t nb_rx_queues;
 
 	uint64_t rate_max;
+	struct rte_eth_stats prev_stats;
 };
 
 /** Current log type. */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD
  2018-09-19 17:39         ` Ferruh Yigit
@ 2018-09-21 11:59           ` Andrzej Ostruszka
  2018-09-21 13:37             ` Ferruh Yigit
  0 siblings, 1 reply; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-09-21 11:59 UTC (permalink / raw)
  To: Ferruh Yigit, dev, dpdk-web

On 19.09.2018 19:39, Ferruh Yigit wrote:
> On 9/19/2018 4:07 PM, Andrzej Ostruszka wrote:
>> On 14.09.2018 18:20, Ferruh Yigit wrote:
[...]
>>> Can you also set a web page patch to add new hardware to supported hw list:
>>> http://core.dpdk.org/supported/
>>> https://git.dpdk.org/tools/dpdk-web/
>>
>> Could you tell me what is the procedure for submitting web page patches?
>>  Same as for code (sending via e-mail to dev)?
> 
> Same process but different mail list: web@dpdk.org

Thanks.  I will send it out as soon as the NETA gets into next-net since
I see there is a custom of pointing to "reference commit" in commit
messages.

Best regards
Andrzej

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD
  2018-09-21 11:59           ` Andrzej Ostruszka
@ 2018-09-21 13:37             ` Ferruh Yigit
  0 siblings, 0 replies; 96+ messages in thread
From: Ferruh Yigit @ 2018-09-21 13:37 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev, dpdk-web

On 9/21/2018 12:59 PM, Andrzej Ostruszka wrote:
> On 19.09.2018 19:39, Ferruh Yigit wrote:
>> On 9/19/2018 4:07 PM, Andrzej Ostruszka wrote:
>>> On 14.09.2018 18:20, Ferruh Yigit wrote:
> [...]
>>>> Can you also set a web page patch to add new hardware to supported hw list:
>>>> http://core.dpdk.org/supported/
>>>> https://git.dpdk.org/tools/dpdk-web/
>>>
>>> Could you tell me what is the procedure for submitting web page patches?
>>>  Same as for code (sending via e-mail to dev)?
>>
>> Same process but different mail list: web@dpdk.org
> 
> Thanks.  I will send it out as soon as the NETA gets into next-net since
> I see there is a custom of pointing to "reference commit" in commit
> messages.

Thanks.
Yes, web page commit log should point to commit that adds the support.

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
@ 2018-09-24  9:21           ` Ferruh Yigit
  2018-09-24  9:35             ` Ferruh Yigit
  2018-09-24  9:57           ` Ferruh Yigit
  2018-09-24 10:03           ` Ferruh Yigit
  2 siblings, 1 reply; 96+ messages in thread
From: Ferruh Yigit @ 2018-09-24  9:21 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev; +Cc: mw, zr, tdu, nadavh

On 9/20/2018 10:05 AM, Andrzej Ostruszka wrote:
> From: Zyta Szpak <zr@semihalf.com>
> 
> Add neta pmd driver skeleton providing base for the further
> development.
> 
> Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
> Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
> Signed-off-by: Dmitri Epshtein <dima@marvell.com>
> Signed-off-by: Zyta Szpak <zr@semihalf.com>
> Signed-off-by: Andrzej Ostruszka <amo@semihalf.com>

<...>

> @@ -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 <drivers/mv_neta.h>
> +#include <drivers/mv_neta_ppio.h>

Can't find mv_neta.h in $(LIBMUSDK_PATH)/include [1]

There is a "mv_neta.h" in "./src/include/drivers/mv_neta.h" but not in the
installed path.
<musdk>/usr/local/include/drivers.

Is there a specific build param required for musdk for neta support?

[1]
.../drivers/net/mvneta/mvneta_ethdev.h:24:10: fatal error: 'drivers/mv_neta.h'
file not found
#include <drivers/mv_neta.h>

         ^~~~~~~~~~~~~~~~~~~

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton
  2018-09-24  9:21           ` Ferruh Yigit
@ 2018-09-24  9:35             ` Ferruh Yigit
  2018-09-24  9:38               ` Ferruh Yigit
  0 siblings, 1 reply; 96+ messages in thread
From: Ferruh Yigit @ 2018-09-24  9:35 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev; +Cc: mw, zr, tdu, nadavh

On 9/24/2018 10:21 AM, Ferruh Yigit wrote:
> On 9/20/2018 10:05 AM, Andrzej Ostruszka wrote:
>> From: Zyta Szpak <zr@semihalf.com>
>>
>> Add neta pmd driver skeleton providing base for the further
>> development.
>>
>> Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
>> Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
>> Signed-off-by: Dmitri Epshtein <dima@marvell.com>
>> Signed-off-by: Zyta Szpak <zr@semihalf.com>
>> Signed-off-by: Andrzej Ostruszka <amo@semihalf.com>
> 
> <...>
> 
>> @@ -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 <drivers/mv_neta.h>
>> +#include <drivers/mv_neta_ppio.h>
> 
> Can't find mv_neta.h in $(LIBMUSDK_PATH)/include [1]
> 
> There is a "mv_neta.h" in "./src/include/drivers/mv_neta.h" but not in the
> installed path.
> <musdk>/usr/local/include/drivers.
> 
> Is there a specific build param required for musdk for neta support?

I found it: --enable-bpool-dma=64 --enable-pp2=no --enable-neta,

But this means I need different musdk builds for mvpp2 and mvneta!
Can't it possible to use single musdk build for both libraries?

> 
> [1]
> .../drivers/net/mvneta/mvneta_ethdev.h:24:10: fatal error: 'drivers/mv_neta.h'
> file not found
> #include <drivers/mv_neta.h>
> 
>          ^~~~~~~~~~~~~~~~~~~
> 

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton
  2018-09-24  9:35             ` Ferruh Yigit
@ 2018-09-24  9:38               ` Ferruh Yigit
  2018-10-01  9:35                 ` Andrzej Ostruszka
  0 siblings, 1 reply; 96+ messages in thread
From: Ferruh Yigit @ 2018-09-24  9:38 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev; +Cc: mw, zr, tdu, nadavh

On 9/24/2018 10:35 AM, Ferruh Yigit wrote:
> On 9/24/2018 10:21 AM, Ferruh Yigit wrote:
>> On 9/20/2018 10:05 AM, Andrzej Ostruszka wrote:
>>> From: Zyta Szpak <zr@semihalf.com>
>>>
>>> Add neta pmd driver skeleton providing base for the further
>>> development.
>>>
>>> Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
>>> Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
>>> Signed-off-by: Dmitri Epshtein <dima@marvell.com>
>>> Signed-off-by: Zyta Szpak <zr@semihalf.com>
>>> Signed-off-by: Andrzej Ostruszka <amo@semihalf.com>
>>
>> <...>
>>
>>> @@ -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 <drivers/mv_neta.h>
>>> +#include <drivers/mv_neta_ppio.h>
>>
>> Can't find mv_neta.h in $(LIBMUSDK_PATH)/include [1]
>>
>> There is a "mv_neta.h" in "./src/include/drivers/mv_neta.h" but not in the
>> installed path.
>> <musdk>/usr/local/include/drivers.
>>
>> Is there a specific build param required for musdk for neta support?
> 
> I found it: --enable-bpool-dma=64 --enable-pp2=no --enable-neta,

btw, getting "configure: WARNING: unrecognized options: --enable-bpool-dma"
FYI

> 
> But this means I need different musdk builds for mvpp2 and mvneta!
> Can't it possible to use single musdk build for both libraries?
> 
>>
>> [1]
>> .../drivers/net/mvneta/mvneta_ethdev.h:24:10: fatal error: 'drivers/mv_neta.h'
>> file not found
>> #include <drivers/mv_neta.h>
>>
>>          ^~~~~~~~~~~~~~~~~~~
>>
> 

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
  2018-09-24  9:21           ` Ferruh Yigit
@ 2018-09-24  9:57           ` Ferruh Yigit
  2018-09-24 10:03           ` Ferruh Yigit
  2 siblings, 0 replies; 96+ messages in thread
From: Ferruh Yigit @ 2018-09-24  9:57 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev; +Cc: mw, zr, tdu, nadavh

On 9/20/2018 10:05 AM, Andrzej Ostruszka wrote:
> From: Zyta Szpak <zr@semihalf.com>
> 
> Add neta pmd driver skeleton providing base for the further
> development.
> 
> Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
> Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
> Signed-off-by: Dmitri Epshtein <dima@marvell.com>
> Signed-off-by: Zyta Szpak <zr@semihalf.com>
> Signed-off-by: Andrzej Ostruszka <amo@semihalf.com>
> ---
>  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/nics/mvneta.rst: WARNING: document isn't included in any toctree

doc/guides/nics/index.rst needs to be updated.

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
  2018-09-24  9:21           ` Ferruh Yigit
  2018-09-24  9:57           ` Ferruh Yigit
@ 2018-09-24 10:03           ` Ferruh Yigit
  2018-10-01  9:30             ` Andrzej Ostruszka
  2 siblings, 1 reply; 96+ messages in thread
From: Ferruh Yigit @ 2018-09-24 10:03 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev; +Cc: mw, zr, tdu, nadavh

On 9/20/2018 10:05 AM, Andrzej Ostruszka wrote:
> +/**
> + * 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);

Giving build error for shared libraries [1], needs to link with rte_common_mvep,

In makefile needed: LDLIBS += -lrte_common_mvep,
please check "mvpp2/Makefile"


[1]
mvneta_ethdev.o: In function `rte_pmd_mvneta_probe':
mvneta_ethdev.c:(.text+0xa58): undefined reference to `rte_mvep_init'
mvneta_ethdev.c:(.text+0xc98): undefined reference to `rte_mvep_deinit'
mvneta_ethdev.c:(.text+0xcb4): undefined reference to `rte_mvep_deinit'
mvneta_ethdev.o: In function `rte_pmd_mvneta_remove':
mvneta_ethdev.c:(.text+0xe58): undefined reference to `rte_mvep_deinit'

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v6 0/8] Add Marvell NETA PMD
  2018-09-20  9:05       ` [dpdk-dev] [PATCH v5 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                           ` (7 preceding siblings ...)
  2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
@ 2018-10-01  9:26         ` Andrzej Ostruszka
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
                             ` (8 more replies)
  8 siblings, 9 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-01  9:26 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu, Andrzej Ostruszka

From: Andrzej Ostruszka <amo@semihalf.com>

This patch series introduces new PMD for Marvell NETA adapters (MVNETA).
See the documentation for more info.

It is split for easier reviewing.

v6:
  * add missing call to rte_eth_dev_probing_finish()
  * update doc to point to MUSDK 18.09
  * add mvep lib to LDLIBS in mvneta Makefile

v5:
  * fixed wrong order of clenup in mvneta_eth_dev_create()
  * inlined one auxilary function (mvneta_priv_create())

v4:
  * rebased on top of next-net (DEV_RX_OFFLOAD_CRC_STRIP removed)
  * Rx/Tx functionality moved to new mvneta_rxtx.c file
  * removed eth_mvneta alias (and docs updated accordingly)
  * fixed additional review comments

v3:
    No changes against v2, just resubmitting again to have clean patch
    set after faulty format-patch.  My apologies for the noise.

v2:
  * fixed couple of checkpatch warnings
  * removed '\n' from MVNETA_LOG invocations (appended by the macro)
  * removed unused MVNETA_MUSDK_DMA_MEMSIZE define
  * changed one printf into MVNETA_LOG
  * removed __func__ from one MVNETA_LOG invocation (inserted
    automatically by the macro)
  * minor grammar/spelling correction in comments
  * removed license text from file with SPDX tag (mvneta.rst)
  * removed misleading part of comment for mvneta_shadow_txq
  * changed authorship of the patches to the original author

Natalie Samsonov (1):
  net/mvneta: add reset statistics callback

Zyta Szpak (7):
  net/mvneta: add neta PMD skeleton
  net/mvneta: add Rx/Tx support
  net/mvneta: support for setting of MTU
  net/mvneta: add link update
  net/mvneta: support for promiscuous
  net/mvneta: add MAC filtering
  net/mvneta: add support for basic stats

 MAINTAINERS                                   |    8 +
 config/common_base                            |    5 +
 devtools/test-build.sh                        |    2 +
 doc/guides/nics/features/mvneta.ini           |   19 +
 doc/guides/nics/mvneta.rst                    |  161 ++++
 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                |   28 +
 drivers/net/mvneta/mvneta_ethdev.c            | 1020 +++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h            |   80 ++
 drivers/net/mvneta/mvneta_rxtx.c              |  850 +++++++++++++++++++++
 drivers/net/mvneta/mvneta_rxtx.h              |  168 ++++
 drivers/net/mvneta/rte_pmd_mvneta_version.map |    3 +
 mk/rte.app.mk                                 |    7 +-
 18 files changed, 2401 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/mvneta_rxtx.c
 create mode 100644 drivers/net/mvneta/mvneta_rxtx.h
 create mode 100644 drivers/net/mvneta/rte_pmd_mvneta_version.map

-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v6 1/8] net/mvneta: add neta PMD skeleton
  2018-10-01  9:26         ` [dpdk-dev] [PATCH v6 0/8] Add Marvell NETA PMD Andrzej Ostruszka
@ 2018-10-01  9:26           ` Andrzej Ostruszka
  2018-10-02 11:53             ` Ferruh Yigit
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
                             ` (7 subsequent siblings)
  8 siblings, 1 reply; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-01  9:26 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu

From: Zyta Szpak <zr@semihalf.com>

Add neta pmd driver skeleton providing base for the further
development.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
Signed-off-by: Andrzej Ostruszka <amo@semihalf.com>
---
 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            | 630 ++++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h            |  75 +++
 drivers/net/mvneta/rte_pmd_mvneta_version.map |   3 +
 mk/rte.app.mk                                 |   7 +-
 16 files changed, 970 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 <zr@semihalf.com>
+M: Dmitri Epshtein <dima@marvell.com>
+M: Natalie Samsonov <nsamsono@marvell.com>
+F: drivers/net/mvneta/
+F: doc/guides/nics/mvneta.rst
+F: doc/guides/nics/features/mvneta.ini
+
 Mellanox mlx4
 M: Matan Azrad <matan@mellanox.com>
 M: Shahaf Shuler <shahafs@mellanox.com>
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 () # <directory> <target> <options>
 		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..1421f44
--- /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.120-armada-18.09
+
+
+- MUSDK (Marvell User-Space SDK) sources
+
+  .. code-block:: console
+
+     git clone https://github.com/MarvellEmbeddedProcessors/musdk-marvell.git -b musdk-armada-18.09
+
+  MUSDK is a light-weight library that provides direct access to Marvell's
+  NETA. Alternatively prebuilt MUSDK library can be
+  requested from `Marvell Extranet <https://extranet.marvell.com>`_. 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-pp2=no --enable-neta
+
+- DPDK environment
+
+  Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>` 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=<toolchain>/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=<musdk>/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 41b9cd8..1c670af 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -88,6 +88,10 @@ New Features
   the specified port. The port must be stopped before the command call in order
   to reconfigure queues.
 
+* **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 5906283..8891e5b 100644
--- a/drivers/net/meson.build
+++ b/drivers/net/meson.build
@@ -22,6 +22,7 @@ drivers = ['af_packet',
 	'mlx4',
 	'mlx5',
 	'mvpp2',
+	'mvneta',
 	'netvsc',
 	'nfp',
 	'null', 'octeontx', 'pcap', 'qede', 'ring',
diff --git a/drivers/net/mvneta/Makefile b/drivers/net/mvneta/Makefile
new file mode 100644
index 0000000..170cec6
--- /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 -lrte_common_mvep
+
+# 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..74ef94d
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -0,0 +1,630 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Marvell International Ltd.
+ * Copyright(c) 2018 Semihalf.
+ * All rights reserved.
+ */
+
+#include <rte_ethdev_driver.h>
+#include <rte_kvargs.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_bus_vdev.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <rte_mvep_common.h>
+
+#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;
+
+	rte_eth_dev_probing_finish(eth_dev);
+	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 <drivers/mv_neta.h>
+#include <drivers/mv_neta_ppio.h>
+
+/** 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
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v6 2/8] net/mvneta: add Rx/Tx support
  2018-10-01  9:26         ` [dpdk-dev] [PATCH v6 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
@ 2018-10-01  9:26           ` Andrzej Ostruszka
  2018-10-02 11:54             ` Ferruh Yigit
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
                             ` (6 subsequent siblings)
  8 siblings, 1 reply; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-01  9:26 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu

From: Zyta Szpak <zr@semihalf.com>

Add part of PMD for actual reception/transmission.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |   3 +
 doc/guides/nics/mvneta.rst          |   4 +
 drivers/net/mvneta/Makefile         |   2 +-
 drivers/net/mvneta/meson.build      |   3 +-
 drivers/net/mvneta/mvneta_ethdev.c  |  51 ++-
 drivers/net/mvneta/mvneta_ethdev.h  |   4 +
 drivers/net/mvneta/mvneta_rxtx.c    | 850 ++++++++++++++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_rxtx.h    | 168 +++++++
 8 files changed, 1080 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/mvneta/mvneta_rxtx.c
 create mode 100644 drivers/net/mvneta/mvneta_rxtx.h

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index ba6fe4b..0a89e2f 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -7,5 +7,8 @@
 Speed capabilities   = Y
 Jumbo frame          = Y
 CRC offload          = Y
+L3 checksum offload  = Y
+L4 checksum offload  = Y
+Packet type parsing  = Y
 ARMv8                = Y
 Usage doc            = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index 1421f44..d46619f 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -27,9 +27,13 @@ Features of the MVNETA PMD are:
 
 - Start/stop
 - tx/rx_queue_setup
+- tx/rx_burst
 - Speed capabilities
 - Jumbo frame
 - CRC offload
+- L3 checksum offload
+- L4 checksum offload
+- Packet type parsing
 
 
 Limitations
diff --git a/drivers/net/mvneta/Makefile b/drivers/net/mvneta/Makefile
index 170cec6..05a0487 100644
--- a/drivers/net/mvneta/Makefile
+++ b/drivers/net/mvneta/Makefile
@@ -37,6 +37,6 @@ LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs -lrte_cfgfile
 LDLIBS += -lrte_bus_vdev -lrte_common_mvep
 
 # library source files
-SRCS-$(CONFIG_RTE_LIBRTE_MVNETA_PMD) += mvneta_ethdev.c
+SRCS-$(CONFIG_RTE_LIBRTE_MVNETA_PMD) += mvneta_ethdev.c mvneta_rxtx.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/mvneta/meson.build b/drivers/net/mvneta/meson.build
index 2f31954..c0b1bce 100644
--- a/drivers/net/mvneta/meson.build
+++ b/drivers/net/mvneta/meson.build
@@ -21,7 +21,8 @@ else
 endif
 
 sources = files(
-	'mvneta_ethdev.c'
+	'mvneta_ethdev.c',
+	'mvneta_rxtx.c'
 )
 
 deps += ['cfgfile', 'common_mvep']
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 74ef94d..bc9a3bf 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -6,8 +6,6 @@
 
 #include <rte_ethdev_driver.h>
 #include <rte_kvargs.h>
-#include <rte_log.h>
-#include <rte_malloc.h>
 #include <rte_bus_vdev.h>
 
 #include <stdio.h>
@@ -23,7 +21,7 @@
 
 #include <rte_mvep_common.h>
 
-#include "mvneta_ethdev.h"
+#include "mvneta_rxtx.h"
 
 
 #define MVNETA_IFACE_NAME_ARG "iface"
@@ -308,6 +306,18 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 		priv->uc_mc_flushed = 1;
 	}
 
+	/* Allocate buffers */
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+		int num = rxq->size;
+
+		ret = mvneta_buffs_alloc(priv, rxq, &num);
+		if (ret || num != rxq->size) {
+			rte_free(rxq);
+			return ret;
+		}
+	}
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up");
@@ -318,6 +328,8 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 	for (i = 0; i < dev->data->nb_tx_queues; i++)
 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
 
+	mvneta_set_tx_function(dev);
+
 	return 0;
 
 out:
@@ -336,11 +348,25 @@ static void
 mvneta_dev_stop(struct rte_eth_dev *dev)
 {
 	struct mvneta_priv *priv = dev->data->dev_private;
+	int i;
 
 	if (!priv->ppio)
 		return;
 
 	mvneta_dev_set_link_down(dev);
+	MVNETA_LOG(INFO, "Flushing rx queues");
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+
+		mvneta_rx_queue_flush(rxq);
+	}
+
+	MVNETA_LOG(INFO, "Flushing tx queues");
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		struct mvneta_txq *txq = dev->data->tx_queues[i];
+
+		mvneta_tx_queue_flush(txq);
+	}
 
 	neta_ppio_deinit(priv->ppio);
 
@@ -357,9 +383,20 @@ static void
 mvneta_dev_close(struct rte_eth_dev *dev)
 {
 	struct mvneta_priv *priv = dev->data->dev_private;
+	int i;
 
 	if (priv->ppio)
 		mvneta_dev_stop(dev);
+
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		mvneta_rx_queue_release(dev->data->rx_queues[i]);
+		dev->data->rx_queues[i] = NULL;
+	}
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		mvneta_tx_queue_release(dev->data->tx_queues[i]);
+		dev->data->tx_queues[i] = NULL;
+	}
 }
 
 /**
@@ -398,6 +435,12 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_set = mvneta_mac_addr_set,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
+	.rxq_info_get = mvneta_rxq_info_get,
+	.txq_info_get = mvneta_txq_info_get,
+	.rx_queue_setup = mvneta_rx_queue_setup,
+	.rx_queue_release = mvneta_rx_queue_release,
+	.tx_queue_setup = mvneta_tx_queue_setup,
+	.tx_queue_release = mvneta_tx_queue_release,
 };
 
 /**
@@ -448,6 +491,8 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
 	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
+	eth_dev->rx_pkt_burst = mvneta_rx_pkt_burst;
+	mvneta_set_tx_function(eth_dev);
 	eth_dev->dev_ops = &mvneta_ops;
 
 	rte_eth_dev_probing_finish(eth_dev);
diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h
index 8b8d726..1a78a41 100644
--- a/drivers/net/mvneta/mvneta_ethdev.h
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -7,6 +7,10 @@
 #ifndef _MVNETA_ETHDEV_H_
 #define _MVNETA_ETHDEV_H_
 
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_log.h>
+
 /*
  * container_of is defined by both DPDK and MUSDK,
  * we'll declare only one version.
diff --git a/drivers/net/mvneta/mvneta_rxtx.c b/drivers/net/mvneta/mvneta_rxtx.c
new file mode 100644
index 0000000..d5ea5a8
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_rxtx.c
@@ -0,0 +1,850 @@
+#include "mvneta_rxtx.h"
+
+uint64_t cookie_addr_high = MVNETA_COOKIE_ADDR_INVALID;
+uint16_t rx_desc_free_thresh = MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN;
+
+static inline void
+mvneta_fill_shadowq(struct mvneta_shadow_txq *sq, struct rte_mbuf *buf)
+{
+	sq->ent[sq->head].cookie = (uint64_t)buf;
+	sq->ent[sq->head].addr = buf ?
+		rte_mbuf_data_iova_default(buf) : 0;
+
+	sq->head = (sq->head + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	sq->size++;
+}
+
+static inline void
+mvneta_fill_desc(struct neta_ppio_desc *desc, struct rte_mbuf *buf)
+{
+	neta_ppio_outq_desc_reset(desc);
+	neta_ppio_outq_desc_set_phys_addr(desc, rte_pktmbuf_iova(buf));
+	neta_ppio_outq_desc_set_pkt_offset(desc, 0);
+	neta_ppio_outq_desc_set_pkt_len(desc, rte_pktmbuf_data_len(buf));
+}
+
+/**
+ * Release already sent buffers to mempool.
+ *
+ * @param ppio
+ *   Pointer to the port structure.
+ * @param sq
+ *   Pointer to the shadow queue.
+ * @param qid
+ *   Queue id number.
+ * @param force
+ *   Force releasing packets.
+ */
+static inline void
+mvneta_sent_buffers_free(struct neta_ppio *ppio,
+			 struct mvneta_shadow_txq *sq, int qid)
+{
+	struct neta_buff_inf *entry;
+	uint16_t nb_done = 0;
+	int i;
+	int tail = sq->tail;
+
+	neta_ppio_get_num_outq_done(ppio, qid, &nb_done);
+
+	if (nb_done > sq->size) {
+		MVNETA_LOG(ERR, "nb_done: %d, sq->size %d",
+			   nb_done, sq->size);
+		return;
+	}
+
+	for (i = 0; i < nb_done; i++) {
+		entry = &sq->ent[tail];
+
+		if (unlikely(!entry->addr)) {
+			MVNETA_LOG(DEBUG,
+				"Shadow memory @%d: cookie(%lx), pa(%lx)!",
+				tail, (u64)entry->cookie,
+				(u64)entry->addr);
+			tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+			continue;
+		}
+
+		struct rte_mbuf *mbuf;
+
+		mbuf = (struct rte_mbuf *)
+			   (cookie_addr_high | entry->cookie);
+		rte_pktmbuf_free(mbuf);
+		tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+
+	sq->tail = tail;
+	sq->size -= nb_done;
+}
+
+/**
+ * Return packet type information and l3/l4 offsets.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ * @param l3_offset
+ *   l3 packet offset.
+ * @param l4_offset
+ *   l4 packet offset.
+ *
+ * @return
+ *   Packet type information.
+ */
+static inline uint64_t
+mvneta_desc_to_packet_type_and_offset(struct neta_ppio_desc *desc,
+				    uint8_t *l3_offset, uint8_t *l4_offset)
+{
+	enum neta_inq_l3_type l3_type;
+	enum neta_inq_l4_type l4_type;
+	uint64_t packet_type;
+
+	neta_ppio_inq_desc_get_l3_info(desc, &l3_type, l3_offset);
+	neta_ppio_inq_desc_get_l4_info(desc, &l4_type, l4_offset);
+
+	packet_type = RTE_PTYPE_L2_ETHER;
+
+	if (NETA_RXD_GET_VLAN_INFO(desc))
+		packet_type |= RTE_PTYPE_L2_ETHER_VLAN;
+
+	switch (l3_type) {
+	case NETA_INQ_L3_TYPE_IPV4_BAD:
+	case NETA_INQ_L3_TYPE_IPV4_OK:
+		packet_type |= RTE_PTYPE_L3_IPV4;
+		break;
+	case NETA_INQ_L3_TYPE_IPV6:
+		packet_type |= RTE_PTYPE_L3_IPV6;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l3 packet type");
+		break;
+	}
+
+	switch (l4_type) {
+	case NETA_INQ_L4_TYPE_TCP:
+		packet_type |= RTE_PTYPE_L4_TCP;
+		break;
+	case NETA_INQ_L4_TYPE_UDP:
+		packet_type |= RTE_PTYPE_L4_UDP;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l4 packet type");
+		break;
+	}
+
+	return packet_type;
+}
+
+/**
+ * Prepare offload information.
+ *
+ * @param ol_flags
+ *   Offload flags.
+ * @param packet_type
+ *   Packet type bitfield.
+ * @param l3_type
+ *   Pointer to the neta_ouq_l3_type structure.
+ * @param l4_type
+ *   Pointer to the neta_outq_l4_type structure.
+ * @param gen_l3_cksum
+ *   Will be set to 1 in case l3 checksum is computed.
+ * @param l4_cksum
+ *   Will be set to 1 in case l4 checksum is computed.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_prepare_proto_info(uint64_t ol_flags, uint32_t packet_type,
+			enum neta_outq_l3_type *l3_type,
+			enum neta_outq_l4_type *l4_type,
+			int *gen_l3_cksum,
+			int *gen_l4_cksum)
+{
+	/*
+	 * Based on ol_flags prepare information
+	 * for neta_ppio_outq_desc_set_proto_info() which setups descriptor
+	 * for offloading.
+	 */
+	if (ol_flags & PKT_TX_IPV4) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV4;
+		*gen_l3_cksum = ol_flags & PKT_TX_IP_CKSUM ? 1 : 0;
+	} else if (ol_flags & PKT_TX_IPV6) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV6;
+		/* no checksum for ipv6 header */
+		*gen_l3_cksum = 0;
+	} else {
+		/* if something different then stop processing */
+		return -1;
+	}
+
+	ol_flags &= PKT_TX_L4_MASK;
+	if ((packet_type & RTE_PTYPE_L4_TCP) &&
+	    ol_flags == PKT_TX_TCP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_TCP;
+		*gen_l4_cksum = 1;
+	} else if ((packet_type & RTE_PTYPE_L4_UDP) &&
+		   ol_flags == PKT_TX_UDP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_UDP;
+		*gen_l4_cksum = 1;
+	} else {
+		*l4_type = NETA_OUTQ_L4_TYPE_OTHER;
+		/* no checksum for other type */
+		*gen_l4_cksum = 0;
+	}
+
+	return 0;
+}
+
+/**
+ * Get offload information from the received packet descriptor.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ *
+ * @return
+ *   Mbuf offload flags.
+ */
+static inline uint64_t
+mvneta_desc_to_ol_flags(struct neta_ppio_desc *desc)
+{
+	uint64_t flags;
+	enum neta_inq_desc_status status;
+
+	status = neta_ppio_inq_desc_get_l3_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags = PKT_RX_IP_CKSUM_BAD;
+	else
+		flags = PKT_RX_IP_CKSUM_GOOD;
+
+	status = neta_ppio_inq_desc_get_l4_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags |= PKT_RX_L4_CKSUM_BAD;
+	else
+		flags |= PKT_RX_L4_CKSUM_GOOD;
+
+	return flags;
+}
+
+/**
+ * DPDK callback for transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts];
+
+	int i, ret, bytes_sent = 0;
+	uint16_t num, sq_free_size;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	if (unlikely(!nb_pkts || !q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+	if (unlikely(nb_pkts > sq_free_size)) {
+		MVNETA_LOG(DEBUG,
+			"No room in shadow queue for %d packets! %d packets will be sent.",
+			nb_pkts, sq_free_size);
+		nb_pkts = sq_free_size;
+	}
+
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		/* Fill first mbuf info in shadow queue */
+		mvneta_fill_shadowq(sq, mbuf);
+		mvneta_fill_desc(&descs[i], mbuf);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[i], l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = nb_pkts;
+	neta_ppio_send(q->priv->ppio, q->queue_id, descs, &nb_pkts);
+
+
+	/* number of packets that were not sent */
+	if (unlikely(num > nb_pkts)) {
+		for (i = nb_pkts; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE + sq->head - 1) &
+				MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = cookie_addr_high | sq->ent[sq->head].cookie;
+			bytes_sent -=
+				rte_pktmbuf_pkt_len((struct rte_mbuf *)addr);
+		}
+		sq->size -= num - nb_pkts;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/** DPDK callback for S/G transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_sg_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts * NETA_PPIO_DESC_NUM_FRAGS];
+	struct neta_ppio_sg_pkts pkts;
+	uint8_t frags[nb_pkts];
+	int i, j, ret, bytes_sent = 0;
+	int tail, tail_first;
+	uint16_t num, sq_free_size;
+	uint16_t nb_segs, total_descs = 0;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	pkts.frags = frags;
+	pkts.num = 0;
+
+	if (unlikely(!q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+	/* Save shadow queue free size */
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+
+	tail = 0;
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		struct rte_mbuf *seg = NULL;
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		nb_segs = mbuf->nb_segs;
+		total_descs += nb_segs;
+
+		/*
+		 * Check if total_descs does not exceed
+		 * shadow queue free size
+		 */
+		if (unlikely(total_descs > sq_free_size)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(DEBUG,
+				"No room in shadow queue for %d packets! "
+				"%d packets will be sent.",
+				nb_pkts, i);
+			break;
+		}
+
+
+		/* Check if nb_segs does not exceed the max nb of desc per
+		 * fragmented packet
+		 */
+		if (unlikely(nb_segs > NETA_PPIO_DESC_NUM_FRAGS)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(ERR,
+				"Too many segments. Packet won't be sent.");
+			break;
+		}
+
+		pkts.frags[pkts.num] = nb_segs;
+		pkts.num++;
+		tail_first = tail;
+
+		seg = mbuf;
+		for (j = 0; j < nb_segs - 1; j++) {
+			/* For the subsequent segments, set shadow queue
+			 * buffer to NULL
+			 */
+			mvneta_fill_shadowq(sq, NULL);
+			mvneta_fill_desc(&descs[tail], seg);
+
+			tail++;
+			seg = seg->next;
+		}
+		/* Put first mbuf info in last shadow queue entry */
+		mvneta_fill_shadowq(sq, mbuf);
+		/* Update descriptor with last segment */
+		mvneta_fill_desc(&descs[tail++], seg);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[tail_first],
+						   l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = total_descs;
+	neta_ppio_send_sg(q->priv->ppio, q->queue_id, descs, &total_descs,
+			  &pkts);
+
+	/* number of packets that were not sent */
+	if (unlikely(num > total_descs)) {
+		for (i = total_descs; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE +
+					sq->head - 1) &
+					MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = sq->ent[sq->head].cookie;
+			if (addr) {
+				struct rte_mbuf *mbuf;
+
+				mbuf = (struct rte_mbuf *)
+						(cookie_addr_high | addr);
+				bytes_sent -= rte_pktmbuf_pkt_len(mbuf);
+			}
+		}
+		sq->size -= num - total_descs;
+		nb_pkts = pkts.num;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/**
+ * Set tx burst function according to offload flag
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+void
+mvneta_set_tx_function(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	/* Use a simple Tx queue (no offloads, no multi segs) if possible */
+	if (priv->multiseg) {
+		MVNETA_LOG(INFO, "Using multi-segment tx callback");
+		dev->tx_pkt_burst = mvneta_tx_sg_pkt_burst;
+	} else {
+		MVNETA_LOG(INFO, "Using single-segment tx callback");
+		dev->tx_pkt_burst = mvneta_tx_pkt_burst;
+	}
+}
+
+/**
+ * DPDK callback for receive.
+ *
+ * @param rxq
+ *   Generic pointer to the receive queue.
+ * @param rx_pkts
+ *   Array to store received packets.
+ * @param nb_pkts
+ *   Maximum number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully received.
+ */
+uint16_t
+mvneta_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_rxq *q = rxq;
+	struct neta_ppio_desc descs[nb_pkts];
+	int i, ret, rx_done = 0, rx_dropped = 0;
+
+	if (unlikely(!q || !q->priv->ppio))
+		return 0;
+
+	ret = neta_ppio_recv(q->priv->ppio, q->queue_id,
+			descs, &nb_pkts);
+
+	if (unlikely(ret < 0)) {
+		MVNETA_LOG(ERR, "Failed to receive packets");
+		return 0;
+	}
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf;
+		uint8_t l3_offset, l4_offset;
+		enum neta_inq_desc_status status;
+		uint64_t addr;
+
+		addr = cookie_addr_high |
+			neta_ppio_inq_desc_get_cookie(&descs[i]);
+		mbuf = (struct rte_mbuf *)addr;
+
+		rte_pktmbuf_reset(mbuf);
+
+		/* drop packet in case of mac, overrun or resource error */
+		status = neta_ppio_inq_desc_get_l2_pkt_error(&descs[i]);
+		if (unlikely(status != NETA_DESC_ERR_OK)) {
+			/* Release the mbuf to the mempool since
+			 * it won't be transferred to tx path
+			 */
+			rte_pktmbuf_free(mbuf);
+			q->drop_mac++;
+			rx_dropped++;
+			continue;
+		}
+
+		mbuf->data_off += MVNETA_PKT_EFFEC_OFFS;
+		mbuf->pkt_len = neta_ppio_inq_desc_get_pkt_len(&descs[i]);
+		mbuf->data_len = mbuf->pkt_len;
+		mbuf->port = q->port_id;
+		mbuf->packet_type =
+			mvneta_desc_to_packet_type_and_offset(&descs[i],
+								&l3_offset,
+								&l4_offset);
+		mbuf->l2_len = l3_offset;
+		mbuf->l3_len = l4_offset - l3_offset;
+
+		if (likely(q->cksum_enabled))
+			mbuf->ol_flags = mvneta_desc_to_ol_flags(&descs[i]);
+
+		rx_pkts[rx_done++] = mbuf;
+		q->bytes_recv += mbuf->pkt_len;
+	}
+	q->pkts_processed += rx_done + rx_dropped;
+
+	if (q->pkts_processed > rx_desc_free_thresh) {
+		int buf_to_refill = rx_desc_free_thresh;
+
+		ret = mvneta_buffs_alloc(q->priv, q, &buf_to_refill);
+		if (ret)
+			MVNETA_LOG(ERR, "Refill failed");
+		q->pkts_processed -= buf_to_refill;
+	}
+
+	return rx_done;
+}
+
+/**
+ * DPDK callback to configure the receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   RX queue index.
+ * @param desc
+ *   Number of descriptors to configure in queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Thresholds parameters (unused_).
+ * @param mp
+ *   Memory pool for buffer allocations.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+int
+mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket,
+		      const struct rte_eth_rxconf *conf __rte_unused,
+		      struct rte_mempool *mp)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_rxq *rxq;
+	uint32_t frame_size, buf_size = rte_pktmbuf_data_room_size(mp);
+	uint32_t max_rx_pkt_len = dev->data->dev_conf.rxmode.max_rx_pkt_len;
+
+	frame_size = buf_size - RTE_PKTMBUF_HEADROOM - MVNETA_PKT_EFFEC_OFFS;
+
+	if (frame_size < max_rx_pkt_len) {
+		MVNETA_LOG(ERR,
+			"Mbuf size must be increased to %u bytes to hold up "
+			"to %u bytes of data.",
+			buf_size + max_rx_pkt_len - frame_size,
+			max_rx_pkt_len);
+		dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
+		MVNETA_LOG(INFO, "Setting max rx pkt len to %u",
+			dev->data->dev_conf.rxmode.max_rx_pkt_len);
+	}
+
+	if (dev->data->rx_queues[idx]) {
+		rte_free(dev->data->rx_queues[idx]);
+		dev->data->rx_queues[idx] = NULL;
+	}
+
+	rxq = rte_zmalloc_socket("rxq", sizeof(*rxq), 0, socket);
+	if (!rxq)
+		return -ENOMEM;
+
+	rxq->priv = priv;
+	rxq->mp = mp;
+	rxq->cksum_enabled = dev->data->dev_conf.rxmode.offloads &
+			     DEV_RX_OFFLOAD_IPV4_CKSUM;
+	rxq->queue_id = idx;
+	rxq->port_id = dev->data->port_id;
+	rxq->size = desc;
+	rx_desc_free_thresh = RTE_MIN(rx_desc_free_thresh, (desc / 2));
+	priv->ppio_params.inqs_params.tcs_params[MRVL_NETA_DEFAULT_TC].size =
+		desc;
+
+	dev->data->rx_queues[idx] = rxq;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to release the receive queue.
+ *
+ * @param rxq
+ *   Generic receive queue pointer.
+ */
+void
+mvneta_rx_queue_release(void *rxq)
+{
+	struct mvneta_rxq *q = rxq;
+
+	if (!q)
+		return;
+
+	/* If dev_stop was called already, mbufs are already
+	 * returned to mempool and ppio is deinitialized.
+	 * Skip this step.
+	 */
+
+	if (q->priv->ppio)
+		mvneta_rx_queue_flush(q);
+
+	rte_free(rxq);
+}
+
+/**
+ * DPDK callback to configure the transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   Transmit queue index.
+ * @param desc
+ *   Number of descriptors to configure in the queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Tx queue configuration parameters.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+int
+mvneta_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket, const struct rte_eth_txconf *conf)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_txq *txq;
+
+	if (dev->data->tx_queues[idx]) {
+		rte_free(dev->data->tx_queues[idx]);
+		dev->data->tx_queues[idx] = NULL;
+	}
+
+	txq = rte_zmalloc_socket("txq", sizeof(*txq), 0, socket);
+	if (!txq)
+		return -ENOMEM;
+
+	txq->priv = priv;
+	txq->queue_id = idx;
+	txq->port_id = dev->data->port_id;
+	txq->tx_deferred_start = conf->tx_deferred_start;
+	dev->data->tx_queues[idx] = txq;
+
+	priv->ppio_params.outqs_params.outqs_params[idx].size = desc;
+	priv->ppio_params.outqs_params.outqs_params[idx].weight = 1;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to release the transmit queue.
+ *
+ * @param txq
+ *   Generic transmit queue pointer.
+ */
+void
+mvneta_tx_queue_release(void *txq)
+{
+	struct mvneta_txq *q = txq;
+
+	if (!q)
+		return;
+
+	rte_free(q);
+}
+
+/**
+ * Return mbufs to mempool.
+ *
+ * @param rxq
+ *    Pointer to rx queue structure
+ * @param desc
+ *    Array of rx descriptors
+ */
+static void
+mvneta_recv_buffs_free(struct neta_ppio_desc *desc, uint16_t num)
+{
+	uint64_t addr;
+	uint8_t i;
+
+	for (i = 0; i < num; i++) {
+		if (desc) {
+			addr = cookie_addr_high |
+					neta_ppio_inq_desc_get_cookie(desc);
+			if (addr)
+				rte_pktmbuf_free((struct rte_mbuf *)addr);
+			desc++;
+		}
+	}
+}
+
+/**
+ * Flush single receive queue.
+ *
+ * @param rxq
+ *   Pointer to rx queue structure.
+ * @param descs
+ *   Array of rx descriptors
+ */
+void
+mvneta_rx_queue_flush(struct mvneta_rxq *rxq)
+{
+	struct neta_ppio_desc *descs;
+	struct neta_buff_inf *bufs;
+	uint16_t num;
+	int ret, i;
+
+	descs = rte_malloc("rxdesc", MRVL_NETA_RXD_MAX * sizeof(*descs), 0);
+	bufs = rte_malloc("buffs", MRVL_NETA_RXD_MAX * sizeof(*bufs), 0);
+
+	do {
+		num = MRVL_NETA_RXD_MAX;
+		ret = neta_ppio_recv(rxq->priv->ppio,
+				     rxq->queue_id,
+				     descs, &num);
+		mvneta_recv_buffs_free(descs, num);
+	} while (ret == 0 && num);
+
+	rxq->pkts_processed = 0;
+
+	num = MRVL_NETA_RXD_MAX;
+
+	neta_ppio_inq_get_all_buffs(rxq->priv->ppio, rxq->queue_id, bufs, &num);
+	MVNETA_LOG(INFO, "freeing %u unused bufs.", num);
+
+	for (i = 0; i < num; i++) {
+		uint64_t addr;
+		if (bufs[i].cookie) {
+			addr = cookie_addr_high | bufs[i].cookie;
+			rte_pktmbuf_free((struct rte_mbuf *)addr);
+		}
+	}
+
+	rte_free(descs);
+	rte_free(bufs);
+}
+
+/**
+ * Flush single transmit queue.
+ *
+ * @param txq
+ *     Pointer to tx queue structure
+ */
+void
+mvneta_tx_queue_flush(struct mvneta_txq *txq)
+{
+	struct mvneta_shadow_txq *sq = &txq->shadow_txq;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(txq->priv->ppio, sq,
+					 txq->queue_id);
+
+	/* free the rest of them */
+	while (sq->tail != sq->head) {
+		uint64_t addr = cookie_addr_high |
+			sq->ent[sq->tail].cookie;
+		rte_pktmbuf_free((struct rte_mbuf *)addr);
+		sq->tail = (sq->tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+	memset(sq, 0, sizeof(*sq));
+}
+
+/**
+ * DPDK callback to get information about specific receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param rx_queue_id
+ *   Receive queue index.
+ * @param qinfo
+ *   Receive queue information structure.
+ */
+void
+mvneta_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		    struct rte_eth_rxq_info *qinfo)
+{
+	struct mvneta_rxq *q = dev->data->rx_queues[rx_queue_id];
+
+	qinfo->mp = q->mp;
+	qinfo->nb_desc = q->size;
+}
+
+/**
+ * DPDK callback to get information about specific transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param tx_queue_id
+ *   Transmit queue index.
+ * @param qinfo
+ *   Transmit queue information structure.
+ */
+void
+mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		    struct rte_eth_txq_info *qinfo)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	qinfo->nb_desc =
+		priv->ppio_params.outqs_params.outqs_params[tx_queue_id].size;
+}
diff --git a/drivers/net/mvneta/mvneta_rxtx.h b/drivers/net/mvneta/mvneta_rxtx.h
new file mode 100644
index 0000000..7867c18
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_rxtx.h
@@ -0,0 +1,168 @@
+#ifndef _MVNETA_RXTX_H_
+#define _MVNETA_RXTX_H_
+
+#include "mvneta_ethdev.h"
+
+#define MVNETA_PKT_EFFEC_OFFS (MRVL_NETA_PKT_OFFS + MV_MH_SIZE)
+
+#define MRVL_NETA_DEFAULT_TC 0
+
+/** Maximum number of descriptors in shadow queue. Must be power of 2 */
+#define MRVL_NETA_TX_SHADOWQ_SIZE MRVL_NETA_TXD_MAX
+
+/** Shadow queue size mask (since shadow queue size is power of 2) */
+#define MRVL_NETA_TX_SHADOWQ_MASK (MRVL_NETA_TX_SHADOWQ_SIZE - 1)
+
+/** Minimum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN	16
+
+/** Maximum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX	64
+
+#define MVNETA_COOKIE_ADDR_INVALID ~0ULL
+#define MVNETA_COOKIE_HIGH_ADDR_SHIFT	(sizeof(neta_cookie_t) * 8)
+#define MVNETA_COOKIE_HIGH_ADDR_MASK	(~0ULL << MVNETA_COOKIE_HIGH_ADDR_SHIFT)
+
+#define MVNETA_SET_COOKIE_HIGH_ADDR(addr) {				\
+	if (unlikely(cookie_addr_high == MVNETA_COOKIE_ADDR_INVALID))	\
+		cookie_addr_high =					\
+			(uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK;\
+}
+
+#define MVNETA_CHECK_COOKIE_HIGH_ADDR(addr)			\
+	((likely(cookie_addr_high ==				\
+	((uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK))) ? 1 : 0)
+
+/*
+ * To use buffer harvesting based on loopback port shadow queue structure
+ * was introduced for buffers information bookkeeping.
+ */
+struct mvneta_shadow_txq {
+	int head;           /* write index - used when sending buffers */
+	int tail;           /* read index - used when releasing buffers */
+	u16 size;           /* queue occupied size */
+	struct neta_buff_inf ent[MRVL_NETA_TX_SHADOWQ_SIZE]; /* q entries */
+};
+
+struct mvneta_rxq {
+	struct mvneta_priv *priv;
+	struct rte_mempool *mp;
+	int queue_id;
+	int port_id;
+	int size;
+	int cksum_enabled;
+	uint64_t bytes_recv;
+	uint64_t drop_mac;
+	uint64_t pkts_processed;
+};
+
+
+struct mvneta_txq {
+	struct mvneta_priv *priv;
+	int queue_id;
+	int port_id;
+	uint64_t bytes_sent;
+	struct mvneta_shadow_txq shadow_txq;
+	int tx_deferred_start;
+};
+
+extern uint64_t cookie_addr_high;
+extern uint16_t rx_desc_free_thresh;
+
+static inline int
+mvneta_buffs_refill(struct mvneta_priv *priv, struct mvneta_rxq *rxq, u16 *num)
+{
+	struct rte_mbuf *mbufs[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	struct neta_buff_inf entries[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	int i, ret;
+	uint16_t nb_desc = *num;
+
+	ret = rte_pktmbuf_alloc_bulk(rxq->mp, mbufs, nb_desc);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to allocate %u mbufs.", nb_desc);
+		*num = 0;
+		return -1;
+	}
+
+	MVNETA_SET_COOKIE_HIGH_ADDR(mbufs[0]);
+
+	for (i = 0; i < nb_desc; i++) {
+		if (unlikely(!MVNETA_CHECK_COOKIE_HIGH_ADDR(mbufs[i]))) {
+			MVNETA_LOG(ERR,
+				"mbuf virt high addr 0x%lx out of range 0x%lx",
+				(uint64_t)mbufs[i] >> 32,
+				cookie_addr_high >> 32);
+			*num = 0;
+			goto out;
+		}
+		entries[i].addr = rte_mbuf_data_iova_default(mbufs[i]);
+		entries[i].cookie = (neta_cookie_t)(uint64_t)mbufs[i];
+	}
+	neta_ppio_inq_put_buffs(priv->ppio, rxq->queue_id, entries, num);
+
+out:
+	for (i = *num; i < nb_desc; i++)
+		rte_pktmbuf_free(mbufs[i]);
+
+	return 0;
+}
+
+/**
+ * Allocate buffers from mempool
+ * and store addresses in rx descriptors.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_buffs_alloc(struct mvneta_priv *priv, struct mvneta_rxq *rxq, int *num)
+{
+	uint16_t nb_desc, nb_desc_burst, sent = 0;
+	int ret = 0;
+
+	nb_desc = *num;
+
+	do {
+		nb_desc_burst =
+			(nb_desc < MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX) ?
+			nb_desc : MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX;
+
+		ret = mvneta_buffs_refill(priv, rxq, &nb_desc_burst);
+		if (unlikely(ret || !nb_desc_burst))
+			break;
+
+		sent += nb_desc_burst;
+		nb_desc -= nb_desc_burst;
+
+	} while (nb_desc);
+
+	*num = sent;
+
+	return ret;
+}
+
+void mvneta_rx_queue_flush(struct mvneta_rxq *rxq);
+void mvneta_tx_queue_flush(struct mvneta_txq *txq);
+
+void mvneta_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+			 struct rte_eth_rxq_info *qinfo);
+void mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+			 struct rte_eth_txq_info *qinfo);
+
+void mvneta_set_tx_function(struct rte_eth_dev *dev);
+uint16_t
+mvneta_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
+
+int
+mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket,
+		      const struct rte_eth_rxconf *conf __rte_unused,
+		      struct rte_mempool *mp);
+int
+mvneta_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket, const struct rte_eth_txconf *conf);
+
+void mvneta_rx_queue_release(void *rxq);
+void mvneta_tx_queue_release(void *txq);
+
+#endif /* _MVNETA_RXTX_H_ */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v6 3/8] net/mvneta: support for setting of MTU
  2018-10-01  9:26         ` [dpdk-dev] [PATCH v6 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
@ 2018-10-01  9:26           ` Andrzej Ostruszka
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 4/8] net/mvneta: add link update Andrzej Ostruszka
                             ` (5 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-01  9:26 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu

From: Zyta Szpak <zr@semihalf.com>

Add callback for setting of MTU.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 78 +++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 0a89e2f..bc4e400 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -5,6 +5,7 @@
 ;
 [Features]
 Speed capabilities   = Y
+MTU update           = Y
 Jumbo frame          = Y
 CRC offload          = Y
 L3 checksum offload  = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index d46619f..b9f87f4 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -30,6 +30,7 @@ Features of the MVNETA PMD are:
 - tx/rx_burst
 - Speed capabilities
 - Jumbo frame
+- MTU update
 - CRC offload
 - L3 checksum offload
 - L4 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index bc9a3bf..a3cefeb 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -221,6 +221,77 @@ mvneta_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
 }
 
 /**
+ * DPDK callback to change the MTU.
+ *
+ * Setting the MTU affects hardware MRU (packets larger than the MRU
+ * will be dropped).
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param mtu
+ *   New MTU.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	uint16_t mbuf_data_size = 0; /* SW buffer size */
+	uint16_t mru;
+	int ret;
+
+	mru = MRVL_NETA_MTU_TO_MRU(mtu);
+	/*
+	 * min_rx_buf_size is equal to mbuf data size
+	 * if pmd didn't set it differently
+	 */
+	mbuf_data_size = dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM;
+	/* Prevent PMD from:
+	 * - setting mru greater than the mbuf size resulting in
+	 * hw and sw buffer size mismatch
+	 * - setting mtu that requires the support of scattered packets
+	 * when this feature has not been enabled/supported so far.
+	 */
+	if (!dev->data->scattered_rx &&
+	    (mru + MRVL_NETA_PKT_OFFS > mbuf_data_size)) {
+		mru = mbuf_data_size - MRVL_NETA_PKT_OFFS;
+		mtu = MRVL_NETA_MRU_TO_MTU(mru);
+		MVNETA_LOG(WARNING, "MTU too big, max MTU possible limitted by"
+			" current mbuf size: %u. Set MTU to %u, MRU to %u",
+			mbuf_data_size, mtu, mru);
+	}
+
+	if (mtu < ETHER_MIN_MTU || mru > MVNETA_PKT_SIZE_MAX) {
+		MVNETA_LOG(ERR, "Invalid MTU [%u] or MRU [%u]", mtu, mru);
+		return -EINVAL;
+	}
+
+	dev->data->mtu = mtu;
+	dev->data->dev_conf.rxmode.max_rx_pkt_len = mru - MV_MH_SIZE;
+
+	if (!priv->ppio)
+		/* It is OK. New MTU will be set later on mvneta_dev_start */
+		return 0;
+
+	ret = neta_ppio_set_mru(priv->ppio, mru);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MRU");
+		return ret;
+	}
+
+	ret = neta_ppio_set_mtu(priv->ppio, mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MTU");
+		return ret;
+	}
+	MVNETA_LOG(INFO, "MTU changed to %u, MRU = %u", mtu, mru);
+
+	return 0;
+}
+
+/**
  * DPDK callback to bring the link up.
  *
  * @param dev
@@ -318,6 +389,12 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 		}
 	}
 
+	ret = mvneta_mtu_set(dev, dev->data->mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to set MTU %d", dev->data->mtu);
+		goto out;
+	}
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up");
@@ -433,6 +510,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
 	.mac_addr_set = mvneta_mac_addr_set,
+	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v6 4/8] net/mvneta: add link update
  2018-10-01  9:26         ` [dpdk-dev] [PATCH v6 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                             ` (2 preceding siblings ...)
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
@ 2018-10-01  9:26           ` Andrzej Ostruszka
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
                             ` (4 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-01  9:26 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu

From: Zyta Szpak <zr@semihalf.com>

Add callback for updating information about link status/info.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 71 +++++++++++++++++++++++++++++++++++++
 3 files changed, 73 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index bc4e400..581ed31 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -5,6 +5,7 @@
 ;
 [Features]
 Speed capabilities   = Y
+Link status          = Y
 MTU update           = Y
 Jumbo frame          = Y
 CRC offload          = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index b9f87f4..290bb1a 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -31,6 +31,7 @@ Features of the MVNETA PMD are:
 - Speed capabilities
 - Jumbo frame
 - MTU update
+- Link status
 - CRC offload
 - L3 checksum offload
 - L4 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index a3cefeb..3c450d2 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -477,6 +477,76 @@ mvneta_dev_close(struct rte_eth_dev *dev)
 }
 
 /**
+ * DPDK callback to retrieve physical link information.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param wait_to_complete
+ *   Wait for request completion (ignored).
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
+{
+	/*
+	 * TODO
+	 * once MUSDK provides necessary API use it here
+	 */
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct ethtool_cmd edata;
+	struct ifreq req;
+	int ret, fd, link_up;
+
+	if (!priv->ppio)
+		return -EPERM;
+
+	edata.cmd = ETHTOOL_GSET;
+
+	strcpy(req.ifr_name, dev->data->name);
+	req.ifr_data = (void *)&edata;
+
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd == -1)
+		return -EFAULT;
+	ret = ioctl(fd, SIOCETHTOOL, &req);
+	if (ret == -1) {
+		close(fd);
+		return -EFAULT;
+	}
+
+	close(fd);
+
+	switch (ethtool_cmd_speed(&edata)) {
+	case SPEED_10:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_10M;
+		break;
+	case SPEED_100:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_100M;
+		break;
+	case SPEED_1000:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_1G;
+		break;
+	case SPEED_2500:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_2_5G;
+		break;
+	default:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE;
+	}
+
+	dev->data->dev_link.link_duplex = edata.duplex ? ETH_LINK_FULL_DUPLEX :
+							 ETH_LINK_HALF_DUPLEX;
+	dev->data->dev_link.link_autoneg = edata.autoneg ? ETH_LINK_AUTONEG :
+							   ETH_LINK_FIXED;
+
+	neta_ppio_get_link_state(priv->ppio, &link_up);
+	dev->data->dev_link.link_status = link_up ? ETH_LINK_UP : ETH_LINK_DOWN;
+
+	return 0;
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -509,6 +579,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_up = mvneta_dev_set_link_up,
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
+	.link_update = mvneta_link_update,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v6 5/8] net/mvneta: support for promiscuous
  2018-10-01  9:26         ` [dpdk-dev] [PATCH v6 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                             ` (3 preceding siblings ...)
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 4/8] net/mvneta: add link update Andrzej Ostruszka
@ 2018-10-01  9:26           ` Andrzej Ostruszka
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
                             ` (3 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-01  9:26 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu

From: Zyta Szpak <zr@semihalf.com>

Add callbacks for enabling/disabling of promiscuous mode.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 54 +++++++++++++++++++++++++++++++++++++
 3 files changed, 56 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 581ed31..6a140a3 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -8,6 +8,7 @@ Speed capabilities   = Y
 Link status          = Y
 MTU update           = Y
 Jumbo frame          = Y
+Promiscuous mode     = Y
 CRC offload          = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index 290bb1a..dc93164 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -31,6 +31,7 @@ Features of the MVNETA PMD are:
 - Speed capabilities
 - Jumbo frame
 - MTU update
+- Promiscuous mode
 - Link status
 - CRC offload
 - L3 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 3c450d2..d3b8885 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -547,6 +547,58 @@ mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
 }
 
 /**
+ * DPDK callback to enable promiscuous mode.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_promiscuous_enable(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	int ret, en;
+
+	if (!priv->ppio)
+		return;
+
+	neta_ppio_get_promisc(priv->ppio, &en);
+	if (en) {
+		MVNETA_LOG(INFO, "Promiscuous already enabled");
+		return;
+	}
+
+	ret = neta_ppio_set_promisc(priv->ppio, 1);
+	if (ret)
+		MVNETA_LOG(ERR, "Failed to enable promiscuous mode");
+}
+
+/**
+ * DPDK callback to disable allmulticast mode.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_promiscuous_disable(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	int ret, en;
+
+	if (!priv->ppio)
+		return;
+
+	neta_ppio_get_promisc(priv->ppio, &en);
+	if (!en) {
+		MVNETA_LOG(INFO, "Promiscuous already disabled");
+		return;
+	}
+
+	ret = neta_ppio_set_promisc(priv->ppio, 0);
+	if (ret)
+		MVNETA_LOG(ERR, "Failed to disable promiscuous mode");
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -580,6 +632,8 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
 	.link_update = mvneta_link_update,
+	.promiscuous_enable = mvneta_promiscuous_enable,
+	.promiscuous_disable = mvneta_promiscuous_disable,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v6 6/8] net/mvneta: add MAC filtering
  2018-10-01  9:26         ` [dpdk-dev] [PATCH v6 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                             ` (4 preceding siblings ...)
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
@ 2018-10-01  9:26           ` Andrzej Ostruszka
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
                             ` (2 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-01  9:26 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu

From: Zyta Szpak <zr@semihalf.com>

Add callbacks for adding/removing MAC addresses.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 69 +++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 6a140a3..59c9c36 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -9,6 +9,7 @@ Link status          = Y
 MTU update           = Y
 Jumbo frame          = Y
 Promiscuous mode     = Y
+Unicast MAC filter   = Y
 CRC offload          = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index dc93164..ece549a 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -32,6 +32,7 @@ Features of the MVNETA PMD are:
 - Jumbo frame
 - MTU update
 - Promiscuous mode
+- Unicast MAC filter
 - Link status
 - CRC offload
 - L3 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index d3b8885..6e0dc3a 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -599,6 +599,73 @@ mvneta_promiscuous_disable(struct rte_eth_dev *dev)
 }
 
 /**
+ * DPDK callback to remove a MAC address.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param index
+ *   MAC address index.
+ */
+static void
+mvneta_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	char buf[ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	if (!priv->ppio)
+		return;
+
+	ret = neta_ppio_remove_mac_addr(priv->ppio,
+				       dev->data->mac_addrs[index].addr_bytes);
+	if (ret) {
+		ether_format_addr(buf, sizeof(buf),
+				  &dev->data->mac_addrs[index]);
+		MVNETA_LOG(ERR, "Failed to remove mac %s", buf);
+	}
+}
+
+/**
+ * DPDK callback to add a MAC address.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param mac_addr
+ *   MAC address to register.
+ * @param index
+ *   MAC address index.
+ * @param vmdq
+ *   VMDq pool index to associate address with (unused).
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
+		  uint32_t index, uint32_t vmdq __rte_unused)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	char buf[ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	if (index == 0)
+		/* For setting index 0, mrvl_mac_addr_set() should be used.*/
+		return -1;
+
+	if (!priv->ppio)
+		return 0;
+
+	ret = neta_ppio_add_mac_addr(priv->ppio, mac_addr->addr_bytes);
+	if (ret) {
+		ether_format_addr(buf, sizeof(buf), mac_addr);
+		MVNETA_LOG(ERR, "Failed to add mac %s", buf);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -634,6 +701,8 @@ static const struct eth_dev_ops mvneta_ops = {
 	.link_update = mvneta_link_update,
 	.promiscuous_enable = mvneta_promiscuous_enable,
 	.promiscuous_disable = mvneta_promiscuous_disable,
+	.mac_addr_remove = mvneta_mac_addr_remove,
+	.mac_addr_add = mvneta_mac_addr_add,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v6 7/8] net/mvneta: add support for basic stats
  2018-10-01  9:26         ` [dpdk-dev] [PATCH v6 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                             ` (5 preceding siblings ...)
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
@ 2018-10-01  9:26           ` Andrzej Ostruszka
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
  2018-10-03  7:22           ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-01  9:26 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu

From: Zyta Szpak <zr@semihalf.com>

Add support for getting of basic statistics for the driver.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 47 +++++++++++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 59c9c36..701eb03 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -14,5 +14,6 @@ CRC offload          = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
 Packet type parsing  = Y
+Basic stats          = Y
 ARMv8                = Y
 Usage doc            = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index ece549a..97b11f6 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -38,6 +38,7 @@ Features of the MVNETA PMD are:
 - L3 checksum offload
 - L4 checksum offload
 - Packet type parsing
+- Basic stats
 
 
 Limitations
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 6e0dc3a..6a5de2f 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -691,6 +691,52 @@ mvneta_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
 	return 0;
 }
 
+/**
+ * DPDK callback to get device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param stats
+ *   Stats structure output buffer.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct neta_ppio_statistics ppio_stats;
+	unsigned int ret;
+
+	if (!priv->ppio)
+		return -EPERM;
+
+	ret = neta_ppio_get_statistics(priv->ppio, &ppio_stats);
+	if (unlikely(ret)) {
+		MVNETA_LOG(ERR, "Failed to update port statistics");
+		return ret;
+	}
+
+	stats->ipackets += ppio_stats.rx_packets +
+			ppio_stats.rx_broadcast_packets +
+			ppio_stats.rx_multicast_packets;
+	stats->opackets += ppio_stats.tx_packets +
+			ppio_stats.tx_broadcast_packets +
+			ppio_stats.tx_multicast_packets;
+	stats->ibytes += ppio_stats.rx_bytes;
+	stats->obytes += ppio_stats.tx_bytes;
+	stats->imissed += ppio_stats.rx_discard +
+			  ppio_stats.rx_overrun;
+
+	stats->ierrors = ppio_stats.rx_packets_err +
+			ppio_stats.rx_errors +
+			ppio_stats.rx_crc_error;
+	stats->oerrors = ppio_stats.tx_errors;
+
+	return 0;
+}
+
 static const struct eth_dev_ops mvneta_ops = {
 	.dev_configure = mvneta_dev_configure,
 	.dev_start = mvneta_dev_start,
@@ -705,6 +751,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_add = mvneta_mac_addr_add,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
+	.stats_get = mvneta_stats_get,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v6 8/8] net/mvneta: add reset statistics callback
  2018-10-01  9:26         ` [dpdk-dev] [PATCH v6 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                             ` (6 preceding siblings ...)
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
@ 2018-10-01  9:26           ` Andrzej Ostruszka
  2018-10-03  7:22           ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-01  9:26 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu, Natalie Samsonov

From: Natalie Samsonov <nsamsono@marvell.com>

Add support for resetting of driver statistics.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 40 +++++++++++++++++++++++++++++++-------
 drivers/net/mvneta/mvneta_ethdev.h |  1 +
 2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 6a5de2f..6e65797 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -720,23 +720,48 @@ mvneta_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 
 	stats->ipackets += ppio_stats.rx_packets +
 			ppio_stats.rx_broadcast_packets +
-			ppio_stats.rx_multicast_packets;
+			ppio_stats.rx_multicast_packets -
+			priv->prev_stats.ipackets;
 	stats->opackets += ppio_stats.tx_packets +
 			ppio_stats.tx_broadcast_packets +
-			ppio_stats.tx_multicast_packets;
-	stats->ibytes += ppio_stats.rx_bytes;
-	stats->obytes += ppio_stats.tx_bytes;
+			ppio_stats.tx_multicast_packets -
+			priv->prev_stats.opackets;
+	stats->ibytes += ppio_stats.rx_bytes - priv->prev_stats.ibytes;
+	stats->obytes += ppio_stats.tx_bytes - priv->prev_stats.obytes;
 	stats->imissed += ppio_stats.rx_discard +
-			  ppio_stats.rx_overrun;
+			  ppio_stats.rx_overrun -
+			  priv->prev_stats.imissed;
 
 	stats->ierrors = ppio_stats.rx_packets_err +
 			ppio_stats.rx_errors +
-			ppio_stats.rx_crc_error;
-	stats->oerrors = ppio_stats.tx_errors;
+			ppio_stats.rx_crc_error -
+			priv->prev_stats.ierrors;
+	stats->oerrors = ppio_stats.tx_errors - priv->prev_stats.oerrors;
 
 	return 0;
 }
 
+/**
+ * DPDK callback to clear device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_stats_reset(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	unsigned int ret;
+
+	if (!priv->ppio)
+		return;
+
+	ret = mvneta_stats_get(dev, &priv->prev_stats);
+	if (unlikely(ret))
+		RTE_LOG(ERR, PMD, "Failed to reset port statistics");
+}
+
+
 static const struct eth_dev_ops mvneta_ops = {
 	.dev_configure = mvneta_dev_configure,
 	.dev_start = mvneta_dev_start,
@@ -752,6 +777,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.stats_get = mvneta_stats_get,
+	.stats_reset = mvneta_stats_reset,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h
index 1a78a41..eeea31a 100644
--- a/drivers/net/mvneta/mvneta_ethdev.h
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -67,6 +67,7 @@ struct mvneta_priv {
 	uint16_t nb_rx_queues;
 
 	uint64_t rate_max;
+	struct rte_eth_stats prev_stats;
 };
 
 /** Current log type. */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton
  2018-09-24 10:03           ` Ferruh Yigit
@ 2018-10-01  9:30             ` Andrzej Ostruszka
  0 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-01  9:30 UTC (permalink / raw)
  To: Ferruh Yigit, dev; +Cc: mw, zr, tdu, nadavh

First of all sorry for late reply.  I was trying to do some more testing
with this NETA and got stuck into what turned out to be HW issue.

On 24.09.2018 12:03, Ferruh Yigit wrote:
> On 9/20/2018 10:05 AM, Andrzej Ostruszka wrote:
[...]
>> +	MVNETA_LOG(INFO, "Perform MUSDK initializations");
>> +
>> +	ret = rte_mvep_init(MVEP_MOD_T_NETA, kvlist);
> 
> Giving build error for shared libraries [1], needs to link with rte_common_mvep,
> 
> In makefile needed: LDLIBS += -lrte_common_mvep,
> please check "mvpp2/Makefile"
> 
> 
> [1]
> mvneta_ethdev.o: In function `rte_pmd_mvneta_probe':
> mvneta_ethdev.c:(.text+0xa58): undefined reference to `rte_mvep_init'
> mvneta_ethdev.c:(.text+0xc98): undefined reference to `rte_mvep_deinit'
> mvneta_ethdev.c:(.text+0xcb4): undefined reference to `rte_mvep_deinit'
> mvneta_ethdev.o: In function `rte_pmd_mvneta_remove':
> mvneta_ethdev.c:(.text+0xe58): undefined reference to `rte_mvep_deinit'

I can't reproduce this, nevertheless I've added mvep to the LDLIBS in
the next version which I've just sent.

Best regards
Andrzej

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton
  2018-09-24  9:38               ` Ferruh Yigit
@ 2018-10-01  9:35                 ` Andrzej Ostruszka
  0 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-01  9:35 UTC (permalink / raw)
  To: Ferruh Yigit, dev; +Cc: mw, zr, tdu, nadavh

On 24.09.2018 11:38, Ferruh Yigit wrote:
> On 9/24/2018 10:35 AM, Ferruh Yigit wrote:
[...]
>>> Is there a specific build param required for musdk for neta support?
>>
>> I found it: --enable-bpool-dma=64 --enable-pp2=no --enable-neta,
> 
> btw, getting "configure: WARNING: unrecognized options: --enable-bpool-dma"
> FYI

This was removed in MUSDK 18.09 - I've updated mvneta doc to point to
proper 18.09 repos and use correct configure line.

Best regards
Andrzej

BTW - this is not supported, but in other mail you were thinking about
having MUSDK with both pp2 and neta enabled.  In my experience if you're
just interested in testing compilation and not intend to test on real HW
then you can enable both of them and have one MUSDK for both.

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v6 1/8] net/mvneta: add neta PMD skeleton
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
@ 2018-10-02 11:53             ` Ferruh Yigit
  0 siblings, 0 replies; 96+ messages in thread
From: Ferruh Yigit @ 2018-10-02 11:53 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev; +Cc: mw, nadavh, zr, tdu

On 10/1/2018 10:26 AM, Andrzej Ostruszka wrote:
> From: Zyta Szpak <zr@semihalf.com>
> 
> Add neta pmd driver skeleton providing base for the further
> development.
> 
> Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
> Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
> Signed-off-by: Dmitri Epshtein <dima@marvell.com>
> Signed-off-by: Zyta Szpak <zr@semihalf.com>
> Signed-off-by: Andrzej Ostruszka <amo@semihalf.com>
> ---
>  MAINTAINERS                                   |   8 +
>  config/common_base                            |   5 +
>  devtools/test-build.sh                        |   2 +
>  doc/guides/nics/features/mvneta.ini           |  11 +
>  doc/guides/nics/mvneta.rst                    | 152 +++++++

dpdk/doc/guides/nics/mvneta.rst: WARNING: document isn't included in any toctree

Please add document to doc/guides/nics/index.rst

<...>

> +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.
> +

Good to have another section to document "Runtime options" (iface)

> +
> +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=<toolchain>/bin/aarch64-linux-gnu-
> +   ./bootstrap
> +   ./configure --host=aarch64-linux-gnu --enable-bpool-dma=64

getting "configure: WARNING: unrecognized options: --enable-bpool-dma"

Is this config option still valid for 18.09?

<...>

> +
> +static int mvneta_dev_num;
> +static int mvneta_lcore_first;
> +static int mvneta_lcore_last;

These static variables seems assigned but not used, can you please check?


<...>

> +
> +RTE_PMD_REGISTER_VDEV(net_mvneta, pmd_mvneta_drv);

Need to document supported devargs with RTE_PMD_REGISTER_PARAM_STRING

<...>

> +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;

Do you need this private variable, isn't it duplicate of "dev->data->nb_rx_queues"?
And as far as I can see "dev->data->nb_rx_queues" one used.

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v6 2/8] net/mvneta: add Rx/Tx support
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
@ 2018-10-02 11:54             ` Ferruh Yigit
  0 siblings, 0 replies; 96+ messages in thread
From: Ferruh Yigit @ 2018-10-02 11:54 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev; +Cc: mw, nadavh, zr, tdu

On 10/1/2018 10:26 AM, Andrzej Ostruszka wrote:
> From: Zyta Szpak <zr@semihalf.com>
> 
> Add part of PMD for actual reception/transmission.
> 
> Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
> Signed-off-by: Dmitri Epshtein <dima@marvell.com>
> Signed-off-by: Zyta Szpak <zr@semihalf.com>

<...>

> @@ -0,0 +1,850 @@
> +#include "mvneta_rxtx.h"
> +
> +uint64_t cookie_addr_high = MVNETA_COOKIE_ADDR_INVALID;
> +uint16_t rx_desc_free_thresh = MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN;

Can these global variables be static?
If not please add a mvneta_ prefix, but please try to make them static.

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD
  2018-10-01  9:26         ` [dpdk-dev] [PATCH v6 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                             ` (7 preceding siblings ...)
  2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
@ 2018-10-03  7:22           ` Andrzej Ostruszka
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
                               ` (8 more replies)
  8 siblings, 9 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-03  7:22 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu, Andrzej Ostruszka

From: Andrzej Ostruszka <amo@semihalf.com>

This patch series introduces new PMD for Marvell NETA adapters (MVNETA).
See the documentation for more info.

It is split for easier reviewing.

v7:
  Addressed last round of review comments:
  * improved documentation by listing it in toc, removing unsupported
    MUSDK option and documenting run time option
  * removed variables that are not really used
  * documented devargs via REGISTER_PARAM_STRING
  * implemented better separation between mvneta_ethdev.c and
    mvneta_rxtx.c (now mvneta_rxtx.h includes only prototypes of
    functions needed by mvneta_ethdev.c)

v6:
  * add missing call to rte_eth_dev_probing_finish()
  * update doc to point to MUSDK 18.09
  * add mvep lib to LDLIBS in mvneta Makefile

v5:
  * fixed wrong order of clenup in mvneta_eth_dev_create()
  * inlined one auxilary function (mvneta_priv_create())

v4:
  * rebased on top of next-net (DEV_RX_OFFLOAD_CRC_STRIP removed)
  * Rx/Tx functionality moved to new mvneta_rxtx.c file
  * removed eth_mvneta alias (and docs updated accordingly)
  * fixed additional review comments

v3:
    No changes against v2, just resubmitting again to have clean patch
    set after faulty format-patch.  My apologies for the noise.

v2:
  * fixed couple of checkpatch warnings
  * removed '\n' from MVNETA_LOG invocations (appended by the macro)
  * removed unused MVNETA_MUSDK_DMA_MEMSIZE define
  * changed one printf into MVNETA_LOG
  * removed __func__ from one MVNETA_LOG invocation (inserted
    automatically by the macro)
  * minor grammar/spelling correction in comments
  * removed license text from file with SPDX tag (mvneta.rst)
  * removed misleading part of comment for mvneta_shadow_txq
  * changed authorship of the patches to the original author

Natalie Samsonov (1):
  net/mvneta: add reset statistics callback

Zyta Szpak (7):
  net/mvneta: add neta PMD skeleton
  net/mvneta: add Rx/Tx support
  net/mvneta: support for setting of MTU
  net/mvneta: add link update
  net/mvneta: support for promiscuous
  net/mvneta: add MAC filtering
  net/mvneta: add support for basic stats

 MAINTAINERS                                   |    8 +
 config/common_base                            |    5 +
 devtools/test-build.sh                        |    2 +
 doc/guides/nics/features/mvneta.ini           |   19 +
 doc/guides/nics/index.rst                     |    1 +
 doc/guides/nics/mvneta.rst                    |  171 +++++
 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                |   28 +
 drivers/net/mvneta/mvneta_ethdev.c            |  993 ++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h            |   79 ++
 drivers/net/mvneta/mvneta_rxtx.c              | 1021 +++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_rxtx.h              |   32 +
 drivers/net/mvneta/rte_pmd_mvneta_version.map |    3 +
 mk/rte.app.mk                                 |    7 +-
 19 files changed, 2419 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/mvneta_rxtx.c
 create mode 100644 drivers/net/mvneta/mvneta_rxtx.h
 create mode 100644 drivers/net/mvneta/rte_pmd_mvneta_version.map

-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v7 1/8] net/mvneta: add neta PMD skeleton
  2018-10-03  7:22           ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Andrzej Ostruszka
@ 2018-10-03  7:22             ` Andrzej Ostruszka
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
                               ` (7 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-03  7:22 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu

From: Zyta Szpak <zr@semihalf.com>

Add neta pmd driver skeleton providing base for the further
development.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
Signed-off-by: Andrzej Ostruszka <amo@semihalf.com>
---
 MAINTAINERS                                   |   8 +
 config/common_base                            |   5 +
 devtools/test-build.sh                        |   2 +
 doc/guides/nics/features/mvneta.ini           |  11 +
 doc/guides/nics/index.rst                     |   1 +
 doc/guides/nics/mvneta.rst                    | 162 +++++++
 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            | 625 ++++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_ethdev.h            |  74 +++
 drivers/net/mvneta/rte_pmd_mvneta_version.map |   3 +
 mk/rte.app.mk                                 |   7 +-
 17 files changed, 975 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 <zr@semihalf.com>
+M: Dmitri Epshtein <dima@marvell.com>
+M: Natalie Samsonov <nsamsono@marvell.com>
+F: drivers/net/mvneta/
+F: doc/guides/nics/mvneta.rst
+F: doc/guides/nics/features/mvneta.ini
+
 Mellanox mlx4
 M: Matan Azrad <matan@mellanox.com>
 M: Shahaf Shuler <shahafs@mellanox.com>
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 () # <directory> <target> <options>
 		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/index.rst b/doc/guides/nics/index.rst
index 59f6063..9aa639d 100644
--- a/doc/guides/nics/index.rst
+++ b/doc/guides/nics/index.rst
@@ -33,6 +33,7 @@ Network Interface Controller Drivers
     mlx4
     mlx5
     mvpp2
+    mvneta
     netvsc
     nfp
     octeontx
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
new file mode 100644
index 0000000..5f4559c
--- /dev/null
+++ b/doc/guides/nics/mvneta.rst
@@ -0,0 +1,162 @@
+..  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.120-armada-18.09
+
+
+- MUSDK (Marvell User-Space SDK) sources
+
+  .. code-block:: console
+
+     git clone https://github.com/MarvellEmbeddedProcessors/musdk-marvell.git -b musdk-armada-18.09
+
+  MUSDK is a light-weight library that provides direct access to Marvell's
+  NETA. Alternatively prebuilt MUSDK library can be
+  requested from `Marvell Extranet <https://extranet.marvell.com>`_. 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-pp2=no --enable-neta
+
+- DPDK environment
+
+  Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>` to setup
+  DPDK environment.
+
+Pre-Installation Configuration
+------------------------------
+
+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.
+
+Runtime options
+~~~~~~~~~~~~~~~
+
+The following ``devargs`` options can be enabled at runtime. They must
+be passed as part of EAL arguments.
+
+- ``iface`` (mandatory, with no default value)
+
+  The name of port (owned by MUSDK) that should be enabled in DPDK.
+  This options can be repeated resulting in a list of ports to be
+  enabled.  For instance below will enable ``eth0`` and ``eth1`` ports.
+
+.. 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=<toolchain>/bin/aarch64-linux-gnu-
+   ./bootstrap
+   ./configure --host=aarch64-linux-gnu --enable-pp2=no --enable-neta
+   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=<musdk>/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 41b9cd8..1c670af 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -88,6 +88,10 @@ New Features
   the specified port. The port must be stopped before the command call in order
   to reconfigure queues.
 
+* **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 5906283..8891e5b 100644
--- a/drivers/net/meson.build
+++ b/drivers/net/meson.build
@@ -22,6 +22,7 @@ drivers = ['af_packet',
 	'mlx4',
 	'mlx5',
 	'mvpp2',
+	'mvneta',
 	'netvsc',
 	'nfp',
 	'null', 'octeontx', 'pcap', 'qede', 'ring',
diff --git a/drivers/net/mvneta/Makefile b/drivers/net/mvneta/Makefile
new file mode 100644
index 0000000..170cec6
--- /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 -lrte_common_mvep
+
+# 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..8b9e262
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -0,0 +1,625 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Marvell International Ltd.
+ * Copyright(c) 2018 Semihalf.
+ * All rights reserved.
+ */
+
+#include <rte_ethdev_driver.h>
+#include <rte_kvargs.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_bus_vdev.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <rte_mvep_common.h>
+
+#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;
+
+/**
+ * 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;
+	/* 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;
+
+	rte_eth_dev_probing_finish(eth_dev);
+	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;
+	}
+
+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_PMD_REGISTER_PARAM_STRING(net_mvneta, "iface=<ifc>");
+
+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..46a29ee
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -0,0 +1,74 @@
+/* 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 <drivers/mv_neta.h>
+#include <drivers/mv_neta_ppio.h>
+
+/** 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;
+
+	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
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v7 2/8] net/mvneta: add Rx/Tx support
  2018-10-03  7:22           ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
@ 2018-10-03  7:22             ` Andrzej Ostruszka
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
                               ` (6 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-03  7:22 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu

From: Zyta Szpak <zr@semihalf.com>

Add part of PMD for actual reception/transmission.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Dmitri Epshtein <dima@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |    3 +
 doc/guides/nics/mvneta.rst          |    4 +
 drivers/net/mvneta/Makefile         |    2 +-
 drivers/net/mvneta/meson.build      |    3 +-
 drivers/net/mvneta/mvneta_ethdev.c  |   31 +-
 drivers/net/mvneta/mvneta_ethdev.h  |    4 +
 drivers/net/mvneta/mvneta_rxtx.c    | 1021 +++++++++++++++++++++++++++++++++++
 drivers/net/mvneta/mvneta_rxtx.h    |   32 ++
 8 files changed, 1094 insertions(+), 6 deletions(-)
 create mode 100644 drivers/net/mvneta/mvneta_rxtx.c
 create mode 100644 drivers/net/mvneta/mvneta_rxtx.h

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index ba6fe4b..0a89e2f 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -7,5 +7,8 @@
 Speed capabilities   = Y
 Jumbo frame          = Y
 CRC offload          = Y
+L3 checksum offload  = Y
+L4 checksum offload  = Y
+Packet type parsing  = Y
 ARMv8                = Y
 Usage doc            = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index 5f4559c..7ea003c 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -27,9 +27,13 @@ Features of the MVNETA PMD are:
 
 - Start/stop
 - tx/rx_queue_setup
+- tx/rx_burst
 - Speed capabilities
 - Jumbo frame
 - CRC offload
+- L3 checksum offload
+- L4 checksum offload
+- Packet type parsing
 
 
 Limitations
diff --git a/drivers/net/mvneta/Makefile b/drivers/net/mvneta/Makefile
index 170cec6..05a0487 100644
--- a/drivers/net/mvneta/Makefile
+++ b/drivers/net/mvneta/Makefile
@@ -37,6 +37,6 @@ LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs -lrte_cfgfile
 LDLIBS += -lrte_bus_vdev -lrte_common_mvep
 
 # library source files
-SRCS-$(CONFIG_RTE_LIBRTE_MVNETA_PMD) += mvneta_ethdev.c
+SRCS-$(CONFIG_RTE_LIBRTE_MVNETA_PMD) += mvneta_ethdev.c mvneta_rxtx.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/mvneta/meson.build b/drivers/net/mvneta/meson.build
index 2f31954..c0b1bce 100644
--- a/drivers/net/mvneta/meson.build
+++ b/drivers/net/mvneta/meson.build
@@ -21,7 +21,8 @@ else
 endif
 
 sources = files(
-	'mvneta_ethdev.c'
+	'mvneta_ethdev.c',
+	'mvneta_rxtx.c'
 )
 
 deps += ['cfgfile', 'common_mvep']
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 8b9e262..146b249 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -6,8 +6,6 @@
 
 #include <rte_ethdev_driver.h>
 #include <rte_kvargs.h>
-#include <rte_log.h>
-#include <rte_malloc.h>
 #include <rte_bus_vdev.h>
 
 #include <stdio.h>
@@ -23,7 +21,7 @@
 
 #include <rte_mvep_common.h>
 
-#include "mvneta_ethdev.h"
+#include "mvneta_rxtx.h"
 
 
 #define MVNETA_IFACE_NAME_ARG "iface"
@@ -305,6 +303,10 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 		priv->uc_mc_flushed = 1;
 	}
 
+	ret = mvneta_alloc_rx_bufs(dev);
+	if (ret)
+		goto out;
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up");
@@ -315,6 +317,8 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 	for (i = 0; i < dev->data->nb_tx_queues; i++)
 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
 
+	mvneta_set_tx_function(dev);
+
 	return 0;
 
 out:
@@ -338,7 +342,7 @@ mvneta_dev_stop(struct rte_eth_dev *dev)
 		return;
 
 	mvneta_dev_set_link_down(dev);
-
+	mvneta_flush_queues(dev);
 	neta_ppio_deinit(priv->ppio);
 
 	priv->ppio = NULL;
@@ -354,9 +358,20 @@ static void
 mvneta_dev_close(struct rte_eth_dev *dev)
 {
 	struct mvneta_priv *priv = dev->data->dev_private;
+	int i;
 
 	if (priv->ppio)
 		mvneta_dev_stop(dev);
+
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		mvneta_rx_queue_release(dev->data->rx_queues[i]);
+		dev->data->rx_queues[i] = NULL;
+	}
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		mvneta_tx_queue_release(dev->data->tx_queues[i]);
+		dev->data->tx_queues[i] = NULL;
+	}
 }
 
 /**
@@ -395,6 +410,12 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_set = mvneta_mac_addr_set,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
+	.rxq_info_get = mvneta_rxq_info_get,
+	.txq_info_get = mvneta_txq_info_get,
+	.rx_queue_setup = mvneta_rx_queue_setup,
+	.rx_queue_release = mvneta_rx_queue_release,
+	.tx_queue_setup = mvneta_tx_queue_setup,
+	.tx_queue_release = mvneta_tx_queue_release,
 };
 
 /**
@@ -445,6 +466,8 @@ mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
 	eth_dev->data->kdrv = RTE_KDRV_NONE;
 	eth_dev->data->dev_private = priv;
 	eth_dev->device = &vdev->device;
+	eth_dev->rx_pkt_burst = mvneta_rx_pkt_burst;
+	mvneta_set_tx_function(eth_dev);
 	eth_dev->dev_ops = &mvneta_ops;
 
 	rte_eth_dev_probing_finish(eth_dev);
diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h
index 46a29ee..836a5e9 100644
--- a/drivers/net/mvneta/mvneta_ethdev.h
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -7,6 +7,10 @@
 #ifndef _MVNETA_ETHDEV_H_
 #define _MVNETA_ETHDEV_H_
 
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_log.h>
+
 /*
  * container_of is defined by both DPDK and MUSDK,
  * we'll declare only one version.
diff --git a/drivers/net/mvneta/mvneta_rxtx.c b/drivers/net/mvneta/mvneta_rxtx.c
new file mode 100644
index 0000000..b10f69a
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_rxtx.c
@@ -0,0 +1,1021 @@
+#include "mvneta_rxtx.h"
+
+#define MVNETA_PKT_EFFEC_OFFS (MRVL_NETA_PKT_OFFS + MV_MH_SIZE)
+
+#define MRVL_NETA_DEFAULT_TC 0
+
+/** Maximum number of descriptors in shadow queue. Must be power of 2 */
+#define MRVL_NETA_TX_SHADOWQ_SIZE MRVL_NETA_TXD_MAX
+
+/** Shadow queue size mask (since shadow queue size is power of 2) */
+#define MRVL_NETA_TX_SHADOWQ_MASK (MRVL_NETA_TX_SHADOWQ_SIZE - 1)
+
+/** Minimum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN	16
+
+/** Maximum number of sent buffers to release from shadow queue to BM */
+#define MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX	64
+
+#define MVNETA_COOKIE_ADDR_INVALID ~0ULL
+#define MVNETA_COOKIE_HIGH_ADDR_SHIFT	(sizeof(neta_cookie_t) * 8)
+#define MVNETA_COOKIE_HIGH_ADDR_MASK	(~0ULL << MVNETA_COOKIE_HIGH_ADDR_SHIFT)
+
+#define MVNETA_SET_COOKIE_HIGH_ADDR(addr) {				\
+	if (unlikely(cookie_addr_high == MVNETA_COOKIE_ADDR_INVALID))	\
+		cookie_addr_high =					\
+			(uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK;\
+}
+
+#define MVNETA_CHECK_COOKIE_HIGH_ADDR(addr)		\
+	((likely(cookie_addr_high ==			\
+	((uint64_t)(addr) & MVNETA_COOKIE_HIGH_ADDR_MASK))) ? 1 : 0)
+
+struct mvneta_rxq {
+	struct mvneta_priv *priv;
+	struct rte_mempool *mp;
+	int queue_id;
+	int port_id;
+	int size;
+	int cksum_enabled;
+	uint64_t bytes_recv;
+	uint64_t drop_mac;
+	uint64_t pkts_processed;
+};
+
+/*
+ * To use buffer harvesting based on loopback port shadow queue structure
+ * was introduced for buffers information bookkeeping.
+ */
+struct mvneta_shadow_txq {
+	int head;           /* write index - used when sending buffers */
+	int tail;           /* read index - used when releasing buffers */
+	u16 size;           /* queue occupied size */
+	struct neta_buff_inf ent[MRVL_NETA_TX_SHADOWQ_SIZE]; /* q entries */
+};
+
+struct mvneta_txq {
+	struct mvneta_priv *priv;
+	int queue_id;
+	int port_id;
+	uint64_t bytes_sent;
+	struct mvneta_shadow_txq shadow_txq;
+	int tx_deferred_start;
+};
+
+static uint64_t cookie_addr_high = MVNETA_COOKIE_ADDR_INVALID;
+static uint16_t rx_desc_free_thresh = MRVL_NETA_BUF_RELEASE_BURST_SIZE_MIN;
+
+static inline int
+mvneta_buffs_refill(struct mvneta_priv *priv, struct mvneta_rxq *rxq, u16 *num)
+{
+	struct rte_mbuf *mbufs[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	struct neta_buff_inf entries[MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX];
+	int i, ret;
+	uint16_t nb_desc = *num;
+
+	ret = rte_pktmbuf_alloc_bulk(rxq->mp, mbufs, nb_desc);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to allocate %u mbufs.", nb_desc);
+		*num = 0;
+		return -1;
+	}
+
+	MVNETA_SET_COOKIE_HIGH_ADDR(mbufs[0]);
+
+	for (i = 0; i < nb_desc; i++) {
+		if (unlikely(!MVNETA_CHECK_COOKIE_HIGH_ADDR(mbufs[i]))) {
+			MVNETA_LOG(ERR,
+				"mbuf virt high addr 0x%lx out of range 0x%lx",
+				(uint64_t)mbufs[i] >> 32,
+				cookie_addr_high >> 32);
+			*num = 0;
+			goto out;
+		}
+		entries[i].addr = rte_mbuf_data_iova_default(mbufs[i]);
+		entries[i].cookie = (neta_cookie_t)(uint64_t)mbufs[i];
+	}
+	neta_ppio_inq_put_buffs(priv->ppio, rxq->queue_id, entries, num);
+
+out:
+	for (i = *num; i < nb_desc; i++)
+		rte_pktmbuf_free(mbufs[i]);
+
+	return 0;
+}
+
+/**
+ * Allocate buffers from mempool
+ * and store addresses in rx descriptors.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_buffs_alloc(struct mvneta_priv *priv, struct mvneta_rxq *rxq, int *num)
+{
+	uint16_t nb_desc, nb_desc_burst, sent = 0;
+	int ret = 0;
+
+	nb_desc = *num;
+
+	do {
+		nb_desc_burst =
+			(nb_desc < MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX) ?
+			nb_desc : MRVL_NETA_BUF_RELEASE_BURST_SIZE_MAX;
+
+		ret = mvneta_buffs_refill(priv, rxq, &nb_desc_burst);
+		if (unlikely(ret || !nb_desc_burst))
+			break;
+
+		sent += nb_desc_burst;
+		nb_desc -= nb_desc_burst;
+
+	} while (nb_desc);
+
+	*num = sent;
+
+	return ret;
+}
+static inline void
+mvneta_fill_shadowq(struct mvneta_shadow_txq *sq, struct rte_mbuf *buf)
+{
+	sq->ent[sq->head].cookie = (uint64_t)buf;
+	sq->ent[sq->head].addr = buf ?
+		rte_mbuf_data_iova_default(buf) : 0;
+
+	sq->head = (sq->head + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	sq->size++;
+}
+
+static inline void
+mvneta_fill_desc(struct neta_ppio_desc *desc, struct rte_mbuf *buf)
+{
+	neta_ppio_outq_desc_reset(desc);
+	neta_ppio_outq_desc_set_phys_addr(desc, rte_pktmbuf_iova(buf));
+	neta_ppio_outq_desc_set_pkt_offset(desc, 0);
+	neta_ppio_outq_desc_set_pkt_len(desc, rte_pktmbuf_data_len(buf));
+}
+
+/**
+ * Release already sent buffers to mempool.
+ *
+ * @param ppio
+ *   Pointer to the port structure.
+ * @param sq
+ *   Pointer to the shadow queue.
+ * @param qid
+ *   Queue id number.
+ * @param force
+ *   Force releasing packets.
+ */
+static inline void
+mvneta_sent_buffers_free(struct neta_ppio *ppio,
+			 struct mvneta_shadow_txq *sq, int qid)
+{
+	struct neta_buff_inf *entry;
+	uint16_t nb_done = 0;
+	int i;
+	int tail = sq->tail;
+
+	neta_ppio_get_num_outq_done(ppio, qid, &nb_done);
+
+	if (nb_done > sq->size) {
+		MVNETA_LOG(ERR, "nb_done: %d, sq->size %d",
+			   nb_done, sq->size);
+		return;
+	}
+
+	for (i = 0; i < nb_done; i++) {
+		entry = &sq->ent[tail];
+
+		if (unlikely(!entry->addr)) {
+			MVNETA_LOG(DEBUG,
+				"Shadow memory @%d: cookie(%lx), pa(%lx)!",
+				tail, (u64)entry->cookie,
+				(u64)entry->addr);
+			tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+			continue;
+		}
+
+		struct rte_mbuf *mbuf;
+
+		mbuf = (struct rte_mbuf *)
+			   (cookie_addr_high | entry->cookie);
+		rte_pktmbuf_free(mbuf);
+		tail = (tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+
+	sq->tail = tail;
+	sq->size -= nb_done;
+}
+
+/**
+ * Return packet type information and l3/l4 offsets.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ * @param l3_offset
+ *   l3 packet offset.
+ * @param l4_offset
+ *   l4 packet offset.
+ *
+ * @return
+ *   Packet type information.
+ */
+static inline uint64_t
+mvneta_desc_to_packet_type_and_offset(struct neta_ppio_desc *desc,
+				    uint8_t *l3_offset, uint8_t *l4_offset)
+{
+	enum neta_inq_l3_type l3_type;
+	enum neta_inq_l4_type l4_type;
+	uint64_t packet_type;
+
+	neta_ppio_inq_desc_get_l3_info(desc, &l3_type, l3_offset);
+	neta_ppio_inq_desc_get_l4_info(desc, &l4_type, l4_offset);
+
+	packet_type = RTE_PTYPE_L2_ETHER;
+
+	if (NETA_RXD_GET_VLAN_INFO(desc))
+		packet_type |= RTE_PTYPE_L2_ETHER_VLAN;
+
+	switch (l3_type) {
+	case NETA_INQ_L3_TYPE_IPV4_BAD:
+	case NETA_INQ_L3_TYPE_IPV4_OK:
+		packet_type |= RTE_PTYPE_L3_IPV4;
+		break;
+	case NETA_INQ_L3_TYPE_IPV6:
+		packet_type |= RTE_PTYPE_L3_IPV6;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l3 packet type");
+		break;
+	}
+
+	switch (l4_type) {
+	case NETA_INQ_L4_TYPE_TCP:
+		packet_type |= RTE_PTYPE_L4_TCP;
+		break;
+	case NETA_INQ_L4_TYPE_UDP:
+		packet_type |= RTE_PTYPE_L4_UDP;
+		break;
+	default:
+		packet_type |= RTE_PTYPE_UNKNOWN;
+		MVNETA_LOG(DEBUG, "Failed to recognize l4 packet type");
+		break;
+	}
+
+	return packet_type;
+}
+
+/**
+ * Prepare offload information.
+ *
+ * @param ol_flags
+ *   Offload flags.
+ * @param packet_type
+ *   Packet type bitfield.
+ * @param l3_type
+ *   Pointer to the neta_ouq_l3_type structure.
+ * @param l4_type
+ *   Pointer to the neta_outq_l4_type structure.
+ * @param gen_l3_cksum
+ *   Will be set to 1 in case l3 checksum is computed.
+ * @param l4_cksum
+ *   Will be set to 1 in case l4 checksum is computed.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static inline int
+mvneta_prepare_proto_info(uint64_t ol_flags, uint32_t packet_type,
+			enum neta_outq_l3_type *l3_type,
+			enum neta_outq_l4_type *l4_type,
+			int *gen_l3_cksum,
+			int *gen_l4_cksum)
+{
+	/*
+	 * Based on ol_flags prepare information
+	 * for neta_ppio_outq_desc_set_proto_info() which setups descriptor
+	 * for offloading.
+	 */
+	if (ol_flags & PKT_TX_IPV4) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV4;
+		*gen_l3_cksum = ol_flags & PKT_TX_IP_CKSUM ? 1 : 0;
+	} else if (ol_flags & PKT_TX_IPV6) {
+		*l3_type = NETA_OUTQ_L3_TYPE_IPV6;
+		/* no checksum for ipv6 header */
+		*gen_l3_cksum = 0;
+	} else {
+		/* if something different then stop processing */
+		return -1;
+	}
+
+	ol_flags &= PKT_TX_L4_MASK;
+	if ((packet_type & RTE_PTYPE_L4_TCP) &&
+	    ol_flags == PKT_TX_TCP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_TCP;
+		*gen_l4_cksum = 1;
+	} else if ((packet_type & RTE_PTYPE_L4_UDP) &&
+		   ol_flags == PKT_TX_UDP_CKSUM) {
+		*l4_type = NETA_OUTQ_L4_TYPE_UDP;
+		*gen_l4_cksum = 1;
+	} else {
+		*l4_type = NETA_OUTQ_L4_TYPE_OTHER;
+		/* no checksum for other type */
+		*gen_l4_cksum = 0;
+	}
+
+	return 0;
+}
+
+/**
+ * Get offload information from the received packet descriptor.
+ *
+ * @param desc
+ *   Pointer to the received packet descriptor.
+ *
+ * @return
+ *   Mbuf offload flags.
+ */
+static inline uint64_t
+mvneta_desc_to_ol_flags(struct neta_ppio_desc *desc)
+{
+	uint64_t flags;
+	enum neta_inq_desc_status status;
+
+	status = neta_ppio_inq_desc_get_l3_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags = PKT_RX_IP_CKSUM_BAD;
+	else
+		flags = PKT_RX_IP_CKSUM_GOOD;
+
+	status = neta_ppio_inq_desc_get_l4_pkt_error(desc);
+	if (unlikely(status != NETA_DESC_ERR_OK))
+		flags |= PKT_RX_L4_CKSUM_BAD;
+	else
+		flags |= PKT_RX_L4_CKSUM_GOOD;
+
+	return flags;
+}
+
+/**
+ * DPDK callback for transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts];
+
+	int i, ret, bytes_sent = 0;
+	uint16_t num, sq_free_size;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	if (unlikely(!nb_pkts || !q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+	if (unlikely(nb_pkts > sq_free_size)) {
+		MVNETA_LOG(DEBUG,
+			"No room in shadow queue for %d packets! %d packets will be sent.",
+			nb_pkts, sq_free_size);
+		nb_pkts = sq_free_size;
+	}
+
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		/* Fill first mbuf info in shadow queue */
+		mvneta_fill_shadowq(sq, mbuf);
+		mvneta_fill_desc(&descs[i], mbuf);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[i], l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = nb_pkts;
+	neta_ppio_send(q->priv->ppio, q->queue_id, descs, &nb_pkts);
+
+
+	/* number of packets that were not sent */
+	if (unlikely(num > nb_pkts)) {
+		for (i = nb_pkts; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE + sq->head - 1) &
+				MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = cookie_addr_high | sq->ent[sq->head].cookie;
+			bytes_sent -=
+				rte_pktmbuf_pkt_len((struct rte_mbuf *)addr);
+		}
+		sq->size -= num - nb_pkts;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/** DPDK callback for S/G transmit.
+ *
+ * @param txq
+ *   Generic pointer transmit queue.
+ * @param tx_pkts
+ *   Packets to transmit.
+ * @param nb_pkts
+ *   Number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully transmitted.
+ */
+static uint16_t
+mvneta_tx_sg_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_txq *q = txq;
+	struct mvneta_shadow_txq *sq;
+	struct neta_ppio_desc descs[nb_pkts * NETA_PPIO_DESC_NUM_FRAGS];
+	struct neta_ppio_sg_pkts pkts;
+	uint8_t frags[nb_pkts];
+	int i, j, ret, bytes_sent = 0;
+	int tail, tail_first;
+	uint16_t num, sq_free_size;
+	uint16_t nb_segs, total_descs = 0;
+	uint64_t addr;
+
+	sq = &q->shadow_txq;
+	pkts.frags = frags;
+	pkts.num = 0;
+
+	if (unlikely(!q->priv->ppio))
+		return 0;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(q->priv->ppio,
+					 sq, q->queue_id);
+	/* Save shadow queue free size */
+	sq_free_size = MRVL_NETA_TX_SHADOWQ_SIZE - sq->size - 1;
+
+	tail = 0;
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf = tx_pkts[i];
+		struct rte_mbuf *seg = NULL;
+		int gen_l3_cksum, gen_l4_cksum;
+		enum neta_outq_l3_type l3_type;
+		enum neta_outq_l4_type l4_type;
+
+		nb_segs = mbuf->nb_segs;
+		total_descs += nb_segs;
+
+		/*
+		 * Check if total_descs does not exceed
+		 * shadow queue free size
+		 */
+		if (unlikely(total_descs > sq_free_size)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(DEBUG,
+				"No room in shadow queue for %d packets! "
+				"%d packets will be sent.",
+				nb_pkts, i);
+			break;
+		}
+
+
+		/* Check if nb_segs does not exceed the max nb of desc per
+		 * fragmented packet
+		 */
+		if (unlikely(nb_segs > NETA_PPIO_DESC_NUM_FRAGS)) {
+			total_descs -= nb_segs;
+			MVNETA_LOG(ERR,
+				"Too many segments. Packet won't be sent.");
+			break;
+		}
+
+		pkts.frags[pkts.num] = nb_segs;
+		pkts.num++;
+		tail_first = tail;
+
+		seg = mbuf;
+		for (j = 0; j < nb_segs - 1; j++) {
+			/* For the subsequent segments, set shadow queue
+			 * buffer to NULL
+			 */
+			mvneta_fill_shadowq(sq, NULL);
+			mvneta_fill_desc(&descs[tail], seg);
+
+			tail++;
+			seg = seg->next;
+		}
+		/* Put first mbuf info in last shadow queue entry */
+		mvneta_fill_shadowq(sq, mbuf);
+		/* Update descriptor with last segment */
+		mvneta_fill_desc(&descs[tail++], seg);
+
+		bytes_sent += rte_pktmbuf_pkt_len(mbuf);
+
+		ret = mvneta_prepare_proto_info(mbuf->ol_flags,
+						mbuf->packet_type,
+						&l3_type, &l4_type,
+						&gen_l3_cksum,
+						&gen_l4_cksum);
+		if (unlikely(ret))
+			continue;
+
+		neta_ppio_outq_desc_set_proto_info(&descs[tail_first],
+						   l3_type, l4_type,
+						   mbuf->l2_len,
+						   mbuf->l2_len + mbuf->l3_len,
+						   gen_l3_cksum, gen_l4_cksum);
+	}
+	num = total_descs;
+	neta_ppio_send_sg(q->priv->ppio, q->queue_id, descs, &total_descs,
+			  &pkts);
+
+	/* number of packets that were not sent */
+	if (unlikely(num > total_descs)) {
+		for (i = total_descs; i < num; i++) {
+			sq->head = (MRVL_NETA_TX_SHADOWQ_SIZE +
+					sq->head - 1) &
+					MRVL_NETA_TX_SHADOWQ_MASK;
+			addr = sq->ent[sq->head].cookie;
+			if (addr) {
+				struct rte_mbuf *mbuf;
+
+				mbuf = (struct rte_mbuf *)
+						(cookie_addr_high | addr);
+				bytes_sent -= rte_pktmbuf_pkt_len(mbuf);
+			}
+		}
+		sq->size -= num - total_descs;
+		nb_pkts = pkts.num;
+	}
+
+	q->bytes_sent += bytes_sent;
+
+	return nb_pkts;
+}
+
+/**
+ * Set tx burst function according to offload flag
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+void
+mvneta_set_tx_function(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	/* Use a simple Tx queue (no offloads, no multi segs) if possible */
+	if (priv->multiseg) {
+		MVNETA_LOG(INFO, "Using multi-segment tx callback");
+		dev->tx_pkt_burst = mvneta_tx_sg_pkt_burst;
+	} else {
+		MVNETA_LOG(INFO, "Using single-segment tx callback");
+		dev->tx_pkt_burst = mvneta_tx_pkt_burst;
+	}
+}
+
+/**
+ * DPDK callback for receive.
+ *
+ * @param rxq
+ *   Generic pointer to the receive queue.
+ * @param rx_pkts
+ *   Array to store received packets.
+ * @param nb_pkts
+ *   Maximum number of packets in array.
+ *
+ * @return
+ *   Number of packets successfully received.
+ */
+uint16_t
+mvneta_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
+{
+	struct mvneta_rxq *q = rxq;
+	struct neta_ppio_desc descs[nb_pkts];
+	int i, ret, rx_done = 0, rx_dropped = 0;
+
+	if (unlikely(!q || !q->priv->ppio))
+		return 0;
+
+	ret = neta_ppio_recv(q->priv->ppio, q->queue_id,
+			descs, &nb_pkts);
+
+	if (unlikely(ret < 0)) {
+		MVNETA_LOG(ERR, "Failed to receive packets");
+		return 0;
+	}
+
+	for (i = 0; i < nb_pkts; i++) {
+		struct rte_mbuf *mbuf;
+		uint8_t l3_offset, l4_offset;
+		enum neta_inq_desc_status status;
+		uint64_t addr;
+
+		addr = cookie_addr_high |
+			neta_ppio_inq_desc_get_cookie(&descs[i]);
+		mbuf = (struct rte_mbuf *)addr;
+
+		rte_pktmbuf_reset(mbuf);
+
+		/* drop packet in case of mac, overrun or resource error */
+		status = neta_ppio_inq_desc_get_l2_pkt_error(&descs[i]);
+		if (unlikely(status != NETA_DESC_ERR_OK)) {
+			/* Release the mbuf to the mempool since
+			 * it won't be transferred to tx path
+			 */
+			rte_pktmbuf_free(mbuf);
+			q->drop_mac++;
+			rx_dropped++;
+			continue;
+		}
+
+		mbuf->data_off += MVNETA_PKT_EFFEC_OFFS;
+		mbuf->pkt_len = neta_ppio_inq_desc_get_pkt_len(&descs[i]);
+		mbuf->data_len = mbuf->pkt_len;
+		mbuf->port = q->port_id;
+		mbuf->packet_type =
+			mvneta_desc_to_packet_type_and_offset(&descs[i],
+								&l3_offset,
+								&l4_offset);
+		mbuf->l2_len = l3_offset;
+		mbuf->l3_len = l4_offset - l3_offset;
+
+		if (likely(q->cksum_enabled))
+			mbuf->ol_flags = mvneta_desc_to_ol_flags(&descs[i]);
+
+		rx_pkts[rx_done++] = mbuf;
+		q->bytes_recv += mbuf->pkt_len;
+	}
+	q->pkts_processed += rx_done + rx_dropped;
+
+	if (q->pkts_processed > rx_desc_free_thresh) {
+		int buf_to_refill = rx_desc_free_thresh;
+
+		ret = mvneta_buffs_alloc(q->priv, q, &buf_to_refill);
+		if (ret)
+			MVNETA_LOG(ERR, "Refill failed");
+		q->pkts_processed -= buf_to_refill;
+	}
+
+	return rx_done;
+}
+
+/**
+ * DPDK callback to configure the receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   RX queue index.
+ * @param desc
+ *   Number of descriptors to configure in queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Thresholds parameters (unused_).
+ * @param mp
+ *   Memory pool for buffer allocations.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+int
+mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket,
+		      const struct rte_eth_rxconf *conf __rte_unused,
+		      struct rte_mempool *mp)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_rxq *rxq;
+	uint32_t frame_size, buf_size = rte_pktmbuf_data_room_size(mp);
+	uint32_t max_rx_pkt_len = dev->data->dev_conf.rxmode.max_rx_pkt_len;
+
+	frame_size = buf_size - RTE_PKTMBUF_HEADROOM - MVNETA_PKT_EFFEC_OFFS;
+
+	if (frame_size < max_rx_pkt_len) {
+		MVNETA_LOG(ERR,
+			"Mbuf size must be increased to %u bytes to hold up "
+			"to %u bytes of data.",
+			buf_size + max_rx_pkt_len - frame_size,
+			max_rx_pkt_len);
+		dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
+		MVNETA_LOG(INFO, "Setting max rx pkt len to %u",
+			dev->data->dev_conf.rxmode.max_rx_pkt_len);
+	}
+
+	if (dev->data->rx_queues[idx]) {
+		rte_free(dev->data->rx_queues[idx]);
+		dev->data->rx_queues[idx] = NULL;
+	}
+
+	rxq = rte_zmalloc_socket("rxq", sizeof(*rxq), 0, socket);
+	if (!rxq)
+		return -ENOMEM;
+
+	rxq->priv = priv;
+	rxq->mp = mp;
+	rxq->cksum_enabled = dev->data->dev_conf.rxmode.offloads &
+			     DEV_RX_OFFLOAD_IPV4_CKSUM;
+	rxq->queue_id = idx;
+	rxq->port_id = dev->data->port_id;
+	rxq->size = desc;
+	rx_desc_free_thresh = RTE_MIN(rx_desc_free_thresh, (desc / 2));
+	priv->ppio_params.inqs_params.tcs_params[MRVL_NETA_DEFAULT_TC].size =
+		desc;
+
+	dev->data->rx_queues[idx] = rxq;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to configure the transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param idx
+ *   Transmit queue index.
+ * @param desc
+ *   Number of descriptors to configure in the queue.
+ * @param socket
+ *   NUMA socket on which memory must be allocated.
+ * @param conf
+ *   Tx queue configuration parameters.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+int
+mvneta_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket, const struct rte_eth_txconf *conf)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct mvneta_txq *txq;
+
+	if (dev->data->tx_queues[idx]) {
+		rte_free(dev->data->tx_queues[idx]);
+		dev->data->tx_queues[idx] = NULL;
+	}
+
+	txq = rte_zmalloc_socket("txq", sizeof(*txq), 0, socket);
+	if (!txq)
+		return -ENOMEM;
+
+	txq->priv = priv;
+	txq->queue_id = idx;
+	txq->port_id = dev->data->port_id;
+	txq->tx_deferred_start = conf->tx_deferred_start;
+	dev->data->tx_queues[idx] = txq;
+
+	priv->ppio_params.outqs_params.outqs_params[idx].size = desc;
+	priv->ppio_params.outqs_params.outqs_params[idx].weight = 1;
+
+	return 0;
+}
+
+/**
+ * DPDK callback to release the transmit queue.
+ *
+ * @param txq
+ *   Generic transmit queue pointer.
+ */
+void
+mvneta_tx_queue_release(void *txq)
+{
+	struct mvneta_txq *q = txq;
+
+	if (!q)
+		return;
+
+	rte_free(q);
+}
+
+/**
+ * Return mbufs to mempool.
+ *
+ * @param rxq
+ *    Pointer to rx queue structure
+ * @param desc
+ *    Array of rx descriptors
+ */
+static void
+mvneta_recv_buffs_free(struct neta_ppio_desc *desc, uint16_t num)
+{
+	uint64_t addr;
+	uint8_t i;
+
+	for (i = 0; i < num; i++) {
+		if (desc) {
+			addr = cookie_addr_high |
+					neta_ppio_inq_desc_get_cookie(desc);
+			if (addr)
+				rte_pktmbuf_free((struct rte_mbuf *)addr);
+			desc++;
+		}
+	}
+}
+
+int mvneta_alloc_rx_bufs(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	int ret = 0, i;
+
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+		int num = rxq->size;
+
+		ret = mvneta_buffs_alloc(priv, rxq, &num);
+		if (ret || num != rxq->size) {
+			rte_free(rxq);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * Flush single receive queue.
+ *
+ * @param rxq
+ *   Pointer to rx queue structure.
+ * @param descs
+ *   Array of rx descriptors
+ */
+static void
+mvneta_rx_queue_flush(struct mvneta_rxq *rxq)
+{
+	struct neta_ppio_desc *descs;
+	struct neta_buff_inf *bufs;
+	uint16_t num;
+	int ret, i;
+
+	descs = rte_malloc("rxdesc", MRVL_NETA_RXD_MAX * sizeof(*descs), 0);
+	bufs = rte_malloc("buffs", MRVL_NETA_RXD_MAX * sizeof(*bufs), 0);
+
+	do {
+		num = MRVL_NETA_RXD_MAX;
+		ret = neta_ppio_recv(rxq->priv->ppio,
+				     rxq->queue_id,
+				     descs, &num);
+		mvneta_recv_buffs_free(descs, num);
+	} while (ret == 0 && num);
+
+	rxq->pkts_processed = 0;
+
+	num = MRVL_NETA_RXD_MAX;
+
+	neta_ppio_inq_get_all_buffs(rxq->priv->ppio, rxq->queue_id, bufs, &num);
+	MVNETA_LOG(INFO, "freeing %u unused bufs.", num);
+
+	for (i = 0; i < num; i++) {
+		uint64_t addr;
+		if (bufs[i].cookie) {
+			addr = cookie_addr_high | bufs[i].cookie;
+			rte_pktmbuf_free((struct rte_mbuf *)addr);
+		}
+	}
+
+	rte_free(descs);
+	rte_free(bufs);
+}
+
+/**
+ * Flush single transmit queue.
+ *
+ * @param txq
+ *     Pointer to tx queue structure
+ */
+static void
+mvneta_tx_queue_flush(struct mvneta_txq *txq)
+{
+	struct mvneta_shadow_txq *sq = &txq->shadow_txq;
+
+	if (sq->size)
+		mvneta_sent_buffers_free(txq->priv->ppio, sq,
+					 txq->queue_id);
+
+	/* free the rest of them */
+	while (sq->tail != sq->head) {
+		uint64_t addr = cookie_addr_high |
+			sq->ent[sq->tail].cookie;
+		rte_pktmbuf_free((struct rte_mbuf *)addr);
+		sq->tail = (sq->tail + 1) & MRVL_NETA_TX_SHADOWQ_MASK;
+	}
+	memset(sq, 0, sizeof(*sq));
+}
+
+void mvneta_flush_queues(struct rte_eth_dev *dev)
+{
+	int i;
+
+	MVNETA_LOG(INFO, "Flushing rx queues");
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct mvneta_rxq *rxq = dev->data->rx_queues[i];
+
+		mvneta_rx_queue_flush(rxq);
+	}
+
+	MVNETA_LOG(INFO, "Flushing tx queues");
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		struct mvneta_txq *txq = dev->data->tx_queues[i];
+
+		mvneta_tx_queue_flush(txq);
+	}
+}
+
+/**
+ * DPDK callback to release the receive queue.
+ *
+ * @param rxq
+ *   Generic receive queue pointer.
+ */
+void
+mvneta_rx_queue_release(void *rxq)
+{
+	struct mvneta_rxq *q = rxq;
+
+	if (!q)
+		return;
+
+	/* If dev_stop was called already, mbufs are already
+	 * returned to mempool and ppio is deinitialized.
+	 * Skip this step.
+	 */
+
+	if (q->priv->ppio)
+		mvneta_rx_queue_flush(q);
+
+	rte_free(rxq);
+}
+
+/**
+ * DPDK callback to get information about specific receive queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param rx_queue_id
+ *   Receive queue index.
+ * @param qinfo
+ *   Receive queue information structure.
+ */
+void
+mvneta_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		    struct rte_eth_rxq_info *qinfo)
+{
+	struct mvneta_rxq *q = dev->data->rx_queues[rx_queue_id];
+
+	qinfo->mp = q->mp;
+	qinfo->nb_desc = q->size;
+}
+
+/**
+ * DPDK callback to get information about specific transmit queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param tx_queue_id
+ *   Transmit queue index.
+ * @param qinfo
+ *   Transmit queue information structure.
+ */
+void
+mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		    struct rte_eth_txq_info *qinfo)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+
+	qinfo->nb_desc =
+		priv->ppio_params.outqs_params.outqs_params[tx_queue_id].size;
+}
diff --git a/drivers/net/mvneta/mvneta_rxtx.h b/drivers/net/mvneta/mvneta_rxtx.h
new file mode 100644
index 0000000..b885bd7
--- /dev/null
+++ b/drivers/net/mvneta/mvneta_rxtx.h
@@ -0,0 +1,32 @@
+#ifndef _MVNETA_RXTX_H_
+#define _MVNETA_RXTX_H_
+
+#include "mvneta_ethdev.h"
+
+int mvneta_alloc_rx_bufs(struct rte_eth_dev *dev);
+
+void mvneta_flush_queues(struct rte_eth_dev *dev);
+
+void mvneta_rxq_info_get(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+			 struct rte_eth_rxq_info *qinfo);
+void mvneta_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+			 struct rte_eth_txq_info *qinfo);
+
+void mvneta_set_tx_function(struct rte_eth_dev *dev);
+
+uint16_t
+mvneta_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
+
+int
+mvneta_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket,
+		      const struct rte_eth_rxconf *conf __rte_unused,
+		      struct rte_mempool *mp);
+int
+mvneta_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
+		      unsigned int socket, const struct rte_eth_txconf *conf);
+
+void mvneta_rx_queue_release(void *rxq);
+void mvneta_tx_queue_release(void *txq);
+
+#endif /* _MVNETA_RXTX_H_ */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v7 3/8] net/mvneta: support for setting of MTU
  2018-10-03  7:22           ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Andrzej Ostruszka
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
@ 2018-10-03  7:22             ` Andrzej Ostruszka
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 4/8] net/mvneta: add link update Andrzej Ostruszka
                               ` (5 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-03  7:22 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu

From: Zyta Szpak <zr@semihalf.com>

Add callback for setting of MTU.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 78 +++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 0a89e2f..bc4e400 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -5,6 +5,7 @@
 ;
 [Features]
 Speed capabilities   = Y
+MTU update           = Y
 Jumbo frame          = Y
 CRC offload          = Y
 L3 checksum offload  = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index 7ea003c..aadeacb 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -30,6 +30,7 @@ Features of the MVNETA PMD are:
 - tx/rx_burst
 - Speed capabilities
 - Jumbo frame
+- MTU update
 - CRC offload
 - L3 checksum offload
 - L4 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 146b249..24f87e2 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -218,6 +218,77 @@ mvneta_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
 }
 
 /**
+ * DPDK callback to change the MTU.
+ *
+ * Setting the MTU affects hardware MRU (packets larger than the MRU
+ * will be dropped).
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param mtu
+ *   New MTU.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	uint16_t mbuf_data_size = 0; /* SW buffer size */
+	uint16_t mru;
+	int ret;
+
+	mru = MRVL_NETA_MTU_TO_MRU(mtu);
+	/*
+	 * min_rx_buf_size is equal to mbuf data size
+	 * if pmd didn't set it differently
+	 */
+	mbuf_data_size = dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM;
+	/* Prevent PMD from:
+	 * - setting mru greater than the mbuf size resulting in
+	 * hw and sw buffer size mismatch
+	 * - setting mtu that requires the support of scattered packets
+	 * when this feature has not been enabled/supported so far.
+	 */
+	if (!dev->data->scattered_rx &&
+	    (mru + MRVL_NETA_PKT_OFFS > mbuf_data_size)) {
+		mru = mbuf_data_size - MRVL_NETA_PKT_OFFS;
+		mtu = MRVL_NETA_MRU_TO_MTU(mru);
+		MVNETA_LOG(WARNING, "MTU too big, max MTU possible limitted by"
+			" current mbuf size: %u. Set MTU to %u, MRU to %u",
+			mbuf_data_size, mtu, mru);
+	}
+
+	if (mtu < ETHER_MIN_MTU || mru > MVNETA_PKT_SIZE_MAX) {
+		MVNETA_LOG(ERR, "Invalid MTU [%u] or MRU [%u]", mtu, mru);
+		return -EINVAL;
+	}
+
+	dev->data->mtu = mtu;
+	dev->data->dev_conf.rxmode.max_rx_pkt_len = mru - MV_MH_SIZE;
+
+	if (!priv->ppio)
+		/* It is OK. New MTU will be set later on mvneta_dev_start */
+		return 0;
+
+	ret = neta_ppio_set_mru(priv->ppio, mru);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MRU");
+		return ret;
+	}
+
+	ret = neta_ppio_set_mtu(priv->ppio, mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to change MTU");
+		return ret;
+	}
+	MVNETA_LOG(INFO, "MTU changed to %u, MRU = %u", mtu, mru);
+
+	return 0;
+}
+
+/**
  * DPDK callback to bring the link up.
  *
  * @param dev
@@ -307,6 +378,12 @@ mvneta_dev_start(struct rte_eth_dev *dev)
 	if (ret)
 		goto out;
 
+	ret = mvneta_mtu_set(dev, dev->data->mtu);
+	if (ret) {
+		MVNETA_LOG(ERR, "Failed to set MTU %d", dev->data->mtu);
+		goto out;
+	}
+
 	ret = mvneta_dev_set_link_up(dev);
 	if (ret) {
 		MVNETA_LOG(ERR, "Failed to set link up");
@@ -408,6 +485,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
 	.mac_addr_set = mvneta_mac_addr_set,
+	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v7 4/8] net/mvneta: add link update
  2018-10-03  7:22           ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                               ` (2 preceding siblings ...)
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
@ 2018-10-03  7:22             ` Andrzej Ostruszka
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
                               ` (4 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-03  7:22 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu

From: Zyta Szpak <zr@semihalf.com>

Add callback for updating information about link status/info.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 71 +++++++++++++++++++++++++++++++++++++
 3 files changed, 73 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index bc4e400..581ed31 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -5,6 +5,7 @@
 ;
 [Features]
 Speed capabilities   = Y
+Link status          = Y
 MTU update           = Y
 Jumbo frame          = Y
 CRC offload          = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index aadeacb..fdea3da 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -31,6 +31,7 @@ Features of the MVNETA PMD are:
 - Speed capabilities
 - Jumbo frame
 - MTU update
+- Link status
 - CRC offload
 - L3 checksum offload
 - L4 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 24f87e2..052e97f 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -452,6 +452,76 @@ mvneta_dev_close(struct rte_eth_dev *dev)
 }
 
 /**
+ * DPDK callback to retrieve physical link information.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param wait_to_complete
+ *   Wait for request completion (ignored).
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
+{
+	/*
+	 * TODO
+	 * once MUSDK provides necessary API use it here
+	 */
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct ethtool_cmd edata;
+	struct ifreq req;
+	int ret, fd, link_up;
+
+	if (!priv->ppio)
+		return -EPERM;
+
+	edata.cmd = ETHTOOL_GSET;
+
+	strcpy(req.ifr_name, dev->data->name);
+	req.ifr_data = (void *)&edata;
+
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd == -1)
+		return -EFAULT;
+	ret = ioctl(fd, SIOCETHTOOL, &req);
+	if (ret == -1) {
+		close(fd);
+		return -EFAULT;
+	}
+
+	close(fd);
+
+	switch (ethtool_cmd_speed(&edata)) {
+	case SPEED_10:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_10M;
+		break;
+	case SPEED_100:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_100M;
+		break;
+	case SPEED_1000:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_1G;
+		break;
+	case SPEED_2500:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_2_5G;
+		break;
+	default:
+		dev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE;
+	}
+
+	dev->data->dev_link.link_duplex = edata.duplex ? ETH_LINK_FULL_DUPLEX :
+							 ETH_LINK_HALF_DUPLEX;
+	dev->data->dev_link.link_autoneg = edata.autoneg ? ETH_LINK_AUTONEG :
+							   ETH_LINK_FIXED;
+
+	neta_ppio_get_link_state(priv->ppio, &link_up);
+	dev->data->dev_link.link_status = link_up ? ETH_LINK_UP : ETH_LINK_DOWN;
+
+	return 0;
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -484,6 +554,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_up = mvneta_dev_set_link_up,
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
+	.link_update = mvneta_link_update,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v7 5/8] net/mvneta: support for promiscuous
  2018-10-03  7:22           ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                               ` (3 preceding siblings ...)
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 4/8] net/mvneta: add link update Andrzej Ostruszka
@ 2018-10-03  7:22             ` Andrzej Ostruszka
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
                               ` (3 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-03  7:22 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu

From: Zyta Szpak <zr@semihalf.com>

Add callbacks for enabling/disabling of promiscuous mode.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 54 +++++++++++++++++++++++++++++++++++++
 3 files changed, 56 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 581ed31..6a140a3 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -8,6 +8,7 @@ Speed capabilities   = Y
 Link status          = Y
 MTU update           = Y
 Jumbo frame          = Y
+Promiscuous mode     = Y
 CRC offload          = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index fdea3da..ccd19f2 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -31,6 +31,7 @@ Features of the MVNETA PMD are:
 - Speed capabilities
 - Jumbo frame
 - MTU update
+- Promiscuous mode
 - Link status
 - CRC offload
 - L3 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 052e97f..a3dbe56 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -522,6 +522,58 @@ mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
 }
 
 /**
+ * DPDK callback to enable promiscuous mode.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_promiscuous_enable(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	int ret, en;
+
+	if (!priv->ppio)
+		return;
+
+	neta_ppio_get_promisc(priv->ppio, &en);
+	if (en) {
+		MVNETA_LOG(INFO, "Promiscuous already enabled");
+		return;
+	}
+
+	ret = neta_ppio_set_promisc(priv->ppio, 1);
+	if (ret)
+		MVNETA_LOG(ERR, "Failed to enable promiscuous mode");
+}
+
+/**
+ * DPDK callback to disable allmulticast mode.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_promiscuous_disable(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	int ret, en;
+
+	if (!priv->ppio)
+		return;
+
+	neta_ppio_get_promisc(priv->ppio, &en);
+	if (!en) {
+		MVNETA_LOG(INFO, "Promiscuous already disabled");
+		return;
+	}
+
+	ret = neta_ppio_set_promisc(priv->ppio, 0);
+	if (ret)
+		MVNETA_LOG(ERR, "Failed to disable promiscuous mode");
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -555,6 +607,8 @@ static const struct eth_dev_ops mvneta_ops = {
 	.dev_set_link_down = mvneta_dev_set_link_down,
 	.dev_close = mvneta_dev_close,
 	.link_update = mvneta_link_update,
+	.promiscuous_enable = mvneta_promiscuous_enable,
+	.promiscuous_disable = mvneta_promiscuous_disable,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v7 6/8] net/mvneta: add MAC filtering
  2018-10-03  7:22           ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                               ` (4 preceding siblings ...)
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
@ 2018-10-03  7:22             ` Andrzej Ostruszka
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
                               ` (2 subsequent siblings)
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-03  7:22 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu

From: Zyta Szpak <zr@semihalf.com>

Add callbacks for adding/removing MAC addresses.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 69 +++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 6a140a3..59c9c36 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -9,6 +9,7 @@ Link status          = Y
 MTU update           = Y
 Jumbo frame          = Y
 Promiscuous mode     = Y
+Unicast MAC filter   = Y
 CRC offload          = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index ccd19f2..068b3a7 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -32,6 +32,7 @@ Features of the MVNETA PMD are:
 - Jumbo frame
 - MTU update
 - Promiscuous mode
+- Unicast MAC filter
 - Link status
 - CRC offload
 - L3 checksum offload
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index a3dbe56..7a64e5a 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -574,6 +574,73 @@ mvneta_promiscuous_disable(struct rte_eth_dev *dev)
 }
 
 /**
+ * DPDK callback to remove a MAC address.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param index
+ *   MAC address index.
+ */
+static void
+mvneta_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	char buf[ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	if (!priv->ppio)
+		return;
+
+	ret = neta_ppio_remove_mac_addr(priv->ppio,
+				       dev->data->mac_addrs[index].addr_bytes);
+	if (ret) {
+		ether_format_addr(buf, sizeof(buf),
+				  &dev->data->mac_addrs[index]);
+		MVNETA_LOG(ERR, "Failed to remove mac %s", buf);
+	}
+}
+
+/**
+ * DPDK callback to add a MAC address.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param mac_addr
+ *   MAC address to register.
+ * @param index
+ *   MAC address index.
+ * @param vmdq
+ *   VMDq pool index to associate address with (unused).
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
+		  uint32_t index, uint32_t vmdq __rte_unused)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	char buf[ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	if (index == 0)
+		/* For setting index 0, mrvl_mac_addr_set() should be used.*/
+		return -1;
+
+	if (!priv->ppio)
+		return 0;
+
+	ret = neta_ppio_add_mac_addr(priv->ppio, mac_addr->addr_bytes);
+	if (ret) {
+		ether_format_addr(buf, sizeof(buf), mac_addr);
+		MVNETA_LOG(ERR, "Failed to add mac %s", buf);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
  * DPDK callback to set the primary MAC address.
  *
  * @param dev
@@ -609,6 +676,8 @@ static const struct eth_dev_ops mvneta_ops = {
 	.link_update = mvneta_link_update,
 	.promiscuous_enable = mvneta_promiscuous_enable,
 	.promiscuous_disable = mvneta_promiscuous_disable,
+	.mac_addr_remove = mvneta_mac_addr_remove,
+	.mac_addr_add = mvneta_mac_addr_add,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.dev_infos_get = mvneta_dev_infos_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v7 7/8] net/mvneta: add support for basic stats
  2018-10-03  7:22           ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                               ` (5 preceding siblings ...)
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
@ 2018-10-03  7:22             ` Andrzej Ostruszka
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
  2018-10-03 13:25             ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Ferruh Yigit
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-03  7:22 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu

From: Zyta Szpak <zr@semihalf.com>

Add support for getting of basic statistics for the driver.

Signed-off-by: Yelena Krivosheev <yelena@marvell.com>
Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
Signed-off-by: Zyta Szpak <zr@semihalf.com>
---
 doc/guides/nics/features/mvneta.ini |  1 +
 doc/guides/nics/mvneta.rst          |  1 +
 drivers/net/mvneta/mvneta_ethdev.c  | 47 +++++++++++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+)

diff --git a/doc/guides/nics/features/mvneta.ini b/doc/guides/nics/features/mvneta.ini
index 59c9c36..701eb03 100644
--- a/doc/guides/nics/features/mvneta.ini
+++ b/doc/guides/nics/features/mvneta.ini
@@ -14,5 +14,6 @@ CRC offload          = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
 Packet type parsing  = Y
+Basic stats          = Y
 ARMv8                = Y
 Usage doc            = Y
diff --git a/doc/guides/nics/mvneta.rst b/doc/guides/nics/mvneta.rst
index 068b3a7..2132a81 100644
--- a/doc/guides/nics/mvneta.rst
+++ b/doc/guides/nics/mvneta.rst
@@ -38,6 +38,7 @@ Features of the MVNETA PMD are:
 - L3 checksum offload
 - L4 checksum offload
 - Packet type parsing
+- Basic stats
 
 
 Limitations
diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index 7a64e5a..d004bfd 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -666,6 +666,52 @@ mvneta_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
 	return 0;
 }
 
+/**
+ * DPDK callback to get device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param stats
+ *   Stats structure output buffer.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mvneta_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	struct neta_ppio_statistics ppio_stats;
+	unsigned int ret;
+
+	if (!priv->ppio)
+		return -EPERM;
+
+	ret = neta_ppio_get_statistics(priv->ppio, &ppio_stats);
+	if (unlikely(ret)) {
+		MVNETA_LOG(ERR, "Failed to update port statistics");
+		return ret;
+	}
+
+	stats->ipackets += ppio_stats.rx_packets +
+			ppio_stats.rx_broadcast_packets +
+			ppio_stats.rx_multicast_packets;
+	stats->opackets += ppio_stats.tx_packets +
+			ppio_stats.tx_broadcast_packets +
+			ppio_stats.tx_multicast_packets;
+	stats->ibytes += ppio_stats.rx_bytes;
+	stats->obytes += ppio_stats.tx_bytes;
+	stats->imissed += ppio_stats.rx_discard +
+			  ppio_stats.rx_overrun;
+
+	stats->ierrors = ppio_stats.rx_packets_err +
+			ppio_stats.rx_errors +
+			ppio_stats.rx_crc_error;
+	stats->oerrors = ppio_stats.tx_errors;
+
+	return 0;
+}
+
 static const struct eth_dev_ops mvneta_ops = {
 	.dev_configure = mvneta_dev_configure,
 	.dev_start = mvneta_dev_start,
@@ -680,6 +726,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_add = mvneta_mac_addr_add,
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
+	.stats_get = mvneta_stats_get,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* [dpdk-dev] [PATCH v7 8/8] net/mvneta: add reset statistics callback
  2018-10-03  7:22           ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                               ` (6 preceding siblings ...)
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
@ 2018-10-03  7:22             ` Andrzej Ostruszka
  2018-10-03 13:25             ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Ferruh Yigit
  8 siblings, 0 replies; 96+ messages in thread
From: Andrzej Ostruszka @ 2018-10-03  7:22 UTC (permalink / raw)
  To: dev; +Cc: mw, nadavh, zr, tdu, Natalie Samsonov

From: Natalie Samsonov <nsamsono@marvell.com>

Add support for resetting of driver statistics.

Signed-off-by: Natalie Samsonov <nsamsono@marvell.com>
---
 drivers/net/mvneta/mvneta_ethdev.c | 40 +++++++++++++++++++++++++++++++-------
 drivers/net/mvneta/mvneta_ethdev.h |  1 +
 2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mvneta/mvneta_ethdev.c b/drivers/net/mvneta/mvneta_ethdev.c
index d004bfd..f7071bc 100644
--- a/drivers/net/mvneta/mvneta_ethdev.c
+++ b/drivers/net/mvneta/mvneta_ethdev.c
@@ -695,23 +695,48 @@ mvneta_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 
 	stats->ipackets += ppio_stats.rx_packets +
 			ppio_stats.rx_broadcast_packets +
-			ppio_stats.rx_multicast_packets;
+			ppio_stats.rx_multicast_packets -
+			priv->prev_stats.ipackets;
 	stats->opackets += ppio_stats.tx_packets +
 			ppio_stats.tx_broadcast_packets +
-			ppio_stats.tx_multicast_packets;
-	stats->ibytes += ppio_stats.rx_bytes;
-	stats->obytes += ppio_stats.tx_bytes;
+			ppio_stats.tx_multicast_packets -
+			priv->prev_stats.opackets;
+	stats->ibytes += ppio_stats.rx_bytes - priv->prev_stats.ibytes;
+	stats->obytes += ppio_stats.tx_bytes - priv->prev_stats.obytes;
 	stats->imissed += ppio_stats.rx_discard +
-			  ppio_stats.rx_overrun;
+			  ppio_stats.rx_overrun -
+			  priv->prev_stats.imissed;
 
 	stats->ierrors = ppio_stats.rx_packets_err +
 			ppio_stats.rx_errors +
-			ppio_stats.rx_crc_error;
-	stats->oerrors = ppio_stats.tx_errors;
+			ppio_stats.rx_crc_error -
+			priv->prev_stats.ierrors;
+	stats->oerrors = ppio_stats.tx_errors - priv->prev_stats.oerrors;
 
 	return 0;
 }
 
+/**
+ * DPDK callback to clear device statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mvneta_stats_reset(struct rte_eth_dev *dev)
+{
+	struct mvneta_priv *priv = dev->data->dev_private;
+	unsigned int ret;
+
+	if (!priv->ppio)
+		return;
+
+	ret = mvneta_stats_get(dev, &priv->prev_stats);
+	if (unlikely(ret))
+		RTE_LOG(ERR, PMD, "Failed to reset port statistics");
+}
+
+
 static const struct eth_dev_ops mvneta_ops = {
 	.dev_configure = mvneta_dev_configure,
 	.dev_start = mvneta_dev_start,
@@ -727,6 +752,7 @@ static const struct eth_dev_ops mvneta_ops = {
 	.mac_addr_set = mvneta_mac_addr_set,
 	.mtu_set = mvneta_mtu_set,
 	.stats_get = mvneta_stats_get,
+	.stats_reset = mvneta_stats_reset,
 	.dev_infos_get = mvneta_dev_infos_get,
 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
 	.rxq_info_get = mvneta_rxq_info_get,
diff --git a/drivers/net/mvneta/mvneta_ethdev.h b/drivers/net/mvneta/mvneta_ethdev.h
index 836a5e9..101b0a8 100644
--- a/drivers/net/mvneta/mvneta_ethdev.h
+++ b/drivers/net/mvneta/mvneta_ethdev.h
@@ -66,6 +66,7 @@ struct mvneta_priv {
 	struct neta_ppio_params ppio_params;
 
 	uint64_t rate_max;
+	struct rte_eth_stats prev_stats;
 };
 
 /** Current log type. */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD
  2018-10-03  7:22           ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Andrzej Ostruszka
                               ` (7 preceding siblings ...)
  2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
@ 2018-10-03 13:25             ` Ferruh Yigit
  2018-10-03 19:46               ` Ferruh Yigit
  8 siblings, 1 reply; 96+ messages in thread
From: Ferruh Yigit @ 2018-10-03 13:25 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev; +Cc: mw, nadavh, zr, tdu

On 10/3/2018 8:22 AM, Andrzej Ostruszka wrote:
> From: Andrzej Ostruszka <amo@semihalf.com>
> 
> This patch series introduces new PMD for Marvell NETA adapters (MVNETA).
> See the documentation for more info.
> 
> It is split for easier reviewing.
> 
> v7:
>   Addressed last round of review comments:
>   * improved documentation by listing it in toc, removing unsupported
>     MUSDK option and documenting run time option
>   * removed variables that are not really used
>   * documented devargs via REGISTER_PARAM_STRING
>   * implemented better separation between mvneta_ethdev.c and
>     mvneta_rxtx.c (now mvneta_rxtx.h includes only prototypes of
>     functions needed by mvneta_ethdev.c)
> 
> v6:
>   * add missing call to rte_eth_dev_probing_finish()
>   * update doc to point to MUSDK 18.09
>   * add mvep lib to LDLIBS in mvneta Makefile
> 
> v5:
>   * fixed wrong order of clenup in mvneta_eth_dev_create()
>   * inlined one auxilary function (mvneta_priv_create())
> 
> v4:
>   * rebased on top of next-net (DEV_RX_OFFLOAD_CRC_STRIP removed)
>   * Rx/Tx functionality moved to new mvneta_rxtx.c file
>   * removed eth_mvneta alias (and docs updated accordingly)
>   * fixed additional review comments
> 
> v3:
>     No changes against v2, just resubmitting again to have clean patch
>     set after faulty format-patch.  My apologies for the noise.
> 
> v2:
>   * fixed couple of checkpatch warnings
>   * removed '\n' from MVNETA_LOG invocations (appended by the macro)
>   * removed unused MVNETA_MUSDK_DMA_MEMSIZE define
>   * changed one printf into MVNETA_LOG
>   * removed __func__ from one MVNETA_LOG invocation (inserted
>     automatically by the macro)
>   * minor grammar/spelling correction in comments
>   * removed license text from file with SPDX tag (mvneta.rst)
>   * removed misleading part of comment for mvneta_shadow_txq
>   * changed authorship of the patches to the original author
> 
> Natalie Samsonov (1):
>   net/mvneta: add reset statistics callback
> 
> Zyta Szpak (7):
>   net/mvneta: add neta PMD skeleton
>   net/mvneta: add Rx/Tx support
>   net/mvneta: support for setting of MTU
>   net/mvneta: add link update
>   net/mvneta: support for promiscuous
>   net/mvneta: add MAC filtering
>   net/mvneta: add support for basic stats

Series applied to dpdk-next-net/master, thanks.

^ permalink raw reply	[flat|nested] 96+ messages in thread

* Re: [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD
  2018-10-03 13:25             ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Ferruh Yigit
@ 2018-10-03 19:46               ` Ferruh Yigit
  0 siblings, 0 replies; 96+ messages in thread
From: Ferruh Yigit @ 2018-10-03 19:46 UTC (permalink / raw)
  To: Andrzej Ostruszka, dev; +Cc: mw, nadavh, zr, tdu

On 10/3/2018 2:25 PM, Ferruh Yigit wrote:
> On 10/3/2018 8:22 AM, Andrzej Ostruszka wrote:
>> From: Andrzej Ostruszka <amo@semihalf.com>
>>
>> This patch series introduces new PMD for Marvell NETA adapters (MVNETA).
>> See the documentation for more info.
>>
>> It is split for easier reviewing.
>>
>> v7:
>>   Addressed last round of review comments:
>>   * improved documentation by listing it in toc, removing unsupported
>>     MUSDK option and documenting run time option
>>   * removed variables that are not really used
>>   * documented devargs via REGISTER_PARAM_STRING
>>   * implemented better separation between mvneta_ethdev.c and
>>     mvneta_rxtx.c (now mvneta_rxtx.h includes only prototypes of
>>     functions needed by mvneta_ethdev.c)
>>
>> v6:
>>   * add missing call to rte_eth_dev_probing_finish()
>>   * update doc to point to MUSDK 18.09
>>   * add mvep lib to LDLIBS in mvneta Makefile
>>
>> v5:
>>   * fixed wrong order of clenup in mvneta_eth_dev_create()
>>   * inlined one auxilary function (mvneta_priv_create())
>>
>> v4:
>>   * rebased on top of next-net (DEV_RX_OFFLOAD_CRC_STRIP removed)
>>   * Rx/Tx functionality moved to new mvneta_rxtx.c file
>>   * removed eth_mvneta alias (and docs updated accordingly)
>>   * fixed additional review comments
>>
>> v3:
>>     No changes against v2, just resubmitting again to have clean patch
>>     set after faulty format-patch.  My apologies for the noise.
>>
>> v2:
>>   * fixed couple of checkpatch warnings
>>   * removed '\n' from MVNETA_LOG invocations (appended by the macro)
>>   * removed unused MVNETA_MUSDK_DMA_MEMSIZE define
>>   * changed one printf into MVNETA_LOG
>>   * removed __func__ from one MVNETA_LOG invocation (inserted
>>     automatically by the macro)
>>   * minor grammar/spelling correction in comments
>>   * removed license text from file with SPDX tag (mvneta.rst)
>>   * removed misleading part of comment for mvneta_shadow_txq
>>   * changed authorship of the patches to the original author
>>
>> Natalie Samsonov (1):
>>   net/mvneta: add reset statistics callback
>>
>> Zyta Szpak (7):
>>   net/mvneta: add neta PMD skeleton
>>   net/mvneta: add Rx/Tx support
>>   net/mvneta: support for setting of MTU
>>   net/mvneta: add link update
>>   net/mvneta: support for promiscuous
>>   net/mvneta: add MAC filtering
>>   net/mvneta: add support for basic stats
> 
> Series applied to dpdk-next-net/master, thanks.

For series,
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>

^ permalink raw reply	[flat|nested] 96+ messages in thread

end of thread, other threads:[~2018-10-03 19:47 UTC | newest]

Thread overview: 96+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-28 15:10 [dpdk-dev] [PATCH 0/8] Add Marvell NETA PMD Andrzej Ostruszka
2018-08-28 15:10 ` [dpdk-dev] [PATCH 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
2018-08-30  8:42   ` Hemant
2018-08-30  9:54     ` Andrzej Ostruszka
2018-08-28 15:10 ` [dpdk-dev] [PATCH 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
2018-08-28 15:10 ` [dpdk-dev] [PATCH 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
2018-08-28 15:10 ` [dpdk-dev] [PATCH 4/8] net/mvneta: add link update Andrzej Ostruszka
2018-08-28 15:10 ` [dpdk-dev] [PATCH 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
2018-08-28 15:10 ` [dpdk-dev] [PATCH 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
2018-08-28 15:10 ` [dpdk-dev] [PATCH 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
2018-08-28 15:10 ` [dpdk-dev] [PATCH 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
2018-08-31 12:25 ` [dpdk-dev] [PATCH v2 0/8] Add Marvell NETA PMD Andrzej Ostruszka
2018-08-31 12:25   ` [dpdk-dev] [PATCH v2 1/8] net/bonding: fix buf corruption in packets Andrzej Ostruszka
2018-08-31 12:33     ` Andrzej Ostruszka
2018-08-31 12:25   ` [dpdk-dev] [PATCH v2 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
2018-08-31 12:25   ` [dpdk-dev] [PATCH v2 2/8] " Andrzej Ostruszka
2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 3/8] " Andrzej Ostruszka
2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 4/8] net/mvneta: add link update Andrzej Ostruszka
2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 4/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
2018-08-31 12:26   ` [dpdk-dev] [PATCH v2 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
2018-08-31 12:59   ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
2018-09-14 16:23       ` Ferruh Yigit
2018-09-19 15:14         ` Andrzej Ostruszka
2018-09-19 17:38           ` Ferruh Yigit
2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
2018-09-14 16:24       ` Ferruh Yigit
2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 4/8] net/mvneta: add link update Andrzej Ostruszka
2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
2018-09-14 16:24       ` Ferruh Yigit
2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
2018-08-31 12:59     ` [dpdk-dev] [PATCH v3 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
2018-09-10  6:11     ` [dpdk-dev] [PATCH v3 0/8] Add Marvell NETA PMD Andrzej Ostruszka
2018-09-14 16:20     ` Ferruh Yigit
2018-09-19 15:07       ` Andrzej Ostruszka
2018-09-19 17:39         ` Ferruh Yigit
2018-09-21 11:59           ` Andrzej Ostruszka
2018-09-21 13:37             ` Ferruh Yigit
2018-09-19 15:01     ` [dpdk-dev] [PATCH v4 " Andrzej Ostruszka
2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
2018-09-19 16:19         ` Stephen Hemminger
2018-09-20  7:45           ` Andrzej Ostruszka
2018-09-19 16:28         ` Stephen Hemminger
2018-09-20  7:57           ` Andrzej Ostruszka
2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 4/8] net/mvneta: add link update Andrzej Ostruszka
2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
2018-09-19 15:01       ` [dpdk-dev] [PATCH v4 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
2018-09-20  9:05       ` [dpdk-dev] [PATCH v5 0/8] Add Marvell NETA PMD Andrzej Ostruszka
2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
2018-09-24  9:21           ` Ferruh Yigit
2018-09-24  9:35             ` Ferruh Yigit
2018-09-24  9:38               ` Ferruh Yigit
2018-10-01  9:35                 ` Andrzej Ostruszka
2018-09-24  9:57           ` Ferruh Yigit
2018-09-24 10:03           ` Ferruh Yigit
2018-10-01  9:30             ` Andrzej Ostruszka
2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 4/8] net/mvneta: add link update Andrzej Ostruszka
2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
2018-09-20  9:05         ` [dpdk-dev] [PATCH v5 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
2018-10-01  9:26         ` [dpdk-dev] [PATCH v6 0/8] Add Marvell NETA PMD Andrzej Ostruszka
2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
2018-10-02 11:53             ` Ferruh Yigit
2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
2018-10-02 11:54             ` Ferruh Yigit
2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 4/8] net/mvneta: add link update Andrzej Ostruszka
2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
2018-10-01  9:26           ` [dpdk-dev] [PATCH v6 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
2018-10-03  7:22           ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Andrzej Ostruszka
2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 1/8] net/mvneta: add neta PMD skeleton Andrzej Ostruszka
2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 2/8] net/mvneta: add Rx/Tx support Andrzej Ostruszka
2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 3/8] net/mvneta: support for setting of MTU Andrzej Ostruszka
2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 4/8] net/mvneta: add link update Andrzej Ostruszka
2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 5/8] net/mvneta: support for promiscuous Andrzej Ostruszka
2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 6/8] net/mvneta: add MAC filtering Andrzej Ostruszka
2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 7/8] net/mvneta: add support for basic stats Andrzej Ostruszka
2018-10-03  7:22             ` [dpdk-dev] [PATCH v7 8/8] net/mvneta: add reset statistics callback Andrzej Ostruszka
2018-10-03 13:25             ` [dpdk-dev] [PATCH v7 0/8] Add Marvell NETA PMD Ferruh Yigit
2018-10-03 19:46               ` Ferruh Yigit

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).