[v4,1/8] net/mvneta: add neta PMD skeleton
diff mbox series

Message ID 1537369294-17099-2-git-send-email-amo@semihalf.com
State Superseded, archived
Delegated to: Ferruh Yigit
Headers show
Series
  • Add Marvell NETA PMD
Related show

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Andrzej Ostruszka Sept. 19, 2018, 3:01 p.m. UTC
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

Comments

Stephen Hemminger Sept. 19, 2018, 4:19 p.m. UTC | #1
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.
Stephen Hemminger Sept. 19, 2018, 4:28 p.m. UTC | #2
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;
> +}
Andrzej Ostruszka Sept. 20, 2018, 7:45 a.m. UTC | #3
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
Andrzej Ostruszka Sept. 20, 2018, 7:57 a.m. UTC | #4
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

Patch
diff mbox series

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