From c1f36c28393a7bb126cbf436cd6a4077a5b5c313 Mon Sep 17 00:00:00 2001
From: Johnny Hughes <johnny@centos.org>
Date: Mon, 04 Feb 2019 16:34:33 +0000
Subject: [PATCH] added extra source files

---
 SOURCES/0040-net-mvpp2-Don-t-use-dynamic-allocs-for-local-variabl.patch |  624 +++++
 SOURCES/0046-net-mvpp2-Fix-clock-resource-by-adding-missing-mg_co.patch |   85 
 SOURCES/0023-device-property-Introduce-fwnode_irq_get.patch             |  114 +
 SOURCES/0005-net-mvpp2-limit-TSO-segments-and-use-stop-wake-thres.patch |   88 
 SOURCES/0012-net-mvpp2-do-not-disable-GMAC-padding.patch                |   51 
 SOURCES/0017-net-mvpp2-split-the-max-ring-size-from-the-default-o.patch |   92 
 SOURCES/0006-BACKPORT-ACPI-bus-Introduce-acpi_get_match_data-func.patch |   80 
 SOURCES/0034-net-mvpp2-jumbo-frames-support.patch                       |  206 +
 SOURCES/0009-net-mvpp2-fix-GOP-statistics-loop-start-and-stop-con.patch |  180 +
 SOURCES/0015-net-mvpp2-fix-the-RSS-table-entry-offset.patch             |   34 
 SOURCES/0042-net-mvpp2-Fix-parser-entry-init-boundary-check.patch       |   34 
 SOURCES/0038-net-mvpp2-use-correct-index-on-array-mvpp2_pools.patch     |   36 
 SOURCES/0021-device-property-Introduce-fwnode_get_mac_address.patch     |  110 
 SOURCES/0024-device-property-Allow-iterating-over-available-child.patch |   85 
 SOURCES/centos-ldup.x509                                                |    0 
 SOURCES/0001-net-mvpp2-remove-useless-goto.patch                        |   31 
 SOURCES/0007-net-mvpp2-simplify-the-Tx-desc-set-DMA-logic.patch         |  116 +
 SOURCES/0003-BACKPORT-arm64-locking-Replace-ticket-lock-implement.patch |  217 +
 SOURCES/0011-net-mvpp2-cleanup-probed-ports-in-the-probe-error-pa.patch |   55 
 SOURCES/0003-net-mvpp2-initialize-the-Tx-FIFO-size.patch                |   83 
 SOURCES/0020-net-mvpp2-adjust-the-coalescing-parameters.patch           |   38 
 SOURCES/0004-BACKPORT-arm64-kconfig-Ensure-spinlock-fastpaths-are.patch |   47 
 SOURCES/0008-BACKPORT-ACPI-bus-Rename-acpi_get_match_data-to-acpi.patch |   73 
 SOURCES/0035-net-mvpp2-mvpp2_check_hw_buf_num-can-be-static.patch       |   30 
 SOURCES/0016-net-mvpp2-only-free-the-TSO-header-buffers-when-it-w.patch |   50 
 SOURCES/0029-net-mvpp2-Add-hardware-offloading-for-VLAN-filtering.patch |  597 +++++
 SOURCES/0032-net-mvpp2-use-a-data-size-of-10kB-for-Tx-FIFO-on-por.patch |   80 
 SOURCES/centos-ca-secureboot.der                                        |    0 
 SOURCES/0002-BACKPORT-arm64-barrier-Implement-smp_cond_load_relax.patch |   48 
 SOURCES/0004-net-mvpp2-initialize-the-RSS-tables.patch                  |  103 
 SOURCES/centossecureboot001.crt                                         |   81 
 SOURCES/0006-net-mvpp2-use-the-aggr-txq-size-define-everywhere.patch    |   51 
 SOURCES/0039-net-mvpp2-Make-mvpp2_prs_hw_read-a-parser-entry-init.patch |  184 +
 SOURCES/0008-net-mvpp2-add-ethtool-GOP-statistics.patch                 |  375 +++
 SOURCES/0043-net-mvpp2-Fix-TCAM-filter-reserved-range.patch             |   43 
 SOURCES/0001-BACKPORT-arm64-cmpwait-Clear-event-register-before-a.patch |   44 
 SOURCES/0026-net-mvpp2-use-device_-fwnode_-APIs-instead-of-of_.patch    |  173 +
 SOURCES/0030-net-mvpp2-use-the-same-buffer-pool-for-all-ports.patch     |  228 ++
 SOURCES/0011-BACKPORT-iommu-enable-bypass-transaction-caching-for.patch |   49 
 SOURCES/0033-net-mvpp2-enable-UDP-TCP-checksum-over-IPv6.patch          |   35 
 SOURCES/0025-net-mvpp2-simplify-maintaining-enabled-ports-list.patch    |   94 
 SOURCES/0022-device-property-Introduce-fwnode_get_phy_mode.patch        |   96 
 SOURCES/centos-kpatch.x509                                              |    0 
 SOURCES/0005-BACKPORT-ahci-Disable-LPM-on-Lenovo-50-series-laptop.patch |  160 +
 SOURCES/0007-BACKPORT-ACPI-bus-Remove-checks-in-acpi_get_match_da.patch |   53 
 SOURCES/0044-net-mvpp2-Fix-DMA-address-mask-size.patch                  |   80 
 SOURCES/0014-net-mvpp2-allocate-zeroed-tx-descriptors.patch             |   39 
 SOURCES/0002-net-mvpp2-set-the-Rx-FIFO-size-depending-on-the-port.patch |   99 
 SOURCES/0045-net-mvpp2-Fix-clk-error-path-in-mvpp2_probe.patch          |   87 
 SOURCES/0037-net-mvpp2-Add-support-for-unicast-filtering.patch          |  465 ++++
 SOURCES/0009-BACKPORT-ata-Disable-AHCI-ALPM-feature-for-Ampere-Co.patch |   72 
 SOURCES/0041-net-mvpp2-Use-relaxed-I-O-in-data-path.patch               |  127 +
 SOURCES/0018-net-mvpp2-align-values-in-ethtool-get_coalesce.patch       |   36 
 SOURCES/0019-net-mvpp2-report-the-tx-usec-coalescing-information-.patch |   33 
 SOURCES/0027-net-mvpp2-enable-ACPI-support-in-the-driver.patch          |  305 ++
 SOURCES/0010-net-mvpp2-fix-the-txq_init-error-path.patch                |   70 
 SOURCES/0036-net-mvpp2-Simplify-MAC-filtering-function-parameters.patch |  115 +
 SOURCES/0010-BACKPORT-perf-xgene-Fix-IOB-SLOW-PMU-parser-error.patch    |   39 
 SOURCES/0031-net-mvpp2-update-the-BM-buffer-free-destroy-logic.patch    |  118 +
 SOURCES/0013-net-mvpp2-check-ethtool-sets-the-Tx-ring-size-is-to-.patch |   41 
 SOURCES/0028-mvpp2-fix-multicast-address-filter.patch                   |   58 
 61 files changed, 6,837 insertions(+), 0 deletions(-)

diff --git a/SOURCES/0001-BACKPORT-arm64-cmpwait-Clear-event-register-before-a.patch b/SOURCES/0001-BACKPORT-arm64-cmpwait-Clear-event-register-before-a.patch
new file mode 100644
index 0000000..d60433e
--- /dev/null
+++ b/SOURCES/0001-BACKPORT-arm64-cmpwait-Clear-event-register-before-a.patch
@@ -0,0 +1,44 @@
+From 3c9a17d64f5fb028a937b135ba4cfaa7e17fcce1 Mon Sep 17 00:00:00 2001
+From: Khuong Dinh <khuong.dinh@amperecomputing.com>
+Date: Mon, 30 Apr 2018 13:56:32 +0100
+Subject: [PATCH 01/11] BACKPORT: arm64: cmpwait: Clear event register before
+ arming exclusive monitor
+
+When waiting for a cacheline to change state in cmpwait, we may immediately
+wake-up the first time around the outer loop if the event register was
+already set (for example, because of the event stream).
+
+Avoid these spurious wakeups by explicitly clearing the event register
+before loading the cacheline and setting the exclusive monitor.
+
+This patch is required to fix kernel lock up due to new implementation of
+queued read write locking from kernel 4.14.
+This patch is backported from:
+https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20180913&id=1cfc63b5ae60fe7e01773f38132f98d8b13a99a0
+
+Change-Id: I1151172c53f0049a54dfae892ff423ab14b067e7
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Khuong Dinh <khuong.dinh@amperecomputing.com>
+---
+ arch/arm64/include/asm/cmpxchg.h | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h
+index ae852ad..0f2e1ab 100644
+--- a/arch/arm64/include/asm/cmpxchg.h
++++ b/arch/arm64/include/asm/cmpxchg.h
+@@ -229,7 +229,9 @@
+ 	unsigned long tmp;						\
+ 									\
+ 	asm volatile(							\
+-	"	ldxr" #sz "\t%" #w "[tmp], %[v]\n"		\
++	"	sevl\n"							\
++	"	wfe\n"							\
++	"	ldxr" #sz "\t%" #w "[tmp], %[v]\n"			\
+ 	"	eor	%" #w "[tmp], %" #w "[tmp], %" #w "[val]\n"	\
+ 	"	cbnz	%" #w "[tmp], 1f\n"				\
+ 	"	wfe\n"							\
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0001-net-mvpp2-remove-useless-goto.patch b/SOURCES/0001-net-mvpp2-remove-useless-goto.patch
new file mode 100644
index 0000000..80d22a4
--- /dev/null
+++ b/SOURCES/0001-net-mvpp2-remove-useless-goto.patch
@@ -0,0 +1,31 @@
+From df729afff345873ba01a0572e2042e68115ab305 Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@free-electrons.com>
+Date: Mon, 18 Sep 2017 15:36:51 +0200
+Subject: [PATCH 01/46] net: mvpp2: remove useless goto
+
+Remove a goto in the PPv2 tx function which jumps to the next line
+anyway. This is a cosmetic commit.
+
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 38c5eb93aca9dc1b21a2c96d583ce7f9886a44e6)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index fcf9ba5..c0f7a41 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -6469,7 +6469,6 @@ static int mvpp2_tx(struct sk_buff *skb, struct net_device *dev)
+ 		if (mvpp2_tx_frag_process(port, skb, aggr_txq, txq)) {
+ 			tx_desc_unmap_put(port, txq, tx_desc);
+ 			frags = 0;
+-			goto out;
+ 		}
+ 	}
+ 
+-- 
+2.7.4
+
diff --git a/SOURCES/0002-BACKPORT-arm64-barrier-Implement-smp_cond_load_relax.patch b/SOURCES/0002-BACKPORT-arm64-barrier-Implement-smp_cond_load_relax.patch
new file mode 100644
index 0000000..121a811
--- /dev/null
+++ b/SOURCES/0002-BACKPORT-arm64-barrier-Implement-smp_cond_load_relax.patch
@@ -0,0 +1,48 @@
+From 999d3c8c40286fc57dfcd194a1b7548b975ec875 Mon Sep 17 00:00:00 2001
+From: Khuong Dinh <khuong.dinh@amperecomputing.com>
+Date: Wed, 31 Jan 2018 15:55:24 +0000
+Subject: [PATCH 02/11] BACKPORT: arm64: barrier: Implement
+ smp_cond_load_relaxed
+
+We can provide an implementation of smp_cond_load_relaxed using READ_ONCE
+and __cmpwait_relaxed.
+
+This patch is required to fix kernel lock up due to new implementation of
+queued read write locking from kernel 4.14.
+This patch is backported from:
+https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20180913&id=598865c5f32d6e11e99f2aac07348e5fd17cdc03
+
+Change-Id: I69a663a3c84301479f5b077f1dd7a342938b92cf
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Khuong Dinh <khuong.dinh@amperecomputing.com>
+---
+ arch/arm64/include/asm/barrier.h | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h
+index 6133f3e..bc814e8 100644
+--- a/arch/arm64/include/asm/barrier.h
++++ b/arch/arm64/include/asm/barrier.h
+@@ -182,6 +182,19 @@ static inline unsigned long array_index_mask_nospec(unsigned long idx,
+ 	__u.__val;							\
+ })
+ 
++#define smp_cond_load_relaxed(ptr, cond_expr)				\
++({									\
++	typeof(ptr) __PTR = (ptr);					\
++	typeof(*ptr) VAL;						\
++	for (;;) {							\
++		VAL = READ_ONCE(*__PTR);				\
++		if (cond_expr)						\
++			break;						\
++		__cmpwait_relaxed(__PTR, VAL);				\
++	}								\
++	VAL;								\
++})
++
+ #define smp_cond_load_acquire(ptr, cond_expr)				\
+ ({									\
+ 	typeof(ptr) __PTR = (ptr);					\
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0002-net-mvpp2-set-the-Rx-FIFO-size-depending-on-the-port.patch b/SOURCES/0002-net-mvpp2-set-the-Rx-FIFO-size-depending-on-the-port.patch
new file mode 100644
index 0000000..459909c
--- /dev/null
+++ b/SOURCES/0002-net-mvpp2-set-the-Rx-FIFO-size-depending-on-the-port.patch
@@ -0,0 +1,99 @@
+From d6bbef303a701b0bfb0cd293de227436cc084f2e Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@free-electrons.com>
+Date: Mon, 30 Oct 2017 11:23:28 +0100
+Subject: [PATCH 02/46] net: mvpp2: set the Rx FIFO size depending on the port
+ speeds for PPv2.2
+
+The Rx FIFO size was set to the same value for all ports. This patch
+sets it depending on the maximum speed a given port can handle. This is
+only working for PPv2.2.
+
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 2d1d7df8a3652697da7f7929791d555e6c5981c2)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 52 +++++++++++++++++++++++++++++++-----
+ 1 file changed, 46 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index c0f7a41..80aa7f7 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -504,9 +504,13 @@
+ #define MVPP2_TX_DESC_ALIGN		(MVPP2_DESC_ALIGNED_SIZE - 1)
+ 
+ /* RX FIFO constants */
+-#define MVPP2_RX_FIFO_PORT_DATA_SIZE	0x2000
+-#define MVPP2_RX_FIFO_PORT_ATTR_SIZE	0x80
+-#define MVPP2_RX_FIFO_PORT_MIN_PKT	0x80
++#define MVPP2_RX_FIFO_PORT_DATA_SIZE_32KB	0x8000
++#define MVPP2_RX_FIFO_PORT_DATA_SIZE_8KB	0x2000
++#define MVPP2_RX_FIFO_PORT_DATA_SIZE_4KB	0x1000
++#define MVPP2_RX_FIFO_PORT_ATTR_SIZE_32KB	0x200
++#define MVPP2_RX_FIFO_PORT_ATTR_SIZE_8KB	0x80
++#define MVPP2_RX_FIFO_PORT_ATTR_SIZE_4KB	0x40
++#define MVPP2_RX_FIFO_PORT_MIN_PKT		0x80
+ 
+ /* RX buffer constants */
+ #define MVPP2_SKB_SHINFO_SIZE \
+@@ -7768,9 +7772,42 @@ static void mvpp2_rx_fifo_init(struct mvpp2 *priv)
+ 
+ 	for (port = 0; port < MVPP2_MAX_PORTS; port++) {
+ 		mvpp2_write(priv, MVPP2_RX_DATA_FIFO_SIZE_REG(port),
+-			    MVPP2_RX_FIFO_PORT_DATA_SIZE);
++			    MVPP2_RX_FIFO_PORT_DATA_SIZE_4KB);
+ 		mvpp2_write(priv, MVPP2_RX_ATTR_FIFO_SIZE_REG(port),
+-			    MVPP2_RX_FIFO_PORT_ATTR_SIZE);
++			    MVPP2_RX_FIFO_PORT_ATTR_SIZE_4KB);
++	}
++
++	mvpp2_write(priv, MVPP2_RX_MIN_PKT_SIZE_REG,
++		    MVPP2_RX_FIFO_PORT_MIN_PKT);
++	mvpp2_write(priv, MVPP2_RX_FIFO_INIT_REG, 0x1);
++}
++
++static void mvpp22_rx_fifo_init(struct mvpp2 *priv)
++{
++	int port;
++
++	/* The FIFO size parameters are set depending on the maximum speed a
++	 * given port can handle:
++	 * - Port 0: 10Gbps
++	 * - Port 1: 2.5Gbps
++	 * - Ports 2 and 3: 1Gbps
++	 */
++
++	mvpp2_write(priv, MVPP2_RX_DATA_FIFO_SIZE_REG(0),
++		    MVPP2_RX_FIFO_PORT_DATA_SIZE_32KB);
++	mvpp2_write(priv, MVPP2_RX_ATTR_FIFO_SIZE_REG(0),
++		    MVPP2_RX_FIFO_PORT_ATTR_SIZE_32KB);
++
++	mvpp2_write(priv, MVPP2_RX_DATA_FIFO_SIZE_REG(1),
++		    MVPP2_RX_FIFO_PORT_DATA_SIZE_8KB);
++	mvpp2_write(priv, MVPP2_RX_ATTR_FIFO_SIZE_REG(1),
++		    MVPP2_RX_FIFO_PORT_ATTR_SIZE_8KB);
++
++	for (port = 2; port < MVPP2_MAX_PORTS; port++) {
++		mvpp2_write(priv, MVPP2_RX_DATA_FIFO_SIZE_REG(port),
++			    MVPP2_RX_FIFO_PORT_DATA_SIZE_4KB);
++		mvpp2_write(priv, MVPP2_RX_ATTR_FIFO_SIZE_REG(port),
++			    MVPP2_RX_FIFO_PORT_ATTR_SIZE_4KB);
+ 	}
+ 
+ 	mvpp2_write(priv, MVPP2_RX_MIN_PKT_SIZE_REG,
+@@ -7874,7 +7911,10 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)
+ 	}
+ 
+ 	/* Rx Fifo Init */
+-	mvpp2_rx_fifo_init(priv);
++	if (priv->hw_version == MVPP21)
++		mvpp2_rx_fifo_init(priv);
++	else
++		mvpp22_rx_fifo_init(priv);
+ 
+ 	if (priv->hw_version == MVPP21)
+ 		writel(MVPP2_EXT_GLOBAL_CTRL_DEFAULT,
+-- 
+2.7.4
+
diff --git a/SOURCES/0003-BACKPORT-arm64-locking-Replace-ticket-lock-implement.patch b/SOURCES/0003-BACKPORT-arm64-locking-Replace-ticket-lock-implement.patch
new file mode 100644
index 0000000..c6efa4a
--- /dev/null
+++ b/SOURCES/0003-BACKPORT-arm64-locking-Replace-ticket-lock-implement.patch
@@ -0,0 +1,217 @@
+From 66af385bfaf97865f0e6d9032db896656b58920d Mon Sep 17 00:00:00 2001
+From: Khuong Dinh <khuong.dinh@amperecomputing.com>
+Date: Tue, 13 Mar 2018 20:45:45 +0000
+Subject: [PATCH 03/11] BACKPORT: arm64: locking: Replace ticket lock
+ implementation with qspinlock
+
+It's fair to say that our ticket lock has served us well over time, but
+it's time to bite the bullet and start using the generic qspinlock code
+so we can make use of explicit MCS queuing and potentially better PV
+performance in future.
+
+This patch is required to fix kernel lock up due to new implementation of
+queued read write locking from kernel 4.14.
+This patch is backported from:
+https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20180913&id=c11090474d70590170cf5fa6afe85864ab494b37
+
+Change-Id: I1b019176c2b7ae1b25e609a54d7fa35bd380bd0a
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Khuong Dinh <khuong.dinh@amperecomputing.com>
+---
+ arch/arm64/Kconfig                      |   1 +
+ arch/arm64/include/asm/Kbuild           |   1 +
+ arch/arm64/include/asm/spinlock.h       | 124 +-------------------------------
+ arch/arm64/include/asm/spinlock_types.h |  17 +----
+ 4 files changed, 4 insertions(+), 139 deletions(-)
+
+diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
+index 651d8d9..fba4bd7 100644
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -41,6 +41,7 @@ config ARM64
+ 	select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE if !PREEMPT
+ 	select ARCH_USE_CMPXCHG_LOCKREF
+ 	select ARCH_USE_QUEUED_RWLOCKS
++	select ARCH_USE_QUEUED_SPINLOCKS
+ 	select ARCH_SUPPORTS_MEMORY_FAILURE
+ 	select ARCH_SUPPORTS_ATOMIC_RMW
+ 	select ARCH_SUPPORTS_NUMA_BALANCING
+diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
+index e63d0a8..ae621cb 100644
+--- a/arch/arm64/include/asm/Kbuild
++++ b/arch/arm64/include/asm/Kbuild
+@@ -17,6 +17,7 @@ generic-y += mm-arch-hooks.h
+ generic-y += msi.h
+ generic-y += preempt.h
+ generic-y += qrwlock.h
++generic-y += qspinlock.h
+ generic-y += rwsem.h
+ generic-y += segment.h
+ generic-y += serial.h
+diff --git a/arch/arm64/include/asm/spinlock.h b/arch/arm64/include/asm/spinlock.h
+index fa1d966..8871cdd 100644
+--- a/arch/arm64/include/asm/spinlock.h
++++ b/arch/arm64/include/asm/spinlock.h
+@@ -16,130 +16,8 @@
+ #ifndef __ASM_SPINLOCK_H
+ #define __ASM_SPINLOCK_H
+ 
+-#include <asm/lse.h>
+-#include <asm/spinlock_types.h>
+-#include <asm/processor.h>
+-
+-/*
+- * Spinlock implementation.
+- *
+- * The memory barriers are implicit with the load-acquire and store-release
+- * instructions.
+- */
+-
+-#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
+-
+-static inline void arch_spin_lock(arch_spinlock_t *lock)
+-{
+-	unsigned int tmp;
+-	arch_spinlock_t lockval, newval;
+-
+-	asm volatile(
+-	/* Atomically increment the next ticket. */
+-	ARM64_LSE_ATOMIC_INSN(
+-	/* LL/SC */
+-"	prfm	pstl1strm, %3\n"
+-"1:	ldaxr	%w0, %3\n"
+-"	add	%w1, %w0, %w5\n"
+-"	stxr	%w2, %w1, %3\n"
+-"	cbnz	%w2, 1b\n",
+-	/* LSE atomics */
+-"	mov	%w2, %w5\n"
+-"	ldadda	%w2, %w0, %3\n"
+-	__nops(3)
+-	)
+-
+-	/* Did we get the lock? */
+-"	eor	%w1, %w0, %w0, ror #16\n"
+-"	cbz	%w1, 3f\n"
+-	/*
+-	 * No: spin on the owner. Send a local event to avoid missing an
+-	 * unlock before the exclusive load.
+-	 */
+-"	sevl\n"
+-"2:	wfe\n"
+-"	ldaxrh	%w2, %4\n"
+-"	eor	%w1, %w2, %w0, lsr #16\n"
+-"	cbnz	%w1, 2b\n"
+-	/* We got the lock. Critical section starts here. */
+-"3:"
+-	: "=&r" (lockval), "=&r" (newval), "=&r" (tmp), "+Q" (*lock)
+-	: "Q" (lock->owner), "I" (1 << TICKET_SHIFT)
+-	: "memory");
+-}
+-
+-static inline int arch_spin_trylock(arch_spinlock_t *lock)
+-{
+-	unsigned int tmp;
+-	arch_spinlock_t lockval;
+-
+-	asm volatile(ARM64_LSE_ATOMIC_INSN(
+-	/* LL/SC */
+-	"	prfm	pstl1strm, %2\n"
+-	"1:	ldaxr	%w0, %2\n"
+-	"	eor	%w1, %w0, %w0, ror #16\n"
+-	"	cbnz	%w1, 2f\n"
+-	"	add	%w0, %w0, %3\n"
+-	"	stxr	%w1, %w0, %2\n"
+-	"	cbnz	%w1, 1b\n"
+-	"2:",
+-	/* LSE atomics */
+-	"	ldr	%w0, %2\n"
+-	"	eor	%w1, %w0, %w0, ror #16\n"
+-	"	cbnz	%w1, 1f\n"
+-	"	add	%w1, %w0, %3\n"
+-	"	casa	%w0, %w1, %2\n"
+-	"	and	%w1, %w1, #0xffff\n"
+-	"	eor	%w1, %w1, %w0, lsr #16\n"
+-	"1:")
+-	: "=&r" (lockval), "=&r" (tmp), "+Q" (*lock)
+-	: "I" (1 << TICKET_SHIFT)
+-	: "memory");
+-
+-	return !tmp;
+-}
+-
+-static inline void arch_spin_unlock(arch_spinlock_t *lock)
+-{
+-	unsigned long tmp;
+-
+-	asm volatile(ARM64_LSE_ATOMIC_INSN(
+-	/* LL/SC */
+-	"	ldrh	%w1, %0\n"
+-	"	add	%w1, %w1, #1\n"
+-	"	stlrh	%w1, %0",
+-	/* LSE atomics */
+-	"	mov	%w1, #1\n"
+-	"	staddlh	%w1, %0\n"
+-	__nops(1))
+-	: "=Q" (lock->owner), "=&r" (tmp)
+-	:
+-	: "memory");
+-}
+-
+-static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
+-{
+-	return lock.owner == lock.next;
+-}
+-
+-static inline int arch_spin_is_locked(arch_spinlock_t *lock)
+-{
+-	/*
+-	 * Ensure prior spin_lock operations to other locks have completed
+-	 * on this CPU before we test whether "lock" is locked.
+-	 */
+-	smp_mb(); /* ^^^ */
+-	return !arch_spin_value_unlocked(READ_ONCE(*lock));
+-}
+-
+-static inline int arch_spin_is_contended(arch_spinlock_t *lock)
+-{
+-	arch_spinlock_t lockval = READ_ONCE(*lock);
+-	return (lockval.next - lockval.owner) > 1;
+-}
+-#define arch_spin_is_contended	arch_spin_is_contended
+-
+ #include <asm/qrwlock.h>
++#include <asm/qspinlock.h>
+ 
+ #define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
+ #define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
+diff --git a/arch/arm64/include/asm/spinlock_types.h b/arch/arm64/include/asm/spinlock_types.h
+index 6b85601..a157ff4 100644
+--- a/arch/arm64/include/asm/spinlock_types.h
++++ b/arch/arm64/include/asm/spinlock_types.h
+@@ -20,22 +20,7 @@
+ # error "please don't include this file directly"
+ #endif
+ 
+-#include <linux/types.h>
+-
+-#define TICKET_SHIFT	16
+-
+-typedef struct {
+-#ifdef __AARCH64EB__
+-	u16 next;
+-	u16 owner;
+-#else
+-	u16 owner;
+-	u16 next;
+-#endif
+-} __aligned(4) arch_spinlock_t;
+-
+-#define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 , 0 }
+-
++#include <asm-generic/qspinlock_types.h>
+ #include <asm-generic/qrwlock_types.h>
+ 
+ #endif
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0003-net-mvpp2-initialize-the-Tx-FIFO-size.patch b/SOURCES/0003-net-mvpp2-initialize-the-Tx-FIFO-size.patch
new file mode 100644
index 0000000..08d12d4
--- /dev/null
+++ b/SOURCES/0003-net-mvpp2-initialize-the-Tx-FIFO-size.patch
@@ -0,0 +1,83 @@
+From c265d5613317c689df3f54ea80332af675e6ea84 Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@free-electrons.com>
+Date: Mon, 30 Oct 2017 11:23:29 +0100
+Subject: [PATCH 03/46] net: mvpp2: initialize the Tx FIFO size
+
+So far only the Rx FIFO size was initialized. For PPv2.2 the Tx FIFO
+size can be set as well. This patch initializes the Tx FIFO size for
+PPv2.2 controllers to 3K.
+
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 7c10f9742d76ec18bed5de14f5f4ed08859f7b7a)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 25 +++++++++++++++++++++----
+ 1 file changed, 21 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 80aa7f7..042afd7 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -38,11 +38,12 @@
+ #include <net/ipv6.h>
+ #include <net/tso.h>
+ 
+-/* RX Fifo Registers */
++/* Fifo Registers */
+ #define MVPP2_RX_DATA_FIFO_SIZE_REG(port)	(0x00 + 4 * (port))
+ #define MVPP2_RX_ATTR_FIFO_SIZE_REG(port)	(0x20 + 4 * (port))
+ #define MVPP2_RX_MIN_PKT_SIZE_REG		0x60
+ #define MVPP2_RX_FIFO_INIT_REG			0x64
++#define MVPP22_TX_FIFO_SIZE_REG(port)		(0x8860 + 4 * (port))
+ 
+ /* RX DMA Top Registers */
+ #define MVPP2_RX_CTRL_REG(port)			(0x140 + 4 * (port))
+@@ -512,6 +513,10 @@
+ #define MVPP2_RX_FIFO_PORT_ATTR_SIZE_4KB	0x40
+ #define MVPP2_RX_FIFO_PORT_MIN_PKT		0x80
+ 
++/* TX FIFO constants */
++#define MVPP22_TX_FIFO_DATA_SIZE_10KB		0xa
++#define MVPP22_TX_FIFO_DATA_SIZE_3KB		0x3
++
+ /* RX buffer constants */
+ #define MVPP2_SKB_SHINFO_SIZE \
+ 	SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
+@@ -7815,6 +7820,16 @@ static void mvpp22_rx_fifo_init(struct mvpp2 *priv)
+ 	mvpp2_write(priv, MVPP2_RX_FIFO_INIT_REG, 0x1);
+ }
+ 
++/* Initialize Tx FIFO's */
++static void mvpp22_tx_fifo_init(struct mvpp2 *priv)
++{
++	int port;
++
++	for (port = 0; port < MVPP2_MAX_PORTS; port++)
++		mvpp2_write(priv, MVPP22_TX_FIFO_SIZE_REG(port),
++			    MVPP22_TX_FIFO_DATA_SIZE_3KB);
++}
++
+ static void mvpp2_axi_init(struct mvpp2 *priv)
+ {
+ 	u32 val, rdval, wrval;
+@@ -7910,11 +7925,13 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)
+ 			return err;
+ 	}
+ 
+-	/* Rx Fifo Init */
+-	if (priv->hw_version == MVPP21)
++	/* Fifo Init */
++	if (priv->hw_version == MVPP21) {
+ 		mvpp2_rx_fifo_init(priv);
+-	else
++	} else {
+ 		mvpp22_rx_fifo_init(priv);
++		mvpp22_tx_fifo_init(priv);
++	}
+ 
+ 	if (priv->hw_version == MVPP21)
+ 		writel(MVPP2_EXT_GLOBAL_CTRL_DEFAULT,
+-- 
+2.7.4
+
diff --git a/SOURCES/0004-BACKPORT-arm64-kconfig-Ensure-spinlock-fastpaths-are.patch b/SOURCES/0004-BACKPORT-arm64-kconfig-Ensure-spinlock-fastpaths-are.patch
new file mode 100644
index 0000000..98e1d85
--- /dev/null
+++ b/SOURCES/0004-BACKPORT-arm64-kconfig-Ensure-spinlock-fastpaths-are.patch
@@ -0,0 +1,47 @@
+From 89bbb4b308e53d30daca20199b6039b64cd90fc1 Mon Sep 17 00:00:00 2001
+From: Khuong Dinh <khuong.dinh@amperecomputing.com>
+Date: Tue, 13 Mar 2018 21:17:01 +0000
+Subject: [PATCH 04/11] BACKPORT: arm64: kconfig: Ensure spinlock fastpaths are
+ inlined if !PREEMPT
+
+When running with CONFIG_PREEMPT=n, the spinlock fastpaths fit inside
+64 bytes, which typically coincides with the L1 I-cache line size.
+
+Inline the spinlock fastpaths, like we do already for rwlocks.
+
+This patch is required to fix kernel lock up due to new implementation of
+queued read write locking from kernel 4.14.
+This patch is backported from:
+https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20180913&id=5d168964aece0b4a41269839c613683c5d7e0fb2
+
+Change-Id: I1d450877a4d589dcd78c080533e71d046c621562
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Khuong Dinh <khuong.dinh@amperecomputing.com>
+---
+ arch/arm64/Kconfig | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
+index fba4bd7..db83519 100644
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -39,6 +39,16 @@ config ARM64
+ 	select ARCH_INLINE_WRITE_UNLOCK_BH if !PREEMPT
+ 	select ARCH_INLINE_WRITE_UNLOCK_IRQ if !PREEMPT
+ 	select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE if !PREEMPT
++	select ARCH_INLINE_SPIN_TRYLOCK if !PREEMPT
++	select ARCH_INLINE_SPIN_TRYLOCK_BH if !PREEMPT
++	select ARCH_INLINE_SPIN_LOCK if !PREEMPT
++	select ARCH_INLINE_SPIN_LOCK_BH if !PREEMPT
++	select ARCH_INLINE_SPIN_LOCK_IRQ if !PREEMPT
++	select ARCH_INLINE_SPIN_LOCK_IRQSAVE if !PREEMPT
++	select ARCH_INLINE_SPIN_UNLOCK if !PREEMPT
++	select ARCH_INLINE_SPIN_UNLOCK_BH if !PREEMPT
++	select ARCH_INLINE_SPIN_UNLOCK_IRQ if !PREEMPT
++	select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE if !PREEMPT
+ 	select ARCH_USE_CMPXCHG_LOCKREF
+ 	select ARCH_USE_QUEUED_RWLOCKS
+ 	select ARCH_USE_QUEUED_SPINLOCKS
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0004-net-mvpp2-initialize-the-RSS-tables.patch b/SOURCES/0004-net-mvpp2-initialize-the-RSS-tables.patch
new file mode 100644
index 0000000..12f27f2
--- /dev/null
+++ b/SOURCES/0004-net-mvpp2-initialize-the-RSS-tables.patch
@@ -0,0 +1,103 @@
+From 114b7c5b1ee39740e6faafdc82debdd4b0e4d9c4 Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@free-electrons.com>
+Date: Mon, 30 Oct 2017 11:23:30 +0100
+Subject: [PATCH 04/46] net: mvpp2: initialize the RSS tables
+
+This patch initialize the RSS tables to evenly (depending on the packets
+RSS hashes) distribute the packets across port Rx queues. This helps to
+handle packets on different CPUs to improve performances, as more queues
+will be used in parallel.
+
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 1d7d15d79fb4660bec3a86e748c50aac7c5d2121)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 50 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 50 insertions(+)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 042afd7..6eb61a9 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -83,6 +83,16 @@
+ #define MVPP2_PRS_TCAM_CTRL_REG			0x1230
+ #define     MVPP2_PRS_TCAM_EN_MASK		BIT(0)
+ 
++/* RSS Registers */
++#define MVPP22_RSS_INDEX			0x1500
++#define     MVPP22_RSS_INDEX_TABLE_ENTRY(idx)	((idx) << 8)
++#define     MVPP22_RSS_INDEX_TABLE(idx)		((idx) << 8)
++#define     MVPP22_RSS_INDEX_QUEUE(idx)		((idx) << 16)
++#define MVPP22_RSS_TABLE_ENTRY			0x1508
++#define MVPP22_RSS_TABLE			0x1510
++#define     MVPP22_RSS_TABLE_POINTER(p)		(p)
++#define MVPP22_RSS_WIDTH			0x150c
++
+ /* Classifier Registers */
+ #define MVPP2_CLS_MODE_REG			0x1800
+ #define     MVPP2_CLS_MODE_ACTIVE_MASK		BIT(0)
+@@ -746,6 +756,10 @@ enum mvpp2_prs_l3_cast {
+ #define MVPP2_CLS_FLOWS_TBL_SIZE	512
+ #define MVPP2_CLS_FLOWS_TBL_DATA_WORDS	3
+ #define MVPP2_CLS_LKP_TBL_SIZE		64
++#define MVPP2_CLS_RX_QUEUES		256
++
++/* RSS constants */
++#define MVPP22_RSS_TABLE_ENTRIES	32
+ 
+ /* BM constants */
+ #define MVPP2_BM_POOLS_NUM		8
+@@ -6792,6 +6806,39 @@ static void mvpp2_irqs_deinit(struct mvpp2_port *port)
+ 	}
+ }
+ 
++static void mvpp22_init_rss(struct mvpp2_port *port)
++{
++	struct mvpp2 *priv = port->priv;
++	int i;
++
++	/* Set the table width: replace the whole classifier Rx queue number
++	 * with the ones configured in RSS table entries.
++	 */
++	mvpp2_write(priv, MVPP22_RSS_INDEX, MVPP22_RSS_INDEX_TABLE(0));
++	mvpp2_write(priv, MVPP22_RSS_WIDTH, 8);
++
++	/* Loop through the classifier Rx Queues and map them to a RSS table.
++	 * Map them all to the first table (0) by default.
++	 */
++	for (i = 0; i < MVPP2_CLS_RX_QUEUES; i++) {
++		mvpp2_write(priv, MVPP22_RSS_INDEX, MVPP22_RSS_INDEX_QUEUE(i));
++		mvpp2_write(priv, MVPP22_RSS_TABLE,
++			    MVPP22_RSS_TABLE_POINTER(0));
++	}
++
++	/* Configure the first table to evenly distribute the packets across
++	 * real Rx Queues. The table entries map a hash to an port Rx Queue.
++	 */
++	for (i = 0; i < MVPP22_RSS_TABLE_ENTRIES; i++) {
++		u32 sel = MVPP22_RSS_INDEX_TABLE(0) |
++			  MVPP22_RSS_INDEX_TABLE_ENTRY(i);
++		mvpp2_write(priv, MVPP22_RSS_INDEX, sel);
++
++		mvpp2_write(priv, MVPP22_RSS_TABLE_ENTRY, i % port->nrxqs);
++	}
++
++}
++
+ static int mvpp2_open(struct net_device *dev)
+ {
+ 	struct mvpp2_port *port = netdev_priv(dev);
+@@ -6866,6 +6913,9 @@ static int mvpp2_open(struct net_device *dev)
+ 
+ 	mvpp2_start_dev(port);
+ 
++	if (priv->hw_version == MVPP22)
++		mvpp22_init_rss(port);
++
+ 	return 0;
+ 
+ err_free_link_irq:
+-- 
+2.7.4
+
diff --git a/SOURCES/0005-BACKPORT-ahci-Disable-LPM-on-Lenovo-50-series-laptop.patch b/SOURCES/0005-BACKPORT-ahci-Disable-LPM-on-Lenovo-50-series-laptop.patch
new file mode 100644
index 0000000..cd8efd8
--- /dev/null
+++ b/SOURCES/0005-BACKPORT-ahci-Disable-LPM-on-Lenovo-50-series-laptop.patch
@@ -0,0 +1,160 @@
+From c75c91833dd0998ece4c2fbc6bf97a87e19551e3 Mon Sep 17 00:00:00 2001
+From: Khuong Dinh <khuong.dinh@amperecomputing.com>
+Date: Sun, 1 Jul 2018 12:15:46 +0200
+Subject: [PATCH 05/11] BACKPORT: ahci: Disable LPM on Lenovo 50 series laptops
+ with a too old BIOS
+
+There have been several reports of LPM related hard freezes about once
+a day on multiple Lenovo 50 series models. Strange enough these reports
+where not disk model specific as LPM issues usually are and some users
+with the exact same disk + laptop where seeing them while other users
+where not seeing these issues.
+
+It turns out that enabling LPM triggers a firmware bug somewhere, which
+has been fixed in later BIOS versions.
+
+This commit adds a new ahci_broken_lpm() function and a new ATA_FLAG_NO_LPM
+for dealing with this.
+
+The ahci_broken_lpm() function contains DMI match info for the 4 models
+which are known to be affected by this and the DMI BIOS date field for
+known good BIOS versions. If the BIOS date is older then the one in the
+table LPM will be disabled and a warning will be printed.
+
+Note the BIOS dates are for known good versions, some older versions may
+work too, but we don't know for sure, the table is using dates from BIOS
+versions for which users have confirmed that upgrading to that version
+makes the problem go away.
+
+Unfortunately I've been unable to get hold of the reporter who reported
+that BIOS version 2.35 fixed the problems on the W541 for him. I've been
+able to verify the DMI_SYS_VENDOR and DMI_PRODUCT_VERSION from an older
+dmidecode, but I don't know the exact BIOS date as reported in the DMI.
+Lenovo keeps a changelog with dates in their release notes, but the
+dates there are the release dates not the build dates which are in DMI.
+So I've chosen to set the date to which we compare to one day past the
+release date of the 2.34 BIOS. I plan to fix this with a follow up
+commit once I've the necessary info.
+
+This patch is required to support AHCI ALPM de-feature for Ampere Computing
+eMAG SATA.
+This patch is backported from:
+https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20180913&id=240630e61870e62e39a97225048f9945848fa5f5
+
+Change-Id: I077e886a4faff18e2cb884c361065d9bd0a22e50
+Cc: stable@vger.kernel.org
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Khuong Dinh <khuong.dinh@amperecomputing.com>
+---
+ drivers/ata/ahci.c        | 59 +++++++++++++++++++++++++++++++++++++++++++++++
+ drivers/ata/libata-core.c |  3 +++
+ include/linux/libata.h    |  1 +
+ 3 files changed, 63 insertions(+)
+
+diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
+index 9f78bb0..e0c2de6 100644
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -1260,6 +1260,59 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
+ 	return strcmp(buf, dmi->driver_data) < 0;
+ }
+ 
++static bool ahci_broken_lpm(struct pci_dev *pdev)
++{
++	static const struct dmi_system_id sysids[] = {
++		/* Various Lenovo 50 series have LPM issues with older BIOSen */
++		{
++			.matches = {
++				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X250"),
++			},
++			.driver_data = "20180406", /* 1.31 */
++		},
++		{
++			.matches = {
++				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L450"),
++			},
++			.driver_data = "20180420", /* 1.28 */
++		},
++		{
++			.matches = {
++				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T450s"),
++			},
++			.driver_data = "20180315", /* 1.33 */
++		},
++		{
++			.matches = {
++				DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++				DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"),
++			},
++			/*
++			 * Note date based on release notes, 2.35 has been
++			 * reported to be good, but I've been unable to get
++			 * a hold of the reporter to get the DMI BIOS date.
++			 * TODO: fix this.
++			 */
++			.driver_data = "20180310", /* 2.35 */
++		},
++		{ }	/* terminate list */
++	};
++	const struct dmi_system_id *dmi = dmi_first_match(sysids);
++	int year, month, date;
++	char buf[9];
++
++	if (!dmi)
++		return false;
++
++	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
++	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
++
++	return strcmp(buf, dmi->driver_data) < 0;
++}
++
+ static bool ahci_broken_online(struct pci_dev *pdev)
+ {
+ #define ENCODE_BUSDEVFN(bus, slot, func)			\
+@@ -1670,6 +1723,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 			"quirky BIOS, skipping spindown on poweroff\n");
+ 	}
+ 
++	if (ahci_broken_lpm(pdev)) {
++		pi.flags |= ATA_FLAG_NO_LPM;
++		dev_warn(&pdev->dev,
++			 "BIOS update required for Link Power Management support\n");
++	}
++
+ 	if (ahci_broken_suspend(pdev)) {
+ 		hpriv->flags |= AHCI_HFLAG_NO_SUSPEND;
+ 		dev_warn(&pdev->dev,
+diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
+index ee4c1ec..35346c1 100644
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -2501,6 +2501,9 @@ int ata_dev_configure(struct ata_device *dev)
+ 	    (id[ATA_ID_SATA_CAPABILITY] & 0xe) == 0x2)
+ 		dev->horkage |= ATA_HORKAGE_NOLPM;
+ 
++	if (ap->flags & ATA_FLAG_NO_LPM)
++		dev->horkage |= ATA_HORKAGE_NOLPM;
++
+ 	if (dev->horkage & ATA_HORKAGE_NOLPM) {
+ 		ata_dev_warn(dev, "LPM support broken, forcing max_power\n");
+ 		dev->link->ap->target_lpm_policy = ATA_LPM_MAX_POWER;
+diff --git a/include/linux/libata.h b/include/linux/libata.h
+index 6b7a196..a4a7e0f 100644
+--- a/include/linux/libata.h
++++ b/include/linux/libata.h
+@@ -211,6 +211,7 @@ enum {
+ 	ATA_FLAG_SLAVE_POSS	= (1 << 0), /* host supports slave dev */
+ 					    /* (doesn't imply presence) */
+ 	ATA_FLAG_SATA		= (1 << 1),
++	ATA_FLAG_NO_LPM		= (1 << 2), /* host not happy with LPM */
+ 	ATA_FLAG_NO_LOG_PAGE	= (1 << 5), /* do not issue log page read */
+ 	ATA_FLAG_NO_ATAPI	= (1 << 6), /* No ATAPI support */
+ 	ATA_FLAG_PIO_DMA	= (1 << 7), /* PIO cmds via DMA */
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0005-net-mvpp2-limit-TSO-segments-and-use-stop-wake-thres.patch b/SOURCES/0005-net-mvpp2-limit-TSO-segments-and-use-stop-wake-thres.patch
new file mode 100644
index 0000000..de02c02
--- /dev/null
+++ b/SOURCES/0005-net-mvpp2-limit-TSO-segments-and-use-stop-wake-thres.patch
@@ -0,0 +1,88 @@
+From 0ae78841cd368b829178f14c810012297a597222 Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@free-electrons.com>
+Date: Mon, 30 Oct 2017 11:23:31 +0100
+Subject: [PATCH 05/46] net: mvpp2: limit TSO segments and use stop/wake
+ thresholds
+
+Too many TSO descriptors can be required for the default queue size,
+when using small MSS values for example. Prevent this by adding a
+maximum number of allowed TSO segments (300). In addition set a stop and
+a wake thresholds to stop the queue when there's no room for a 1 "worst
+case scenario skb". Wake up the queue when the number of descriptors is
+low enough.
+
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 1d17db08c056c1f7f4abbff6aff8711b7c3a3b7f)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 6eb61a9..79e6958 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -493,6 +493,13 @@
+ /* Maximum number of TXQs used by single port */
+ #define MVPP2_MAX_TXQ			8
+ 
++/* MVPP2_MAX_TSO_SEGS is the maximum number of fragments to allow in the GSO
++ * skb. As we need a maxium of two descriptors per fragments (1 header, 1 data),
++ * multiply this value by two to count the maximum number of skb descs needed.
++ */
++#define MVPP2_MAX_TSO_SEGS		300
++#define MVPP2_MAX_SKB_DESCS		(MVPP2_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS)
++
+ /* Dfault number of RXQs in use */
+ #define MVPP2_DEFAULT_RXQ		4
+ 
+@@ -1045,6 +1052,9 @@ struct mvpp2_txq_pcpu {
+ 	 */
+ 	int count;
+ 
++	int wake_threshold;
++	int stop_threshold;
++
+ 	/* Number of Tx DMA descriptors reserved for each CPU */
+ 	int reserved_num;
+ 
+@@ -5393,7 +5403,7 @@ static void mvpp2_txq_done(struct mvpp2_port *port, struct mvpp2_tx_queue *txq,
+ 	txq_pcpu->count -= tx_done;
+ 
+ 	if (netif_tx_queue_stopped(nq))
+-		if (txq_pcpu->size - txq_pcpu->count >= MAX_SKB_FRAGS + 1)
++		if (txq_pcpu->count <= txq_pcpu->wake_threshold)
+ 			netif_tx_wake_queue(nq);
+ }
+ 
+@@ -5636,6 +5646,9 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
+ 		txq_pcpu->txq_put_index = 0;
+ 		txq_pcpu->txq_get_index = 0;
+ 
++		txq_pcpu->stop_threshold = txq->size - MVPP2_MAX_SKB_DESCS;
++		txq_pcpu->wake_threshold = txq_pcpu->stop_threshold / 2;
++
+ 		txq_pcpu->tso_headers =
+ 			dma_alloc_coherent(port->dev->dev.parent,
+ 					   txq_pcpu->size * TSO_HEADER_SIZE,
+@@ -6508,7 +6521,7 @@ static int mvpp2_tx(struct sk_buff *skb, struct net_device *dev)
+ 		wmb();
+ 		mvpp2_aggr_txq_pend_desc_add(port, frags);
+ 
+-		if (txq_pcpu->size - txq_pcpu->count < MAX_SKB_FRAGS + 1)
++		if (txq_pcpu->count >= txq_pcpu->stop_threshold)
+ 			netif_tx_stop_queue(nq);
+ 
+ 		u64_stats_update_begin(&stats->syncp);
+@@ -7736,6 +7749,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 	dev->features = features | NETIF_F_RXCSUM;
+ 	dev->hw_features |= features | NETIF_F_RXCSUM | NETIF_F_GRO;
+ 	dev->vlan_features |= features;
++	dev->gso_max_segs = MVPP2_MAX_TSO_SEGS;
+ 
+ 	/* MTU range: 68 - 9676 */
+ 	dev->min_mtu = ETH_MIN_MTU;
+-- 
+2.7.4
+
diff --git a/SOURCES/0006-BACKPORT-ACPI-bus-Introduce-acpi_get_match_data-func.patch b/SOURCES/0006-BACKPORT-ACPI-bus-Introduce-acpi_get_match_data-func.patch
new file mode 100644
index 0000000..1f6ae43
--- /dev/null
+++ b/SOURCES/0006-BACKPORT-ACPI-bus-Introduce-acpi_get_match_data-func.patch
@@ -0,0 +1,80 @@
+From 62b61856762a48709e29bbfc5f804b6185b79d93 Mon Sep 17 00:00:00 2001
+From: Khuong Dinh <khuong.dinh@amperecomputing.com>
+Date: Wed, 13 Dec 2017 02:20:48 -0500
+Subject: [PATCH 06/11] BACKPORT: ACPI / bus: Introduce acpi_get_match_data()
+ function
+
+OF has of_device_get_match_data() function to extract driver specific data
+structure. Add a similar function for ACPI.
+
+This patch is required to support AHCI ALPM de-feature for Ampere Computing
+eMAG SATA.
+This patch is backported from:
+https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20180913&id=80212a162329e590fde02d8457af16ea0ab0a55f
+
+Change-Id: I764d8e7ef1e9375561dc895bba74f8edb5888d06
+Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
+Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Vinod Koul <vinod.koul@intel.com>
+Signed-off-by: Khuong Dinh <khuong.dinh@amperecomputing.com>
+---
+ drivers/acpi/bus.c   | 18 ++++++++++++++++++
+ include/linux/acpi.h |  6 ++++++
+ 2 files changed, 24 insertions(+)
+
+diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
+index 4d0979e..f87ed3b 100644
+--- a/drivers/acpi/bus.c
++++ b/drivers/acpi/bus.c
+@@ -785,6 +785,24 @@ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
+ }
+ EXPORT_SYMBOL_GPL(acpi_match_device);
+ 
++void *acpi_get_match_data(const struct device *dev)
++{
++	const struct acpi_device_id *match;
++
++	if (!dev->driver)
++		return NULL;
++
++	if (!dev->driver->acpi_match_table)
++		return NULL;
++
++	match = acpi_match_device(dev->driver->acpi_match_table, dev);
++	if (!match)
++		return NULL;
++
++	return (void *)match->driver_data;
++}
++EXPORT_SYMBOL_GPL(acpi_get_match_data);
++
+ int acpi_match_device_ids(struct acpi_device *device,
+ 			  const struct acpi_device_id *ids)
+ {
+diff --git a/include/linux/acpi.h b/include/linux/acpi.h
+index 8bcfe3d..42e1565 100644
+--- a/include/linux/acpi.h
++++ b/include/linux/acpi.h
+@@ -584,6 +584,7 @@ extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
+ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
+ 					       const struct device *dev);
+ 
++void *acpi_get_match_data(const struct device *dev);
+ extern bool acpi_driver_match_device(struct device *dev,
+ 				     const struct device_driver *drv);
+ int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *);
+@@ -755,6 +756,11 @@ static inline const struct acpi_device_id *acpi_match_device(
+ 	return NULL;
+ }
+ 
++static inline void *acpi_get_match_data(const struct device *dev)
++{
++	return NULL;
++}
++
+ static inline bool acpi_driver_match_device(struct device *dev,
+ 					    const struct device_driver *drv)
+ {
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0006-net-mvpp2-use-the-aggr-txq-size-define-everywhere.patch b/SOURCES/0006-net-mvpp2-use-the-aggr-txq-size-define-everywhere.patch
new file mode 100644
index 0000000..065ff65
--- /dev/null
+++ b/SOURCES/0006-net-mvpp2-use-the-aggr-txq-size-define-everywhere.patch
@@ -0,0 +1,51 @@
+From 5b24b458fb1934cc91d9cbf31841bd067cf74737 Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@free-electrons.com>
+Date: Mon, 30 Oct 2017 11:23:32 +0100
+Subject: [PATCH 06/46] net: mvpp2: use the aggr txq size define everywhere
+
+Cosmetic patch using the MVPP2_AGGR_TXQ_SIZE everywhere instead of the
+size field of aggr_txq, as the size never change and is always equal to
+the MVPP2_AGGR_TXQ_SIZE define.
+
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 02856a3ba6333c536f13d27cc847fcb442a23d9b)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 79e6958..9a9decb 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -5055,7 +5055,7 @@ static void mvpp2_aggr_txq_pend_desc_add(struct mvpp2_port *port, int pending)
+ static int mvpp2_aggr_desc_num_check(struct mvpp2 *priv,
+ 				     struct mvpp2_tx_queue *aggr_txq, int num)
+ {
+-	if ((aggr_txq->count + num) > aggr_txq->size) {
++	if ((aggr_txq->count + num) > MVPP2_AGGR_TXQ_SIZE) {
+ 		/* Update number of occupied aggregated Tx descriptors */
+ 		int cpu = smp_processor_id();
+ 		u32 val = mvpp2_read(priv, MVPP2_AGGR_TXQ_STATUS_REG(cpu));
+@@ -5063,7 +5063,7 @@ static int mvpp2_aggr_desc_num_check(struct mvpp2 *priv,
+ 		aggr_txq->count = val & MVPP2_AGGR_TXQ_PENDING_MASK;
+ 	}
+ 
+-	if ((aggr_txq->count + num) > aggr_txq->size)
++	if ((aggr_txq->count + num) > MVPP2_AGGR_TXQ_SIZE)
+ 		return -ENOMEM;
+ 
+ 	return 0;
+@@ -5447,7 +5447,7 @@ static int mvpp2_aggr_txq_init(struct platform_device *pdev,
+ 	if (!aggr_txq->descs)
+ 		return -ENOMEM;
+ 
+-	aggr_txq->last_desc = aggr_txq->size - 1;
++	aggr_txq->last_desc = MVPP2_AGGR_TXQ_SIZE - 1;
+ 
+ 	/* Aggr TXQ no reset WA */
+ 	aggr_txq->next_desc_to_proc = mvpp2_read(priv,
+-- 
+2.7.4
+
diff --git a/SOURCES/0007-BACKPORT-ACPI-bus-Remove-checks-in-acpi_get_match_da.patch b/SOURCES/0007-BACKPORT-ACPI-bus-Remove-checks-in-acpi_get_match_da.patch
new file mode 100644
index 0000000..05f8f8f
--- /dev/null
+++ b/SOURCES/0007-BACKPORT-ACPI-bus-Remove-checks-in-acpi_get_match_da.patch
@@ -0,0 +1,53 @@
+From 4b8a8385da13bd51d7403c5b08bbeab02e05c393 Mon Sep 17 00:00:00 2001
+From: Khuong Dinh <khuong.dinh@amperecomputing.com>
+Date: Fri, 9 Feb 2018 17:38:34 +0200
+Subject: [PATCH 07/11] BACKPORT: ACPI / bus: Remove checks in
+ acpi_get_match_data()
+
+As well as its sibling of_device_get_match_data() has no such checks,
+no need to do it in acpi_get_match_data().
+
+First of all, we are not supposed to call fwnode API like this without
+driver attached.
+
+Second, since __acpi_match_device() does check input parameter there is
+no need to duplicate it outside.
+
+And last but not least one, the API should still serve the cases when
+ACPI device is enumerated via PRP0001. In such case driver has neither
+ACPI table nor driver data there.
+
+This patch is required to support AHCI ALPM de-feature for Ampere Computing
+eMAG SATA.
+This patch is backported from:
+https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20180913&id=8ff277c5bf87d750a44a656d4f113462493acbfc
+
+Change-Id: Id2f1d591f59af93e21741cd62c8ced0ff6a747b8
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Khuong Dinh <khuong.dinh@amperecomputing.com>
+---
+ drivers/acpi/bus.c | 6 ------
+ 1 file changed, 6 deletions(-)
+
+diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
+index f87ed3b..b271eb1 100644
+--- a/drivers/acpi/bus.c
++++ b/drivers/acpi/bus.c
+@@ -789,12 +789,6 @@ void *acpi_get_match_data(const struct device *dev)
+ {
+ 	const struct acpi_device_id *match;
+ 
+-	if (!dev->driver)
+-		return NULL;
+-
+-	if (!dev->driver->acpi_match_table)
+-		return NULL;
+-
+ 	match = acpi_match_device(dev->driver->acpi_match_table, dev);
+ 	if (!match)
+ 		return NULL;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0007-net-mvpp2-simplify-the-Tx-desc-set-DMA-logic.patch b/SOURCES/0007-net-mvpp2-simplify-the-Tx-desc-set-DMA-logic.patch
new file mode 100644
index 0000000..1f56fc1
--- /dev/null
+++ b/SOURCES/0007-net-mvpp2-simplify-the-Tx-desc-set-DMA-logic.patch
@@ -0,0 +1,116 @@
+From ed377c192631a3b01501f6332156328efa11babf Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@free-electrons.com>
+Date: Mon, 30 Oct 2017 11:23:33 +0100
+Subject: [PATCH 07/46] net: mvpp2: simplify the Tx desc set DMA logic
+
+Two functions were always used to set the DMA addresses in Tx
+descriptors, because this address is split into a base+offset in the
+descriptors. A mask was used to come up with the base and offset
+addresses and two functions were called, mvpp2_txdesc_dma_addr_set() and
+mvpp2_txdesc_offset_set().
+
+This patch moves the base+offset calculation logic to
+mvpp2_txdesc_dma_addr_set(), and removes mvpp2_txdesc_offset_set() to
+simplify things.
+
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 6eb5d375cefcbd60ebb4251b150ea95d47140fe0)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 39 ++++++++++++------------------------
+ 1 file changed, 13 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 9a9decb..fb0d9c0 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -1290,13 +1290,20 @@ static void mvpp2_txdesc_dma_addr_set(struct mvpp2_port *port,
+ 				      struct mvpp2_tx_desc *tx_desc,
+ 				      dma_addr_t dma_addr)
+ {
++	dma_addr_t addr, offset;
++
++	addr = dma_addr & ~MVPP2_TX_DESC_ALIGN;
++	offset = dma_addr & MVPP2_TX_DESC_ALIGN;
++
+ 	if (port->priv->hw_version == MVPP21) {
+-		tx_desc->pp21.buf_dma_addr = dma_addr;
++		tx_desc->pp21.buf_dma_addr = addr;
++		tx_desc->pp21.packet_offset = offset;
+ 	} else {
+-		u64 val = (u64)dma_addr;
++		u64 val = (u64)addr;
+ 
+ 		tx_desc->pp22.buf_dma_addr_ptp &= ~GENMASK_ULL(40, 0);
+ 		tx_desc->pp22.buf_dma_addr_ptp |= val;
++		tx_desc->pp22.packet_offset = offset;
+ 	}
+ }
+ 
+@@ -1339,16 +1346,6 @@ static void mvpp2_txdesc_cmd_set(struct mvpp2_port *port,
+ 		tx_desc->pp22.command = command;
+ }
+ 
+-static void mvpp2_txdesc_offset_set(struct mvpp2_port *port,
+-				    struct mvpp2_tx_desc *tx_desc,
+-				    unsigned int offset)
+-{
+-	if (port->priv->hw_version == MVPP21)
+-		tx_desc->pp21.packet_offset = offset;
+-	else
+-		tx_desc->pp22.packet_offset = offset;
+-}
+-
+ static unsigned int mvpp2_txdesc_offset_get(struct mvpp2_port *port,
+ 					    struct mvpp2_tx_desc *tx_desc)
+ {
+@@ -6292,10 +6289,7 @@ static int mvpp2_tx_frag_process(struct mvpp2_port *port, struct sk_buff *skb,
+ 			goto cleanup;
+ 		}
+ 
+-		mvpp2_txdesc_offset_set(port, tx_desc,
+-					buf_dma_addr & MVPP2_TX_DESC_ALIGN);
+-		mvpp2_txdesc_dma_addr_set(port, tx_desc,
+-					  buf_dma_addr & ~MVPP2_TX_DESC_ALIGN);
++		mvpp2_txdesc_dma_addr_set(port, tx_desc, buf_dma_addr);
+ 
+ 		if (i == (skb_shinfo(skb)->nr_frags - 1)) {
+ 			/* Last descriptor */
+@@ -6338,8 +6332,7 @@ static inline void mvpp2_tso_put_hdr(struct sk_buff *skb,
+ 
+ 	addr = txq_pcpu->tso_headers_dma +
+ 	       txq_pcpu->txq_put_index * TSO_HEADER_SIZE;
+-	mvpp2_txdesc_offset_set(port, tx_desc, addr & MVPP2_TX_DESC_ALIGN);
+-	mvpp2_txdesc_dma_addr_set(port, tx_desc, addr & ~MVPP2_TX_DESC_ALIGN);
++	mvpp2_txdesc_dma_addr_set(port, tx_desc, addr);
+ 
+ 	mvpp2_txdesc_cmd_set(port, tx_desc, mvpp2_skb_tx_csum(port, skb) |
+ 					    MVPP2_TXD_F_DESC |
+@@ -6368,10 +6361,7 @@ static inline int mvpp2_tso_put_data(struct sk_buff *skb,
+ 		return -ENOMEM;
+ 	}
+ 
+-	mvpp2_txdesc_offset_set(port, tx_desc,
+-				buf_dma_addr & MVPP2_TX_DESC_ALIGN);
+-	mvpp2_txdesc_dma_addr_set(port, tx_desc,
+-				  buf_dma_addr & ~MVPP2_TX_DESC_ALIGN);
++	mvpp2_txdesc_dma_addr_set(port, tx_desc, buf_dma_addr);
+ 
+ 	if (!left) {
+ 		mvpp2_txdesc_cmd_set(port, tx_desc, MVPP2_TXD_L_DESC);
+@@ -6483,10 +6473,7 @@ static int mvpp2_tx(struct sk_buff *skb, struct net_device *dev)
+ 		goto out;
+ 	}
+ 
+-	mvpp2_txdesc_offset_set(port, tx_desc,
+-				buf_dma_addr & MVPP2_TX_DESC_ALIGN);
+-	mvpp2_txdesc_dma_addr_set(port, tx_desc,
+-				  buf_dma_addr & ~MVPP2_TX_DESC_ALIGN);
++	mvpp2_txdesc_dma_addr_set(port, tx_desc, buf_dma_addr);
+ 
+ 	tx_cmd = mvpp2_skb_tx_csum(port, skb);
+ 
+-- 
+2.7.4
+
diff --git a/SOURCES/0008-BACKPORT-ACPI-bus-Rename-acpi_get_match_data-to-acpi.patch b/SOURCES/0008-BACKPORT-ACPI-bus-Rename-acpi_get_match_data-to-acpi.patch
new file mode 100644
index 0000000..478690a
--- /dev/null
+++ b/SOURCES/0008-BACKPORT-ACPI-bus-Rename-acpi_get_match_data-to-acpi.patch
@@ -0,0 +1,73 @@
+From 0fe2601c5f132408da07b3e674d5932549375616 Mon Sep 17 00:00:00 2001
+From: Khuong Dinh <khuong.dinh@amperecomputing.com>
+Date: Fri, 9 Feb 2018 17:38:35 +0200
+Subject: [PATCH 08/11] BACKPORT: ACPI / bus: Rename acpi_get_match_data() to
+ acpi_device_get_match_data()
+
+Do the renaming to be consistent with its sibling, i.e.
+of_device_get_match_data().
+
+No functional change.
+
+This patch is required to support AHCI ALPM de-feature for Ampere Computing
+eMAG SATA.
+This patch is backported from:
+https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20180913&id=29d5325a14ab49375476e3a6442ff40a008a8c9a
+
+Change-Id: I1e4becb2b3aced73f30b77ec99b2882983639f50
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Khuong Dinh <khuong.dinh@amperecomputing.com>
+---
+ drivers/acpi/bus.c   | 4 ++--
+ include/linux/acpi.h | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
+index b271eb1..da29c10 100644
+--- a/drivers/acpi/bus.c
++++ b/drivers/acpi/bus.c
+@@ -785,7 +785,7 @@ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
+ }
+ EXPORT_SYMBOL_GPL(acpi_match_device);
+ 
+-void *acpi_get_match_data(const struct device *dev)
++void *acpi_device_get_match_data(const struct device *dev)
+ {
+ 	const struct acpi_device_id *match;
+ 
+@@ -795,7 +795,7 @@ void *acpi_get_match_data(const struct device *dev)
+ 
+ 	return (void *)match->driver_data;
+ }
+-EXPORT_SYMBOL_GPL(acpi_get_match_data);
++EXPORT_SYMBOL_GPL(acpi_device_get_match_data);
+ 
+ int acpi_match_device_ids(struct acpi_device *device,
+ 			  const struct acpi_device_id *ids)
+diff --git a/include/linux/acpi.h b/include/linux/acpi.h
+index 42e1565..379619e 100644
+--- a/include/linux/acpi.h
++++ b/include/linux/acpi.h
+@@ -584,7 +584,7 @@ extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
+ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
+ 					       const struct device *dev);
+ 
+-void *acpi_get_match_data(const struct device *dev);
++void *acpi_device_get_match_data(const struct device *dev);
+ extern bool acpi_driver_match_device(struct device *dev,
+ 				     const struct device_driver *drv);
+ int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *);
+@@ -756,7 +756,7 @@ static inline const struct acpi_device_id *acpi_match_device(
+ 	return NULL;
+ }
+ 
+-static inline void *acpi_get_match_data(const struct device *dev)
++static inline void *acpi_device_get_match_data(const struct device *dev)
+ {
+ 	return NULL;
+ }
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0008-net-mvpp2-add-ethtool-GOP-statistics.patch b/SOURCES/0008-net-mvpp2-add-ethtool-GOP-statistics.patch
new file mode 100644
index 0000000..817333f
--- /dev/null
+++ b/SOURCES/0008-net-mvpp2-add-ethtool-GOP-statistics.patch
@@ -0,0 +1,375 @@
+From 274098c872141c923ee78936e9bf1e9c2597c82b Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@free-electrons.com>
+Date: Mon, 6 Nov 2017 22:56:53 +0100
+Subject: [PATCH 08/46] net: mvpp2: add ethtool GOP statistics
+
+Add ethtool statistics support by reading the GOP statistics from the
+hardware counters. Also implement a workqueue to gather the statistics
+every second or some 32-bit counters could overflow.
+
+Suggested-by: Stefan Chulski <stefanc@marvell.com>
+Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 118d6298f6f0556e54331a6e86de2313d134fdbb)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 228 ++++++++++++++++++++++++++++++++++-
+ 1 file changed, 223 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index fb0d9c0..a79d2ff 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -799,6 +799,42 @@ enum mvpp2_bm_type {
+ 	MVPP2_BM_SWF_SHORT
+ };
+ 
++/* GMAC MIB Counters register definitions */
++#define MVPP21_MIB_COUNTERS_OFFSET		0x1000
++#define MVPP21_MIB_COUNTERS_PORT_SZ		0x400
++#define MVPP22_MIB_COUNTERS_OFFSET		0x0
++#define MVPP22_MIB_COUNTERS_PORT_SZ		0x100
++
++#define MVPP2_MIB_GOOD_OCTETS_RCVD		0x0
++#define MVPP2_MIB_BAD_OCTETS_RCVD		0x8
++#define MVPP2_MIB_CRC_ERRORS_SENT		0xc
++#define MVPP2_MIB_UNICAST_FRAMES_RCVD		0x10
++#define MVPP2_MIB_BROADCAST_FRAMES_RCVD		0x18
++#define MVPP2_MIB_MULTICAST_FRAMES_RCVD		0x1c
++#define MVPP2_MIB_FRAMES_64_OCTETS		0x20
++#define MVPP2_MIB_FRAMES_65_TO_127_OCTETS	0x24
++#define MVPP2_MIB_FRAMES_128_TO_255_OCTETS	0x28
++#define MVPP2_MIB_FRAMES_256_TO_511_OCTETS	0x2c
++#define MVPP2_MIB_FRAMES_512_TO_1023_OCTETS	0x30
++#define MVPP2_MIB_FRAMES_1024_TO_MAX_OCTETS	0x34
++#define MVPP2_MIB_GOOD_OCTETS_SENT		0x38
++#define MVPP2_MIB_UNICAST_FRAMES_SENT		0x40
++#define MVPP2_MIB_MULTICAST_FRAMES_SENT		0x48
++#define MVPP2_MIB_BROADCAST_FRAMES_SENT		0x4c
++#define MVPP2_MIB_FC_SENT			0x54
++#define MVPP2_MIB_FC_RCVD			0x58
++#define MVPP2_MIB_RX_FIFO_OVERRUN		0x5c
++#define MVPP2_MIB_UNDERSIZE_RCVD		0x60
++#define MVPP2_MIB_FRAGMENTS_RCVD		0x64
++#define MVPP2_MIB_OVERSIZE_RCVD			0x68
++#define MVPP2_MIB_JABBER_RCVD			0x6c
++#define MVPP2_MIB_MAC_RCV_ERROR			0x70
++#define MVPP2_MIB_BAD_CRC_EVENT			0x74
++#define MVPP2_MIB_COLLISION			0x78
++#define MVPP2_MIB_LATE_COLLISION		0x7c
++
++#define MVPP2_MIB_COUNTERS_STATS_DELAY		(1 * HZ)
++
+ /* Definitions */
+ 
+ /* Shared Packet Processor resources */
+@@ -826,6 +862,7 @@ struct mvpp2 {
+ 	struct clk *axi_clk;
+ 
+ 	/* List of pointers to port structures */
++	int port_count;
+ 	struct mvpp2_port **port_list;
+ 
+ 	/* Aggregated TXQs */
+@@ -847,6 +884,12 @@ struct mvpp2 {
+ 
+ 	/* Maximum number of RXQs per port */
+ 	unsigned int max_port_rxqs;
++
++	/* Workqueue to gather hardware statistics with its lock */
++	struct mutex gather_stats_lock;
++	struct delayed_work stats_work;
++	char queue_name[30];
++	struct workqueue_struct *stats_queue;
+ };
+ 
+ struct mvpp2_pcpu_stats {
+@@ -891,6 +934,7 @@ struct mvpp2_port {
+ 
+ 	/* Per-port registers' base address */
+ 	void __iomem *base;
++	void __iomem *stats_base;
+ 
+ 	struct mvpp2_rx_queue **rxqs;
+ 	unsigned int nrxqs;
+@@ -909,6 +953,7 @@ struct mvpp2_port {
+ 	u16 tx_ring_size;
+ 	u16 rx_ring_size;
+ 	struct mvpp2_pcpu_stats __percpu *stats;
++	u64 *ethtool_stats;
+ 
+ 	phy_interface_t phy_interface;
+ 	struct device_node *phy_node;
+@@ -4778,9 +4823,136 @@ static void mvpp2_port_loopback_set(struct mvpp2_port *port)
+ 	writel(val, port->base + MVPP2_GMAC_CTRL_1_REG);
+ }
+ 
++struct mvpp2_ethtool_counter {
++	unsigned int offset;
++	const char string[ETH_GSTRING_LEN];
++	bool reg_is_64b;
++};
++
++static u64 mvpp2_read_count(struct mvpp2_port *port,
++			    const struct mvpp2_ethtool_counter *counter)
++{
++	u64 val;
++
++	val = readl(port->stats_base + counter->offset);
++	if (counter->reg_is_64b)
++		val += (u64)readl(port->stats_base + counter->offset + 4) << 32;
++
++	return val;
++}
++
++/* Due to the fact that software statistics and hardware statistics are, by
++ * design, incremented at different moments in the chain of packet processing,
++ * it is very likely that incoming packets could have been dropped after being
++ * counted by hardware but before reaching software statistics (most probably
++ * multicast packets), and in the oppposite way, during transmission, FCS bytes
++ * are added in between as well as TSO skb will be split and header bytes added.
++ * Hence, statistics gathered from userspace with ifconfig (software) and
++ * ethtool (hardware) cannot be compared.
++ */
++static const struct mvpp2_ethtool_counter mvpp2_ethtool_regs[] = {
++	{ MVPP2_MIB_GOOD_OCTETS_RCVD, "good_octets_received", true },
++	{ MVPP2_MIB_BAD_OCTETS_RCVD, "bad_octets_received" },
++	{ MVPP2_MIB_CRC_ERRORS_SENT, "crc_errors_sent" },
++	{ MVPP2_MIB_UNICAST_FRAMES_RCVD, "unicast_frames_received" },
++	{ MVPP2_MIB_BROADCAST_FRAMES_RCVD, "broadcast_frames_received" },
++	{ MVPP2_MIB_MULTICAST_FRAMES_RCVD, "multicast_frames_received" },
++	{ MVPP2_MIB_FRAMES_64_OCTETS, "frames_64_octets" },
++	{ MVPP2_MIB_FRAMES_65_TO_127_OCTETS, "frames_65_to_127_octet" },
++	{ MVPP2_MIB_FRAMES_128_TO_255_OCTETS, "frames_128_to_255_octet" },
++	{ MVPP2_MIB_FRAMES_256_TO_511_OCTETS, "frames_256_to_511_octet" },
++	{ MVPP2_MIB_FRAMES_512_TO_1023_OCTETS, "frames_512_to_1023_octet" },
++	{ MVPP2_MIB_FRAMES_1024_TO_MAX_OCTETS, "frames_1024_to_max_octet" },
++	{ MVPP2_MIB_GOOD_OCTETS_SENT, "good_octets_sent", true },
++	{ MVPP2_MIB_UNICAST_FRAMES_SENT, "unicast_frames_sent" },
++	{ MVPP2_MIB_MULTICAST_FRAMES_SENT, "multicast_frames_sent" },
++	{ MVPP2_MIB_BROADCAST_FRAMES_SENT, "broadcast_frames_sent" },
++	{ MVPP2_MIB_FC_SENT, "fc_sent" },
++	{ MVPP2_MIB_FC_RCVD, "fc_received" },
++	{ MVPP2_MIB_RX_FIFO_OVERRUN, "rx_fifo_overrun" },
++	{ MVPP2_MIB_UNDERSIZE_RCVD, "undersize_received" },
++	{ MVPP2_MIB_FRAGMENTS_RCVD, "fragments_received" },
++	{ MVPP2_MIB_OVERSIZE_RCVD, "oversize_received" },
++	{ MVPP2_MIB_JABBER_RCVD, "jabber_received" },
++	{ MVPP2_MIB_MAC_RCV_ERROR, "mac_receive_error" },
++	{ MVPP2_MIB_BAD_CRC_EVENT, "bad_crc_event" },
++	{ MVPP2_MIB_COLLISION, "collision" },
++	{ MVPP2_MIB_LATE_COLLISION, "late_collision" },
++};
++
++static void mvpp2_ethtool_get_strings(struct net_device *netdev, u32 sset,
++				      u8 *data)
++{
++	if (sset == ETH_SS_STATS) {
++		int i;
++
++		for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_regs); i++)
++			memcpy(data + i * ETH_GSTRING_LEN,
++			       &mvpp2_ethtool_regs[i].string, ETH_GSTRING_LEN);
++	}
++}
++
++static void mvpp2_gather_hw_statistics(struct work_struct *work)
++{
++	struct delayed_work *del_work = to_delayed_work(work);
++	struct mvpp2 *priv = container_of(del_work, struct mvpp2, stats_work);
++	struct mvpp2_port *port;
++	u64 *pstats;
++	int i, j;
++
++	mutex_lock(&priv->gather_stats_lock);
++
++	for (i = 0; i < priv->port_count; i++) {
++		if (!priv->port_list[i])
++			continue;
++
++		port = priv->port_list[i];
++		pstats = port->ethtool_stats;
++		for (j = 0; j < ARRAY_SIZE(mvpp2_ethtool_regs); j++)
++			*pstats++ += mvpp2_read_count(port,
++						      &mvpp2_ethtool_regs[j]);
++	}
++
++	/* No need to read again the counters right after this function if it
++	 * was called asynchronously by the user (ie. use of ethtool).
++	 */
++	cancel_delayed_work(&priv->stats_work);
++	queue_delayed_work(priv->stats_queue, &priv->stats_work,
++			   MVPP2_MIB_COUNTERS_STATS_DELAY);
++
++	mutex_unlock(&priv->gather_stats_lock);
++}
++
++static void mvpp2_ethtool_get_stats(struct net_device *dev,
++				    struct ethtool_stats *stats, u64 *data)
++{
++	struct mvpp2_port *port = netdev_priv(dev);
++
++	/* Update statistics for all ports, copy only those actually needed */
++	mvpp2_gather_hw_statistics(&port->priv->stats_work.work);
++
++	mutex_lock(&port->priv->gather_stats_lock);
++	memcpy(data, port->ethtool_stats,
++	       sizeof(u64) * ARRAY_SIZE(mvpp2_ethtool_regs));
++	mutex_unlock(&port->priv->gather_stats_lock);
++}
++
++static int mvpp2_ethtool_get_sset_count(struct net_device *dev, int sset)
++{
++	if (sset == ETH_SS_STATS)
++		return ARRAY_SIZE(mvpp2_ethtool_regs);
++
++	return -EOPNOTSUPP;
++}
++
+ static void mvpp2_port_reset(struct mvpp2_port *port)
+ {
+ 	u32 val;
++	unsigned int i;
++
++	/* Read the GOP statistics to reset the hardware counters */
++	for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_regs); i++)
++		mvpp2_read_count(port, &mvpp2_ethtool_regs[i]);
+ 
+ 	val = readl(port->base + MVPP2_GMAC_CTRL_2_REG) &
+ 		    ~MVPP2_GMAC_PORT_RESET_MASK;
+@@ -6916,6 +7088,10 @@ static int mvpp2_open(struct net_device *dev)
+ 	if (priv->hw_version == MVPP22)
+ 		mvpp22_init_rss(port);
+ 
++	/* Start hardware statistics gathering */
++	queue_delayed_work(priv->stats_queue, &priv->stats_work,
++			   MVPP2_MIB_COUNTERS_STATS_DELAY);
++
+ 	return 0;
+ 
+ err_free_link_irq:
+@@ -6960,6 +7136,9 @@ static int mvpp2_stop(struct net_device *dev)
+ 	mvpp2_cleanup_rxqs(port);
+ 	mvpp2_cleanup_txqs(port);
+ 
++	cancel_delayed_work_sync(&priv->stats_work);
++	flush_workqueue(priv->stats_queue);
++
+ 	return 0;
+ }
+ 
+@@ -7271,6 +7450,9 @@ static const struct ethtool_ops mvpp2_eth_tool_ops = {
+ 	.get_drvinfo	= mvpp2_ethtool_get_drvinfo,
+ 	.get_ringparam	= mvpp2_ethtool_get_ringparam,
+ 	.set_ringparam	= mvpp2_ethtool_set_ringparam,
++	.get_strings	= mvpp2_ethtool_get_strings,
++	.get_ethtool_stats = mvpp2_ethtool_get_stats,
++	.get_sset_count	= mvpp2_ethtool_get_sset_count,
+ 	.get_link_ksettings = phy_ethtool_get_link_ksettings,
+ 	.set_link_ksettings = phy_ethtool_set_link_ksettings,
+ };
+@@ -7674,6 +7856,10 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 			err = PTR_ERR(port->base);
+ 			goto err_free_irq;
+ 		}
++
++		port->stats_base = port->priv->lms_base +
++				   MVPP21_MIB_COUNTERS_OFFSET +
++				   port->gop_id * MVPP21_MIB_COUNTERS_PORT_SZ;
+ 	} else {
+ 		if (of_property_read_u32(port_node, "gop-port-id",
+ 					 &port->gop_id)) {
+@@ -7683,15 +7869,26 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 		}
+ 
+ 		port->base = priv->iface_base + MVPP22_GMAC_BASE(port->gop_id);
++		port->stats_base = port->priv->iface_base +
++				   MVPP22_MIB_COUNTERS_OFFSET +
++				   port->gop_id * MVPP22_MIB_COUNTERS_PORT_SZ;
+ 	}
+ 
+-	/* Alloc per-cpu stats */
++	/* Alloc per-cpu and ethtool stats */
+ 	port->stats = netdev_alloc_pcpu_stats(struct mvpp2_pcpu_stats);
+ 	if (!port->stats) {
+ 		err = -ENOMEM;
+ 		goto err_free_irq;
+ 	}
+ 
++	port->ethtool_stats = devm_kcalloc(&pdev->dev,
++					   ARRAY_SIZE(mvpp2_ethtool_regs),
++					   sizeof(u64), GFP_KERNEL);
++	if (!port->ethtool_stats) {
++		err = -ENOMEM;
++		goto err_free_stats;
++	}
++
+ 	mvpp2_port_copy_mac_addr(dev, priv, port_node, &mac_from);
+ 
+ 	port->tx_ring_size = MVPP2_MAX_TXD;
+@@ -8014,7 +8211,7 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 	struct mvpp2 *priv;
+ 	struct resource *res;
+ 	void __iomem *base;
+-	int port_count, i;
++	int i;
+ 	int err;
+ 
+ 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+@@ -8129,14 +8326,14 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 		goto err_mg_clk;
+ 	}
+ 
+-	port_count = of_get_available_child_count(dn);
+-	if (port_count == 0) {
++	priv->port_count = of_get_available_child_count(dn);
++	if (priv->port_count == 0) {
+ 		dev_err(&pdev->dev, "no ports enabled\n");
+ 		err = -ENODEV;
+ 		goto err_mg_clk;
+ 	}
+ 
+-	priv->port_list = devm_kcalloc(&pdev->dev, port_count,
++	priv->port_list = devm_kcalloc(&pdev->dev, priv->port_count,
+ 				       sizeof(*priv->port_list),
+ 				       GFP_KERNEL);
+ 	if (!priv->port_list) {
+@@ -8153,6 +8350,24 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 		i++;
+ 	}
+ 
++	/* Statistics must be gathered regularly because some of them (like
++	 * packets counters) are 32-bit registers and could overflow quite
++	 * quickly. For instance, a 10Gb link used at full bandwidth with the
++	 * smallest packets (64B) will overflow a 32-bit counter in less than
++	 * 30 seconds. Then, use a workqueue to fill 64-bit counters.
++	 */
++	mutex_init(&priv->gather_stats_lock);
++	snprintf(priv->queue_name, sizeof(priv->queue_name),
++		 "stats-wq-%s%s", netdev_name(priv->port_list[0]->dev),
++		 priv->port_count > 1 ? "+" : "");
++	priv->stats_queue = create_singlethread_workqueue(priv->queue_name);
++	if (!priv->stats_queue) {
++		err = -ENOMEM;
++		goto err_mg_clk;
++	}
++
++	INIT_DELAYED_WORK(&priv->stats_work, mvpp2_gather_hw_statistics);
++
+ 	platform_set_drvdata(pdev, priv);
+ 	return 0;
+ 
+@@ -8174,6 +8389,9 @@ static int mvpp2_remove(struct platform_device *pdev)
+ 	struct device_node *port_node;
+ 	int i = 0;
+ 
++	destroy_workqueue(priv->stats_queue);
++	mutex_destroy(&priv->gather_stats_lock);
++
+ 	for_each_available_child_of_node(dn, port_node) {
+ 		if (priv->port_list[i])
+ 			mvpp2_port_remove(priv->port_list[i]);
+-- 
+2.7.4
+
diff --git a/SOURCES/0009-BACKPORT-ata-Disable-AHCI-ALPM-feature-for-Ampere-Co.patch b/SOURCES/0009-BACKPORT-ata-Disable-AHCI-ALPM-feature-for-Ampere-Co.patch
new file mode 100644
index 0000000..69f0a22
--- /dev/null
+++ b/SOURCES/0009-BACKPORT-ata-Disable-AHCI-ALPM-feature-for-Ampere-Co.patch
@@ -0,0 +1,72 @@
+From 38b559f8ab1a556cab575c907202dcc7027bc4d2 Mon Sep 17 00:00:00 2001
+From: Khuong Dinh <khuong.dinh@amperecomputing.com>
+Date: Fri, 7 Sep 2018 08:32:17 -0600
+Subject: [PATCH 09/11] BACKPORT ata: Disable AHCI ALPM feature for Ampere
+ Computing eMAG SATA
+
+Due to hardware errata, Ampere Computing eMAG SATA can't support
+AHCI ALPM feature. This patch disables the AHCI ALPM feature for
+eMAG SATA.
+
+This patch is backported from:
+https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20180913&id=20bdc376b427cb420836f39ee8f281ea85dbaeef
+
+Change-Id: I21d4a6ed7bd1f103f696b3865248c562288e2886
+Signed-off-by: Suman Trpathi <stripathi@amperecomputing.com>
+Signed-off-by: Rameshwar Prasad Sahu <rameshwar.sahu@amperecomputing.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Khuong Dinh <khuong.dinh@amperecomputing.com>
+---
+ drivers/ata/ahci_platform.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
+index 99f9a89..9ba283f 100644
+--- a/drivers/ata/ahci_platform.c
++++ b/drivers/ata/ahci_platform.c
+@@ -33,6 +33,13 @@
+ 	.port_ops	= &ahci_platform_ops,
+ };
+ 
++static const struct ata_port_info ahci_port_info_nolpm = {
++	.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NO_LPM,
++	.pio_mask	= ATA_PIO4,
++	.udma_mask	= ATA_UDMA6,
++	.port_ops	= &ahci_platform_ops,
++};
++
+ static struct scsi_host_template ahci_platform_sht = {
+ 	AHCI_SHT(DRV_NAME),
+ };
+@@ -41,6 +48,7 @@ static int ahci_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct ahci_host_priv *hpriv;
++	const struct ata_port_info *port;
+ 	int rc;
+ 
+ 	hpriv = ahci_platform_get_resources(pdev);
+@@ -57,7 +65,11 @@ static int ahci_probe(struct platform_device *pdev)
+ 	if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci"))
+ 		hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ;
+ 
+-	rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info,
++	port = acpi_device_get_match_data(dev);
++	if (!port)
++		port = &ahci_port_info;
++
++	rc = ahci_platform_init_host(pdev, hpriv, port,
+ 				     &ahci_platform_sht);
+ 	if (rc)
+ 		goto disable_resources;
+@@ -85,6 +97,7 @@ static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
+ MODULE_DEVICE_TABLE(of, ahci_of_match);
+ 
+ static const struct acpi_device_id ahci_acpi_match[] = {
++	{ "APMC0D33", (unsigned long)&ahci_port_info_nolpm },
+ 	{ ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) },
+ 	{},
+ };
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0009-net-mvpp2-fix-GOP-statistics-loop-start-and-stop-con.patch b/SOURCES/0009-net-mvpp2-fix-GOP-statistics-loop-start-and-stop-con.patch
new file mode 100644
index 0000000..e7c62dc
--- /dev/null
+++ b/SOURCES/0009-net-mvpp2-fix-GOP-statistics-loop-start-and-stop-con.patch
@@ -0,0 +1,180 @@
+From 7dc5b326b4430a292de27c404b2f36fcdb5ec67f Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@free-electrons.com>
+Date: Wed, 8 Nov 2017 08:59:40 +0100
+Subject: [PATCH 09/46] net: mvpp2: fix GOP statistics loop start and stop
+ conditions
+
+GOP statistics from all ports of one instance of the driver are gathered
+with one work recalled in loop in a workqueue. The loop is started when
+a port is up, and stopped when a port is down. This last condition is
+obviously wrong.
+
+Fix this by having a work per port. This way, starting and stoping it
+when the port is up or down will be fine, while minimizing unnecessary
+CPU usage.
+
+Fixes: 118d6298f6f0 ("net: mvpp2: add ethtool GOP statistics")
+Reported-by: Stefan Chulski <stefanc@marvell.com>
+Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit e5c500eb298a9f5ef9b80d16fcea9662c89467b7)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 62 +++++++++++++++++-------------------
+ 1 file changed, 30 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index a79d2ff..6c20e81 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -885,9 +885,7 @@ struct mvpp2 {
+ 	/* Maximum number of RXQs per port */
+ 	unsigned int max_port_rxqs;
+ 
+-	/* Workqueue to gather hardware statistics with its lock */
+-	struct mutex gather_stats_lock;
+-	struct delayed_work stats_work;
++	/* Workqueue to gather hardware statistics */
+ 	char queue_name[30];
+ 	struct workqueue_struct *stats_queue;
+ };
+@@ -955,6 +953,10 @@ struct mvpp2_port {
+ 	struct mvpp2_pcpu_stats __percpu *stats;
+ 	u64 *ethtool_stats;
+ 
++	/* Per-port work and its lock to gather hardware statistics */
++	struct mutex gather_stats_lock;
++	struct delayed_work stats_work;
++
+ 	phy_interface_t phy_interface;
+ 	struct device_node *phy_node;
+ 	struct phy *comphy;
+@@ -4895,32 +4897,25 @@ static void mvpp2_ethtool_get_strings(struct net_device *netdev, u32 sset,
+ static void mvpp2_gather_hw_statistics(struct work_struct *work)
+ {
+ 	struct delayed_work *del_work = to_delayed_work(work);
+-	struct mvpp2 *priv = container_of(del_work, struct mvpp2, stats_work);
+-	struct mvpp2_port *port;
++	struct mvpp2_port *port = container_of(del_work, struct mvpp2_port,
++					       stats_work);
+ 	u64 *pstats;
+-	int i, j;
+-
+-	mutex_lock(&priv->gather_stats_lock);
++	int i;
+ 
+-	for (i = 0; i < priv->port_count; i++) {
+-		if (!priv->port_list[i])
+-			continue;
++	mutex_lock(&port->gather_stats_lock);
+ 
+-		port = priv->port_list[i];
+-		pstats = port->ethtool_stats;
+-		for (j = 0; j < ARRAY_SIZE(mvpp2_ethtool_regs); j++)
+-			*pstats++ += mvpp2_read_count(port,
+-						      &mvpp2_ethtool_regs[j]);
+-	}
++	pstats = port->ethtool_stats;
++	for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_regs); i++)
++		*pstats++ += mvpp2_read_count(port, &mvpp2_ethtool_regs[i]);
+ 
+ 	/* No need to read again the counters right after this function if it
+ 	 * was called asynchronously by the user (ie. use of ethtool).
+ 	 */
+-	cancel_delayed_work(&priv->stats_work);
+-	queue_delayed_work(priv->stats_queue, &priv->stats_work,
++	cancel_delayed_work(&port->stats_work);
++	queue_delayed_work(port->priv->stats_queue, &port->stats_work,
+ 			   MVPP2_MIB_COUNTERS_STATS_DELAY);
+ 
+-	mutex_unlock(&priv->gather_stats_lock);
++	mutex_unlock(&port->gather_stats_lock);
+ }
+ 
+ static void mvpp2_ethtool_get_stats(struct net_device *dev,
+@@ -4928,13 +4923,15 @@ static void mvpp2_ethtool_get_stats(struct net_device *dev,
+ {
+ 	struct mvpp2_port *port = netdev_priv(dev);
+ 
+-	/* Update statistics for all ports, copy only those actually needed */
+-	mvpp2_gather_hw_statistics(&port->priv->stats_work.work);
++	/* Update statistics for the given port, then take the lock to avoid
++	 * concurrent accesses on the ethtool_stats structure during its copy.
++	 */
++	mvpp2_gather_hw_statistics(&port->stats_work.work);
+ 
+-	mutex_lock(&port->priv->gather_stats_lock);
++	mutex_lock(&port->gather_stats_lock);
+ 	memcpy(data, port->ethtool_stats,
+ 	       sizeof(u64) * ARRAY_SIZE(mvpp2_ethtool_regs));
+-	mutex_unlock(&port->priv->gather_stats_lock);
++	mutex_unlock(&port->gather_stats_lock);
+ }
+ 
+ static int mvpp2_ethtool_get_sset_count(struct net_device *dev, int sset)
+@@ -7089,7 +7086,7 @@ static int mvpp2_open(struct net_device *dev)
+ 		mvpp22_init_rss(port);
+ 
+ 	/* Start hardware statistics gathering */
+-	queue_delayed_work(priv->stats_queue, &priv->stats_work,
++	queue_delayed_work(priv->stats_queue, &port->stats_work,
+ 			   MVPP2_MIB_COUNTERS_STATS_DELAY);
+ 
+ 	return 0;
+@@ -7136,8 +7133,7 @@ static int mvpp2_stop(struct net_device *dev)
+ 	mvpp2_cleanup_rxqs(port);
+ 	mvpp2_cleanup_txqs(port);
+ 
+-	cancel_delayed_work_sync(&priv->stats_work);
+-	flush_workqueue(priv->stats_queue);
++	cancel_delayed_work_sync(&port->stats_work);
+ 
+ 	return 0;
+ }
+@@ -7889,6 +7885,9 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 		goto err_free_stats;
+ 	}
+ 
++	mutex_init(&port->gather_stats_lock);
++	INIT_DELAYED_WORK(&port->stats_work, mvpp2_gather_hw_statistics);
++
+ 	mvpp2_port_copy_mac_addr(dev, priv, port_node, &mac_from);
+ 
+ 	port->tx_ring_size = MVPP2_MAX_TXD;
+@@ -8356,7 +8355,6 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 	 * smallest packets (64B) will overflow a 32-bit counter in less than
+ 	 * 30 seconds. Then, use a workqueue to fill 64-bit counters.
+ 	 */
+-	mutex_init(&priv->gather_stats_lock);
+ 	snprintf(priv->queue_name, sizeof(priv->queue_name),
+ 		 "stats-wq-%s%s", netdev_name(priv->port_list[0]->dev),
+ 		 priv->port_count > 1 ? "+" : "");
+@@ -8366,8 +8364,6 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 		goto err_mg_clk;
+ 	}
+ 
+-	INIT_DELAYED_WORK(&priv->stats_work, mvpp2_gather_hw_statistics);
+-
+ 	platform_set_drvdata(pdev, priv);
+ 	return 0;
+ 
+@@ -8389,12 +8385,14 @@ static int mvpp2_remove(struct platform_device *pdev)
+ 	struct device_node *port_node;
+ 	int i = 0;
+ 
++	flush_workqueue(priv->stats_queue);
+ 	destroy_workqueue(priv->stats_queue);
+-	mutex_destroy(&priv->gather_stats_lock);
+ 
+ 	for_each_available_child_of_node(dn, port_node) {
+-		if (priv->port_list[i])
++		if (priv->port_list[i]) {
++			mutex_destroy(&priv->port_list[i]->gather_stats_lock);
+ 			mvpp2_port_remove(priv->port_list[i]);
++		}
+ 		i++;
+ 	}
+ 
+-- 
+2.7.4
+
diff --git a/SOURCES/0010-BACKPORT-perf-xgene-Fix-IOB-SLOW-PMU-parser-error.patch b/SOURCES/0010-BACKPORT-perf-xgene-Fix-IOB-SLOW-PMU-parser-error.patch
new file mode 100644
index 0000000..0a0a7e6
--- /dev/null
+++ b/SOURCES/0010-BACKPORT-perf-xgene-Fix-IOB-SLOW-PMU-parser-error.patch
@@ -0,0 +1,39 @@
+From 55f37c369d9f564cdb7b738fd2a47b7b8975ac52 Mon Sep 17 00:00:00 2001
+From: Hoan Tran <hoan.tran@amperecomputing.com>
+Date: Tue, 5 Jun 2018 14:48:44 -0700
+Subject: [PATCH 10/11] BACKPORT: perf: xgene: Fix IOB SLOW PMU parser error
+
+This patch fixes the below parser error of the IOB SLOW PMU.
+
+	# perf stat -a -e iob-slow0/cycle-count/ sleep 1
+	evenf syntax error: 'iob-slow0/cycle-count/'
+        	                 \___ parser error
+
+It replaces the "-" character by "_" character inside the PMU name.
+
+Without this patch, perf for "iob-slow0" PMU does not work.
+
+This patch is backported from https://lkml.org/lkml/2018/6/6/754
+
+Change-Id: Ia5085c305e32f5651e8deedee2958a8b2a987c15
+Signed-off-by: Hoan Tran <hoan.tran@amperecomputing.com>
+---
+ drivers/perf/xgene_pmu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/perf/xgene_pmu.c b/drivers/perf/xgene_pmu.c
+index eb23311..8b79c2f 100644
+--- a/drivers/perf/xgene_pmu.c
++++ b/drivers/perf/xgene_pmu.c
+@@ -1463,7 +1463,7 @@ static char *xgene_pmu_dev_name(struct device *dev, u32 type, int id)
+ 	case PMU_TYPE_IOB:
+ 		return devm_kasprintf(dev, GFP_KERNEL, "iob%d", id);
+ 	case PMU_TYPE_IOB_SLOW:
+-		return devm_kasprintf(dev, GFP_KERNEL, "iob-slow%d", id);
++		return devm_kasprintf(dev, GFP_KERNEL, "iob_slow%d", id);
+ 	case PMU_TYPE_MCB:
+ 		return devm_kasprintf(dev, GFP_KERNEL, "mcb%d", id);
+ 	case PMU_TYPE_MC:
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0010-net-mvpp2-fix-the-txq_init-error-path.patch b/SOURCES/0010-net-mvpp2-fix-the-txq_init-error-path.patch
new file mode 100644
index 0000000..5a68c25
--- /dev/null
+++ b/SOURCES/0010-net-mvpp2-fix-the-txq_init-error-path.patch
@@ -0,0 +1,70 @@
+From 7be8a46cfb0d162f7733ccd6dd57810285a0ce9e Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@free-electrons.com>
+Date: Tue, 28 Nov 2017 14:19:48 +0100
+Subject: [PATCH 10/46] net: mvpp2: fix the txq_init error path
+
+When an allocation in the txq_init path fails, the allocated buffers
+end-up being freed twice: in the txq_init error path, and in txq_deinit.
+This lead to issues as txq_deinit would work on already freed memory
+regions:
+
+    kernel BUG at mm/slub.c:3915!
+    Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
+
+This patch fixes this by removing the txq_init own error path, as the
+txq_deinit function is always called on errors. This was introduced by
+TSO as way more buffers are allocated.
+
+Fixes: 186cd4d4e414 ("net: mvpp2: software tso support")
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit ba2d8d887d962c2f790e6dc01b2fd25b4608720b)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 20 ++------------------
+ 1 file changed, 2 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 6c20e81..79f01cd 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -5805,7 +5805,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
+ 						sizeof(*txq_pcpu->buffs),
+ 						GFP_KERNEL);
+ 		if (!txq_pcpu->buffs)
+-			goto cleanup;
++			return -ENOMEM;
+ 
+ 		txq_pcpu->count = 0;
+ 		txq_pcpu->reserved_num = 0;
+@@ -5821,26 +5821,10 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
+ 					   &txq_pcpu->tso_headers_dma,
+ 					   GFP_KERNEL);
+ 		if (!txq_pcpu->tso_headers)
+-			goto cleanup;
++			return -ENOMEM;
+ 	}
+ 
+ 	return 0;
+-cleanup:
+-	for_each_present_cpu(cpu) {
+-		txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
+-		kfree(txq_pcpu->buffs);
+-
+-		dma_free_coherent(port->dev->dev.parent,
+-				  txq_pcpu->size * TSO_HEADER_SIZE,
+-				  txq_pcpu->tso_headers,
+-				  txq_pcpu->tso_headers_dma);
+-	}
+-
+-	dma_free_coherent(port->dev->dev.parent,
+-			  txq->size * MVPP2_DESC_ALIGNED_SIZE,
+-			  txq->descs, txq->descs_dma);
+-
+-	return -ENOMEM;
+ }
+ 
+ /* Free allocated TXQ resources */
+-- 
+2.7.4
+
diff --git a/SOURCES/0011-BACKPORT-iommu-enable-bypass-transaction-caching-for.patch b/SOURCES/0011-BACKPORT-iommu-enable-bypass-transaction-caching-for.patch
new file mode 100644
index 0000000..a2920f4
--- /dev/null
+++ b/SOURCES/0011-BACKPORT-iommu-enable-bypass-transaction-caching-for.patch
@@ -0,0 +1,49 @@
+From ecf036e63e2a910a7ed1de6b89fe3d8ccf4c4d78 Mon Sep 17 00:00:00 2001
+From: Khuong Dinh <kdinh@apm.com>
+Date: Fri, 13 Oct 2017 16:07:46 -0600
+Subject: [PATCH 11/11] BACKPORT: iommu: enable bypass transaction caching for
+ ARM SMMU 500
+
+The ARM SMMU identity mapping performance was poor compared with the
+DMA mode. It was found that enable caching would restore the performance
+back to normal. The S2CRB_TLBEN bit in the ACR register would allow for
+caching of the stream to context register bypass transaction information.
+
+This patch is required to properly support PCIe in virtual environment
+for Ampere eMag SoC's.
+
+This patch is backported from:
+https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20180504&id=74f55d34414c866dbf3a69e28a2f963abe61ca58
+and was accepted from kernel v4.15.
+
+Reviewed-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Feng Kan <fkan@apm.com>
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+---
+ drivers/iommu/arm-smmu.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
+index 91ff442..d40f154 100644
+--- a/drivers/iommu/arm-smmu.c
++++ b/drivers/iommu/arm-smmu.c
+@@ -61,6 +61,7 @@
+ #define ARM_MMU500_ACTLR_CPRE		(1 << 1)
+ 
+ #define ARM_MMU500_ACR_CACHE_LOCK	(1 << 26)
++#define ARM_MMU500_ACR_S2CRB_TLBEN	(1 << 10)
+ #define ARM_MMU500_ACR_SMTNMB_TLBEN	(1 << 8)
+ 
+ #define TLB_LOOP_TIMEOUT		1000000	/* 1s! */
+@@ -1608,7 +1609,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
+ 		 * Allow unmatched Stream IDs to allocate bypass
+ 		 * TLB entries for reduced latency.
+ 		 */
+-		reg |= ARM_MMU500_ACR_SMTNMB_TLBEN;
++		reg |= ARM_MMU500_ACR_SMTNMB_TLBEN | ARM_MMU500_ACR_S2CRB_TLBEN;
+ 		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sACR);
+ 	}
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0011-net-mvpp2-cleanup-probed-ports-in-the-probe-error-pa.patch b/SOURCES/0011-net-mvpp2-cleanup-probed-ports-in-the-probe-error-pa.patch
new file mode 100644
index 0000000..9c416e0
--- /dev/null
+++ b/SOURCES/0011-net-mvpp2-cleanup-probed-ports-in-the-probe-error-pa.patch
@@ -0,0 +1,55 @@
+From 0691379d3ed50fa89cf16d9b443553a4eb7c9d79 Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@free-electrons.com>
+Date: Tue, 28 Nov 2017 14:19:49 +0100
+Subject: [PATCH 11/46] net: mvpp2: cleanup probed ports in the probe error
+ path
+
+This patches fixes the probe error path by cleaning up probed ports, to
+avoid leaving registered net devices when the driver failed to probe.
+
+Fixes: 3f518509dedc ("ethernet: Add new driver for Marvell Armada 375 network unit")
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 26146b0e6b6869c6cd8a45ab3a4a5562e7a91b23)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 79f01cd..afae4fe 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -8329,7 +8329,7 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 	for_each_available_child_of_node(dn, port_node) {
+ 		err = mvpp2_port_probe(pdev, port_node, priv, i);
+ 		if (err < 0)
+-			goto err_mg_clk;
++			goto err_port_probe;
+ 		i++;
+ 	}
+ 
+@@ -8345,12 +8345,19 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 	priv->stats_queue = create_singlethread_workqueue(priv->queue_name);
+ 	if (!priv->stats_queue) {
+ 		err = -ENOMEM;
+-		goto err_mg_clk;
++		goto err_port_probe;
+ 	}
+ 
+ 	platform_set_drvdata(pdev, priv);
+ 	return 0;
+ 
++err_port_probe:
++	i = 0;
++	for_each_available_child_of_node(dn, port_node) {
++		if (priv->port_list[i])
++			mvpp2_port_remove(priv->port_list[i]);
++		i++;
++	}
+ err_mg_clk:
+ 	clk_disable_unprepare(priv->axi_clk);
+ 	if (priv->hw_version == MVPP22)
+-- 
+2.7.4
+
diff --git a/SOURCES/0012-net-mvpp2-do-not-disable-GMAC-padding.patch b/SOURCES/0012-net-mvpp2-do-not-disable-GMAC-padding.patch
new file mode 100644
index 0000000..52f72b7
--- /dev/null
+++ b/SOURCES/0012-net-mvpp2-do-not-disable-GMAC-padding.patch
@@ -0,0 +1,51 @@
+From 5eae17c1e83b13aaa843f45eca112221eb634c78 Mon Sep 17 00:00:00 2001
+From: Yan Markman <ymarkman@marvell.com>
+Date: Tue, 28 Nov 2017 14:19:50 +0100
+Subject: [PATCH 12/46] net: mvpp2: do not disable GMAC padding
+
+Short fragmented packets may never be sent by the hardware when padding
+is disabled. This patch stop modifying the GMAC padding bits, to leave
+them to their reset value (disabled).
+
+Fixes: 3919357fb0bb ("net: mvpp2: initialize the GMAC when using a port")
+Signed-off-by: Yan Markman <ymarkman@marvell.com>
+[Antoine: commit message]
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+
+(cherry picked from commit e749aca84b10f3987b2ee1f76e0c7d8aacc5653c)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 9 ---------
+ 1 file changed, 9 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index afae4fe..5be58b0 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -4629,11 +4629,6 @@ static void mvpp2_port_mii_gmac_configure_mode(struct mvpp2_port *port)
+ 		       MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE;
+ 		val &= ~MVPP22_CTRL4_EXT_PIN_GMII_SEL;
+ 		writel(val, port->base + MVPP22_GMAC_CTRL_4_REG);
+-
+-		val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+-		val |= MVPP2_GMAC_DISABLE_PADDING;
+-		val &= ~MVPP2_GMAC_FLOW_CTRL_MASK;
+-		writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+ 	} else if (phy_interface_mode_is_rgmii(port->phy_interface)) {
+ 		val = readl(port->base + MVPP22_GMAC_CTRL_4_REG);
+ 		val |= MVPP22_CTRL4_EXT_PIN_GMII_SEL |
+@@ -4641,10 +4636,6 @@ static void mvpp2_port_mii_gmac_configure_mode(struct mvpp2_port *port)
+ 		       MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE;
+ 		val &= ~MVPP22_CTRL4_DP_CLK_SEL;
+ 		writel(val, port->base + MVPP22_GMAC_CTRL_4_REG);
+-
+-		val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+-		val &= ~MVPP2_GMAC_DISABLE_PADDING;
+-		writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+ 	}
+ 
+ 	/* The port is connected to a copper PHY */
+-- 
+2.7.4
+
diff --git a/SOURCES/0013-net-mvpp2-check-ethtool-sets-the-Tx-ring-size-is-to-.patch b/SOURCES/0013-net-mvpp2-check-ethtool-sets-the-Tx-ring-size-is-to-.patch
new file mode 100644
index 0000000..5f67a76
--- /dev/null
+++ b/SOURCES/0013-net-mvpp2-check-ethtool-sets-the-Tx-ring-size-is-to-.patch
@@ -0,0 +1,41 @@
+From d624fd6fd3b32311a6060d43e5af4e9328611805 Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@free-electrons.com>
+Date: Tue, 28 Nov 2017 14:19:51 +0100
+Subject: [PATCH 13/46] net: mvpp2: check ethtool sets the Tx ring size is to a
+ valid min value
+
+This patch fixes the Tx ring size checks when using ethtool, by adding
+an extra check in the PPv2 check_ringparam_valid helper. The Tx ring
+size cannot be set to a value smaller than the minimum number of
+descriptors needed for TSO.
+
+Fixes: 1d17db08c056 ("net: mvpp2: limit TSO segments and use stop/wake thresholds")
+Suggested-by: Yan Markman <ymarkman@marvell.com>
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 76e583c5f50ef539caea6935d37af3595034befb)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 5be58b0..d83a78b 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -6842,6 +6842,12 @@ static int mvpp2_check_ringparam_valid(struct net_device *dev,
+ 	else if (!IS_ALIGNED(ring->tx_pending, 32))
+ 		new_tx_pending = ALIGN(ring->tx_pending, 32);
+ 
++	/* The Tx ring size cannot be smaller than the minimum number of
++	 * descriptors needed for TSO.
++	 */
++	if (new_tx_pending < MVPP2_MAX_SKB_DESCS)
++		new_tx_pending = ALIGN(MVPP2_MAX_SKB_DESCS, 32);
++
+ 	if (ring->rx_pending != new_rx_pending) {
+ 		netdev_info(dev, "illegal Rx ring size value %d, round to %d\n",
+ 			    ring->rx_pending, new_rx_pending);
+-- 
+2.7.4
+
diff --git a/SOURCES/0014-net-mvpp2-allocate-zeroed-tx-descriptors.patch b/SOURCES/0014-net-mvpp2-allocate-zeroed-tx-descriptors.patch
new file mode 100644
index 0000000..32e4f6c
--- /dev/null
+++ b/SOURCES/0014-net-mvpp2-allocate-zeroed-tx-descriptors.patch
@@ -0,0 +1,39 @@
+From 8002403d50a1be9857e01ed14c3d78473352eef6 Mon Sep 17 00:00:00 2001
+From: Yan Markman <ymarkman@marvell.com>
+Date: Thu, 30 Nov 2017 10:49:46 +0100
+Subject: [PATCH 14/46] net: mvpp2: allocate zeroed tx descriptors
+
+Reserved and unused fields in the Tx descriptors should be 0. The PPv2
+driver doesn't clear them at run-time (for performance reasons) but
+these descriptors aren't zeroed when allocated, which can lead to
+unpredictable behaviors. This patch fixes this by using
+dma_zalloc_coherent instead of dma_alloc_coherent.
+
+Fixes: 3f518509dedc ("ethernet: Add new driver for Marvell Armada 375 network unit")
+Signed-off-by: Yan Markman <ymarkman@marvell.com>
+[Antoine: commit message]
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+
+(cherry picked from commit a154f8e399a063137fc42b961f437248d55ece29)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index d83a78b..fed2b2f 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -5598,7 +5598,7 @@ static int mvpp2_aggr_txq_init(struct platform_device *pdev,
+ 	u32 txq_dma;
+ 
+ 	/* Allocate memory for TX descriptors */
+-	aggr_txq->descs = dma_alloc_coherent(&pdev->dev,
++	aggr_txq->descs = dma_zalloc_coherent(&pdev->dev,
+ 				MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE,
+ 				&aggr_txq->descs_dma, GFP_KERNEL);
+ 	if (!aggr_txq->descs)
+-- 
+2.7.4
+
diff --git a/SOURCES/0015-net-mvpp2-fix-the-RSS-table-entry-offset.patch b/SOURCES/0015-net-mvpp2-fix-the-RSS-table-entry-offset.patch
new file mode 100644
index 0000000..58b2b8e
--- /dev/null
+++ b/SOURCES/0015-net-mvpp2-fix-the-RSS-table-entry-offset.patch
@@ -0,0 +1,34 @@
+From 80baeade5961a9692c9dd313fb9aacd951dde1e8 Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@free-electrons.com>
+Date: Fri, 8 Dec 2017 10:24:20 +0100
+Subject: [PATCH 15/46] net: mvpp2: fix the RSS table entry offset
+
+The macro used to access or set an RSS table entry was using an offset
+of 8, while it should use an offset of 0. This lead to wrongly configure
+the RSS table, not accessing the right entries.
+
+Fixes: 1d7d15d79fb4 ("net: mvpp2: initialize the RSS tables")
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 8a7b741e76cd31b6000636f0391e67ba6793ad1c)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index fed2b2f..634b2f4 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -85,7 +85,7 @@
+ 
+ /* RSS Registers */
+ #define MVPP22_RSS_INDEX			0x1500
+-#define     MVPP22_RSS_INDEX_TABLE_ENTRY(idx)	((idx) << 8)
++#define     MVPP22_RSS_INDEX_TABLE_ENTRY(idx)	(idx)
+ #define     MVPP22_RSS_INDEX_TABLE(idx)		((idx) << 8)
+ #define     MVPP22_RSS_INDEX_QUEUE(idx)		((idx) << 16)
+ #define MVPP22_RSS_TABLE_ENTRY			0x1508
+-- 
+2.7.4
+
diff --git a/SOURCES/0016-net-mvpp2-only-free-the-TSO-header-buffers-when-it-w.patch b/SOURCES/0016-net-mvpp2-only-free-the-TSO-header-buffers-when-it-w.patch
new file mode 100644
index 0000000..82d56ba
--- /dev/null
+++ b/SOURCES/0016-net-mvpp2-only-free-the-TSO-header-buffers-when-it-w.patch
@@ -0,0 +1,50 @@
+From ee5e257740c16b87408633288ee4247835ec2782 Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@free-electrons.com>
+Date: Mon, 11 Dec 2017 09:13:25 +0100
+Subject: [PATCH 16/46] net: mvpp2: only free the TSO header buffers when it
+ was allocated
+
+This patch adds a check to only free the TSO header buffer when its
+allocation previously succeeded.
+
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit b70d4a5195c7193d1d55af791d9811477522e25a)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 634b2f4..f203f08 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -5802,6 +5802,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
+ 		txq_pcpu->reserved_num = 0;
+ 		txq_pcpu->txq_put_index = 0;
+ 		txq_pcpu->txq_get_index = 0;
++		txq_pcpu->tso_headers = NULL;
+ 
+ 		txq_pcpu->stop_threshold = txq->size - MVPP2_MAX_SKB_DESCS;
+ 		txq_pcpu->wake_threshold = txq_pcpu->stop_threshold / 2;
+@@ -5829,10 +5830,13 @@ static void mvpp2_txq_deinit(struct mvpp2_port *port,
+ 		txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
+ 		kfree(txq_pcpu->buffs);
+ 
+-		dma_free_coherent(port->dev->dev.parent,
+-				  txq_pcpu->size * TSO_HEADER_SIZE,
+-				  txq_pcpu->tso_headers,
+-				  txq_pcpu->tso_headers_dma);
++		if (txq_pcpu->tso_headers)
++			dma_free_coherent(port->dev->dev.parent,
++					  txq_pcpu->size * TSO_HEADER_SIZE,
++					  txq_pcpu->tso_headers,
++					  txq_pcpu->tso_headers_dma);
++
++		txq_pcpu->tso_headers = NULL;
+ 	}
+ 
+ 	if (txq->descs)
+-- 
+2.7.4
+
diff --git a/SOURCES/0017-net-mvpp2-split-the-max-ring-size-from-the-default-o.patch b/SOURCES/0017-net-mvpp2-split-the-max-ring-size-from-the-default-o.patch
new file mode 100644
index 0000000..86b7f26
--- /dev/null
+++ b/SOURCES/0017-net-mvpp2-split-the-max-ring-size-from-the-default-o.patch
@@ -0,0 +1,92 @@
+From cd2a3c67f9810ec7f6f873985655ebbba820c9ce Mon Sep 17 00:00:00 2001
+From: Yan Markman <ymarkman@marvell.com>
+Date: Mon, 11 Dec 2017 09:13:26 +0100
+Subject: [PATCH 17/46] net: mvpp2: split the max ring size from the default
+ one
+
+The Rx/Tx ring sizes can be adjusted thanks to ethtool given specific
+network needs. This commit splits the default ring size from its max
+value to allow ethtool to vary the parameters in both ways.
+
+Signed-off-by: Yan Markman <ymarkman@marvell.com>
+[Antoine: commit message]
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+
+(cherry picked from commit 7cf87e4a5c2b120967b3fa3a1beb7123eb704d85)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 24 +++++++++++++-----------
+ 1 file changed, 13 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index f203f08..5e88403 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -504,10 +504,12 @@
+ #define MVPP2_DEFAULT_RXQ		4
+ 
+ /* Max number of Rx descriptors */
+-#define MVPP2_MAX_RXD			128
++#define MVPP2_MAX_RXD_MAX		1024
++#define MVPP2_MAX_RXD_DFLT		128
+ 
+ /* Max number of Tx descriptors */
+-#define MVPP2_MAX_TXD			1024
++#define MVPP2_MAX_TXD_MAX		2048
++#define MVPP2_MAX_TXD_DFLT		1024
+ 
+ /* Amount of Tx descriptors that can be reserved at once by CPU */
+ #define MVPP2_CPU_DESC_CHUNK		64
+@@ -6836,13 +6838,13 @@ static int mvpp2_check_ringparam_valid(struct net_device *dev,
+ 	if (ring->rx_pending == 0 || ring->tx_pending == 0)
+ 		return -EINVAL;
+ 
+-	if (ring->rx_pending > MVPP2_MAX_RXD)
+-		new_rx_pending = MVPP2_MAX_RXD;
++	if (ring->rx_pending > MVPP2_MAX_RXD_MAX)
++		new_rx_pending = MVPP2_MAX_RXD_MAX;
+ 	else if (!IS_ALIGNED(ring->rx_pending, 16))
+ 		new_rx_pending = ALIGN(ring->rx_pending, 16);
+ 
+-	if (ring->tx_pending > MVPP2_MAX_TXD)
+-		new_tx_pending = MVPP2_MAX_TXD;
++	if (ring->tx_pending > MVPP2_MAX_TXD_MAX)
++		new_tx_pending = MVPP2_MAX_TXD_MAX;
+ 	else if (!IS_ALIGNED(ring->tx_pending, 32))
+ 		new_tx_pending = ALIGN(ring->tx_pending, 32);
+ 
+@@ -7344,8 +7346,8 @@ static void mvpp2_ethtool_get_ringparam(struct net_device *dev,
+ {
+ 	struct mvpp2_port *port = netdev_priv(dev);
+ 
+-	ring->rx_max_pending = MVPP2_MAX_RXD;
+-	ring->tx_max_pending = MVPP2_MAX_TXD;
++	ring->rx_max_pending = MVPP2_MAX_RXD_MAX;
++	ring->tx_max_pending = MVPP2_MAX_TXD_MAX;
+ 	ring->rx_pending = port->rx_ring_size;
+ 	ring->tx_pending = port->tx_ring_size;
+ }
+@@ -7792,7 +7794,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 		goto err_free_netdev;
+ 	}
+ 
+-	dev->tx_queue_len = MVPP2_MAX_TXD;
++	dev->tx_queue_len = MVPP2_MAX_TXD_MAX;
+ 	dev->watchdog_timeo = 5 * HZ;
+ 	dev->netdev_ops = &mvpp2_netdev_ops;
+ 	dev->ethtool_ops = &mvpp2_eth_tool_ops;
+@@ -7875,8 +7877,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 
+ 	mvpp2_port_copy_mac_addr(dev, priv, port_node, &mac_from);
+ 
+-	port->tx_ring_size = MVPP2_MAX_TXD;
+-	port->rx_ring_size = MVPP2_MAX_RXD;
++	port->tx_ring_size = MVPP2_MAX_TXD_DFLT;
++	port->rx_ring_size = MVPP2_MAX_RXD_DFLT;
+ 	SET_NETDEV_DEV(dev, &pdev->dev);
+ 
+ 	err = mvpp2_port_init(port);
+-- 
+2.7.4
+
diff --git a/SOURCES/0018-net-mvpp2-align-values-in-ethtool-get_coalesce.patch b/SOURCES/0018-net-mvpp2-align-values-in-ethtool-get_coalesce.patch
new file mode 100644
index 0000000..6e66e98
--- /dev/null
+++ b/SOURCES/0018-net-mvpp2-align-values-in-ethtool-get_coalesce.patch
@@ -0,0 +1,36 @@
+From 4e8b835b21bdbf54edefc37e9db8976b831e2b51 Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@free-electrons.com>
+Date: Mon, 11 Dec 2017 09:13:27 +0100
+Subject: [PATCH 18/46] net: mvpp2: align values in ethtool get_coalesce
+
+Cosmetic patch aligning values in the ethtool get_coalesce function.
+This patch do not modify in anyway the driver's behaviour.
+
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 385c284fee84d2ad1da3b67111f199cd5641a867)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 5e88403..5c16731 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -7324,9 +7324,9 @@ static int mvpp2_ethtool_get_coalesce(struct net_device *dev,
+ {
+ 	struct mvpp2_port *port = netdev_priv(dev);
+ 
+-	c->rx_coalesce_usecs        = port->rxqs[0]->time_coal;
+-	c->rx_max_coalesced_frames  = port->rxqs[0]->pkts_coal;
+-	c->tx_max_coalesced_frames =  port->txqs[0]->done_pkts_coal;
++	c->rx_coalesce_usecs       = port->rxqs[0]->time_coal;
++	c->rx_max_coalesced_frames = port->rxqs[0]->pkts_coal;
++	c->tx_max_coalesced_frames = port->txqs[0]->done_pkts_coal;
+ 	return 0;
+ }
+ 
+-- 
+2.7.4
+
diff --git a/SOURCES/0019-net-mvpp2-report-the-tx-usec-coalescing-information-.patch b/SOURCES/0019-net-mvpp2-report-the-tx-usec-coalescing-information-.patch
new file mode 100644
index 0000000..21f6a27
--- /dev/null
+++ b/SOURCES/0019-net-mvpp2-report-the-tx-usec-coalescing-information-.patch
@@ -0,0 +1,33 @@
+From 0e17bb46c36869108f65cb5e7fca0b60d6b0556e Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@free-electrons.com>
+Date: Mon, 11 Dec 2017 09:13:28 +0100
+Subject: [PATCH 19/46] net: mvpp2: report the tx-usec coalescing information
+ to ethtool
+
+This patch adds the tx-usec value to the informations reported to
+ethtool by the get_coalesce function.
+
+Suggested-by: Yan Markman <ymarkman@marvell.com>
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 24b28ccb8575481672a9f037c423f7ebcea119b9)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 5c16731..aa72109 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -7327,6 +7327,7 @@ static int mvpp2_ethtool_get_coalesce(struct net_device *dev,
+ 	c->rx_coalesce_usecs       = port->rxqs[0]->time_coal;
+ 	c->rx_max_coalesced_frames = port->rxqs[0]->pkts_coal;
+ 	c->tx_max_coalesced_frames = port->txqs[0]->done_pkts_coal;
++	c->tx_coalesce_usecs       = port->tx_time_coal;
+ 	return 0;
+ }
+ 
+-- 
+2.7.4
+
diff --git a/SOURCES/0020-net-mvpp2-adjust-the-coalescing-parameters.patch b/SOURCES/0020-net-mvpp2-adjust-the-coalescing-parameters.patch
new file mode 100644
index 0000000..ad2274d
--- /dev/null
+++ b/SOURCES/0020-net-mvpp2-adjust-the-coalescing-parameters.patch
@@ -0,0 +1,38 @@
+From cf0b1f85ed5e488d830cba267e96dd1dda5e2a2c Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@free-electrons.com>
+Date: Mon, 11 Dec 2017 09:13:29 +0100
+Subject: [PATCH 20/46] net: mvpp2: adjust the coalescing parameters
+
+This patch adjust the coalescing parameters to the vendor
+recommendations for the PPv2 network controller.
+
+Suggested-by: Yan Markman <ymarkman@marvell.com>
+Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 86162281c25fd76e604978ffa0b2838e86ad4287)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index aa72109..a197607 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -454,11 +454,11 @@
+ /* Various constants */
+ 
+ /* Coalescing */
+-#define MVPP2_TXDONE_COAL_PKTS_THRESH	15
++#define MVPP2_TXDONE_COAL_PKTS_THRESH	64
+ #define MVPP2_TXDONE_HRTIMER_PERIOD_NS	1000000UL
+ #define MVPP2_TXDONE_COAL_USEC		1000
+ #define MVPP2_RX_COAL_PKTS		32
+-#define MVPP2_RX_COAL_USEC		100
++#define MVPP2_RX_COAL_USEC		64
+ 
+ /* The two bytes Marvell header. Either contains a special value used
+  * by Marvell switches when a specific hardware mode is enabled (not
+-- 
+2.7.4
+
diff --git a/SOURCES/0021-device-property-Introduce-fwnode_get_mac_address.patch b/SOURCES/0021-device-property-Introduce-fwnode_get_mac_address.patch
new file mode 100644
index 0000000..b053f74
--- /dev/null
+++ b/SOURCES/0021-device-property-Introduce-fwnode_get_mac_address.patch
@@ -0,0 +1,110 @@
+From b81c9307109512d284a07d864fe886c29df61778 Mon Sep 17 00:00:00 2001
+From: Marcin Wojtas <mw@semihalf.com>
+Date: Thu, 18 Jan 2018 13:31:38 +0100
+Subject: [PATCH 21/46] device property: Introduce fwnode_get_mac_address()
+
+Until now there were two almost identical functions for
+obtaining MAC address - of_get_mac_address() and, more generic,
+device_get_mac_address(). However it is not uncommon,
+that the network interface is represented as a child
+of the actual controller, hence it is not associated
+directly to any struct device, required by the latter
+routine.
+
+This commit allows for getting the MAC address for
+children nodes in the ACPI world by introducing a new function -
+fwnode_get_mac_address(). This commit also changes
+device_get_mac_address() routine to be its wrapper, in order
+to prevent unnecessary duplication.
+
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit babe2dbb28e780177ae2fba6a5640be1712f4af0)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/base/property.c  | 28 ++++++++++++++++++++--------
+ include/linux/property.h |  2 ++
+ 2 files changed, 22 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/base/property.c b/drivers/base/property.c
+index 7ed99c1..fa488e5 100644
+--- a/drivers/base/property.c
++++ b/drivers/base/property.c
+@@ -1148,11 +1148,11 @@ int device_get_phy_mode(struct device *dev)
+ }
+ EXPORT_SYMBOL_GPL(device_get_phy_mode);
+ 
+-static void *device_get_mac_addr(struct device *dev,
++static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
+ 				 const char *name, char *addr,
+ 				 int alen)
+ {
+-	int ret = device_property_read_u8_array(dev, name, addr, alen);
++	int ret = fwnode_property_read_u8_array(fwnode, name, addr, alen);
+ 
+ 	if (ret == 0 && alen == ETH_ALEN && is_valid_ether_addr(addr))
+ 		return addr;
+@@ -1160,8 +1160,8 @@ static void *device_get_mac_addr(struct device *dev,
+ }
+ 
+ /**
+- * device_get_mac_address - Get the MAC for a given device
+- * @dev:	Pointer to the device
++ * fwnode_get_mac_address - Get the MAC from the firmware node
++ * @fwnode:	Pointer to the firmware node
+  * @addr:	Address of buffer to store the MAC in
+  * @alen:	Length of the buffer pointed to by addr, should be ETH_ALEN
+  *
+@@ -1182,19 +1182,31 @@ static void *device_get_mac_addr(struct device *dev,
+  * In this case, the real MAC is in 'local-mac-address', and 'mac-address'
+  * exists but is all zeros.
+ */
+-void *device_get_mac_address(struct device *dev, char *addr, int alen)
++void *fwnode_get_mac_address(struct fwnode_handle *fwnode, char *addr, int alen)
+ {
+ 	char *res;
+ 
+-	res = device_get_mac_addr(dev, "mac-address", addr, alen);
++	res = fwnode_get_mac_addr(fwnode, "mac-address", addr, alen);
+ 	if (res)
+ 		return res;
+ 
+-	res = device_get_mac_addr(dev, "local-mac-address", addr, alen);
++	res = fwnode_get_mac_addr(fwnode, "local-mac-address", addr, alen);
+ 	if (res)
+ 		return res;
+ 
+-	return device_get_mac_addr(dev, "address", addr, alen);
++	return fwnode_get_mac_addr(fwnode, "address", addr, alen);
++}
++EXPORT_SYMBOL(fwnode_get_mac_address);
++
++/**
++ * device_get_mac_address - Get the MAC for a given device
++ * @dev:	Pointer to the device
++ * @addr:	Address of buffer to store the MAC in
++ * @alen:	Length of the buffer pointed to by addr, should be ETH_ALEN
++ */
++void *device_get_mac_address(struct device *dev, char *addr, int alen)
++{
++	return fwnode_get_mac_address(dev_fwnode(dev), addr, alen);
+ }
+ EXPORT_SYMBOL(device_get_mac_address);
+ 
+diff --git a/include/linux/property.h b/include/linux/property.h
+index 6bebee1..04d8552 100644
+--- a/include/linux/property.h
++++ b/include/linux/property.h
+@@ -279,6 +279,8 @@ int device_get_phy_mode(struct device *dev);
+ 
+ void *device_get_mac_address(struct device *dev, char *addr, int alen);
+ 
++void *fwnode_get_mac_address(struct fwnode_handle *fwnode,
++			     char *addr, int alen);
+ struct fwnode_handle *fwnode_graph_get_next_endpoint(
+ 	const struct fwnode_handle *fwnode, struct fwnode_handle *prev);
+ struct fwnode_handle *
+-- 
+2.7.4
+
diff --git a/SOURCES/0022-device-property-Introduce-fwnode_get_phy_mode.patch b/SOURCES/0022-device-property-Introduce-fwnode_get_phy_mode.patch
new file mode 100644
index 0000000..8369ecc
--- /dev/null
+++ b/SOURCES/0022-device-property-Introduce-fwnode_get_phy_mode.patch
@@ -0,0 +1,96 @@
+From 9cb42aa8f9f9e9fdf56e6a232fb65ecb881e30c9 Mon Sep 17 00:00:00 2001
+From: Marcin Wojtas <mw@semihalf.com>
+Date: Thu, 18 Jan 2018 13:31:39 +0100
+Subject: [PATCH 22/46] device property: Introduce fwnode_get_phy_mode()
+
+Until now there were two almost identical functions for
+obtaining network PHY mode - of_get_phy_mode() and,
+more generic, device_get_phy_mode(). However it is not uncommon,
+that the network interface is represented as a child
+of the actual controller, hence it is not associated
+directly to any struct device, required by the latter
+routine.
+
+This commit allows for getting the PHY mode for
+children nodes in the ACPI world by introducing a new function -
+fwnode_get_phy_mode(). This commit also changes
+device_get_phy_mode() routine to be its wrapper, in order
+to prevent unnecessary duplication.
+
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit b28f263b86709a1e26d7207112030e970abf4aab)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/base/property.c  | 24 +++++++++++++++++++-----
+ include/linux/property.h |  1 +
+ 2 files changed, 20 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/base/property.c b/drivers/base/property.c
+index fa488e5..9f69d18 100644
+--- a/drivers/base/property.c
++++ b/drivers/base/property.c
+@@ -1121,21 +1121,21 @@ enum dev_dma_attr device_get_dma_attr(struct device *dev)
+ EXPORT_SYMBOL_GPL(device_get_dma_attr);
+ 
+ /**
+- * device_get_phy_mode - Get phy mode for given device
+- * @dev:	Pointer to the given device
++ * fwnode_get_phy_mode - Get phy mode for given firmware node
++ * @fwnode:	Pointer to the given node
+  *
+  * The function gets phy interface string from property 'phy-mode' or
+  * 'phy-connection-type', and return its index in phy_modes table, or errno in
+  * error case.
+  */
+-int device_get_phy_mode(struct device *dev)
++int fwnode_get_phy_mode(struct fwnode_handle *fwnode)
+ {
+ 	const char *pm;
+ 	int err, i;
+ 
+-	err = device_property_read_string(dev, "phy-mode", &pm);
++	err = fwnode_property_read_string(fwnode, "phy-mode", &pm);
+ 	if (err < 0)
+-		err = device_property_read_string(dev,
++		err = fwnode_property_read_string(fwnode,
+ 						  "phy-connection-type", &pm);
+ 	if (err < 0)
+ 		return err;
+@@ -1146,6 +1146,20 @@ int device_get_phy_mode(struct device *dev)
+ 
+ 	return -ENODEV;
+ }
++EXPORT_SYMBOL_GPL(fwnode_get_phy_mode);
++
++/**
++ * device_get_phy_mode - Get phy mode for given device
++ * @dev:	Pointer to the given device
++ *
++ * The function gets phy interface string from property 'phy-mode' or
++ * 'phy-connection-type', and return its index in phy_modes table, or errno in
++ * error case.
++ */
++int device_get_phy_mode(struct device *dev)
++{
++	return fwnode_get_phy_mode(dev_fwnode(dev));
++}
+ EXPORT_SYMBOL_GPL(device_get_phy_mode);
+ 
+ static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
+diff --git a/include/linux/property.h b/include/linux/property.h
+index 04d8552..d29eef4 100644
+--- a/include/linux/property.h
++++ b/include/linux/property.h
+@@ -279,6 +279,7 @@ int device_get_phy_mode(struct device *dev);
+ 
+ void *device_get_mac_address(struct device *dev, char *addr, int alen);
+ 
++int fwnode_get_phy_mode(struct fwnode_handle *fwnode);
+ void *fwnode_get_mac_address(struct fwnode_handle *fwnode,
+ 			     char *addr, int alen);
+ struct fwnode_handle *fwnode_graph_get_next_endpoint(
+-- 
+2.7.4
+
diff --git a/SOURCES/0023-device-property-Introduce-fwnode_irq_get.patch b/SOURCES/0023-device-property-Introduce-fwnode_irq_get.patch
new file mode 100644
index 0000000..aef1974
--- /dev/null
+++ b/SOURCES/0023-device-property-Introduce-fwnode_irq_get.patch
@@ -0,0 +1,114 @@
+From b3db52952272989cfa614893148b4939cc51e982 Mon Sep 17 00:00:00 2001
+From: Marcin Wojtas <mw@semihalf.com>
+Date: Thu, 18 Jan 2018 13:31:40 +0100
+Subject: [PATCH 23/46] device property: Introduce fwnode_irq_get()
+
+Until now there were two very similar functions allowing
+to get Linux IRQ number from ACPI handle (acpi_irq_get())
+and OF node (of_irq_get()). The first one appeared to be used
+only as a subroutine of platform_irq_get(), which (in the generic
+code) limited IRQ obtaining from _CRS method only to nodes
+associated to kernel's struct platform_device.
+
+This patch introduces a new helper routine - fwnode_irq_get(),
+which allows to get the IRQ number directly from the fwnode
+to be used as common for OF/ACPI worlds. It is usable not
+only for the parents fwnodes, but also for the child nodes
+comprising their own _CRS methods with interrupts description.
+
+In order to be able o satisfy compilation with !CONFIG_ACPI
+and also simplify the new code, introduce a helper macro
+(ACPI_HANDLE_FWNODE), with which it is possible to reach
+an ACPI handle directly from its fwnode.
+
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 7c6c57f2ab2c5113844fe187a7c45c4bd76dc671)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/base/property.c  | 26 ++++++++++++++++++++++++++
+ include/linux/acpi.h     |  3 +++
+ include/linux/property.h |  2 ++
+ 3 files changed, 31 insertions(+)
+
+diff --git a/drivers/base/property.c b/drivers/base/property.c
+index 9f69d18..3a20e2c 100644
+--- a/drivers/base/property.c
++++ b/drivers/base/property.c
+@@ -16,6 +16,7 @@
+ #include <linux/of.h>
+ #include <linux/of_address.h>
+ #include <linux/of_graph.h>
++#include <linux/of_irq.h>
+ #include <linux/property.h>
+ #include <linux/etherdevice.h>
+ #include <linux/phy.h>
+@@ -1225,6 +1226,31 @@ void *device_get_mac_address(struct device *dev, char *addr, int alen)
+ EXPORT_SYMBOL(device_get_mac_address);
+ 
+ /**
++ * fwnode_irq_get - Get IRQ directly from a fwnode
++ * @fwnode:	Pointer to the firmware node
++ * @index:	Zero-based index of the IRQ
++ *
++ * Returns Linux IRQ number on success. Other values are determined
++ * accordingly to acpi_/of_ irq_get() operation.
++ */
++int fwnode_irq_get(struct fwnode_handle *fwnode, unsigned int index)
++{
++	struct device_node *of_node = to_of_node(fwnode);
++	struct resource res;
++	int ret;
++
++	if (IS_ENABLED(CONFIG_OF) && of_node)
++		return of_irq_get(of_node, index);
++
++	ret = acpi_irq_get(ACPI_HANDLE_FWNODE(fwnode), index, &res);
++	if (ret)
++		return ret;
++
++	return res.start;
++}
++EXPORT_SYMBOL(fwnode_irq_get);
++
++/**
+  * device_graph_get_next_endpoint - Get next endpoint firmware node
+  * @fwnode: Pointer to the parent firmware node
+  * @prev: Previous endpoint node or %NULL to get the first
+diff --git a/include/linux/acpi.h b/include/linux/acpi.h
+index 502af53..0c9ee53 100644
+--- a/include/linux/acpi.h
++++ b/include/linux/acpi.h
+@@ -56,6 +56,8 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev)
+ #define ACPI_COMPANION_SET(dev, adev)	set_primary_fwnode(dev, (adev) ? \
+ 	acpi_fwnode_handle(adev) : NULL)
+ #define ACPI_HANDLE(dev)		acpi_device_handle(ACPI_COMPANION(dev))
++#define ACPI_HANDLE_FWNODE(fwnode)	\
++				acpi_device_handle(to_acpi_device_node(fwnode))
+ 
+ static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
+ {
+@@ -626,6 +628,7 @@ int acpi_arch_timer_mem_init(struct arch_timer_mem *timer_mem, int *timer_count)
+ #define ACPI_COMPANION(dev)		(NULL)
+ #define ACPI_COMPANION_SET(dev, adev)	do { } while (0)
+ #define ACPI_HANDLE(dev)		(NULL)
++#define ACPI_HANDLE_FWNODE(fwnode)	(NULL)
+ #define ACPI_DEVICE_CLASS(_cls, _msk)	.cls = (0), .cls_msk = (0),
+ 
+ struct fwnode_handle;
+diff --git a/include/linux/property.h b/include/linux/property.h
+index d29eef4..cd70998 100644
+--- a/include/linux/property.h
++++ b/include/linux/property.h
+@@ -103,6 +103,8 @@ struct fwnode_handle *device_get_named_child_node(struct device *dev,
+ void fwnode_handle_get(struct fwnode_handle *fwnode);
+ void fwnode_handle_put(struct fwnode_handle *fwnode);
+ 
++int fwnode_irq_get(struct fwnode_handle *fwnode, unsigned int index);
++
+ unsigned int device_get_child_node_count(struct device *dev);
+ 
+ static inline bool device_property_read_bool(struct device *dev,
+-- 
+2.7.4
+
diff --git a/SOURCES/0024-device-property-Allow-iterating-over-available-child.patch b/SOURCES/0024-device-property-Allow-iterating-over-available-child.patch
new file mode 100644
index 0000000..44d7571
--- /dev/null
+++ b/SOURCES/0024-device-property-Allow-iterating-over-available-child.patch
@@ -0,0 +1,85 @@
+From 154dfb69cffd35f4bbbc5a82d823579119491dcd Mon Sep 17 00:00:00 2001
+From: Marcin Wojtas <mw@semihalf.com>
+Date: Thu, 18 Jan 2018 13:31:41 +0100
+Subject: [PATCH 24/46] device property: Allow iterating over available child
+ fwnodes
+
+Implement a new helper function fwnode_get_next_available_child_node(),
+which enables obtaining next enabled child fwnode, which
+works on a similar basis to OF's of_get_next_available_child().
+
+This commit also introduces a macro, thanks to which it is
+possible to iterate over the available fwnodes, using the
+new function described above.
+
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 3395de96ae5998692bd86024d0d5e4dd55cd6cc3)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/base/property.c  | 26 ++++++++++++++++++++++++++
+ include/linux/property.h |  6 ++++++
+ 2 files changed, 32 insertions(+)
+
+diff --git a/drivers/base/property.c b/drivers/base/property.c
+index 3a20e2c..75aec5b 100644
+--- a/drivers/base/property.c
++++ b/drivers/base/property.c
+@@ -998,6 +998,32 @@ fwnode_get_next_child_node(const struct fwnode_handle *fwnode,
+ EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
+ 
+ /**
++ * fwnode_get_next_available_child_node - Return the next
++ * available child node handle for a node
++ * @fwnode: Firmware node to find the next child node for.
++ * @child: Handle to one of the node's child nodes or a %NULL handle.
++ */
++struct fwnode_handle *
++fwnode_get_next_available_child_node(const struct fwnode_handle *fwnode,
++				     struct fwnode_handle *child)
++{
++	struct fwnode_handle *next_child = child;
++
++	if (!fwnode)
++		return NULL;
++
++	do {
++		next_child = fwnode_get_next_child_node(fwnode, next_child);
++
++		if (!next_child || fwnode_device_is_available(next_child))
++			break;
++	} while (next_child);
++
++	return next_child;
++}
++EXPORT_SYMBOL_GPL(fwnode_get_next_available_child_node);
++
++/**
+  * device_get_next_child_node - Return the next child node handle for a device
+  * @dev: Device to find the next child node for.
+  * @child: Handle to one of the device's child nodes or a null handle.
+diff --git a/include/linux/property.h b/include/linux/property.h
+index cd70998..f8ba672 100644
+--- a/include/linux/property.h
++++ b/include/linux/property.h
+@@ -83,11 +83,17 @@ struct fwnode_handle *fwnode_get_next_parent(
+ 	struct fwnode_handle *fwnode);
+ struct fwnode_handle *fwnode_get_next_child_node(
+ 	const struct fwnode_handle *fwnode, struct fwnode_handle *child);
++struct fwnode_handle *fwnode_get_next_available_child_node(
++	const struct fwnode_handle *fwnode, struct fwnode_handle *child);
+ 
+ #define fwnode_for_each_child_node(fwnode, child)			\
+ 	for (child = fwnode_get_next_child_node(fwnode, NULL); child;	\
+ 	     child = fwnode_get_next_child_node(fwnode, child))
+ 
++#define fwnode_for_each_available_child_node(fwnode, child)		       \
++	for (child = fwnode_get_next_available_child_node(fwnode, NULL); child;\
++	     child = fwnode_get_next_available_child_node(fwnode, child))
++
+ struct fwnode_handle *device_get_next_child_node(
+ 	struct device *dev, struct fwnode_handle *child);
+ 
+-- 
+2.7.4
+
diff --git a/SOURCES/0025-net-mvpp2-simplify-maintaining-enabled-ports-list.patch b/SOURCES/0025-net-mvpp2-simplify-maintaining-enabled-ports-list.patch
new file mode 100644
index 0000000..2ca1bae
--- /dev/null
+++ b/SOURCES/0025-net-mvpp2-simplify-maintaining-enabled-ports-list.patch
@@ -0,0 +1,94 @@
+From 8c444fab46352985bc5e9a9e0796f5fe7fe19e5c Mon Sep 17 00:00:00 2001
+From: Marcin Wojtas <mw@semihalf.com>
+Date: Thu, 18 Jan 2018 13:31:42 +0100
+Subject: [PATCH 25/46] net: mvpp2: simplify maintaining enabled ports' list
+
+'port_count' field of the mvpp2 structure holds an overall amount
+of available ports, based on DT nodes status. In order to be prepared
+to support other HW description, obtain the value by incrementing it
+upon each successful port initialization. This allowed for simplifying
+port indexing in the controller's private array, whose size is now not
+dynamically allocated, but fixed to MVPP2_MAX_PORTS.
+
+This patch simplifies creating and filling list of enabled ports and
+is a part of the preparation for adding ACPI support in the mvpp2 driver.
+
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit bf147153d7f4b0d7337b28040837d9272c1a99fe)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 32 +++++++++++---------------------
+ 1 file changed, 11 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index a197607..7f42d90 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -865,7 +865,7 @@ struct mvpp2 {
+ 
+ 	/* List of pointers to port structures */
+ 	int port_count;
+-	struct mvpp2_port **port_list;
++	struct mvpp2_port *port_list[MVPP2_MAX_PORTS];
+ 
+ 	/* Aggregated TXQs */
+ 	struct mvpp2_tx_queue *aggr_txqs;
+@@ -7741,7 +7741,7 @@ static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv,
+ /* Ports initialization */
+ static int mvpp2_port_probe(struct platform_device *pdev,
+ 			    struct device_node *port_node,
+-			    struct mvpp2 *priv, int index)
++			    struct mvpp2 *priv)
+ {
+ 	struct device_node *phy_node;
+ 	struct phy *comphy;
+@@ -7934,7 +7934,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 	}
+ 	netdev_info(dev, "Using %s mac address %pM\n", mac_from, dev->dev_addr);
+ 
+-	priv->port_list[index] = port;
++	priv->port_list[priv->port_count++] = port;
++
+ 	return 0;
+ 
+ err_free_port_pcpu:
+@@ -8313,28 +8314,17 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 		goto err_mg_clk;
+ 	}
+ 
+-	priv->port_count = of_get_available_child_count(dn);
+-	if (priv->port_count == 0) {
+-		dev_err(&pdev->dev, "no ports enabled\n");
+-		err = -ENODEV;
+-		goto err_mg_clk;
+-	}
+-
+-	priv->port_list = devm_kcalloc(&pdev->dev, priv->port_count,
+-				       sizeof(*priv->port_list),
+-				       GFP_KERNEL);
+-	if (!priv->port_list) {
+-		err = -ENOMEM;
+-		goto err_mg_clk;
+-	}
+-
+ 	/* Initialize ports */
+-	i = 0;
+ 	for_each_available_child_of_node(dn, port_node) {
+-		err = mvpp2_port_probe(pdev, port_node, priv, i);
++		err = mvpp2_port_probe(pdev, port_node, priv);
+ 		if (err < 0)
+ 			goto err_port_probe;
+-		i++;
++	}
++
++	if (priv->port_count == 0) {
++		dev_err(&pdev->dev, "no ports enabled\n");
++		err = -ENODEV;
++		goto err_mg_clk;
+ 	}
+ 
+ 	/* Statistics must be gathered regularly because some of them (like
+-- 
+2.7.4
+
diff --git a/SOURCES/0026-net-mvpp2-use-device_-fwnode_-APIs-instead-of-of_.patch b/SOURCES/0026-net-mvpp2-use-device_-fwnode_-APIs-instead-of-of_.patch
new file mode 100644
index 0000000..7441230
--- /dev/null
+++ b/SOURCES/0026-net-mvpp2-use-device_-fwnode_-APIs-instead-of-of_.patch
@@ -0,0 +1,173 @@
+From b1d7cdef19d9ba1eba6a89b582d36de59ce1363c Mon Sep 17 00:00:00 2001
+From: Marcin Wojtas <mw@semihalf.com>
+Date: Thu, 18 Jan 2018 13:31:43 +0100
+Subject: [PATCH 26/46] net: mvpp2: use device_*/fwnode_* APIs instead of of_*
+
+OF functions can be used only for the driver using DT.
+As a preparation for introducing ACPI support in mvpp2
+driver, use struct fwnode_handle in order to obtain
+properties from the hardware description.
+
+This patch replaces of_* function with device_*/fwnode_*
+where possible in the mvpp2.
+
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 248122212f68dcf13433ec56bb03ddc799259026)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 45 +++++++++++++++++++-----------------
+ 1 file changed, 24 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 7f42d90..f16448e 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -932,6 +932,9 @@ struct mvpp2_port {
+ 
+ 	struct mvpp2 *priv;
+ 
++	/* Firmware node associated to the port */
++	struct fwnode_handle *fwnode;
++
+ 	/* Per-port registers' base address */
+ 	void __iomem *base;
+ 	void __iomem *stats_base;
+@@ -7711,17 +7714,16 @@ static bool mvpp2_port_has_tx_irqs(struct mvpp2 *priv,
+ }
+ 
+ static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv,
+-				     struct device_node *port_node,
++				     struct fwnode_handle *fwnode,
+ 				     char **mac_from)
+ {
+ 	struct mvpp2_port *port = netdev_priv(dev);
+ 	char hw_mac_addr[ETH_ALEN] = {0};
+-	const char *dt_mac_addr;
++	char fw_mac_addr[ETH_ALEN];
+ 
+-	dt_mac_addr = of_get_mac_address(port_node);
+-	if (dt_mac_addr && is_valid_ether_addr(dt_mac_addr)) {
+-		*mac_from = "device tree";
+-		ether_addr_copy(dev->dev_addr, dt_mac_addr);
++	if (fwnode_get_mac_address(fwnode, fw_mac_addr, ETH_ALEN)) {
++		*mac_from = "firmware node";
++		ether_addr_copy(dev->dev_addr, fw_mac_addr);
+ 		return;
+ 	}
+ 
+@@ -7740,13 +7742,14 @@ static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv,
+ 
+ /* Ports initialization */
+ static int mvpp2_port_probe(struct platform_device *pdev,
+-			    struct device_node *port_node,
++			    struct fwnode_handle *port_fwnode,
+ 			    struct mvpp2 *priv)
+ {
+ 	struct device_node *phy_node;
+ 	struct phy *comphy;
+ 	struct mvpp2_port *port;
+ 	struct mvpp2_port_pcpu *port_pcpu;
++	struct device_node *port_node = to_of_node(port_fwnode);
+ 	struct net_device *dev;
+ 	struct resource *res;
+ 	char *mac_from = "";
+@@ -7773,7 +7776,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 		return -ENOMEM;
+ 
+ 	phy_node = of_parse_phandle(port_node, "phy", 0);
+-	phy_mode = of_get_phy_mode(port_node);
++	phy_mode = fwnode_get_phy_mode(port_fwnode);
+ 	if (phy_mode < 0) {
+ 		dev_err(&pdev->dev, "incorrect phy mode\n");
+ 		err = phy_mode;
+@@ -7789,7 +7792,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 		comphy = NULL;
+ 	}
+ 
+-	if (of_property_read_u32(port_node, "port-id", &id)) {
++	if (fwnode_property_read_u32(port_fwnode, "port-id", &id)) {
+ 		err = -EINVAL;
+ 		dev_err(&pdev->dev, "missing port-id value\n");
+ 		goto err_free_netdev;
+@@ -7820,7 +7823,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 		/* the link irq is optional */
+ 		port->link_irq = 0;
+ 
+-	if (of_property_read_bool(port_node, "marvell,loopback"))
++	if (fwnode_property_read_bool(port_fwnode, "marvell,loopback"))
+ 		port->flags |= MVPP2_F_LOOPBACK;
+ 
+ 	port->id = id;
+@@ -7845,8 +7848,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 				   MVPP21_MIB_COUNTERS_OFFSET +
+ 				   port->gop_id * MVPP21_MIB_COUNTERS_PORT_SZ;
+ 	} else {
+-		if (of_property_read_u32(port_node, "gop-port-id",
+-					 &port->gop_id)) {
++		if (fwnode_property_read_u32(port_fwnode, "gop-port-id",
++					     &port->gop_id)) {
+ 			err = -EINVAL;
+ 			dev_err(&pdev->dev, "missing gop-port-id value\n");
+ 			goto err_deinit_qvecs;
+@@ -7876,7 +7879,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 	mutex_init(&port->gather_stats_lock);
+ 	INIT_DELAYED_WORK(&port->stats_work, mvpp2_gather_hw_statistics);
+ 
+-	mvpp2_port_copy_mac_addr(dev, priv, port_node, &mac_from);
++	mvpp2_port_copy_mac_addr(dev, priv, port_fwnode, &mac_from);
+ 
+ 	port->tx_ring_size = MVPP2_MAX_TXD_DFLT;
+ 	port->rx_ring_size = MVPP2_MAX_RXD_DFLT;
+@@ -8194,8 +8197,8 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)
+ 
+ static int mvpp2_probe(struct platform_device *pdev)
+ {
+-	struct device_node *dn = pdev->dev.of_node;
+-	struct device_node *port_node;
++	struct fwnode_handle *fwnode = pdev->dev.fwnode;
++	struct fwnode_handle *port_fwnode;
+ 	struct mvpp2 *priv;
+ 	struct resource *res;
+ 	void __iomem *base;
+@@ -8315,8 +8318,8 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	/* Initialize ports */
+-	for_each_available_child_of_node(dn, port_node) {
+-		err = mvpp2_port_probe(pdev, port_node, priv);
++	fwnode_for_each_available_child_node(fwnode, port_fwnode) {
++		err = mvpp2_port_probe(pdev, port_fwnode, priv);
+ 		if (err < 0)
+ 			goto err_port_probe;
+ 	}
+@@ -8347,7 +8350,7 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 
+ err_port_probe:
+ 	i = 0;
+-	for_each_available_child_of_node(dn, port_node) {
++	fwnode_for_each_available_child_node(fwnode, port_fwnode) {
+ 		if (priv->port_list[i])
+ 			mvpp2_port_remove(priv->port_list[i]);
+ 		i++;
+@@ -8366,14 +8369,14 @@ static int mvpp2_probe(struct platform_device *pdev)
+ static int mvpp2_remove(struct platform_device *pdev)
+ {
+ 	struct mvpp2 *priv = platform_get_drvdata(pdev);
+-	struct device_node *dn = pdev->dev.of_node;
+-	struct device_node *port_node;
++	struct fwnode_handle *fwnode = pdev->dev.fwnode;
++	struct fwnode_handle *port_fwnode;
+ 	int i = 0;
+ 
+ 	flush_workqueue(priv->stats_queue);
+ 	destroy_workqueue(priv->stats_queue);
+ 
+-	for_each_available_child_of_node(dn, port_node) {
++	fwnode_for_each_available_child_node(fwnode, port_fwnode) {
+ 		if (priv->port_list[i]) {
+ 			mutex_destroy(&priv->port_list[i]->gather_stats_lock);
+ 			mvpp2_port_remove(priv->port_list[i]);
+-- 
+2.7.4
+
diff --git a/SOURCES/0027-net-mvpp2-enable-ACPI-support-in-the-driver.patch b/SOURCES/0027-net-mvpp2-enable-ACPI-support-in-the-driver.patch
new file mode 100644
index 0000000..498cadb
--- /dev/null
+++ b/SOURCES/0027-net-mvpp2-enable-ACPI-support-in-the-driver.patch
@@ -0,0 +1,305 @@
+From 2626faa285fac645ade962a29001558fd0f567a5 Mon Sep 17 00:00:00 2001
+From: Marcin Wojtas <mw@semihalf.com>
+Date: Thu, 18 Jan 2018 13:31:44 +0100
+Subject: [PATCH 27/46] net: mvpp2: enable ACPI support in the driver
+
+This patch introduces an alternative way of obtaining resources - via
+ACPI tables provided by firmware. Enabling coexistence with the DT
+support, in addition to the OF_*->device_*/fwnode_* API replacement,
+required following steps to be taken:
+
+* Add mvpp2_acpi_match table
+* Omit clock configuration and obtain tclk from the property - in ACPI
+  world, the firmware is responsible for clock maintenance.
+* Disable comphy and syscon handling as they are not available for ACPI.
+* Modify way of obtaining interrupts - use newly introduced
+  fwnode_irq_get() routine
+* Until proper MDIO bus and PHY handling with ACPI is established in the
+  kernel, use only link interrupts feature in the driver. For the RGMII
+  port it results in depending on GMAC settings done during firmware
+  stage.
+* When booting with ACPI MVPP2_QDIST_MULTI_MODE is picked by
+  default, as there is no need to keep any kind of the backward
+  compatibility.
+
+Moreover, a memory region used by mvmdio driver is usually placed in
+the middle of the address space of the PP2 network controller.
+The MDIO base address is obtained without requesting memory region
+(by devm_ioremap() call) in mvmdio.c, later overlapping resources are
+requested by the network driver, which is responsible for avoiding
+a concurrent access.
+
+In case the MDIO memory region is declared in the ACPI, it can
+already appear as 'in-use' in the OS. Because it is overlapped by second
+region of the network controller, make sure it is released, before
+requesting it again. The care is taken by mvpp2 driver to avoid
+concurrent access to this memory region.
+
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit a75edc7c2eab329d20a4ffbbfb15f2aa4a95454f)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 133 +++++++++++++++++++++++++----------
+ 1 file changed, 94 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index f16448e..a1d7b88 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -10,6 +10,7 @@
+  * warranty of any kind, whether express or implied.
+  */
+ 
++#include <linux/acpi.h>
+ #include <linux/kernel.h>
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+@@ -7502,7 +7503,10 @@ static int mvpp2_multi_queue_vectors_init(struct mvpp2_port *port,
+ 			strncpy(irqname, "rx-shared", sizeof(irqname));
+ 		}
+ 
+-		v->irq = of_irq_get_byname(port_node, irqname);
++		if (port_node)
++			v->irq = of_irq_get_byname(port_node, irqname);
++		else
++			v->irq = fwnode_irq_get(port->fwnode, i);
+ 		if (v->irq <= 0) {
+ 			ret = -EINVAL;
+ 			goto err;
+@@ -7746,7 +7750,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 			    struct mvpp2 *priv)
+ {
+ 	struct device_node *phy_node;
+-	struct phy *comphy;
++	struct phy *comphy = NULL;
+ 	struct mvpp2_port *port;
+ 	struct mvpp2_port_pcpu *port_pcpu;
+ 	struct device_node *port_node = to_of_node(port_fwnode);
+@@ -7760,7 +7764,12 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 	int phy_mode;
+ 	int err, i, cpu;
+ 
+-	has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
++	if (port_node) {
++		has_tx_irqs = mvpp2_port_has_tx_irqs(priv, port_node);
++	} else {
++		has_tx_irqs = true;
++		queue_mode = MVPP2_QDIST_MULTI_MODE;
++	}
+ 
+ 	if (!has_tx_irqs)
+ 		queue_mode = MVPP2_QDIST_SINGLE_MODE;
+@@ -7775,7 +7784,11 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 	if (!dev)
+ 		return -ENOMEM;
+ 
+-	phy_node = of_parse_phandle(port_node, "phy", 0);
++	if (port_node)
++		phy_node = of_parse_phandle(port_node, "phy", 0);
++	else
++		phy_node = NULL;
++
+ 	phy_mode = fwnode_get_phy_mode(port_fwnode);
+ 	if (phy_mode < 0) {
+ 		dev_err(&pdev->dev, "incorrect phy mode\n");
+@@ -7783,13 +7796,15 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 		goto err_free_netdev;
+ 	}
+ 
+-	comphy = devm_of_phy_get(&pdev->dev, port_node, NULL);
+-	if (IS_ERR(comphy)) {
+-		if (PTR_ERR(comphy) == -EPROBE_DEFER) {
+-			err = -EPROBE_DEFER;
+-			goto err_free_netdev;
++	if (port_node) {
++		comphy = devm_of_phy_get(&pdev->dev, port_node, NULL);
++		if (IS_ERR(comphy)) {
++			if (PTR_ERR(comphy) == -EPROBE_DEFER) {
++				err = -EPROBE_DEFER;
++				goto err_free_netdev;
++			}
++			comphy = NULL;
+ 		}
+-		comphy = NULL;
+ 	}
+ 
+ 	if (fwnode_property_read_u32(port_fwnode, "port-id", &id)) {
+@@ -7805,6 +7820,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 
+ 	port = netdev_priv(dev);
+ 	port->dev = dev;
++	port->fwnode = port_fwnode;
+ 	port->ntxqs = ntxqs;
+ 	port->nrxqs = nrxqs;
+ 	port->priv = priv;
+@@ -7814,7 +7830,10 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 	if (err)
+ 		goto err_free_netdev;
+ 
+-	port->link_irq = of_irq_get_byname(port_node, "link");
++	if (port_node)
++		port->link_irq = of_irq_get_byname(port_node, "link");
++	else
++		port->link_irq = fwnode_irq_get(port_fwnode, port->nqvecs + 1);
+ 	if (port->link_irq == -EPROBE_DEFER) {
+ 		err = -EPROBE_DEFER;
+ 		goto err_deinit_qvecs;
+@@ -8197,6 +8216,7 @@ static int mvpp2_init(struct platform_device *pdev, struct mvpp2 *priv)
+ 
+ static int mvpp2_probe(struct platform_device *pdev)
+ {
++	const struct acpi_device_id *acpi_id;
+ 	struct fwnode_handle *fwnode = pdev->dev.fwnode;
+ 	struct fwnode_handle *port_fwnode;
+ 	struct mvpp2 *priv;
+@@ -8209,8 +8229,14 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 	if (!priv)
+ 		return -ENOMEM;
+ 
+-	priv->hw_version =
+-		(unsigned long)of_device_get_match_data(&pdev->dev);
++	if (has_acpi_companion(&pdev->dev)) {
++		acpi_id = acpi_match_device(pdev->dev.driver->acpi_match_table,
++					    &pdev->dev);
++		priv->hw_version = (unsigned long)acpi_id->driver_data;
++	} else {
++		priv->hw_version =
++			(unsigned long)of_device_get_match_data(&pdev->dev);
++	}
+ 
+ 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ 	base = devm_ioremap_resource(&pdev->dev, res);
+@@ -8224,10 +8250,23 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 			return PTR_ERR(priv->lms_base);
+ 	} else {
+ 		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++		if (has_acpi_companion(&pdev->dev)) {
++			/* In case the MDIO memory region is declared in
++			 * the ACPI, it can already appear as 'in-use'
++			 * in the OS. Because it is overlapped by second
++			 * region of the network controller, make
++			 * sure it is released, before requesting it again.
++			 * The care is taken by mvpp2 driver to avoid
++			 * concurrent access to this memory region.
++			 */
++			release_resource(res);
++		}
+ 		priv->iface_base = devm_ioremap_resource(&pdev->dev, res);
+ 		if (IS_ERR(priv->iface_base))
+ 			return PTR_ERR(priv->iface_base);
++	}
+ 
++	if (priv->hw_version == MVPP22 && dev_of_node(&pdev->dev)) {
+ 		priv->sysctrl_base =
+ 			syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ 							"marvell,system-controller");
+@@ -8253,32 +8292,34 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 	else
+ 		priv->max_port_rxqs = 32;
+ 
+-	priv->pp_clk = devm_clk_get(&pdev->dev, "pp_clk");
+-	if (IS_ERR(priv->pp_clk))
+-		return PTR_ERR(priv->pp_clk);
+-	err = clk_prepare_enable(priv->pp_clk);
+-	if (err < 0)
+-		return err;
+-
+-	priv->gop_clk = devm_clk_get(&pdev->dev, "gop_clk");
+-	if (IS_ERR(priv->gop_clk)) {
+-		err = PTR_ERR(priv->gop_clk);
+-		goto err_pp_clk;
+-	}
+-	err = clk_prepare_enable(priv->gop_clk);
+-	if (err < 0)
+-		goto err_pp_clk;
++	if (dev_of_node(&pdev->dev)) {
++		priv->pp_clk = devm_clk_get(&pdev->dev, "pp_clk");
++		if (IS_ERR(priv->pp_clk))
++			return PTR_ERR(priv->pp_clk);
++		err = clk_prepare_enable(priv->pp_clk);
++		if (err < 0)
++			return err;
+ 
+-	if (priv->hw_version == MVPP22) {
+-		priv->mg_clk = devm_clk_get(&pdev->dev, "mg_clk");
+-		if (IS_ERR(priv->mg_clk)) {
+-			err = PTR_ERR(priv->mg_clk);
+-			goto err_gop_clk;
++		priv->gop_clk = devm_clk_get(&pdev->dev, "gop_clk");
++		if (IS_ERR(priv->gop_clk)) {
++			err = PTR_ERR(priv->gop_clk);
++			goto err_pp_clk;
+ 		}
+-
+-		err = clk_prepare_enable(priv->mg_clk);
++		err = clk_prepare_enable(priv->gop_clk);
+ 		if (err < 0)
+-			goto err_gop_clk;
++			goto err_pp_clk;
++
++		if (priv->hw_version == MVPP22) {
++			priv->mg_clk = devm_clk_get(&pdev->dev, "mg_clk");
++			if (IS_ERR(priv->mg_clk)) {
++				err = PTR_ERR(priv->mg_clk);
++				goto err_gop_clk;
++			}
++
++			err = clk_prepare_enable(priv->mg_clk);
++			if (err < 0)
++				goto err_gop_clk;
++		}
+ 
+ 		priv->axi_clk = devm_clk_get(&pdev->dev, "axi_clk");
+ 		if (IS_ERR(priv->axi_clk)) {
+@@ -8291,10 +8332,14 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 			if (err < 0)
+ 				goto err_gop_clk;
+ 		}
+-	}
+ 
+-	/* Get system's tclk rate */
+-	priv->tclk = clk_get_rate(priv->pp_clk);
++		/* Get system's tclk rate */
++		priv->tclk = clk_get_rate(priv->pp_clk);
++	} else if (device_property_read_u32(&pdev->dev, "clock-frequency",
++					    &priv->tclk)) {
++		dev_err(&pdev->dev, "missing clock-frequency value\n");
++		return -EINVAL;
++	}
+ 
+ 	if (priv->hw_version == MVPP22) {
+ 		err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(40));
+@@ -8399,6 +8444,9 @@ static int mvpp2_remove(struct platform_device *pdev)
+ 				  aggr_txq->descs_dma);
+ 	}
+ 
++	if (is_acpi_node(port_fwnode))
++		return 0;
++
+ 	clk_disable_unprepare(priv->axi_clk);
+ 	clk_disable_unprepare(priv->mg_clk);
+ 	clk_disable_unprepare(priv->pp_clk);
+@@ -8420,12 +8468,19 @@ static const struct of_device_id mvpp2_match[] = {
+ };
+ MODULE_DEVICE_TABLE(of, mvpp2_match);
+ 
++static const struct acpi_device_id mvpp2_acpi_match[] = {
++	{ "MRVL0110", MVPP22 },
++	{ },
++};
++MODULE_DEVICE_TABLE(acpi, mvpp2_acpi_match);
++
+ static struct platform_driver mvpp2_driver = {
+ 	.probe = mvpp2_probe,
+ 	.remove = mvpp2_remove,
+ 	.driver = {
+ 		.name = MVPP2_DRIVER_NAME,
+ 		.of_match_table = mvpp2_match,
++		.acpi_match_table = ACPI_PTR(mvpp2_acpi_match),
+ 	},
+ };
+ 
+-- 
+2.7.4
+
diff --git a/SOURCES/0028-mvpp2-fix-multicast-address-filter.patch b/SOURCES/0028-mvpp2-fix-multicast-address-filter.patch
new file mode 100644
index 0000000..91f5733
--- /dev/null
+++ b/SOURCES/0028-mvpp2-fix-multicast-address-filter.patch
@@ -0,0 +1,58 @@
+From 251852630ac787021e7088933187948f27bae241 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Sun, 11 Feb 2018 18:10:28 -0500
+Subject: [PATCH 28/46] mvpp2: fix multicast address filter
+
+IPv6 doesn't work on the MacchiatoBIN board. It is caused by broken
+multicast address filter in the mvpp2 driver.
+
+The driver loads doesn't load any multicast entries if "allmulti" is not
+set. This condition should be reversed.
+
+The condition !netdev_mc_empty(dev) is useless (because
+netdev_for_each_mc_addr is nop if the list is empty).
+
+This patch also fixes a possible overflow of the multicast list - if
+mvpp2_prs_mac_da_accept fails, we set the allmulti flag and retry.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 7ac8ff95f48cbfa609a060fd6a1e361dd62feeb3)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index a1d7b88..5a1668c 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -7137,6 +7137,7 @@ static void mvpp2_set_rx_mode(struct net_device *dev)
+ 	int id = port->id;
+ 	bool allmulti = dev->flags & IFF_ALLMULTI;
+ 
++retry:
+ 	mvpp2_prs_mac_promisc_set(priv, id, dev->flags & IFF_PROMISC);
+ 	mvpp2_prs_mac_multi_set(priv, id, MVPP2_PE_MAC_MC_ALL, allmulti);
+ 	mvpp2_prs_mac_multi_set(priv, id, MVPP2_PE_MAC_MC_IP6, allmulti);
+@@ -7144,9 +7145,13 @@ static void mvpp2_set_rx_mode(struct net_device *dev)
+ 	/* Remove all port->id's mcast enries */
+ 	mvpp2_prs_mcast_del_all(priv, id);
+ 
+-	if (allmulti && !netdev_mc_empty(dev)) {
+-		netdev_for_each_mc_addr(ha, dev)
+-			mvpp2_prs_mac_da_accept(priv, id, ha->addr, true);
++	if (!allmulti) {
++		netdev_for_each_mc_addr(ha, dev) {
++			if (mvpp2_prs_mac_da_accept(priv, id, ha->addr, true)) {
++				allmulti = true;
++				goto retry;
++			}
++		}
+ 	}
+ }
+ 
+-- 
+2.7.4
+
diff --git a/SOURCES/0029-net-mvpp2-Add-hardware-offloading-for-VLAN-filtering.patch b/SOURCES/0029-net-mvpp2-Add-hardware-offloading-for-VLAN-filtering.patch
new file mode 100644
index 0000000..129307a
--- /dev/null
+++ b/SOURCES/0029-net-mvpp2-Add-hardware-offloading-for-VLAN-filtering.patch
@@ -0,0 +1,597 @@
+From 1f9adeb81aaa5d359b357aa771c9aaaf1a1cc80f Mon Sep 17 00:00:00 2001
+From: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Date: Wed, 28 Feb 2018 10:14:13 +0100
+Subject: [PATCH 29/46] net: mvpp2: Add hardware offloading for VLAN filtering
+
+Marvell PPv2 controller allows for generic packet filtering. This commit
+adds entries to implement VLAN filtering. The approach taken is :
+
+ - Filter entries that would match on the presence of the VLAN tag
+   (existing VLAN detection, DSA / EDSA detection) will set the next
+   lookup ID to be for the VID.
+
+ - For each VLAN existing on a given port, we add an entry that matches
+   this specific VID. If the incoming packet matches the VID entry, it is
+   set for the next lookup in the chain (LU_L2).
+
+ - A Guard entry is added for each port, that will match if the incoming
+   packet didn't match any of the above VID entries. This entry tags the
+   packet to be dropped.
+
+Due to this design, and the fact that the total 256 filter entries are
+also used for other purposes, we have a limit of 10 VLANs per port. To
+accommodate the case where we would need more VLANS on one port, this
+patch implements the ndo_set_features to allow for disabling of VLAN
+filtering using ethtool.
+
+The default config has VLAN filtering disabled.
+
+Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 56beda3db6020428885f0589a0ac16768ea94543)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 414 ++++++++++++++++++++++++++++++++---
+ 1 file changed, 380 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 5a1668c..9418f6ee 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -65,6 +65,10 @@
+ #define     MVPP2_RXQ_PACKET_OFFSET_MASK	0x70000000
+ #define     MVPP2_RXQ_DISABLE_MASK		BIT(31)
+ 
++/* Top Registers */
++#define MVPP2_MH_REG(port)			(0x5040 + 4 * (port))
++#define MVPP2_DSA_EXTENDED			BIT(5)
++
+ /* Parser Registers */
+ #define MVPP2_PRS_INIT_LOOKUP_REG		0x1000
+ #define     MVPP2_PRS_PORT_LU_MAX		0xf
+@@ -473,6 +477,7 @@
+ #define MVPP2_ETH_TYPE_LEN		2
+ #define MVPP2_PPPOE_HDR_SIZE		8
+ #define MVPP2_VLAN_TAG_LEN		4
++#define MVPP2_VLAN_TAG_EDSA_LEN		8
+ 
+ /* Lbtd 802.3 type */
+ #define MVPP2_IP_LBDT_TYPE		0xfffa
+@@ -609,35 +614,64 @@ enum mvpp2_tag_type {
+ #define MVPP2_PRS_TCAM_LU_BYTE			20
+ #define MVPP2_PRS_TCAM_EN_OFFS(offs)		((offs) + 2)
+ #define MVPP2_PRS_TCAM_INV_WORD			5
++
++#define MVPP2_PRS_VID_TCAM_BYTE         2
++
++/* There is a TCAM range reserved for VLAN filtering entries, range size is 33
++ * 10 VLAN ID filter entries per port
++ * 1 default VLAN filter entry per port
++ * It is assumed that there are 3 ports for filter, not including loopback port
++ */
++#define MVPP2_PRS_VLAN_FILT_MAX		11
++#define MVPP2_PRS_VLAN_FILT_RANGE_SIZE	33
++
++#define MVPP2_PRS_VLAN_FILT_MAX_ENTRY   (MVPP2_PRS_VLAN_FILT_MAX - 2)
++#define MVPP2_PRS_VLAN_FILT_DFLT_ENTRY  (MVPP2_PRS_VLAN_FILT_MAX - 1)
++
+ /* Tcam entries ID */
+ #define MVPP2_PE_DROP_ALL		0
+ #define MVPP2_PE_FIRST_FREE_TID		1
+-#define MVPP2_PE_LAST_FREE_TID		(MVPP2_PRS_TCAM_SRAM_SIZE - 31)
++
++/* VLAN filtering range */
++#define MVPP2_PE_VID_FILT_RANGE_END     (MVPP2_PRS_TCAM_SRAM_SIZE - 31)
++#define MVPP2_PE_VID_FILT_RANGE_START   (MVPP2_PE_VID_FILT_RANGE_END - \
++					 MVPP2_PRS_VLAN_FILT_RANGE_SIZE + 1)
++#define MVPP2_PE_LAST_FREE_TID          (MVPP2_PE_VID_FILT_RANGE_START - 1)
+ #define MVPP2_PE_IP6_EXT_PROTO_UN	(MVPP2_PRS_TCAM_SRAM_SIZE - 30)
+ #define MVPP2_PE_MAC_MC_IP6		(MVPP2_PRS_TCAM_SRAM_SIZE - 29)
+ #define MVPP2_PE_IP6_ADDR_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 28)
+ #define MVPP2_PE_IP4_ADDR_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 27)
+ #define MVPP2_PE_LAST_DEFAULT_FLOW	(MVPP2_PRS_TCAM_SRAM_SIZE - 26)
+-#define MVPP2_PE_FIRST_DEFAULT_FLOW	(MVPP2_PRS_TCAM_SRAM_SIZE - 19)
+-#define MVPP2_PE_EDSA_TAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 18)
+-#define MVPP2_PE_EDSA_UNTAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 17)
+-#define MVPP2_PE_DSA_TAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 16)
+-#define MVPP2_PE_DSA_UNTAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 15)
+-#define MVPP2_PE_ETYPE_EDSA_TAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 14)
+-#define MVPP2_PE_ETYPE_EDSA_UNTAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 13)
+-#define MVPP2_PE_ETYPE_DSA_TAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 12)
+-#define MVPP2_PE_ETYPE_DSA_UNTAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 11)
+-#define MVPP2_PE_MH_DEFAULT		(MVPP2_PRS_TCAM_SRAM_SIZE - 10)
+-#define MVPP2_PE_DSA_DEFAULT		(MVPP2_PRS_TCAM_SRAM_SIZE - 9)
+-#define MVPP2_PE_IP6_PROTO_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 8)
+-#define MVPP2_PE_IP4_PROTO_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 7)
+-#define MVPP2_PE_ETH_TYPE_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 6)
++#define MVPP2_PE_FIRST_DEFAULT_FLOW	(MVPP2_PRS_TCAM_SRAM_SIZE - 21)
++#define MVPP2_PE_EDSA_TAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 20)
++#define MVPP2_PE_EDSA_UNTAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 19)
++#define MVPP2_PE_DSA_TAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 18)
++#define MVPP2_PE_DSA_UNTAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 17)
++#define MVPP2_PE_ETYPE_EDSA_TAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 16)
++#define MVPP2_PE_ETYPE_EDSA_UNTAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 15)
++#define MVPP2_PE_ETYPE_DSA_TAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 14)
++#define MVPP2_PE_ETYPE_DSA_UNTAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 13)
++#define MVPP2_PE_MH_DEFAULT		(MVPP2_PRS_TCAM_SRAM_SIZE - 12)
++#define MVPP2_PE_DSA_DEFAULT		(MVPP2_PRS_TCAM_SRAM_SIZE - 11)
++#define MVPP2_PE_IP6_PROTO_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 10)
++#define MVPP2_PE_IP4_PROTO_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 9)
++#define MVPP2_PE_ETH_TYPE_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 8)
++#define MVPP2_PE_VID_FLTR_DEFAULT	(MVPP2_PRS_TCAM_SRAM_SIZE - 7)
++#define MVPP2_PE_VID_EDSA_FLTR_DEFAULT	(MVPP2_PRS_TCAM_SRAM_SIZE - 6)
+ #define MVPP2_PE_VLAN_DBL		(MVPP2_PRS_TCAM_SRAM_SIZE - 5)
+ #define MVPP2_PE_VLAN_NONE		(MVPP2_PRS_TCAM_SRAM_SIZE - 4)
+ #define MVPP2_PE_MAC_MC_ALL		(MVPP2_PRS_TCAM_SRAM_SIZE - 3)
+ #define MVPP2_PE_MAC_PROMISCUOUS	(MVPP2_PRS_TCAM_SRAM_SIZE - 2)
+ #define MVPP2_PE_MAC_NON_PROMISCUOUS	(MVPP2_PRS_TCAM_SRAM_SIZE - 1)
+ 
++#define MVPP2_PRS_VID_PORT_FIRST(port)	(MVPP2_PE_VID_FILT_RANGE_START + \
++					 ((port) * MVPP2_PRS_VLAN_FILT_MAX))
++#define MVPP2_PRS_VID_PORT_LAST(port)	(MVPP2_PRS_VID_PORT_FIRST(port) \
++					 + MVPP2_PRS_VLAN_FILT_MAX_ENTRY)
++/* Index of default vid filter for given port */
++#define MVPP2_PRS_VID_PORT_DFLT(port)	(MVPP2_PRS_VID_PORT_FIRST(port) \
++					 + MVPP2_PRS_VLAN_FILT_DFLT_ENTRY)
++
+ /* Sram structure
+  * The fields are represented by MVPP2_PRS_TCAM_DATA_REG(3)->(0).
+  */
+@@ -725,6 +759,7 @@ enum mvpp2_tag_type {
+ #define MVPP2_PRS_IPV6_EXT_AH_L4_AI_BIT		BIT(4)
+ #define MVPP2_PRS_SINGLE_VLAN_AI		0
+ #define MVPP2_PRS_DBL_VLAN_AI_BIT		BIT(7)
++#define MVPP2_PRS_EDSA_VID_AI_BIT		BIT(0)
+ 
+ /* DSA/EDSA type */
+ #define MVPP2_PRS_TAGGED		true
+@@ -747,6 +782,7 @@ enum mvpp2_prs_lookup {
+ 	MVPP2_PRS_LU_MAC,
+ 	MVPP2_PRS_LU_DSA,
+ 	MVPP2_PRS_LU_VLAN,
++	MVPP2_PRS_LU_VID,
+ 	MVPP2_PRS_LU_L2,
+ 	MVPP2_PRS_LU_PPPOE,
+ 	MVPP2_PRS_LU_IP4,
+@@ -1662,6 +1698,14 @@ static void mvpp2_prs_match_etype(struct mvpp2_prs_entry *pe, int offset,
+ 	mvpp2_prs_tcam_data_byte_set(pe, offset + 1, ethertype & 0xff, 0xff);
+ }
+ 
++/* Set vid in tcam sw entry */
++static void mvpp2_prs_match_vid(struct mvpp2_prs_entry *pe, int offset,
++				unsigned short vid)
++{
++	mvpp2_prs_tcam_data_byte_set(pe, offset + 0, (vid & 0xf00) >> 8, 0xf);
++	mvpp2_prs_tcam_data_byte_set(pe, offset + 1, vid & 0xff, 0xff);
++}
++
+ /* Set bits in sram sw entry */
+ static void mvpp2_prs_sram_bits_set(struct mvpp2_prs_entry *pe, int bit_num,
+ 				    int val)
+@@ -2029,24 +2073,30 @@ static void mvpp2_prs_dsa_tag_set(struct mvpp2 *priv, int port, bool add,
+ 		mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_DSA);
+ 		pe.index = tid;
+ 
+-		/* Shift 4 bytes if DSA tag or 8 bytes in case of EDSA tag*/
+-		mvpp2_prs_sram_shift_set(&pe, shift,
+-					 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+-
+ 		/* Update shadow table */
+ 		mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_DSA);
+ 
+ 		if (tagged) {
+ 			/* Set tagged bit in DSA tag */
+ 			mvpp2_prs_tcam_data_byte_set(&pe, 0,
+-						     MVPP2_PRS_TCAM_DSA_TAGGED_BIT,
+-						     MVPP2_PRS_TCAM_DSA_TAGGED_BIT);
+-			/* Clear all ai bits for next iteration */
+-			mvpp2_prs_sram_ai_update(&pe, 0,
+-						 MVPP2_PRS_SRAM_AI_MASK);
+-			/* If packet is tagged continue check vlans */
+-			mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VLAN);
++					     MVPP2_PRS_TCAM_DSA_TAGGED_BIT,
++					     MVPP2_PRS_TCAM_DSA_TAGGED_BIT);
++
++			/* Set ai bits for next iteration */
++			if (extend)
++				mvpp2_prs_sram_ai_update(&pe, 1,
++							MVPP2_PRS_SRAM_AI_MASK);
++			else
++				mvpp2_prs_sram_ai_update(&pe, 0,
++							MVPP2_PRS_SRAM_AI_MASK);
++
++			/* If packet is tagged continue check vid filtering */
++			mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VID);
+ 		} else {
++			/* Shift 4 bytes for DSA tag or 8 bytes for EDSA tag*/
++			mvpp2_prs_sram_shift_set(&pe, shift,
++					MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
++
+ 			/* Set result info bits to 'no vlans' */
+ 			mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_NONE,
+ 						 MVPP2_PRS_RI_VLAN_MASK);
+@@ -2231,10 +2281,9 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
+ 
+ 		mvpp2_prs_match_etype(pe, 0, tpid);
+ 
+-		mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_L2);
+-		/* Shift 4 bytes - skip 1 vlan tag */
+-		mvpp2_prs_sram_shift_set(pe, MVPP2_VLAN_TAG_LEN,
+-					 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
++		/* VLAN tag detected, proceed with VID filtering */
++		mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_VID);
++
+ 		/* Clear all ai bits for next iteration */
+ 		mvpp2_prs_sram_ai_update(pe, 0, MVPP2_PRS_SRAM_AI_MASK);
+ 
+@@ -2375,8 +2424,8 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
+ 		mvpp2_prs_match_etype(pe, 4, tpid2);
+ 
+ 		mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_VLAN);
+-		/* Shift 8 bytes - skip 2 vlan tags */
+-		mvpp2_prs_sram_shift_set(pe, 2 * MVPP2_VLAN_TAG_LEN,
++		/* Shift 4 bytes - skip outer vlan tag */
++		mvpp2_prs_sram_shift_set(pe, MVPP2_VLAN_TAG_LEN,
+ 					 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+ 		mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_DOUBLE,
+ 					 MVPP2_PRS_RI_VLAN_MASK);
+@@ -2755,6 +2804,62 @@ static void mvpp2_prs_dsa_init(struct mvpp2 *priv)
+ 	mvpp2_prs_hw_write(priv, &pe);
+ }
+ 
++/* Initialize parser entries for VID filtering */
++static void mvpp2_prs_vid_init(struct mvpp2 *priv)
++{
++	struct mvpp2_prs_entry pe;
++
++	memset(&pe, 0, sizeof(pe));
++
++	/* Set default vid entry */
++	pe.index = MVPP2_PE_VID_FLTR_DEFAULT;
++	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VID);
++
++	mvpp2_prs_tcam_ai_update(&pe, 0, MVPP2_PRS_EDSA_VID_AI_BIT);
++
++	/* Skip VLAN header - Set offset to 4 bytes */
++	mvpp2_prs_sram_shift_set(&pe, MVPP2_VLAN_TAG_LEN,
++				 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
++
++	/* Clear all ai bits for next iteration */
++	mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
++
++	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
++
++	/* Unmask all ports */
++	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
++
++	/* Update shadow table and hw entry */
++	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VID);
++	mvpp2_prs_hw_write(priv, &pe);
++
++	/* Set default vid entry for extended DSA*/
++	memset(&pe, 0, sizeof(pe));
++
++	/* Set default vid entry */
++	pe.index = MVPP2_PE_VID_EDSA_FLTR_DEFAULT;
++	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VID);
++
++	mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_EDSA_VID_AI_BIT,
++				 MVPP2_PRS_EDSA_VID_AI_BIT);
++
++	/* Skip VLAN header - Set offset to 8 bytes */
++	mvpp2_prs_sram_shift_set(&pe, MVPP2_VLAN_TAG_EDSA_LEN,
++				 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
++
++	/* Clear all ai bits for next iteration */
++	mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
++
++	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
++
++	/* Unmask all ports */
++	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
++
++	/* Update shadow table and hw entry */
++	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VID);
++	mvpp2_prs_hw_write(priv, &pe);
++}
++
+ /* Match basic ethertypes */
+ static int mvpp2_prs_etype_init(struct mvpp2 *priv)
+ {
+@@ -3023,7 +3128,8 @@ static int mvpp2_prs_vlan_init(struct platform_device *pdev, struct mvpp2 *priv)
+ 	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VLAN);
+ 	pe.index = MVPP2_PE_VLAN_DBL;
+ 
+-	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
++	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VID);
++
+ 	/* Clear ai for next iterations */
+ 	mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
+ 	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_DOUBLE,
+@@ -3386,6 +3492,192 @@ static int mvpp2_prs_ip6_init(struct mvpp2 *priv)
+ 	return 0;
+ }
+ 
++/* Find tcam entry with matched pair <vid,port> */
++static int mvpp2_prs_vid_range_find(struct mvpp2 *priv, int pmap, u16 vid,
++				    u16 mask)
++{
++	unsigned char byte[2], enable[2];
++	struct mvpp2_prs_entry pe;
++	u16 rvid, rmask;
++	int tid;
++
++	/* Go through the all entries with MVPP2_PRS_LU_VID */
++	for (tid = MVPP2_PE_VID_FILT_RANGE_START;
++	     tid <= MVPP2_PE_VID_FILT_RANGE_END; tid++) {
++		if (!priv->prs_shadow[tid].valid ||
++		    priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VID)
++			continue;
++
++		pe.index = tid;
++
++		mvpp2_prs_hw_read(priv, &pe);
++		mvpp2_prs_tcam_data_byte_get(&pe, 2, &byte[0], &enable[0]);
++		mvpp2_prs_tcam_data_byte_get(&pe, 3, &byte[1], &enable[1]);
++
++		rvid = ((byte[0] & 0xf) << 8) + byte[1];
++		rmask = ((enable[0] & 0xf) << 8) + enable[1];
++
++		if (rvid != vid || rmask != mask)
++			continue;
++
++		return tid;
++	}
++
++	return 0;
++}
++
++/* Write parser entry for VID filtering */
++static int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
++{
++	unsigned int vid_start = MVPP2_PE_VID_FILT_RANGE_START +
++				 port->id * MVPP2_PRS_VLAN_FILT_MAX;
++	unsigned int mask = 0xfff, reg_val, shift;
++	struct mvpp2 *priv = port->priv;
++	struct mvpp2_prs_entry pe;
++	int tid;
++
++	/* Scan TCAM and see if entry with this <vid,port> already exist */
++	tid = mvpp2_prs_vid_range_find(priv, (1 << port->id), vid, mask);
++
++	reg_val = mvpp2_read(priv, MVPP2_MH_REG(port->id));
++	if (reg_val & MVPP2_DSA_EXTENDED)
++		shift = MVPP2_VLAN_TAG_EDSA_LEN;
++	else
++		shift = MVPP2_VLAN_TAG_LEN;
++
++	/* No such entry */
++	if (!tid) {
++		memset(&pe, 0, sizeof(pe));
++
++		/* Go through all entries from first to last in vlan range */
++		tid = mvpp2_prs_tcam_first_free(priv, vid_start,
++						vid_start +
++						MVPP2_PRS_VLAN_FILT_MAX_ENTRY);
++
++		/* There isn't room for a new VID filter */
++		if (tid < 0)
++			return tid;
++
++		mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VID);
++		pe.index = tid;
++
++		/* Mask all ports */
++		mvpp2_prs_tcam_port_map_set(&pe, 0);
++	} else {
++		mvpp2_prs_hw_read(priv, &pe);
++	}
++
++	/* Enable the current port */
++	mvpp2_prs_tcam_port_set(&pe, port->id, true);
++
++	/* Continue - set next lookup */
++	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
++
++	/* Skip VLAN header - Set offset to 4 or 8 bytes */
++	mvpp2_prs_sram_shift_set(&pe, shift, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
++
++	/* Set match on VID */
++	mvpp2_prs_match_vid(&pe, MVPP2_PRS_VID_TCAM_BYTE, vid);
++
++	/* Clear all ai bits for next iteration */
++	mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
++
++	/* Update shadow table */
++	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VID);
++	mvpp2_prs_hw_write(priv, &pe);
++
++	return 0;
++}
++
++/* Write parser entry for VID filtering */
++static void mvpp2_prs_vid_entry_remove(struct mvpp2_port *port, u16 vid)
++{
++	struct mvpp2 *priv = port->priv;
++	int tid;
++
++	/* Scan TCAM and see if entry with this <vid,port> already exist */
++	tid = mvpp2_prs_vid_range_find(priv, (1 << port->id), vid, 0xfff);
++
++	/* No such entry */
++	if (tid)
++		return;
++
++	mvpp2_prs_hw_inv(priv, tid);
++	priv->prs_shadow[tid].valid = false;
++}
++
++/* Remove all existing VID filters on this port */
++static void mvpp2_prs_vid_remove_all(struct mvpp2_port *port)
++{
++	struct mvpp2 *priv = port->priv;
++	int tid;
++
++	for (tid = MVPP2_PRS_VID_PORT_FIRST(port->id);
++	     tid <= MVPP2_PRS_VID_PORT_LAST(port->id); tid++) {
++		if (priv->prs_shadow[tid].valid)
++			mvpp2_prs_vid_entry_remove(port, tid);
++	}
++}
++
++/* Remove VID filering entry for this port */
++static void mvpp2_prs_vid_disable_filtering(struct mvpp2_port *port)
++{
++	unsigned int tid = MVPP2_PRS_VID_PORT_DFLT(port->id);
++	struct mvpp2 *priv = port->priv;
++
++	/* Invalidate the guard entry */
++	mvpp2_prs_hw_inv(priv, tid);
++
++	priv->prs_shadow[tid].valid = false;
++}
++
++/* Add guard entry that drops packets when no VID is matched on this port */
++static void mvpp2_prs_vid_enable_filtering(struct mvpp2_port *port)
++{
++	unsigned int tid = MVPP2_PRS_VID_PORT_DFLT(port->id);
++	struct mvpp2 *priv = port->priv;
++	unsigned int reg_val, shift;
++	struct mvpp2_prs_entry pe;
++
++	if (priv->prs_shadow[tid].valid)
++		return;
++
++	memset(&pe, 0, sizeof(pe));
++
++	pe.index = tid;
++
++	reg_val = mvpp2_read(priv, MVPP2_MH_REG(port->id));
++	if (reg_val & MVPP2_DSA_EXTENDED)
++		shift = MVPP2_VLAN_TAG_EDSA_LEN;
++	else
++		shift = MVPP2_VLAN_TAG_LEN;
++
++	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VID);
++
++	/* Mask all ports */
++	mvpp2_prs_tcam_port_map_set(&pe, 0);
++
++	/* Update port mask */
++	mvpp2_prs_tcam_port_set(&pe, port->id, true);
++
++	/* Continue - set next lookup */
++	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
++
++	/* Skip VLAN header - Set offset to 4 or 8 bytes */
++	mvpp2_prs_sram_shift_set(&pe, shift, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
++
++	/* Drop VLAN packets that don't belong to any VIDs on this port */
++	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_DROP_MASK,
++				 MVPP2_PRS_RI_DROP_MASK);
++
++	/* Clear all ai bits for next iteration */
++	mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
++
++	/* Update shadow table */
++	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VID);
++	mvpp2_prs_hw_write(priv, &pe);
++}
++
+ /* Parser default initialization */
+ static int mvpp2_prs_default_init(struct platform_device *pdev,
+ 				  struct mvpp2 *priv)
+@@ -3429,6 +3721,8 @@ static int mvpp2_prs_default_init(struct platform_device *pdev,
+ 
+ 	mvpp2_prs_dsa_init(priv);
+ 
++	mvpp2_prs_vid_init(priv);
++
+ 	err = mvpp2_prs_etype_init(priv);
+ 	if (err)
+ 		return err;
+@@ -7153,6 +7447,12 @@ static void mvpp2_set_rx_mode(struct net_device *dev)
+ 			}
+ 		}
+ 	}
++
++	/* Disable VLAN filtering in promiscuous mode */
++	if (dev->flags & IFF_PROMISC)
++		mvpp2_prs_vid_disable_filtering(port);
++	else
++		mvpp2_prs_vid_enable_filtering(port);
+ }
+ 
+ static int mvpp2_set_mac_address(struct net_device *dev, void *p)
+@@ -7292,6 +7592,48 @@ static int mvpp2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ 	return ret;
+ }
+ 
++static int mvpp2_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
++{
++	struct mvpp2_port *port = netdev_priv(dev);
++	int ret;
++
++	ret = mvpp2_prs_vid_entry_add(port, vid);
++	if (ret)
++		netdev_err(dev, "rx-vlan-filter offloading cannot accept more than %d VIDs per port\n",
++			   MVPP2_PRS_VLAN_FILT_MAX - 1);
++	return ret;
++}
++
++static int mvpp2_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
++{
++	struct mvpp2_port *port = netdev_priv(dev);
++
++	mvpp2_prs_vid_entry_remove(port, vid);
++	return 0;
++}
++
++static int mvpp2_set_features(struct net_device *dev,
++			      netdev_features_t features)
++{
++	netdev_features_t changed = dev->features ^ features;
++	struct mvpp2_port *port = netdev_priv(dev);
++
++	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
++		if (features & NETIF_F_HW_VLAN_CTAG_FILTER) {
++			mvpp2_prs_vid_enable_filtering(port);
++		} else {
++			/* Invalidate all registered VID filters for this
++			 * port
++			 */
++			mvpp2_prs_vid_remove_all(port);
++
++			mvpp2_prs_vid_disable_filtering(port);
++		}
++	}
++
++	return 0;
++}
++
+ /* Ethtool methods */
+ 
+ /* Set interrupt coalescing for ethtools */
+@@ -7433,6 +7775,9 @@ static const struct net_device_ops mvpp2_netdev_ops = {
+ 	.ndo_change_mtu		= mvpp2_change_mtu,
+ 	.ndo_get_stats64	= mvpp2_get_stats64,
+ 	.ndo_do_ioctl		= mvpp2_ioctl,
++	.ndo_vlan_rx_add_vid	= mvpp2_vlan_rx_add_vid,
++	.ndo_vlan_rx_kill_vid	= mvpp2_vlan_rx_kill_vid,
++	.ndo_set_features	= mvpp2_set_features,
+ };
+ 
+ static const struct ethtool_ops mvpp2_eth_tool_ops = {
+@@ -7945,7 +8290,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 
+ 	features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
+ 	dev->features = features | NETIF_F_RXCSUM;
+-	dev->hw_features |= features | NETIF_F_RXCSUM | NETIF_F_GRO;
++	dev->hw_features |= features | NETIF_F_RXCSUM | NETIF_F_GRO |
++			    NETIF_F_HW_VLAN_CTAG_FILTER;
+ 	dev->vlan_features |= features;
+ 	dev->gso_max_segs = MVPP2_MAX_TSO_SEGS;
+ 
+-- 
+2.7.4
+
diff --git a/SOURCES/0030-net-mvpp2-use-the-same-buffer-pool-for-all-ports.patch b/SOURCES/0030-net-mvpp2-use-the-same-buffer-pool-for-all-ports.patch
new file mode 100644
index 0000000..23999ac
--- /dev/null
+++ b/SOURCES/0030-net-mvpp2-use-the-same-buffer-pool-for-all-ports.patch
@@ -0,0 +1,228 @@
+From 448424ade0c3a7fd4d72c6acd6a2c40e44bdfcc2 Mon Sep 17 00:00:00 2001
+From: Stefan Chulski <stefanc@marvell.com>
+Date: Mon, 5 Mar 2018 15:16:50 +0100
+Subject: [PATCH 30/46] net: mvpp2: use the same buffer pool for all ports
+
+This patch configures the buffer manager long pool for all ports part of
+the same CP. Long pool separation between ports is redundant since there
+are no performance improvement when different pools are used.
+
+Signed-off-by: Stefan Chulski <stefanc@marvell.com>
+[Antoine: cosmetic cleanup, commit message]
+Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+
+(cherry picked from commit 01d049366529544f1df44139f5ca225d4c36ec31)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 76 ++++++++++++++++++------------------
+ 1 file changed, 37 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 9418f6ee..d6cce0f 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -808,23 +808,23 @@ enum mvpp2_prs_l3_cast {
+ #define MVPP22_RSS_TABLE_ENTRIES	32
+ 
+ /* BM constants */
+-#define MVPP2_BM_POOLS_NUM		8
+ #define MVPP2_BM_LONG_BUF_NUM		1024
+ #define MVPP2_BM_SHORT_BUF_NUM		2048
+ #define MVPP2_BM_POOL_SIZE_MAX		(16*1024 - MVPP2_BM_POOL_PTR_ALIGN/4)
+ #define MVPP2_BM_POOL_PTR_ALIGN		128
+-#define MVPP2_BM_SWF_LONG_POOL(port)	((port > 2) ? 2 : port)
+-#define MVPP2_BM_SWF_SHORT_POOL		3
+ 
+ /* BM cookie (32 bits) definition */
+ #define MVPP2_BM_COOKIE_POOL_OFFS	8
+ #define MVPP2_BM_COOKIE_CPU_OFFS	24
+ 
++#define MVPP2_BM_SHORT_FRAME_SIZE		512
++#define MVPP2_BM_LONG_FRAME_SIZE		2048
+ /* BM short pool packet size
+  * These value assure that for SWF the total number
+  * of bytes allocated for each buffer will be 512
+  */
+-#define MVPP2_BM_SHORT_PKT_SIZE		MVPP2_RX_MAX_PKT_SIZE(512)
++#define MVPP2_BM_SHORT_PKT_SIZE	MVPP2_RX_MAX_PKT_SIZE(MVPP2_BM_SHORT_FRAME_SIZE)
++#define MVPP2_BM_LONG_PKT_SIZE	MVPP2_RX_MAX_PKT_SIZE(MVPP2_BM_LONG_FRAME_SIZE)
+ 
+ #define MVPP21_ADDR_SPACE_SZ		0
+ #define MVPP22_ADDR_SPACE_SZ		SZ_64K
+@@ -832,12 +832,17 @@ enum mvpp2_prs_l3_cast {
+ #define MVPP2_MAX_THREADS		8
+ #define MVPP2_MAX_QVECS			MVPP2_MAX_THREADS
+ 
+-enum mvpp2_bm_type {
+-	MVPP2_BM_FREE,
+-	MVPP2_BM_SWF_LONG,
+-	MVPP2_BM_SWF_SHORT
++enum mvpp2_bm_pool_log_num {
++	MVPP2_BM_SHORT,
++	MVPP2_BM_LONG,
++	MVPP2_BM_POOLS_NUM
+ };
+ 
++static struct {
++	int pkt_size;
++	int buf_num;
++} mvpp2_pools[MVPP2_BM_POOLS_NUM];
++
+ /* GMAC MIB Counters register definitions */
+ #define MVPP21_MIB_COUNTERS_OFFSET		0x1000
+ #define MVPP21_MIB_COUNTERS_PORT_SZ		0x400
+@@ -1266,7 +1271,6 @@ struct mvpp2_cls_lookup_entry {
+ struct mvpp2_bm_pool {
+ 	/* Pool number in the range 0-7 */
+ 	int id;
+-	enum mvpp2_bm_type type;
+ 
+ 	/* Buffer Pointers Pool External (BPPE) size */
+ 	int size;
+@@ -4195,7 +4199,6 @@ static int mvpp2_bm_pool_create(struct platform_device *pdev,
+ 	val |= MVPP2_BM_START_MASK;
+ 	mvpp2_write(priv, MVPP2_BM_POOL_CTRL_REG(bm_pool->id), val);
+ 
+-	bm_pool->type = MVPP2_BM_FREE;
+ 	bm_pool->size = size;
+ 	bm_pool->pkt_size = 0;
+ 	bm_pool->buf_num = 0;
+@@ -4345,6 +4348,17 @@ static int mvpp2_bm_init(struct platform_device *pdev, struct mvpp2 *priv)
+ 	return 0;
+ }
+ 
++static void mvpp2_setup_bm_pool(void)
++{
++	/* Short pool */
++	mvpp2_pools[MVPP2_BM_SHORT].buf_num  = MVPP2_BM_SHORT_BUF_NUM;
++	mvpp2_pools[MVPP2_BM_SHORT].pkt_size = MVPP2_BM_SHORT_PKT_SIZE;
++
++	/* Long pool */
++	mvpp2_pools[MVPP2_BM_LONG].buf_num  = MVPP2_BM_LONG_BUF_NUM;
++	mvpp2_pools[MVPP2_BM_LONG].pkt_size = MVPP2_BM_LONG_PKT_SIZE;
++}
++
+ /* Attach long pool to rxq */
+ static void mvpp2_rxq_long_pool_set(struct mvpp2_port *port,
+ 				    int lrxq, int long_pool)
+@@ -4483,13 +4497,11 @@ static int mvpp2_bm_bufs_add(struct mvpp2_port *port,
+ 	bm_pool->buf_num += i;
+ 
+ 	netdev_dbg(port->dev,
+-		   "%s pool %d: pkt_size=%4d, buf_size=%4d, total_size=%4d\n",
+-		   bm_pool->type == MVPP2_BM_SWF_SHORT ? "short" : " long",
++		   "pool %d: pkt_size=%4d, buf_size=%4d, total_size=%4d\n",
+ 		   bm_pool->id, bm_pool->pkt_size, buf_size, total_size);
+ 
+ 	netdev_dbg(port->dev,
+-		   "%s pool %d: %d of %d buffers added\n",
+-		   bm_pool->type == MVPP2_BM_SWF_SHORT ? "short" : " long",
++		   "pool %d: %d of %d buffers added\n",
+ 		   bm_pool->id, i, buf_num);
+ 	return i;
+ }
+@@ -4498,25 +4510,20 @@ static int mvpp2_bm_bufs_add(struct mvpp2_port *port,
+  * pool pointer on success
+  */
+ static struct mvpp2_bm_pool *
+-mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum mvpp2_bm_type type,
+-		  int pkt_size)
++mvpp2_bm_pool_use(struct mvpp2_port *port, unsigned pool, int pkt_size)
+ {
+ 	struct mvpp2_bm_pool *new_pool = &port->priv->bm_pools[pool];
+ 	int num;
+ 
+-	if (new_pool->type != MVPP2_BM_FREE && new_pool->type != type) {
+-		netdev_err(port->dev, "mixing pool types is forbidden\n");
++	if (pool >= MVPP2_BM_POOLS_NUM) {
++		netdev_err(port->dev, "Invalid pool %d\n", pool);
+ 		return NULL;
+ 	}
+ 
+-	if (new_pool->type == MVPP2_BM_FREE)
+-		new_pool->type = type;
+-
+ 	/* Allocate buffers in case BM pool is used as long pool, but packet
+ 	 * size doesn't match MTU or BM pool hasn't being used yet
+ 	 */
+-	if (((type == MVPP2_BM_SWF_LONG) && (pkt_size > new_pool->pkt_size)) ||
+-	    (new_pool->pkt_size == 0)) {
++	if (new_pool->pkt_size == 0) {
+ 		int pkts_num;
+ 
+ 		/* Set default buffer number or free all the buffers in case
+@@ -4524,9 +4531,7 @@ mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum mvpp2_bm_type type,
+ 		 */
+ 		pkts_num = new_pool->buf_num;
+ 		if (pkts_num == 0)
+-			pkts_num = type == MVPP2_BM_SWF_LONG ?
+-				   MVPP2_BM_LONG_BUF_NUM :
+-				   MVPP2_BM_SHORT_BUF_NUM;
++			pkts_num = mvpp2_pools[pool].buf_num;
+ 		else
+ 			mvpp2_bm_bufs_free(port->dev->dev.parent,
+ 					   port->priv, new_pool);
+@@ -4558,9 +4563,8 @@ static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
+ 
+ 	if (!port->pool_long) {
+ 		port->pool_long =
+-		       mvpp2_bm_pool_use(port, MVPP2_BM_SWF_LONG_POOL(port->id),
+-					 MVPP2_BM_SWF_LONG,
+-					 port->pkt_size);
++			mvpp2_bm_pool_use(port, MVPP2_BM_LONG,
++					  mvpp2_pools[MVPP2_BM_LONG].pkt_size);
+ 		if (!port->pool_long)
+ 			return -ENOMEM;
+ 
+@@ -4572,9 +4576,8 @@ static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
+ 
+ 	if (!port->pool_short) {
+ 		port->pool_short =
+-			mvpp2_bm_pool_use(port, MVPP2_BM_SWF_SHORT_POOL,
+-					  MVPP2_BM_SWF_SHORT,
+-					  MVPP2_BM_SHORT_PKT_SIZE);
++			mvpp2_bm_pool_use(port, MVPP2_BM_SHORT,
++					  mvpp2_pools[MVPP2_BM_SHORT].pkt_size);
+ 		if (!port->pool_short)
+ 			return -ENOMEM;
+ 
+@@ -4593,7 +4596,6 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
+ 	struct mvpp2_port *port = netdev_priv(dev);
+ 	struct mvpp2_bm_pool *port_pool = port->pool_long;
+ 	int num, pkts_num = port_pool->buf_num;
+-	int pkt_size = MVPP2_RX_PKT_SIZE(mtu);
+ 
+ 	/* Update BM pool with new buffer size */
+ 	mvpp2_bm_bufs_free(dev->dev.parent, port->priv, port_pool);
+@@ -4602,18 +4604,12 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
+ 		return -EIO;
+ 	}
+ 
+-	port_pool->pkt_size = pkt_size;
+-	port_pool->frag_size = SKB_DATA_ALIGN(MVPP2_RX_BUF_SIZE(pkt_size)) +
+-		MVPP2_SKB_SHINFO_SIZE;
+ 	num = mvpp2_bm_bufs_add(port, port_pool, pkts_num);
+ 	if (num != pkts_num) {
+ 		WARN(1, "pool %d: %d of %d allocated\n",
+ 		     port_pool->id, num, pkts_num);
+ 		return -EIO;
+ 	}
+-
+-	mvpp2_bm_pool_bufsize_set(port->priv, port_pool,
+-				  MVPP2_RX_BUF_SIZE(port_pool->pkt_size));
+ 	dev->mtu = mtu;
+ 	netdev_update_features(dev);
+ 	return 0;
+@@ -8630,6 +8626,8 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 			priv->sysctrl_base = NULL;
+ 	}
+ 
++	mvpp2_setup_bm_pool();
++
+ 	for (i = 0; i < MVPP2_MAX_THREADS; i++) {
+ 		u32 addr_space_sz;
+ 
+-- 
+2.7.4
+
diff --git a/SOURCES/0031-net-mvpp2-update-the-BM-buffer-free-destroy-logic.patch b/SOURCES/0031-net-mvpp2-update-the-BM-buffer-free-destroy-logic.patch
new file mode 100644
index 0000000..8874171
--- /dev/null
+++ b/SOURCES/0031-net-mvpp2-update-the-BM-buffer-free-destroy-logic.patch
@@ -0,0 +1,118 @@
+From 3c8018ee16773da23db291dfc969dc3de31a8db0 Mon Sep 17 00:00:00 2001
+From: Stefan Chulski <stefanc@marvell.com>
+Date: Mon, 5 Mar 2018 15:16:51 +0100
+Subject: [PATCH 31/46] net: mvpp2: update the BM buffer free/destroy logic
+
+The buffer free routine is updated to release only given a number of
+buffers, and the destroy routine now checks the actual number of buffers
+in the (BPPI and BPPE) HW counters before draining the pools. This
+change helps getting jumbo frames support.
+
+Signed-off-by: Stefan Chulski <stefanc@marvell.com>
+[Antoine: cosmetic cleanup, commit message]
+Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+
+(cherry picked from commit effbf5f58d64b1d1f93cb687d9797b42f291d5fd)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 45 ++++++++++++++++++++++++++++++------
+ 1 file changed, 38 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index d6cce0f..c7b8093 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -258,6 +258,7 @@
+ #define MVPP2_BM_BPPI_READ_PTR_REG(pool)	(0x6100 + ((pool) * 4))
+ #define MVPP2_BM_BPPI_PTRS_NUM_REG(pool)	(0x6140 + ((pool) * 4))
+ #define     MVPP2_BM_BPPI_PTR_NUM_MASK		0x7ff
++#define MVPP22_BM_POOL_PTRS_NUM_MASK		0xfff8
+ #define     MVPP2_BM_BPPI_PREFETCH_FULL_MASK	BIT(16)
+ #define MVPP2_BM_POOL_CTRL_REG(pool)		(0x6200 + ((pool) * 4))
+ #define     MVPP2_BM_START_MASK			BIT(0)
+@@ -4251,11 +4252,17 @@ static void mvpp2_bm_bufs_get_addrs(struct device *dev, struct mvpp2 *priv,
+ 
+ /* Free all buffers from the pool */
+ static void mvpp2_bm_bufs_free(struct device *dev, struct mvpp2 *priv,
+-			       struct mvpp2_bm_pool *bm_pool)
++			       struct mvpp2_bm_pool *bm_pool, int buf_num)
+ {
+ 	int i;
+ 
+-	for (i = 0; i < bm_pool->buf_num; i++) {
++	if (buf_num > bm_pool->buf_num) {
++		WARN(1, "Pool does not have so many bufs pool(%d) bufs(%d)\n",
++		     bm_pool->id, buf_num);
++		buf_num = bm_pool->buf_num;
++	}
++
++	for (i = 0; i < buf_num; i++) {
+ 		dma_addr_t buf_dma_addr;
+ 		phys_addr_t buf_phys_addr;
+ 		void *data;
+@@ -4277,16 +4284,39 @@ static void mvpp2_bm_bufs_free(struct device *dev, struct mvpp2 *priv,
+ 	bm_pool->buf_num -= i;
+ }
+ 
++/* Check number of buffers in BM pool */
++int mvpp2_check_hw_buf_num(struct mvpp2 *priv, struct mvpp2_bm_pool *bm_pool)
++{
++	int buf_num = 0;
++
++	buf_num += mvpp2_read(priv, MVPP2_BM_POOL_PTRS_NUM_REG(bm_pool->id)) &
++				    MVPP22_BM_POOL_PTRS_NUM_MASK;
++	buf_num += mvpp2_read(priv, MVPP2_BM_BPPI_PTRS_NUM_REG(bm_pool->id)) &
++				    MVPP2_BM_BPPI_PTR_NUM_MASK;
++
++	/* HW has one buffer ready which is not reflected in the counters */
++	if (buf_num)
++		buf_num += 1;
++
++	return buf_num;
++}
++
+ /* Cleanup pool */
+ static int mvpp2_bm_pool_destroy(struct platform_device *pdev,
+ 				 struct mvpp2 *priv,
+ 				 struct mvpp2_bm_pool *bm_pool)
+ {
++	int buf_num;
+ 	u32 val;
+ 
+-	mvpp2_bm_bufs_free(&pdev->dev, priv, bm_pool);
+-	if (bm_pool->buf_num) {
+-		WARN(1, "cannot free all buffers in pool %d\n", bm_pool->id);
++	buf_num = mvpp2_check_hw_buf_num(priv, bm_pool);
++	mvpp2_bm_bufs_free(&pdev->dev, priv, bm_pool, buf_num);
++
++	/* Check buffer counters after free */
++	buf_num = mvpp2_check_hw_buf_num(priv, bm_pool);
++	if (buf_num) {
++		WARN(1, "cannot free all buffers in pool %d, buf_num left %d\n",
++		     bm_pool->id, bm_pool->buf_num);
+ 		return 0;
+ 	}
+ 
+@@ -4534,7 +4564,7 @@ mvpp2_bm_pool_use(struct mvpp2_port *port, unsigned pool, int pkt_size)
+ 			pkts_num = mvpp2_pools[pool].buf_num;
+ 		else
+ 			mvpp2_bm_bufs_free(port->dev->dev.parent,
+-					   port->priv, new_pool);
++					   port->priv, new_pool, pkts_num);
+ 
+ 		new_pool->pkt_size = pkt_size;
+ 		new_pool->frag_size =
+@@ -4598,7 +4628,8 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
+ 	int num, pkts_num = port_pool->buf_num;
+ 
+ 	/* Update BM pool with new buffer size */
+-	mvpp2_bm_bufs_free(dev->dev.parent, port->priv, port_pool);
++	mvpp2_bm_bufs_free(dev->dev.parent, port->priv, port_pool,
++			   port_pool->buf_num);
+ 	if (port_pool->buf_num) {
+ 		WARN(1, "cannot free all buffers in pool %d\n", port_pool->id);
+ 		return -EIO;
+-- 
+2.7.4
+
diff --git a/SOURCES/0032-net-mvpp2-use-a-data-size-of-10kB-for-Tx-FIFO-on-por.patch b/SOURCES/0032-net-mvpp2-use-a-data-size-of-10kB-for-Tx-FIFO-on-por.patch
new file mode 100644
index 0000000..179516a
--- /dev/null
+++ b/SOURCES/0032-net-mvpp2-use-a-data-size-of-10kB-for-Tx-FIFO-on-por.patch
@@ -0,0 +1,80 @@
+From 8640f0bae756590eefc23c8987465ad1f843d02c Mon Sep 17 00:00:00 2001
+From: Yan Markman <ymarkman@marvell.com>
+Date: Mon, 5 Mar 2018 15:16:52 +0100
+Subject: [PATCH 32/46] net: mvpp2: use a data size of 10kB for Tx FIFO on port
+ 0
+
+This patch sets the Tx FIFO data size on port 0 to 10kB. This prepares
+the PPv2 driver for the Jumbo frame support addition as the hardware
+will need big enough Tx FIFO buffers when dealing with frames going
+through an interface with an MTU of 9000.
+
+Signed-off-by: Yan Markman <ymarkman@marvell.com>
+[Antoine: commit message, small reworks.]
+Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+
+(cherry picked from commit 93ff130f1c2bae00c0378f065e441e988b0cd1e7)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 27 ++++++++++++++++++++++-----
+ 1 file changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index c7b8093..c37d2be 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -44,6 +44,7 @@
+ #define MVPP2_RX_ATTR_FIFO_SIZE_REG(port)	(0x20 + 4 * (port))
+ #define MVPP2_RX_MIN_PKT_SIZE_REG		0x60
+ #define MVPP2_RX_FIFO_INIT_REG			0x64
++#define MVPP22_TX_FIFO_THRESH_REG(port)		(0x8840 + 4 * (port))
+ #define MVPP22_TX_FIFO_SIZE_REG(port)		(0x8860 + 4 * (port))
+ 
+ /* RX DMA Top Registers */
+@@ -542,6 +543,11 @@
+ /* TX FIFO constants */
+ #define MVPP22_TX_FIFO_DATA_SIZE_10KB		0xa
+ #define MVPP22_TX_FIFO_DATA_SIZE_3KB		0x3
++#define MVPP2_TX_FIFO_THRESHOLD_MIN		256
++#define MVPP2_TX_FIFO_THRESHOLD_10KB	\
++	(MVPP22_TX_FIFO_DATA_SIZE_10KB * 1024 - MVPP2_TX_FIFO_THRESHOLD_MIN)
++#define MVPP2_TX_FIFO_THRESHOLD_3KB	\
++	(MVPP22_TX_FIFO_DATA_SIZE_3KB * 1024 - MVPP2_TX_FIFO_THRESHOLD_MIN)
+ 
+ /* RX buffer constants */
+ #define MVPP2_SKB_SHINFO_SIZE \
+@@ -8456,14 +8462,25 @@ static void mvpp22_rx_fifo_init(struct mvpp2 *priv)
+ 	mvpp2_write(priv, MVPP2_RX_FIFO_INIT_REG, 0x1);
+ }
+ 
+-/* Initialize Tx FIFO's */
++/* Initialize Tx FIFO's: the total FIFO size is 19kB on PPv2.2 and 10G
++ * interfaces must have a Tx FIFO size of 10kB. As only port 0 can do 10G,
++ * configure its Tx FIFO size to 10kB and the others ports Tx FIFO size to 3kB.
++ */
+ static void mvpp22_tx_fifo_init(struct mvpp2 *priv)
+ {
+-	int port;
++	int port, size, thrs;
+ 
+-	for (port = 0; port < MVPP2_MAX_PORTS; port++)
+-		mvpp2_write(priv, MVPP22_TX_FIFO_SIZE_REG(port),
+-			    MVPP22_TX_FIFO_DATA_SIZE_3KB);
++	for (port = 0; port < MVPP2_MAX_PORTS; port++) {
++		if (port == 0) {
++			size = MVPP22_TX_FIFO_DATA_SIZE_10KB;
++			thrs = MVPP2_TX_FIFO_THRESHOLD_10KB;
++		} else {
++			size = MVPP22_TX_FIFO_DATA_SIZE_3KB;
++			thrs = MVPP2_TX_FIFO_THRESHOLD_3KB;
++		}
++		mvpp2_write(priv, MVPP22_TX_FIFO_SIZE_REG(port), size);
++		mvpp2_write(priv, MVPP22_TX_FIFO_THRESH_REG(port), thrs);
++	}
+ }
+ 
+ static void mvpp2_axi_init(struct mvpp2 *priv)
+-- 
+2.7.4
+
diff --git a/SOURCES/0033-net-mvpp2-enable-UDP-TCP-checksum-over-IPv6.patch b/SOURCES/0033-net-mvpp2-enable-UDP-TCP-checksum-over-IPv6.patch
new file mode 100644
index 0000000..c9f0847
--- /dev/null
+++ b/SOURCES/0033-net-mvpp2-enable-UDP-TCP-checksum-over-IPv6.patch
@@ -0,0 +1,35 @@
+From 703db3f458f22893c3af350a1d2873182d19eb88 Mon Sep 17 00:00:00 2001
+From: Antoine Tenart <antoine.tenart@bootlin.com>
+Date: Mon, 5 Mar 2018 15:16:53 +0100
+Subject: [PATCH 33/46] net: mvpp2: enable UDP/TCP checksum over IPv6
+
+This patch adds the NETIF_F_IPV6_CSUM to the driver's features to enable
+UDP/TCP checksum over IPv6. No extra configuration of the engine is
+needed on top of the IPv4 counterpart, which already is in the features
+list (NETIF_F_IP_CSUM).
+
+Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 381c56712db43af1112a21cce6bdc37281890cdb)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index c37d2be..ede4f6a 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -8321,7 +8321,8 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 		}
+ 	}
+ 
+-	features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
++	features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
++		   NETIF_F_TSO;
+ 	dev->features = features | NETIF_F_RXCSUM;
+ 	dev->hw_features |= features | NETIF_F_RXCSUM | NETIF_F_GRO |
+ 			    NETIF_F_HW_VLAN_CTAG_FILTER;
+-- 
+2.7.4
+
diff --git a/SOURCES/0034-net-mvpp2-jumbo-frames-support.patch b/SOURCES/0034-net-mvpp2-jumbo-frames-support.patch
new file mode 100644
index 0000000..4992071
--- /dev/null
+++ b/SOURCES/0034-net-mvpp2-jumbo-frames-support.patch
@@ -0,0 +1,206 @@
+From 2ae42f92867be7d4c88666d56892a1fee14ef1cd Mon Sep 17 00:00:00 2001
+From: Stefan Chulski <stefanc@marvell.com>
+Date: Mon, 5 Mar 2018 15:16:54 +0100
+Subject: [PATCH 34/46] net: mvpp2: jumbo frames support
+
+This patch adds the support for jumbo frames in the Marvell PPv2 driver.
+A third buffer pool is added with 10KB buffers, which is used if the MTU
+is higher than 1518B for packets larger than 1518B. Please note only the
+port 0 supports hardware checksum offload due to the Tx FIFO size
+limitation.
+
+Signed-off-by: Stefan Chulski <stefanc@marvell.com>
+[Antoine: cosmetic cleanup, commit message]
+Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+
+(cherry picked from commit 576193f2d57904cb78454d7b73eecfcac74fdf22)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 98 +++++++++++++++++++++++++++---------
+ 1 file changed, 75 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index ede4f6a..ac0a0dc 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -815,6 +815,7 @@ enum mvpp2_prs_l3_cast {
+ #define MVPP22_RSS_TABLE_ENTRIES	32
+ 
+ /* BM constants */
++#define MVPP2_BM_JUMBO_BUF_NUM		512
+ #define MVPP2_BM_LONG_BUF_NUM		1024
+ #define MVPP2_BM_SHORT_BUF_NUM		2048
+ #define MVPP2_BM_POOL_SIZE_MAX		(16*1024 - MVPP2_BM_POOL_PTR_ALIGN/4)
+@@ -826,12 +827,14 @@ enum mvpp2_prs_l3_cast {
+ 
+ #define MVPP2_BM_SHORT_FRAME_SIZE		512
+ #define MVPP2_BM_LONG_FRAME_SIZE		2048
++#define MVPP2_BM_JUMBO_FRAME_SIZE		10240
+ /* BM short pool packet size
+  * These value assure that for SWF the total number
+  * of bytes allocated for each buffer will be 512
+  */
+ #define MVPP2_BM_SHORT_PKT_SIZE	MVPP2_RX_MAX_PKT_SIZE(MVPP2_BM_SHORT_FRAME_SIZE)
+ #define MVPP2_BM_LONG_PKT_SIZE	MVPP2_RX_MAX_PKT_SIZE(MVPP2_BM_LONG_FRAME_SIZE)
++#define MVPP2_BM_JUMBO_PKT_SIZE	MVPP2_RX_MAX_PKT_SIZE(MVPP2_BM_JUMBO_FRAME_SIZE)
+ 
+ #define MVPP21_ADDR_SPACE_SZ		0
+ #define MVPP22_ADDR_SPACE_SZ		SZ_64K
+@@ -842,6 +845,7 @@ enum mvpp2_prs_l3_cast {
+ enum mvpp2_bm_pool_log_num {
+ 	MVPP2_BM_SHORT,
+ 	MVPP2_BM_LONG,
++	MVPP2_BM_JUMBO,
+ 	MVPP2_BM_POOLS_NUM
+ };
+ 
+@@ -4393,6 +4397,10 @@ static void mvpp2_setup_bm_pool(void)
+ 	/* Long pool */
+ 	mvpp2_pools[MVPP2_BM_LONG].buf_num  = MVPP2_BM_LONG_BUF_NUM;
+ 	mvpp2_pools[MVPP2_BM_LONG].pkt_size = MVPP2_BM_LONG_PKT_SIZE;
++
++	/* Jumbo pool */
++	mvpp2_pools[MVPP2_BM_JUMBO].buf_num  = MVPP2_BM_JUMBO_BUF_NUM;
++	mvpp2_pools[MVPP2_BM_JUMBO].pkt_size = MVPP2_BM_JUMBO_PKT_SIZE;
+ }
+ 
+ /* Attach long pool to rxq */
+@@ -4596,15 +4604,28 @@ mvpp2_bm_pool_use(struct mvpp2_port *port, unsigned pool, int pkt_size)
+ static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
+ {
+ 	int rxq;
++	enum mvpp2_bm_pool_log_num long_log_pool, short_log_pool;
++
++	/* If port pkt_size is higher than 1518B:
++	 * HW Long pool - SW Jumbo pool, HW Short pool - SW Long pool
++	 * else: HW Long pool - SW Long pool, HW Short pool - SW Short pool
++	 */
++	if (port->pkt_size > MVPP2_BM_LONG_PKT_SIZE) {
++		long_log_pool = MVPP2_BM_JUMBO;
++		short_log_pool = MVPP2_BM_LONG;
++	} else {
++		long_log_pool = MVPP2_BM_LONG;
++		short_log_pool = MVPP2_BM_SHORT;
++	}
+ 
+ 	if (!port->pool_long) {
+ 		port->pool_long =
+-			mvpp2_bm_pool_use(port, MVPP2_BM_LONG,
+-					  mvpp2_pools[MVPP2_BM_LONG].pkt_size);
++			mvpp2_bm_pool_use(port, long_log_pool,
++					  mvpp2_pools[long_log_pool].pkt_size);
+ 		if (!port->pool_long)
+ 			return -ENOMEM;
+ 
+-		port->pool_long->port_map |= (1 << port->id);
++		port->pool_long->port_map |= BIT(port->id);
+ 
+ 		for (rxq = 0; rxq < port->nrxqs; rxq++)
+ 			mvpp2_rxq_long_pool_set(port, rxq, port->pool_long->id);
+@@ -4612,12 +4633,12 @@ static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
+ 
+ 	if (!port->pool_short) {
+ 		port->pool_short =
+-			mvpp2_bm_pool_use(port, MVPP2_BM_SHORT,
+-					  mvpp2_pools[MVPP2_BM_SHORT].pkt_size);
++			mvpp2_bm_pool_use(port, short_log_pool,
++					  mvpp2_pools[long_log_pool].pkt_size);
+ 		if (!port->pool_short)
+ 			return -ENOMEM;
+ 
+-		port->pool_short->port_map |= (1 << port->id);
++		port->pool_short->port_map |= BIT(port->id);
+ 
+ 		for (rxq = 0; rxq < port->nrxqs; rxq++)
+ 			mvpp2_rxq_short_pool_set(port, rxq,
+@@ -4630,24 +4651,49 @@ static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
+ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
+ {
+ 	struct mvpp2_port *port = netdev_priv(dev);
+-	struct mvpp2_bm_pool *port_pool = port->pool_long;
+-	int num, pkts_num = port_pool->buf_num;
++	enum mvpp2_bm_pool_log_num new_long_pool;
++	int pkt_size = MVPP2_RX_PKT_SIZE(mtu);
+ 
+-	/* Update BM pool with new buffer size */
+-	mvpp2_bm_bufs_free(dev->dev.parent, port->priv, port_pool,
+-			   port_pool->buf_num);
+-	if (port_pool->buf_num) {
+-		WARN(1, "cannot free all buffers in pool %d\n", port_pool->id);
+-		return -EIO;
++	/* If port MTU is higher than 1518B:
++	 * HW Long pool - SW Jumbo pool, HW Short pool - SW Long pool
++	 * else: HW Long pool - SW Long pool, HW Short pool - SW Short pool
++	 */
++	if (pkt_size > MVPP2_BM_LONG_PKT_SIZE)
++		new_long_pool = MVPP2_BM_JUMBO;
++	else
++		new_long_pool = MVPP2_BM_LONG;
++
++	if (new_long_pool != port->pool_long->id) {
++		/* Remove port from old short & long pool */
++		port->pool_long = mvpp2_bm_pool_use(port, port->pool_long->id,
++						    port->pool_long->pkt_size);
++		port->pool_long->port_map &= ~BIT(port->id);
++		port->pool_long = NULL;
++
++		port->pool_short = mvpp2_bm_pool_use(port, port->pool_short->id,
++						     port->pool_short->pkt_size);
++		port->pool_short->port_map &= ~BIT(port->id);
++		port->pool_short = NULL;
++
++		port->pkt_size =  pkt_size;
++
++		/* Add port to new short & long pool */
++		mvpp2_swf_bm_pool_init(port);
++
++		/* Update L4 checksum when jumbo enable/disable on port */
++		if (new_long_pool == MVPP2_BM_JUMBO && port->id != 0) {
++			dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
++			dev->hw_features &= ~(NETIF_F_IP_CSUM |
++					      NETIF_F_IPV6_CSUM);
++		} else {
++			dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
++			dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
++		}
+ 	}
+ 
+-	num = mvpp2_bm_bufs_add(port, port_pool, pkts_num);
+-	if (num != pkts_num) {
+-		WARN(1, "pool %d: %d of %d allocated\n",
+-		     port_pool->id, num, pkts_num);
+-		return -EIO;
+-	}
+ 	dev->mtu = mtu;
++	dev->wanted_features = dev->features;
++
+ 	netdev_update_features(dev);
+ 	return 0;
+ }
+@@ -8326,13 +8372,19 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 	dev->features = features | NETIF_F_RXCSUM;
+ 	dev->hw_features |= features | NETIF_F_RXCSUM | NETIF_F_GRO |
+ 			    NETIF_F_HW_VLAN_CTAG_FILTER;
++
++	if (port->pool_long->id == MVPP2_BM_JUMBO && port->id != 0) {
++		dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
++		dev->hw_features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
++	}
++
+ 	dev->vlan_features |= features;
+ 	dev->gso_max_segs = MVPP2_MAX_TSO_SEGS;
+ 
+-	/* MTU range: 68 - 9676 */
++	/* MTU range: 68 - 9704 */
+ 	dev->min_mtu = ETH_MIN_MTU;
+-	/* 9676 == 9700 - 20 and rounding to 8 */
+-	dev->max_mtu = 9676;
++	/* 9704 == 9728 - 20 and rounding to 8 */
++	dev->max_mtu = MVPP2_BM_JUMBO_PKT_SIZE;
+ 
+ 	err = register_netdev(dev);
+ 	if (err < 0) {
+-- 
+2.7.4
+
diff --git a/SOURCES/0035-net-mvpp2-mvpp2_check_hw_buf_num-can-be-static.patch b/SOURCES/0035-net-mvpp2-mvpp2_check_hw_buf_num-can-be-static.patch
new file mode 100644
index 0000000..a8e4b06
--- /dev/null
+++ b/SOURCES/0035-net-mvpp2-mvpp2_check_hw_buf_num-can-be-static.patch
@@ -0,0 +1,30 @@
+From 10f692ff0730de2f3cb2f46e436685313a3bfed5 Mon Sep 17 00:00:00 2001
+From: kbuild test robot <fengguang.wu@intel.com>
+Date: Tue, 6 Mar 2018 13:05:06 +0800
+Subject: [PATCH 35/46] net: mvpp2: mvpp2_check_hw_buf_num() can be static
+
+Fixes: effbf5f58d64 ("net: mvpp2: update the BM buffer free/destroy logic")
+Signed-off-by: Fengguang Wu <fengguang.wu@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 6e61e10a8a9655424cf03c0fb44d282b40f402a2)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index ac0a0dc..338c94d 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -4295,7 +4295,7 @@ static void mvpp2_bm_bufs_free(struct device *dev, struct mvpp2 *priv,
+ }
+ 
+ /* Check number of buffers in BM pool */
+-int mvpp2_check_hw_buf_num(struct mvpp2 *priv, struct mvpp2_bm_pool *bm_pool)
++static int mvpp2_check_hw_buf_num(struct mvpp2 *priv, struct mvpp2_bm_pool *bm_pool)
+ {
+ 	int buf_num = 0;
+ 
+-- 
+2.7.4
+
diff --git a/SOURCES/0036-net-mvpp2-Simplify-MAC-filtering-function-parameters.patch b/SOURCES/0036-net-mvpp2-Simplify-MAC-filtering-function-parameters.patch
new file mode 100644
index 0000000..373a00e
--- /dev/null
+++ b/SOURCES/0036-net-mvpp2-Simplify-MAC-filtering-function-parameters.patch
@@ -0,0 +1,115 @@
+From 4351d1b0b3bd5ee74e3eee44c22459b95e32222d Mon Sep 17 00:00:00 2001
+From: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Date: Wed, 7 Mar 2018 15:18:03 +0100
+Subject: [PATCH 36/46] net: mvpp2: Simplify MAC filtering function parameters
+
+The mvpp2_prs_mac_da_accept function takes into parameter both the
+struct representing the controller and the port id. This is meaningful
+when we want to create TCAM entries for non-initialized ports, but in
+this case we expect the port to be initialized before starting adding or
+removing MAC addresses to the per-port filter.
+
+This commit changes the function so that it takes struct mvpp2_port as
+a parameter instead.
+
+Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit ce2a27c761acaba032f61f8322ff9447fd084671)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 30 +++++++++++++++---------------
+ 1 file changed, 15 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 338c94d..8796456 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -3817,16 +3817,17 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
+ }
+ 
+ /* Update parser's mac da entry */
+-static int mvpp2_prs_mac_da_accept(struct mvpp2 *priv, int port,
+-				   const u8 *da, bool add)
++static int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da,
++				   bool add)
+ {
+-	struct mvpp2_prs_entry *pe;
+-	unsigned int pmap, len, ri;
+ 	unsigned char mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
++	struct mvpp2 *priv = port->priv;
++	unsigned int pmap, len, ri;
++	struct mvpp2_prs_entry *pe;
+ 	int tid;
+ 
+ 	/* Scan TCAM and see if entry with this <MAC DA, port> already exist */
+-	pe = mvpp2_prs_mac_da_range_find(priv, (1 << port), da, mask,
++	pe = mvpp2_prs_mac_da_range_find(priv, BIT(port->id), da, mask,
+ 					 MVPP2_PRS_UDF_MAC_DEF);
+ 
+ 	/* No such entry */
+@@ -3861,7 +3862,7 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2 *priv, int port,
+ 	}
+ 
+ 	/* Update port mask */
+-	mvpp2_prs_tcam_port_set(pe, port, add);
++	mvpp2_prs_tcam_port_set(pe, port->id, add);
+ 
+ 	/* Invalidate the entry if no ports are left enabled */
+ 	pmap = mvpp2_prs_tcam_port_map_get(pe);
+@@ -3917,13 +3918,12 @@ static int mvpp2_prs_update_mac_da(struct net_device *dev, const u8 *da)
+ 	int err;
+ 
+ 	/* Remove old parser entry */
+-	err = mvpp2_prs_mac_da_accept(port->priv, port->id, dev->dev_addr,
+-				      false);
++	err = mvpp2_prs_mac_da_accept(port, dev->dev_addr, false);
+ 	if (err)
+ 		return err;
+ 
+ 	/* Add new parser entry */
+-	err = mvpp2_prs_mac_da_accept(port->priv, port->id, da, true);
++	err = mvpp2_prs_mac_da_accept(port, da, true);
+ 	if (err)
+ 		return err;
+ 
+@@ -3959,7 +3959,8 @@ static void mvpp2_prs_mcast_del_all(struct mvpp2 *priv, int port)
+ 
+ 		if (is_multicast_ether_addr(da) && !is_broadcast_ether_addr(da))
+ 			/* Delete this entry */
+-			mvpp2_prs_mac_da_accept(priv, port, da, false);
++			mvpp2_prs_mac_da_accept(priv->port_list[port], da,
++						false);
+ 	}
+ }
+ 
+@@ -7380,15 +7381,14 @@ static int mvpp2_open(struct net_device *dev)
+ 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ 	int err;
+ 
+-	err = mvpp2_prs_mac_da_accept(port->priv, port->id, mac_bcast, true);
++	err = mvpp2_prs_mac_da_accept(port, mac_bcast, true);
+ 	if (err) {
+ 		netdev_err(dev, "mvpp2_prs_mac_da_accept BC failed\n");
+ 		return err;
+ 	}
+-	err = mvpp2_prs_mac_da_accept(port->priv, port->id,
+-				      dev->dev_addr, true);
++	err = mvpp2_prs_mac_da_accept(port, dev->dev_addr, true);
+ 	if (err) {
+-		netdev_err(dev, "mvpp2_prs_mac_da_accept MC failed\n");
++		netdev_err(dev, "mvpp2_prs_mac_da_accept own addr failed\n");
+ 		return err;
+ 	}
+ 	err = mvpp2_prs_tag_mode_set(port->priv, port->id, MVPP2_TAG_TYPE_MH);
+@@ -7520,7 +7520,7 @@ static void mvpp2_set_rx_mode(struct net_device *dev)
+ 
+ 	if (!allmulti) {
+ 		netdev_for_each_mc_addr(ha, dev) {
+-			if (mvpp2_prs_mac_da_accept(priv, id, ha->addr, true)) {
++			if (mvpp2_prs_mac_da_accept(port, ha->addr, true)) {
+ 				allmulti = true;
+ 				goto retry;
+ 			}
+-- 
+2.7.4
+
diff --git a/SOURCES/0037-net-mvpp2-Add-support-for-unicast-filtering.patch b/SOURCES/0037-net-mvpp2-Add-support-for-unicast-filtering.patch
new file mode 100644
index 0000000..29fa8d4
--- /dev/null
+++ b/SOURCES/0037-net-mvpp2-Add-support-for-unicast-filtering.patch
@@ -0,0 +1,465 @@
+From 45725549315f8d6ad373c0ca24d9d286871929ea Mon Sep 17 00:00:00 2001
+From: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Date: Wed, 7 Mar 2018 15:18:04 +0100
+Subject: [PATCH 37/46] net: mvpp2: Add support for unicast filtering
+
+Marvell PPv2 controller can be used to implement packet filtering based
+on the destination MAC address. This is already used to implement
+multicast filtering. This patch adds support for Unicast filtering.
+
+Filtering is based on so-called "TCAM entries" to implement filtering.
+Due to their limited number and the fact that these are also used for
+other purposes, we reserve 80 entries for both unicast and multicast
+filters. On top of the broadcast address, and each interface's own MAC
+address, we reserve 25 entries per port, 4 for unicast filters, 21 for
+multicast.
+
+Whenever unicast or multicast range for one port is full, the filtering
+is disabled and port goes into promiscuous mode for the given type of
+addresses.
+
+Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 10fea26ce2aaf46c4da834664fb5f8476108a783)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 296 +++++++++++++++++++----------------
+ 1 file changed, 161 insertions(+), 135 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 8796456..9bd35f22 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -601,6 +601,9 @@ enum mvpp2_tag_type {
+ #define MVPP2_PRS_TCAM_PROTO_MASK	0xff
+ #define MVPP2_PRS_TCAM_PROTO_MASK_L	0x3f
+ #define MVPP2_PRS_DBL_VLANS_MAX		100
++#define MVPP2_PRS_CAST_MASK		BIT(0)
++#define MVPP2_PRS_MCAST_VAL		BIT(0)
++#define MVPP2_PRS_UCAST_VAL		0x0
+ 
+ /* Tcam structure:
+  * - lookup ID - 4 bits
+@@ -624,6 +627,19 @@ enum mvpp2_tag_type {
+ 
+ #define MVPP2_PRS_VID_TCAM_BYTE         2
+ 
++/* TCAM range for unicast and multicast filtering. We have 25 entries per port,
++ * with 4 dedicated to UC filtering and the rest to multicast filtering.
++ * Additionnally we reserve one entry for the broadcast address, and one for
++ * each port's own address.
++ */
++#define MVPP2_PRS_MAC_UC_MC_FILT_MAX	25
++#define MVPP2_PRS_MAC_RANGE_SIZE	80
++
++/* Number of entries per port dedicated to UC and MC filtering */
++#define MVPP2_PRS_MAC_UC_FILT_MAX	4
++#define MVPP2_PRS_MAC_MC_FILT_MAX	(MVPP2_PRS_MAC_UC_MC_FILT_MAX - \
++					 MVPP2_PRS_MAC_UC_FILT_MAX)
++
+ /* There is a TCAM range reserved for VLAN filtering entries, range size is 33
+  * 10 VLAN ID filter entries per port
+  * 1 default VLAN filter entry per port
+@@ -639,36 +655,40 @@ enum mvpp2_tag_type {
+ #define MVPP2_PE_DROP_ALL		0
+ #define MVPP2_PE_FIRST_FREE_TID		1
+ 
++/* MAC filtering range */
++#define MVPP2_PE_MAC_RANGE_END		(MVPP2_PE_VID_FILT_RANGE_START - 1)
++#define MVPP2_PE_MAC_RANGE_START	(MVPP2_PE_MAC_RANGE_END - \
++						MVPP2_PRS_MAC_RANGE_SIZE + 1)
+ /* VLAN filtering range */
+ #define MVPP2_PE_VID_FILT_RANGE_END     (MVPP2_PRS_TCAM_SRAM_SIZE - 31)
+ #define MVPP2_PE_VID_FILT_RANGE_START   (MVPP2_PE_VID_FILT_RANGE_END - \
+ 					 MVPP2_PRS_VLAN_FILT_RANGE_SIZE + 1)
+ #define MVPP2_PE_LAST_FREE_TID          (MVPP2_PE_VID_FILT_RANGE_START - 1)
+ #define MVPP2_PE_IP6_EXT_PROTO_UN	(MVPP2_PRS_TCAM_SRAM_SIZE - 30)
+-#define MVPP2_PE_MAC_MC_IP6		(MVPP2_PRS_TCAM_SRAM_SIZE - 29)
+-#define MVPP2_PE_IP6_ADDR_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 28)
+-#define MVPP2_PE_IP4_ADDR_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 27)
+-#define MVPP2_PE_LAST_DEFAULT_FLOW	(MVPP2_PRS_TCAM_SRAM_SIZE - 26)
+-#define MVPP2_PE_FIRST_DEFAULT_FLOW	(MVPP2_PRS_TCAM_SRAM_SIZE - 21)
+-#define MVPP2_PE_EDSA_TAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 20)
+-#define MVPP2_PE_EDSA_UNTAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 19)
+-#define MVPP2_PE_DSA_TAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 18)
+-#define MVPP2_PE_DSA_UNTAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 17)
+-#define MVPP2_PE_ETYPE_EDSA_TAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 16)
+-#define MVPP2_PE_ETYPE_EDSA_UNTAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 15)
+-#define MVPP2_PE_ETYPE_DSA_TAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 14)
+-#define MVPP2_PE_ETYPE_DSA_UNTAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 13)
+-#define MVPP2_PE_MH_DEFAULT		(MVPP2_PRS_TCAM_SRAM_SIZE - 12)
+-#define MVPP2_PE_DSA_DEFAULT		(MVPP2_PRS_TCAM_SRAM_SIZE - 11)
+-#define MVPP2_PE_IP6_PROTO_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 10)
+-#define MVPP2_PE_IP4_PROTO_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 9)
+-#define MVPP2_PE_ETH_TYPE_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 8)
+-#define MVPP2_PE_VID_FLTR_DEFAULT	(MVPP2_PRS_TCAM_SRAM_SIZE - 7)
+-#define MVPP2_PE_VID_EDSA_FLTR_DEFAULT	(MVPP2_PRS_TCAM_SRAM_SIZE - 6)
+-#define MVPP2_PE_VLAN_DBL		(MVPP2_PRS_TCAM_SRAM_SIZE - 5)
+-#define MVPP2_PE_VLAN_NONE		(MVPP2_PRS_TCAM_SRAM_SIZE - 4)
+-#define MVPP2_PE_MAC_MC_ALL		(MVPP2_PRS_TCAM_SRAM_SIZE - 3)
+-#define MVPP2_PE_MAC_PROMISCUOUS	(MVPP2_PRS_TCAM_SRAM_SIZE - 2)
++#define MVPP2_PE_IP6_ADDR_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 29)
++#define MVPP2_PE_IP4_ADDR_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 28)
++#define MVPP2_PE_LAST_DEFAULT_FLOW	(MVPP2_PRS_TCAM_SRAM_SIZE - 27)
++#define MVPP2_PE_FIRST_DEFAULT_FLOW	(MVPP2_PRS_TCAM_SRAM_SIZE - 22)
++#define MVPP2_PE_EDSA_TAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 21)
++#define MVPP2_PE_EDSA_UNTAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 20)
++#define MVPP2_PE_DSA_TAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 19)
++#define MVPP2_PE_DSA_UNTAGGED		(MVPP2_PRS_TCAM_SRAM_SIZE - 18)
++#define MVPP2_PE_ETYPE_EDSA_TAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 17)
++#define MVPP2_PE_ETYPE_EDSA_UNTAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 16)
++#define MVPP2_PE_ETYPE_DSA_TAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 15)
++#define MVPP2_PE_ETYPE_DSA_UNTAGGED	(MVPP2_PRS_TCAM_SRAM_SIZE - 14)
++#define MVPP2_PE_MH_DEFAULT		(MVPP2_PRS_TCAM_SRAM_SIZE - 13)
++#define MVPP2_PE_DSA_DEFAULT		(MVPP2_PRS_TCAM_SRAM_SIZE - 12)
++#define MVPP2_PE_IP6_PROTO_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 11)
++#define MVPP2_PE_IP4_PROTO_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 10)
++#define MVPP2_PE_ETH_TYPE_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 9)
++#define MVPP2_PE_VID_FLTR_DEFAULT	(MVPP2_PRS_TCAM_SRAM_SIZE - 8)
++#define MVPP2_PE_VID_EDSA_FLTR_DEFAULT	(MVPP2_PRS_TCAM_SRAM_SIZE - 7)
++#define MVPP2_PE_VLAN_DBL		(MVPP2_PRS_TCAM_SRAM_SIZE - 6)
++#define MVPP2_PE_VLAN_NONE		(MVPP2_PRS_TCAM_SRAM_SIZE - 5)
++/* reserved */
++#define MVPP2_PE_MAC_MC_PROMISCUOUS	(MVPP2_PRS_TCAM_SRAM_SIZE - 3)
++#define MVPP2_PE_MAC_UC_PROMISCUOUS	(MVPP2_PRS_TCAM_SRAM_SIZE - 2)
+ #define MVPP2_PE_MAC_NON_PROMISCUOUS	(MVPP2_PRS_TCAM_SRAM_SIZE - 1)
+ 
+ #define MVPP2_PRS_VID_PORT_FIRST(port)	(MVPP2_PE_VID_FILT_RANGE_START + \
+@@ -798,6 +818,12 @@ enum mvpp2_prs_lookup {
+ 	MVPP2_PRS_LU_LAST,
+ };
+ 
++/* L2 cast enum */
++enum mvpp2_prs_l2_cast {
++	MVPP2_PRS_L2_UNI_CAST,
++	MVPP2_PRS_L2_MULTI_CAST,
++};
++
+ /* L3 cast enum */
+ enum mvpp2_prs_l3_cast {
+ 	MVPP2_PRS_L3_UNI_CAST,
+@@ -1973,78 +1999,43 @@ static void mvpp2_prs_mac_drop_all_set(struct mvpp2 *priv, int port, bool add)
+ 	mvpp2_prs_hw_write(priv, &pe);
+ }
+ 
+-/* Set port to promiscuous mode */
+-static void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port, bool add)
++/* Set port to unicast or multicast promiscuous mode */
++static void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port,
++				      enum mvpp2_prs_l2_cast l2_cast, bool add)
+ {
+ 	struct mvpp2_prs_entry pe;
++	unsigned char cast_match;
++	unsigned int ri;
++	int tid;
+ 
+-	/* Promiscuous mode - Accept unknown packets */
+-
+-	if (priv->prs_shadow[MVPP2_PE_MAC_PROMISCUOUS].valid) {
+-		/* Entry exist - update port only */
+-		pe.index = MVPP2_PE_MAC_PROMISCUOUS;
+-		mvpp2_prs_hw_read(priv, &pe);
++	if (l2_cast == MVPP2_PRS_L2_UNI_CAST) {
++		cast_match = MVPP2_PRS_UCAST_VAL;
++		tid = MVPP2_PE_MAC_UC_PROMISCUOUS;
++		ri = MVPP2_PRS_RI_L2_UCAST;
+ 	} else {
+-		/* Entry doesn't exist - create new */
+-		memset(&pe, 0, sizeof(pe));
+-		mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
+-		pe.index = MVPP2_PE_MAC_PROMISCUOUS;
+-
+-		/* Continue - set next lookup */
+-		mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_DSA);
+-
+-		/* Set result info bits */
+-		mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L2_UCAST,
+-					 MVPP2_PRS_RI_L2_CAST_MASK);
+-
+-		/* Shift to ethertype */
+-		mvpp2_prs_sram_shift_set(&pe, 2 * ETH_ALEN,
+-					 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+-
+-		/* Mask all ports */
+-		mvpp2_prs_tcam_port_map_set(&pe, 0);
+-
+-		/* Update shadow table */
+-		mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
++		cast_match = MVPP2_PRS_MCAST_VAL;
++		tid = MVPP2_PE_MAC_MC_PROMISCUOUS;
++		ri = MVPP2_PRS_RI_L2_MCAST;
+ 	}
+ 
+-	/* Update port mask */
+-	mvpp2_prs_tcam_port_set(&pe, port, add);
+-
+-	mvpp2_prs_hw_write(priv, &pe);
+-}
+-
+-/* Accept multicast */
+-static void mvpp2_prs_mac_multi_set(struct mvpp2 *priv, int port, int index,
+-				    bool add)
+-{
+-	struct mvpp2_prs_entry pe;
+-	unsigned char da_mc;
+-
+-	/* Ethernet multicast address first byte is
+-	 * 0x01 for IPv4 and 0x33 for IPv6
+-	 */
+-	da_mc = (index == MVPP2_PE_MAC_MC_ALL) ? 0x01 : 0x33;
+-
+-	if (priv->prs_shadow[index].valid) {
+-		/* Entry exist - update port only */
+-		pe.index = index;
++	/* promiscuous mode - Accept unknown unicast or multicast packets */
++	if (priv->prs_shadow[tid].valid) {
++		pe.index = tid;
+ 		mvpp2_prs_hw_read(priv, &pe);
+ 	} else {
+-		/* Entry doesn't exist - create new */
+ 		memset(&pe, 0, sizeof(pe));
+ 		mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
+-		pe.index = index;
++		pe.index = tid;
+ 
+ 		/* Continue - set next lookup */
+ 		mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_DSA);
+ 
+ 		/* Set result info bits */
+-		mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L2_MCAST,
+-					 MVPP2_PRS_RI_L2_CAST_MASK);
++		mvpp2_prs_sram_ri_update(&pe, ri, MVPP2_PRS_RI_L2_CAST_MASK);
+ 
+-		/* Update tcam entry data first byte */
+-		mvpp2_prs_tcam_data_byte_set(&pe, 0, da_mc, 0xff);
++		/* Match UC or MC addresses */
++		mvpp2_prs_tcam_data_byte_set(&pe, 0, cast_match,
++					     MVPP2_PRS_CAST_MASK);
+ 
+ 		/* Shift to ethertype */
+ 		mvpp2_prs_sram_shift_set(&pe, 2 * ETH_ALEN,
+@@ -2758,11 +2749,10 @@ static void mvpp2_prs_mac_init(struct mvpp2 *priv)
+ 	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
+ 	mvpp2_prs_hw_write(priv, &pe);
+ 
+-	/* place holders only - no ports */
++	/* Create dummy entries for drop all and promiscuous modes */
+ 	mvpp2_prs_mac_drop_all_set(priv, 0, false);
+-	mvpp2_prs_mac_promisc_set(priv, 0, false);
+-	mvpp2_prs_mac_multi_set(priv, 0, MVPP2_PE_MAC_MC_ALL, false);
+-	mvpp2_prs_mac_multi_set(priv, 0, MVPP2_PE_MAC_MC_IP6, false);
++	mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_UNI_CAST, false);
++	mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_MULTI_CAST, false);
+ }
+ 
+ /* Set default entries for various types of dsa packets */
+@@ -3794,8 +3784,8 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
+ 	mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC);
+ 
+ 	/* Go through the all entires with MVPP2_PRS_LU_MAC */
+-	for (tid = MVPP2_PE_FIRST_FREE_TID;
+-	     tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
++	for (tid = MVPP2_PE_MAC_RANGE_START;
++	     tid <= MVPP2_PE_MAC_RANGE_END; tid++) {
+ 		unsigned int entry_pmap;
+ 
+ 		if (!priv->prs_shadow[tid].valid ||
+@@ -3836,18 +3826,10 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da,
+ 			return 0;
+ 
+ 		/* Create new TCAM entry */
+-		/* Find first range mac entry*/
+-		for (tid = MVPP2_PE_FIRST_FREE_TID;
+-		     tid <= MVPP2_PE_LAST_FREE_TID; tid++)
+-			if (priv->prs_shadow[tid].valid &&
+-			    (priv->prs_shadow[tid].lu == MVPP2_PRS_LU_MAC) &&
+-			    (priv->prs_shadow[tid].udf ==
+-						       MVPP2_PRS_UDF_MAC_RANGE))
+-				break;
+-
+ 		/* Go through the all entries from first to last */
+-		tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+-						tid - 1);
++		tid = mvpp2_prs_tcam_first_free(priv,
++						MVPP2_PE_MAC_RANGE_START,
++						MVPP2_PE_MAC_RANGE_END);
+ 		if (tid < 0)
+ 			return tid;
+ 
+@@ -3886,12 +3868,16 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da,
+ 		mvpp2_prs_tcam_data_byte_set(pe, len, da[len], 0xff);
+ 
+ 	/* Set result info bits */
+-	if (is_broadcast_ether_addr(da))
++	if (is_broadcast_ether_addr(da)) {
+ 		ri = MVPP2_PRS_RI_L2_BCAST;
+-	else if (is_multicast_ether_addr(da))
++	} else if (is_multicast_ether_addr(da)) {
+ 		ri = MVPP2_PRS_RI_L2_MCAST;
+-	else
+-		ri = MVPP2_PRS_RI_L2_UCAST | MVPP2_PRS_RI_MAC_ME_MASK;
++	} else {
++		ri = MVPP2_PRS_RI_L2_UCAST;
++
++		if (ether_addr_equal(da, port->dev->dev_addr))
++			ri |= MVPP2_PRS_RI_MAC_ME_MASK;
++	}
+ 
+ 	mvpp2_prs_sram_ri_update(pe, ri, MVPP2_PRS_RI_L2_CAST_MASK |
+ 				 MVPP2_PRS_RI_MAC_ME_MASK);
+@@ -3933,14 +3919,15 @@ static int mvpp2_prs_update_mac_da(struct net_device *dev, const u8 *da)
+ 	return 0;
+ }
+ 
+-/* Delete all port's multicast simple (not range) entries */
+-static void mvpp2_prs_mcast_del_all(struct mvpp2 *priv, int port)
++static void mvpp2_prs_mac_del_all(struct mvpp2_port *port)
+ {
++	struct mvpp2 *priv = port->priv;
+ 	struct mvpp2_prs_entry pe;
++	unsigned long pmap;
+ 	int index, tid;
+ 
+-	for (tid = MVPP2_PE_FIRST_FREE_TID;
+-	     tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
++	for (tid = MVPP2_PE_MAC_RANGE_START;
++	     tid <= MVPP2_PE_MAC_RANGE_END; tid++) {
+ 		unsigned char da[ETH_ALEN], da_mask[ETH_ALEN];
+ 
+ 		if (!priv->prs_shadow[tid].valid ||
+@@ -3948,19 +3935,29 @@ static void mvpp2_prs_mcast_del_all(struct mvpp2 *priv, int port)
+ 		    (priv->prs_shadow[tid].udf != MVPP2_PRS_UDF_MAC_DEF))
+ 			continue;
+ 
+-		/* Only simple mac entries */
+ 		pe.index = tid;
+ 		mvpp2_prs_hw_read(priv, &pe);
+ 
++		pmap = mvpp2_prs_tcam_port_map_get(&pe);
++
++		/* We only want entries active on this port */
++		if (!test_bit(port->id, &pmap))
++			continue;
++
+ 		/* Read mac addr from entry */
+ 		for (index = 0; index < ETH_ALEN; index++)
+ 			mvpp2_prs_tcam_data_byte_get(&pe, index, &da[index],
+ 						     &da_mask[index]);
+ 
+-		if (is_multicast_ether_addr(da) && !is_broadcast_ether_addr(da))
+-			/* Delete this entry */
+-			mvpp2_prs_mac_da_accept(priv->port_list[port], da,
+-						false);
++		/* Special cases : Don't remove broadcast and port's own
++		 * address
++		 */
++		if (is_broadcast_ether_addr(da) ||
++		    ether_addr_equal(da, port->dev->dev_addr))
++			continue;
++
++		/* Remove entry from TCAM */
++		mvpp2_prs_mac_da_accept(port, da, false);
+ 	}
+ }
+ 
+@@ -7502,36 +7499,64 @@ static int mvpp2_stop(struct net_device *dev)
+ 	return 0;
+ }
+ 
+-static void mvpp2_set_rx_mode(struct net_device *dev)
++static int mvpp2_prs_mac_da_accept_list(struct mvpp2_port *port,
++					struct netdev_hw_addr_list *list)
+ {
+-	struct mvpp2_port *port = netdev_priv(dev);
+-	struct mvpp2 *priv = port->priv;
+ 	struct netdev_hw_addr *ha;
+-	int id = port->id;
+-	bool allmulti = dev->flags & IFF_ALLMULTI;
+-
+-retry:
+-	mvpp2_prs_mac_promisc_set(priv, id, dev->flags & IFF_PROMISC);
+-	mvpp2_prs_mac_multi_set(priv, id, MVPP2_PE_MAC_MC_ALL, allmulti);
+-	mvpp2_prs_mac_multi_set(priv, id, MVPP2_PE_MAC_MC_IP6, allmulti);
+-
+-	/* Remove all port->id's mcast enries */
+-	mvpp2_prs_mcast_del_all(priv, id);
+-
+-	if (!allmulti) {
+-		netdev_for_each_mc_addr(ha, dev) {
+-			if (mvpp2_prs_mac_da_accept(port, ha->addr, true)) {
+-				allmulti = true;
+-				goto retry;
+-			}
+-		}
++	int ret;
++
++	netdev_hw_addr_list_for_each(ha, list) {
++		ret = mvpp2_prs_mac_da_accept(port, ha->addr, true);
++		if (ret)
++			return ret;
+ 	}
+ 
+-	/* Disable VLAN filtering in promiscuous mode */
+-	if (dev->flags & IFF_PROMISC)
+-		mvpp2_prs_vid_disable_filtering(port);
+-	else
++	return 0;
++}
++
++static void mvpp2_set_rx_promisc(struct mvpp2_port *port, bool enable)
++{
++	if (!enable && (port->dev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
+ 		mvpp2_prs_vid_enable_filtering(port);
++	else
++		mvpp2_prs_vid_disable_filtering(port);
++
++	mvpp2_prs_mac_promisc_set(port->priv, port->id,
++				  MVPP2_PRS_L2_UNI_CAST, enable);
++
++	mvpp2_prs_mac_promisc_set(port->priv, port->id,
++				  MVPP2_PRS_L2_MULTI_CAST, enable);
++}
++
++static void mvpp2_set_rx_mode(struct net_device *dev)
++{
++	struct mvpp2_port *port = netdev_priv(dev);
++
++	/* Clear the whole UC and MC list */
++	mvpp2_prs_mac_del_all(port);
++
++	if (dev->flags & IFF_PROMISC) {
++		mvpp2_set_rx_promisc(port, true);
++		return;
++	}
++
++	mvpp2_set_rx_promisc(port, false);
++
++	if (netdev_uc_count(dev) > MVPP2_PRS_MAC_UC_FILT_MAX ||
++	    mvpp2_prs_mac_da_accept_list(port, &dev->uc))
++		mvpp2_prs_mac_promisc_set(port->priv, port->id,
++					  MVPP2_PRS_L2_UNI_CAST, true);
++
++	if (dev->flags & IFF_ALLMULTI) {
++		mvpp2_prs_mac_promisc_set(port->priv, port->id,
++					  MVPP2_PRS_L2_MULTI_CAST, true);
++		return;
++	}
++
++	if (netdev_mc_count(dev) > MVPP2_PRS_MAC_MC_FILT_MAX ||
++	    mvpp2_prs_mac_da_accept_list(port, &dev->mc))
++		mvpp2_prs_mac_promisc_set(port->priv, port->id,
++					  MVPP2_PRS_L2_MULTI_CAST, true);
+ }
+ 
+ static int mvpp2_set_mac_address(struct net_device *dev, void *p)
+@@ -8380,6 +8405,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
+ 
+ 	dev->vlan_features |= features;
+ 	dev->gso_max_segs = MVPP2_MAX_TSO_SEGS;
++	dev->priv_flags |= IFF_UNICAST_FLT;
+ 
+ 	/* MTU range: 68 - 9704 */
+ 	dev->min_mtu = ETH_MIN_MTU;
+-- 
+2.7.4
+
diff --git a/SOURCES/0038-net-mvpp2-use-correct-index-on-array-mvpp2_pools.patch b/SOURCES/0038-net-mvpp2-use-correct-index-on-array-mvpp2_pools.patch
new file mode 100644
index 0000000..7cb437a
--- /dev/null
+++ b/SOURCES/0038-net-mvpp2-use-correct-index-on-array-mvpp2_pools.patch
@@ -0,0 +1,36 @@
+From 4c764b207404d9f895d12193e2f0d5f2146a87c7 Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.king@canonical.com>
+Date: Wed, 21 Mar 2018 17:31:15 +0000
+Subject: [PATCH 38/46] net: mvpp2: use correct index on array mvpp2_pools
+
+Array mvpp2_pools is being indexed by long_log_pool, however this
+looks like a cut-n-paste bug and in fact should be short_log_pool.
+
+Detected by CoverityScan, CID#1466113 ("Copy-paste error")
+
+Fixes: 576193f2d579 ("net: mvpp2: jumbo frames support")
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Acked-by: Antoine Tenart <antoine.tenart@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit e2e031640b3a9482b137b68193b7d59b8308185c)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 9bd35f22..f8bc3d4 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -4632,7 +4632,7 @@ static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
+ 	if (!port->pool_short) {
+ 		port->pool_short =
+ 			mvpp2_bm_pool_use(port, short_log_pool,
+-					  mvpp2_pools[long_log_pool].pkt_size);
++					  mvpp2_pools[short_log_pool].pkt_size);
+ 		if (!port->pool_short)
+ 			return -ENOMEM;
+ 
+-- 
+2.7.4
+
diff --git a/SOURCES/0039-net-mvpp2-Make-mvpp2_prs_hw_read-a-parser-entry-init.patch b/SOURCES/0039-net-mvpp2-Make-mvpp2_prs_hw_read-a-parser-entry-init.patch
new file mode 100644
index 0000000..43ed6c8
--- /dev/null
+++ b/SOURCES/0039-net-mvpp2-Make-mvpp2_prs_hw_read-a-parser-entry-init.patch
@@ -0,0 +1,184 @@
+From 3a858388746ad5cbea5a215147f341a066579211 Mon Sep 17 00:00:00 2001
+From: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Date: Mon, 26 Mar 2018 15:34:22 +0200
+Subject: [PATCH 39/46] net: mvpp2: Make mvpp2_prs_hw_read a parser entry init
+ function
+
+The mvpp2_prs_hw_read function uses the 'index' field of the struct
+mvpp2_prs_entry to initialize the rest of the fields. This makes it
+unclear from a caller's perspective, who needs to manipulate a struct
+that is not entirely initialized.
+
+This commit makes it an init function for prs_entry, by passing it the
+index as a parameter. The function now zeroes the entry, and sets the
+index field before doing all other init from HW.
+
+The function is renamed 'mvpp2_prs_init_from_hw' to make that clear.
+
+Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 47e0e14eb1a688c0868385e02db263093d2df6db)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 48 ++++++++++++++----------------------
+ 1 file changed, 19 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index f8bc3d4..f51dcb3 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -1582,14 +1582,18 @@ static int mvpp2_prs_hw_write(struct mvpp2 *priv, struct mvpp2_prs_entry *pe)
+ 	return 0;
+ }
+ 
+-/* Read tcam entry from hw */
+-static int mvpp2_prs_hw_read(struct mvpp2 *priv, struct mvpp2_prs_entry *pe)
++/* Initialize tcam entry from hw */
++static int mvpp2_prs_init_from_hw(struct mvpp2 *priv,
++				  struct mvpp2_prs_entry *pe, int tid)
+ {
+ 	int i;
+ 
+ 	if (pe->index > MVPP2_PRS_TCAM_SRAM_SIZE - 1)
+ 		return -EINVAL;
+ 
++	memset(pe, 0, sizeof(*pe));
++	pe->index = tid;
++
+ 	/* Write tcam index - indirect access */
+ 	mvpp2_write(priv, MVPP2_PRS_TCAM_IDX_REG, pe->index);
+ 
+@@ -1931,8 +1935,7 @@ static struct mvpp2_prs_entry *mvpp2_prs_flow_find(struct mvpp2 *priv, int flow)
+ 		    priv->prs_shadow[tid].lu != MVPP2_PRS_LU_FLOWS)
+ 			continue;
+ 
+-		pe->index = tid;
+-		mvpp2_prs_hw_read(priv, pe);
++		mvpp2_prs_init_from_hw(priv, pe, tid);
+ 		bits = mvpp2_prs_sram_ai_get(pe);
+ 
+ 		/* Sram store classification lookup ID in AI bits [5:0] */
+@@ -1971,8 +1974,7 @@ static void mvpp2_prs_mac_drop_all_set(struct mvpp2 *priv, int port, bool add)
+ 
+ 	if (priv->prs_shadow[MVPP2_PE_DROP_ALL].valid) {
+ 		/* Entry exist - update port only */
+-		pe.index = MVPP2_PE_DROP_ALL;
+-		mvpp2_prs_hw_read(priv, &pe);
++		mvpp2_prs_init_from_hw(priv, &pe, MVPP2_PE_DROP_ALL);
+ 	} else {
+ 		/* Entry doesn't exist - create new */
+ 		memset(&pe, 0, sizeof(pe));
+@@ -2020,8 +2022,7 @@ static void mvpp2_prs_mac_promisc_set(struct mvpp2 *priv, int port,
+ 
+ 	/* promiscuous mode - Accept unknown unicast or multicast packets */
+ 	if (priv->prs_shadow[tid].valid) {
+-		pe.index = tid;
+-		mvpp2_prs_hw_read(priv, &pe);
++		mvpp2_prs_init_from_hw(priv, &pe, tid);
+ 	} else {
+ 		memset(&pe, 0, sizeof(pe));
+ 		mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
+@@ -2071,8 +2072,7 @@ static void mvpp2_prs_dsa_tag_set(struct mvpp2 *priv, int port, bool add,
+ 
+ 	if (priv->prs_shadow[tid].valid) {
+ 		/* Entry exist - update port only */
+-		pe.index = tid;
+-		mvpp2_prs_hw_read(priv, &pe);
++		mvpp2_prs_init_from_hw(priv, &pe, tid);
+ 	} else {
+ 		/* Entry doesn't exist - create new */
+ 		memset(&pe, 0, sizeof(pe));
+@@ -2140,8 +2140,7 @@ static void mvpp2_prs_dsa_tag_ethertype_set(struct mvpp2 *priv, int port,
+ 
+ 	if (priv->prs_shadow[tid].valid) {
+ 		/* Entry exist - update port only */
+-		pe.index = tid;
+-		mvpp2_prs_hw_read(priv, &pe);
++		mvpp2_prs_init_from_hw(priv, &pe, tid);
+ 	} else {
+ 		/* Entry doesn't exist - create new */
+ 		memset(&pe, 0, sizeof(pe));
+@@ -2210,9 +2209,7 @@ static struct mvpp2_prs_entry *mvpp2_prs_vlan_find(struct mvpp2 *priv,
+ 		    priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
+ 			continue;
+ 
+-		pe->index = tid;
+-
+-		mvpp2_prs_hw_read(priv, pe);
++		mvpp2_prs_init_from_hw(priv, pe, tid);
+ 		match = mvpp2_prs_tcam_data_cmp(pe, 0, swab16(tpid));
+ 		if (!match)
+ 			continue;
+@@ -2268,8 +2265,7 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
+ 			    priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
+ 				continue;
+ 
+-			pe->index = tid_aux;
+-			mvpp2_prs_hw_read(priv, pe);
++			mvpp2_prs_init_from_hw(priv, pe, tid_aux);
+ 			ri_bits = mvpp2_prs_sram_ri_get(pe);
+ 			if ((ri_bits & MVPP2_PRS_RI_VLAN_MASK) ==
+ 			    MVPP2_PRS_RI_VLAN_DOUBLE)
+@@ -2351,8 +2347,7 @@ static struct mvpp2_prs_entry *mvpp2_prs_double_vlan_find(struct mvpp2 *priv,
+ 		    priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
+ 			continue;
+ 
+-		pe->index = tid;
+-		mvpp2_prs_hw_read(priv, pe);
++		mvpp2_prs_init_from_hw(priv, pe, tid);
+ 
+ 		match = mvpp2_prs_tcam_data_cmp(pe, 0, swab16(tpid1))
+ 			&& mvpp2_prs_tcam_data_cmp(pe, 4, swab16(tpid2));
+@@ -2406,8 +2401,7 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
+ 			    priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
+ 				continue;
+ 
+-			pe->index = tid_aux;
+-			mvpp2_prs_hw_read(priv, pe);
++			mvpp2_prs_init_from_hw(priv, pe, tid_aux);
+ 			ri_bits = mvpp2_prs_sram_ri_get(pe);
+ 			ri_bits &= MVPP2_PRS_RI_VLAN_MASK;
+ 			if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE ||
+@@ -3513,9 +3507,7 @@ static int mvpp2_prs_vid_range_find(struct mvpp2 *priv, int pmap, u16 vid,
+ 		    priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VID)
+ 			continue;
+ 
+-		pe.index = tid;
+-
+-		mvpp2_prs_hw_read(priv, &pe);
++		mvpp2_prs_init_from_hw(priv, &pe, tid);
+ 		mvpp2_prs_tcam_data_byte_get(&pe, 2, &byte[0], &enable[0]);
+ 		mvpp2_prs_tcam_data_byte_get(&pe, 3, &byte[1], &enable[1]);
+ 
+@@ -3569,7 +3561,7 @@ static int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
+ 		/* Mask all ports */
+ 		mvpp2_prs_tcam_port_map_set(&pe, 0);
+ 	} else {
+-		mvpp2_prs_hw_read(priv, &pe);
++		mvpp2_prs_init_from_hw(priv, &pe, tid);
+ 	}
+ 
+ 	/* Enable the current port */
+@@ -3793,8 +3785,7 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
+ 		    (priv->prs_shadow[tid].udf != udf_type))
+ 			continue;
+ 
+-		pe->index = tid;
+-		mvpp2_prs_hw_read(priv, pe);
++		mvpp2_prs_init_from_hw(priv, pe, tid);
+ 		entry_pmap = mvpp2_prs_tcam_port_map_get(pe);
+ 
+ 		if (mvpp2_prs_mac_range_equals(pe, da, mask) &&
+@@ -3935,8 +3926,7 @@ static void mvpp2_prs_mac_del_all(struct mvpp2_port *port)
+ 		    (priv->prs_shadow[tid].udf != MVPP2_PRS_UDF_MAC_DEF))
+ 			continue;
+ 
+-		pe.index = tid;
+-		mvpp2_prs_hw_read(priv, &pe);
++		mvpp2_prs_init_from_hw(priv, &pe, tid);
+ 
+ 		pmap = mvpp2_prs_tcam_port_map_get(&pe);
+ 
+-- 
+2.7.4
+
diff --git a/SOURCES/0040-net-mvpp2-Don-t-use-dynamic-allocs-for-local-variabl.patch b/SOURCES/0040-net-mvpp2-Don-t-use-dynamic-allocs-for-local-variabl.patch
new file mode 100644
index 0000000..2d193f2
--- /dev/null
+++ b/SOURCES/0040-net-mvpp2-Don-t-use-dynamic-allocs-for-local-variabl.patch
@@ -0,0 +1,624 @@
+From 02b9107cc82ceb1a238990f00bcac7a247e25ef8 Mon Sep 17 00:00:00 2001
+From: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Date: Mon, 26 Mar 2018 15:34:23 +0200
+Subject: [PATCH 40/46] net: mvpp2: Don't use dynamic allocs for local
+ variables
+
+Some helper functions that search for given entries in the TCAM filter
+on PPv2 controller make use of dynamically alloced temporary variables,
+allocated with GFP_KERNEL. These functions can be called in atomic
+context, and dynamic alloc is not really needed in these cases anyways.
+
+This commit gets rid of dynamic allocs and use stack allocation in the
+following functions, and where they're used :
+ - mvpp2_prs_flow_find
+ - mvpp2_prs_vlan_find
+ - mvpp2_prs_double_vlan_find
+ - mvpp2_prs_mac_da_range_find
+
+For all these functions, instead of returning an temporary object
+representing the TCAM entry, we simply return the TCAM id that matches
+the requested entry.
+
+Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 0c6d9b44145d8134ebe4e9ebfa02e0dd23744723)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 286 +++++++++++++++--------------------
+ 1 file changed, 125 insertions(+), 161 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index f51dcb3..7075e5a 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -1917,16 +1917,11 @@ static void mvpp2_prs_sram_offset_set(struct mvpp2_prs_entry *pe,
+ }
+ 
+ /* Find parser flow entry */
+-static struct mvpp2_prs_entry *mvpp2_prs_flow_find(struct mvpp2 *priv, int flow)
++static int mvpp2_prs_flow_find(struct mvpp2 *priv, int flow)
+ {
+-	struct mvpp2_prs_entry *pe;
++	struct mvpp2_prs_entry pe;
+ 	int tid;
+ 
+-	pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+-	if (!pe)
+-		return NULL;
+-	mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_FLOWS);
+-
+ 	/* Go through the all entires with MVPP2_PRS_LU_FLOWS */
+ 	for (tid = MVPP2_PRS_TCAM_SRAM_SIZE - 1; tid >= 0; tid--) {
+ 		u8 bits;
+@@ -1935,16 +1930,15 @@ static struct mvpp2_prs_entry *mvpp2_prs_flow_find(struct mvpp2 *priv, int flow)
+ 		    priv->prs_shadow[tid].lu != MVPP2_PRS_LU_FLOWS)
+ 			continue;
+ 
+-		mvpp2_prs_init_from_hw(priv, pe, tid);
+-		bits = mvpp2_prs_sram_ai_get(pe);
++		mvpp2_prs_init_from_hw(priv, &pe, tid);
++		bits = mvpp2_prs_sram_ai_get(&pe);
+ 
+ 		/* Sram store classification lookup ID in AI bits [5:0] */
+ 		if ((bits & MVPP2_PRS_FLOW_ID_MASK) == flow)
+-			return pe;
++			return tid;
+ 	}
+-	kfree(pe);
+ 
+-	return NULL;
++	return -ENOENT;
+ }
+ 
+ /* Return first free tcam index, seeking from start to end */
+@@ -2188,17 +2182,11 @@ static void mvpp2_prs_dsa_tag_ethertype_set(struct mvpp2 *priv, int port,
+ }
+ 
+ /* Search for existing single/triple vlan entry */
+-static struct mvpp2_prs_entry *mvpp2_prs_vlan_find(struct mvpp2 *priv,
+-						   unsigned short tpid, int ai)
++static int mvpp2_prs_vlan_find(struct mvpp2 *priv, unsigned short tpid, int ai)
+ {
+-	struct mvpp2_prs_entry *pe;
++	struct mvpp2_prs_entry pe;
+ 	int tid;
+ 
+-	pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+-	if (!pe)
+-		return NULL;
+-	mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
+-
+ 	/* Go through the all entries with MVPP2_PRS_LU_VLAN */
+ 	for (tid = MVPP2_PE_FIRST_FREE_TID;
+ 	     tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
+@@ -2209,17 +2197,17 @@ static struct mvpp2_prs_entry *mvpp2_prs_vlan_find(struct mvpp2 *priv,
+ 		    priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
+ 			continue;
+ 
+-		mvpp2_prs_init_from_hw(priv, pe, tid);
+-		match = mvpp2_prs_tcam_data_cmp(pe, 0, swab16(tpid));
++		mvpp2_prs_init_from_hw(priv, &pe, tid);
++		match = mvpp2_prs_tcam_data_cmp(&pe, 0, swab16(tpid));
+ 		if (!match)
+ 			continue;
+ 
+ 		/* Get vlan type */
+-		ri_bits = mvpp2_prs_sram_ri_get(pe);
++		ri_bits = mvpp2_prs_sram_ri_get(&pe);
+ 		ri_bits &= MVPP2_PRS_RI_VLAN_MASK;
+ 
+ 		/* Get current ai value from tcam */
+-		ai_bits = mvpp2_prs_tcam_ai_get(pe);
++		ai_bits = mvpp2_prs_tcam_ai_get(&pe);
+ 		/* Clear double vlan bit */
+ 		ai_bits &= ~MVPP2_PRS_DBL_VLAN_AI_BIT;
+ 
+@@ -2228,34 +2216,31 @@ static struct mvpp2_prs_entry *mvpp2_prs_vlan_find(struct mvpp2 *priv,
+ 
+ 		if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE ||
+ 		    ri_bits == MVPP2_PRS_RI_VLAN_TRIPLE)
+-			return pe;
++			return tid;
+ 	}
+-	kfree(pe);
+ 
+-	return NULL;
++	return -ENOENT;
+ }
+ 
+ /* Add/update single/triple vlan entry */
+ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
+ 			      unsigned int port_map)
+ {
+-	struct mvpp2_prs_entry *pe;
++	struct mvpp2_prs_entry pe;
+ 	int tid_aux, tid;
+ 	int ret = 0;
+ 
+-	pe = mvpp2_prs_vlan_find(priv, tpid, ai);
++	memset(&pe, 0, sizeof(pe));
++
++	tid = mvpp2_prs_vlan_find(priv, tpid, ai);
+ 
+-	if (!pe) {
++	if (tid < 0) {
+ 		/* Create new tcam entry */
+ 		tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_LAST_FREE_TID,
+ 						MVPP2_PE_FIRST_FREE_TID);
+ 		if (tid < 0)
+ 			return tid;
+ 
+-		pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+-		if (!pe)
+-			return -ENOMEM;
+-
+ 		/* Get last double vlan tid */
+ 		for (tid_aux = MVPP2_PE_LAST_FREE_TID;
+ 		     tid_aux >= MVPP2_PE_FIRST_FREE_TID; tid_aux--) {
+@@ -2265,48 +2250,46 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
+ 			    priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
+ 				continue;
+ 
+-			mvpp2_prs_init_from_hw(priv, pe, tid_aux);
+-			ri_bits = mvpp2_prs_sram_ri_get(pe);
++			mvpp2_prs_init_from_hw(priv, &pe, tid_aux);
++			ri_bits = mvpp2_prs_sram_ri_get(&pe);
+ 			if ((ri_bits & MVPP2_PRS_RI_VLAN_MASK) ==
+ 			    MVPP2_PRS_RI_VLAN_DOUBLE)
+ 				break;
+ 		}
+ 
+-		if (tid <= tid_aux) {
+-			ret = -EINVAL;
+-			goto free_pe;
+-		}
++		if (tid <= tid_aux)
++			return -EINVAL;
+ 
+-		memset(pe, 0, sizeof(*pe));
+-		mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
+-		pe->index = tid;
++		memset(&pe, 0, sizeof(pe));
++		pe.index = tid;
++		mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VLAN);
+ 
+-		mvpp2_prs_match_etype(pe, 0, tpid);
++		mvpp2_prs_match_etype(&pe, 0, tpid);
+ 
+ 		/* VLAN tag detected, proceed with VID filtering */
+-		mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_VID);
++		mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VID);
+ 
+ 		/* Clear all ai bits for next iteration */
+-		mvpp2_prs_sram_ai_update(pe, 0, MVPP2_PRS_SRAM_AI_MASK);
++		mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
+ 
+ 		if (ai == MVPP2_PRS_SINGLE_VLAN_AI) {
+-			mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_SINGLE,
++			mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_SINGLE,
+ 						 MVPP2_PRS_RI_VLAN_MASK);
+ 		} else {
+ 			ai |= MVPP2_PRS_DBL_VLAN_AI_BIT;
+-			mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_TRIPLE,
++			mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_TRIPLE,
+ 						 MVPP2_PRS_RI_VLAN_MASK);
+ 		}
+-		mvpp2_prs_tcam_ai_update(pe, ai, MVPP2_PRS_SRAM_AI_MASK);
++		mvpp2_prs_tcam_ai_update(&pe, ai, MVPP2_PRS_SRAM_AI_MASK);
+ 
+-		mvpp2_prs_shadow_set(priv, pe->index, MVPP2_PRS_LU_VLAN);
++		mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN);
++	} else {
++		mvpp2_prs_init_from_hw(priv, &pe, tid);
+ 	}
+ 	/* Update ports' mask */
+-	mvpp2_prs_tcam_port_map_set(pe, port_map);
++	mvpp2_prs_tcam_port_map_set(&pe, port_map);
+ 
+-	mvpp2_prs_hw_write(priv, pe);
+-free_pe:
+-	kfree(pe);
++	mvpp2_prs_hw_write(priv, &pe);
+ 
+ 	return ret;
+ }
+@@ -2325,18 +2308,12 @@ static int mvpp2_prs_double_vlan_ai_free_get(struct mvpp2 *priv)
+ }
+ 
+ /* Search for existing double vlan entry */
+-static struct mvpp2_prs_entry *mvpp2_prs_double_vlan_find(struct mvpp2 *priv,
+-							  unsigned short tpid1,
+-							  unsigned short tpid2)
++static int mvpp2_prs_double_vlan_find(struct mvpp2 *priv, unsigned short tpid1,
++				      unsigned short tpid2)
+ {
+-	struct mvpp2_prs_entry *pe;
++	struct mvpp2_prs_entry pe;
+ 	int tid;
+ 
+-	pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+-	if (!pe)
+-		return NULL;
+-	mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
+-
+ 	/* Go through the all entries with MVPP2_PRS_LU_VLAN */
+ 	for (tid = MVPP2_PE_FIRST_FREE_TID;
+ 	     tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
+@@ -2347,21 +2324,20 @@ static struct mvpp2_prs_entry *mvpp2_prs_double_vlan_find(struct mvpp2 *priv,
+ 		    priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
+ 			continue;
+ 
+-		mvpp2_prs_init_from_hw(priv, pe, tid);
++		mvpp2_prs_init_from_hw(priv, &pe, tid);
+ 
+-		match = mvpp2_prs_tcam_data_cmp(pe, 0, swab16(tpid1))
+-			&& mvpp2_prs_tcam_data_cmp(pe, 4, swab16(tpid2));
++		match = mvpp2_prs_tcam_data_cmp(&pe, 0, swab16(tpid1)) &&
++			mvpp2_prs_tcam_data_cmp(&pe, 4, swab16(tpid2));
+ 
+ 		if (!match)
+ 			continue;
+ 
+-		ri_mask = mvpp2_prs_sram_ri_get(pe) & MVPP2_PRS_RI_VLAN_MASK;
++		ri_mask = mvpp2_prs_sram_ri_get(&pe) & MVPP2_PRS_RI_VLAN_MASK;
+ 		if (ri_mask == MVPP2_PRS_RI_VLAN_DOUBLE)
+-			return pe;
++			return tid;
+ 	}
+-	kfree(pe);
+ 
+-	return NULL;
++	return -ENOENT;
+ }
+ 
+ /* Add or update double vlan entry */
+@@ -2369,28 +2345,24 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
+ 				     unsigned short tpid2,
+ 				     unsigned int port_map)
+ {
+-	struct mvpp2_prs_entry *pe;
+ 	int tid_aux, tid, ai, ret = 0;
++	struct mvpp2_prs_entry pe;
+ 
+-	pe = mvpp2_prs_double_vlan_find(priv, tpid1, tpid2);
++	memset(&pe, 0, sizeof(pe));
++
++	tid = mvpp2_prs_double_vlan_find(priv, tpid1, tpid2);
+ 
+-	if (!pe) {
++	if (tid < 0) {
+ 		/* Create new tcam entry */
+ 		tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+ 				MVPP2_PE_LAST_FREE_TID);
+ 		if (tid < 0)
+ 			return tid;
+ 
+-		pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+-		if (!pe)
+-			return -ENOMEM;
+-
+ 		/* Set ai value for new double vlan entry */
+ 		ai = mvpp2_prs_double_vlan_ai_free_get(priv);
+-		if (ai < 0) {
+-			ret = ai;
+-			goto free_pe;
+-		}
++		if (ai < 0)
++			return ai;
+ 
+ 		/* Get first single/triple vlan tid */
+ 		for (tid_aux = MVPP2_PE_FIRST_FREE_TID;
+@@ -2401,45 +2373,44 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
+ 			    priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
+ 				continue;
+ 
+-			mvpp2_prs_init_from_hw(priv, pe, tid_aux);
+-			ri_bits = mvpp2_prs_sram_ri_get(pe);
++			mvpp2_prs_init_from_hw(priv, &pe, tid_aux);
++			ri_bits = mvpp2_prs_sram_ri_get(&pe);
+ 			ri_bits &= MVPP2_PRS_RI_VLAN_MASK;
+ 			if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE ||
+ 			    ri_bits == MVPP2_PRS_RI_VLAN_TRIPLE)
+ 				break;
+ 		}
+ 
+-		if (tid >= tid_aux) {
+-			ret = -ERANGE;
+-			goto free_pe;
+-		}
++		if (tid >= tid_aux)
++			return -ERANGE;
+ 
+-		memset(pe, 0, sizeof(*pe));
+-		mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
+-		pe->index = tid;
++		memset(&pe, 0, sizeof(pe));
++		mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VLAN);
++		pe.index = tid;
+ 
+ 		priv->prs_double_vlans[ai] = true;
+ 
+-		mvpp2_prs_match_etype(pe, 0, tpid1);
+-		mvpp2_prs_match_etype(pe, 4, tpid2);
++		mvpp2_prs_match_etype(&pe, 0, tpid1);
++		mvpp2_prs_match_etype(&pe, 4, tpid2);
+ 
+-		mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_VLAN);
++		mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VLAN);
+ 		/* Shift 4 bytes - skip outer vlan tag */
+-		mvpp2_prs_sram_shift_set(pe, MVPP2_VLAN_TAG_LEN,
++		mvpp2_prs_sram_shift_set(&pe, MVPP2_VLAN_TAG_LEN,
+ 					 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+-		mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_DOUBLE,
++		mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_DOUBLE,
+ 					 MVPP2_PRS_RI_VLAN_MASK);
+-		mvpp2_prs_sram_ai_update(pe, ai | MVPP2_PRS_DBL_VLAN_AI_BIT,
++		mvpp2_prs_sram_ai_update(&pe, ai | MVPP2_PRS_DBL_VLAN_AI_BIT,
+ 					 MVPP2_PRS_SRAM_AI_MASK);
+ 
+-		mvpp2_prs_shadow_set(priv, pe->index, MVPP2_PRS_LU_VLAN);
++		mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN);
++	} else {
++		mvpp2_prs_init_from_hw(priv, &pe, tid);
+ 	}
+ 
+ 	/* Update ports' mask */
+-	mvpp2_prs_tcam_port_map_set(pe, port_map);
+-	mvpp2_prs_hw_write(priv, pe);
+-free_pe:
+-	kfree(pe);
++	mvpp2_prs_tcam_port_map_set(&pe, port_map);
++	mvpp2_prs_hw_write(priv, &pe);
++
+ 	return ret;
+ }
+ 
+@@ -3508,6 +3479,7 @@ static int mvpp2_prs_vid_range_find(struct mvpp2 *priv, int pmap, u16 vid,
+ 			continue;
+ 
+ 		mvpp2_prs_init_from_hw(priv, &pe, tid);
++
+ 		mvpp2_prs_tcam_data_byte_get(&pe, 2, &byte[0], &enable[0]);
+ 		mvpp2_prs_tcam_data_byte_get(&pe, 3, &byte[1], &enable[1]);
+ 
+@@ -3520,7 +3492,7 @@ static int mvpp2_prs_vid_range_find(struct mvpp2 *priv, int pmap, u16 vid,
+ 		return tid;
+ 	}
+ 
+-	return 0;
++	return -ENOENT;
+ }
+ 
+ /* Write parser entry for VID filtering */
+@@ -3533,6 +3505,8 @@ static int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
+ 	struct mvpp2_prs_entry pe;
+ 	int tid;
+ 
++	memset(&pe, 0, sizeof(pe));
++
+ 	/* Scan TCAM and see if entry with this <vid,port> already exist */
+ 	tid = mvpp2_prs_vid_range_find(priv, (1 << port->id), vid, mask);
+ 
+@@ -3543,8 +3517,7 @@ static int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
+ 		shift = MVPP2_VLAN_TAG_LEN;
+ 
+ 	/* No such entry */
+-	if (!tid) {
+-		memset(&pe, 0, sizeof(pe));
++	if (tid < 0) {
+ 
+ 		/* Go through all entries from first to last in vlan range */
+ 		tid = mvpp2_prs_tcam_first_free(priv, vid_start,
+@@ -3596,7 +3569,7 @@ static void mvpp2_prs_vid_entry_remove(struct mvpp2_port *port, u16 vid)
+ 	tid = mvpp2_prs_vid_range_find(priv, (1 << port->id), vid, 0xfff);
+ 
+ 	/* No such entry */
+-	if (tid)
++	if (tid < 0)
+ 		return;
+ 
+ 	mvpp2_prs_hw_inv(priv, tid);
+@@ -3763,18 +3736,13 @@ static bool mvpp2_prs_mac_range_equals(struct mvpp2_prs_entry *pe,
+ }
+ 
+ /* Find tcam entry with matched pair <MAC DA, port> */
+-static struct mvpp2_prs_entry *
++static int
+ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
+ 			    unsigned char *mask, int udf_type)
+ {
+-	struct mvpp2_prs_entry *pe;
++	struct mvpp2_prs_entry pe;
+ 	int tid;
+ 
+-	pe = kzalloc(sizeof(*pe), GFP_ATOMIC);
+-	if (!pe)
+-		return NULL;
+-	mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC);
+-
+ 	/* Go through the all entires with MVPP2_PRS_LU_MAC */
+ 	for (tid = MVPP2_PE_MAC_RANGE_START;
+ 	     tid <= MVPP2_PE_MAC_RANGE_END; tid++) {
+@@ -3785,16 +3753,15 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
+ 		    (priv->prs_shadow[tid].udf != udf_type))
+ 			continue;
+ 
+-		mvpp2_prs_init_from_hw(priv, pe, tid);
+-		entry_pmap = mvpp2_prs_tcam_port_map_get(pe);
++		mvpp2_prs_init_from_hw(priv, &pe, tid);
++		entry_pmap = mvpp2_prs_tcam_port_map_get(&pe);
+ 
+-		if (mvpp2_prs_mac_range_equals(pe, da, mask) &&
++		if (mvpp2_prs_mac_range_equals(&pe, da, mask) &&
+ 		    entry_pmap == pmap)
+-			return pe;
++			return tid;
+ 	}
+-	kfree(pe);
+ 
+-	return NULL;
++	return -ENOENT;
+ }
+ 
+ /* Update parser's mac da entry */
+@@ -3804,15 +3771,17 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da,
+ 	unsigned char mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ 	struct mvpp2 *priv = port->priv;
+ 	unsigned int pmap, len, ri;
+-	struct mvpp2_prs_entry *pe;
++	struct mvpp2_prs_entry pe;
+ 	int tid;
+ 
++	memset(&pe, 0, sizeof(pe));
++
+ 	/* Scan TCAM and see if entry with this <MAC DA, port> already exist */
+-	pe = mvpp2_prs_mac_da_range_find(priv, BIT(port->id), da, mask,
+-					 MVPP2_PRS_UDF_MAC_DEF);
++	tid = mvpp2_prs_mac_da_range_find(priv, BIT(port->id), da, mask,
++					  MVPP2_PRS_UDF_MAC_DEF);
+ 
+ 	/* No such entry */
+-	if (!pe) {
++	if (tid < 0) {
+ 		if (!add)
+ 			return 0;
+ 
+@@ -3824,39 +3793,37 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da,
+ 		if (tid < 0)
+ 			return tid;
+ 
+-		pe = kzalloc(sizeof(*pe), GFP_ATOMIC);
+-		if (!pe)
+-			return -ENOMEM;
+-		mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC);
+-		pe->index = tid;
++		pe.index = tid;
+ 
+ 		/* Mask all ports */
+-		mvpp2_prs_tcam_port_map_set(pe, 0);
++		mvpp2_prs_tcam_port_map_set(&pe, 0);
++	} else {
++		mvpp2_prs_init_from_hw(priv, &pe, tid);
+ 	}
+ 
++	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
++
+ 	/* Update port mask */
+-	mvpp2_prs_tcam_port_set(pe, port->id, add);
++	mvpp2_prs_tcam_port_set(&pe, port->id, add);
+ 
+ 	/* Invalidate the entry if no ports are left enabled */
+-	pmap = mvpp2_prs_tcam_port_map_get(pe);
++	pmap = mvpp2_prs_tcam_port_map_get(&pe);
+ 	if (pmap == 0) {
+-		if (add) {
+-			kfree(pe);
++		if (add)
+ 			return -EINVAL;
+-		}
+-		mvpp2_prs_hw_inv(priv, pe->index);
+-		priv->prs_shadow[pe->index].valid = false;
+-		kfree(pe);
++
++		mvpp2_prs_hw_inv(priv, pe.index);
++		priv->prs_shadow[pe.index].valid = false;
+ 		return 0;
+ 	}
+ 
+ 	/* Continue - set next lookup */
+-	mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_DSA);
++	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_DSA);
+ 
+ 	/* Set match on DA */
+ 	len = ETH_ALEN;
+ 	while (len--)
+-		mvpp2_prs_tcam_data_byte_set(pe, len, da[len], 0xff);
++		mvpp2_prs_tcam_data_byte_set(&pe, len, da[len], 0xff);
+ 
+ 	/* Set result info bits */
+ 	if (is_broadcast_ether_addr(da)) {
+@@ -3870,21 +3837,19 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da,
+ 			ri |= MVPP2_PRS_RI_MAC_ME_MASK;
+ 	}
+ 
+-	mvpp2_prs_sram_ri_update(pe, ri, MVPP2_PRS_RI_L2_CAST_MASK |
++	mvpp2_prs_sram_ri_update(&pe, ri, MVPP2_PRS_RI_L2_CAST_MASK |
+ 				 MVPP2_PRS_RI_MAC_ME_MASK);
+-	mvpp2_prs_shadow_ri_set(priv, pe->index, ri, MVPP2_PRS_RI_L2_CAST_MASK |
++	mvpp2_prs_shadow_ri_set(priv, pe.index, ri, MVPP2_PRS_RI_L2_CAST_MASK |
+ 				MVPP2_PRS_RI_MAC_ME_MASK);
+ 
+ 	/* Shift to ethertype */
+-	mvpp2_prs_sram_shift_set(pe, 2 * ETH_ALEN,
++	mvpp2_prs_sram_shift_set(&pe, 2 * ETH_ALEN,
+ 				 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+ 
+ 	/* Update shadow table and hw entry */
+-	priv->prs_shadow[pe->index].udf = MVPP2_PRS_UDF_MAC_DEF;
+-	mvpp2_prs_shadow_set(priv, pe->index, MVPP2_PRS_LU_MAC);
+-	mvpp2_prs_hw_write(priv, pe);
+-
+-	kfree(pe);
++	priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_MAC_DEF;
++	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
++	mvpp2_prs_hw_write(priv, &pe);
+ 
+ 	return 0;
+ }
+@@ -4004,13 +3969,15 @@ static int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type)
+ /* Set prs flow for the port */
+ static int mvpp2_prs_def_flow(struct mvpp2_port *port)
+ {
+-	struct mvpp2_prs_entry *pe;
++	struct mvpp2_prs_entry pe;
+ 	int tid;
+ 
+-	pe = mvpp2_prs_flow_find(port->priv, port->id);
++	memset(&pe, 0, sizeof(pe));
++
++	tid = mvpp2_prs_flow_find(port->priv, port->id);
+ 
+ 	/* Such entry not exist */
+-	if (!pe) {
++	if (tid < 0) {
+ 		/* Go through the all entires from last to first */
+ 		tid = mvpp2_prs_tcam_first_free(port->priv,
+ 						MVPP2_PE_LAST_FREE_TID,
+@@ -4018,24 +3985,21 @@ static int mvpp2_prs_def_flow(struct mvpp2_port *port)
+ 		if (tid < 0)
+ 			return tid;
+ 
+-		pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+-		if (!pe)
+-			return -ENOMEM;
+-
+-		mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_FLOWS);
+-		pe->index = tid;
++		pe.index = tid;
+ 
+ 		/* Set flow ID*/
+-		mvpp2_prs_sram_ai_update(pe, port->id, MVPP2_PRS_FLOW_ID_MASK);
+-		mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_LU_DONE_BIT, 1);
++		mvpp2_prs_sram_ai_update(&pe, port->id, MVPP2_PRS_FLOW_ID_MASK);
++		mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_DONE_BIT, 1);
+ 
+ 		/* Update shadow table */
+-		mvpp2_prs_shadow_set(port->priv, pe->index, MVPP2_PRS_LU_FLOWS);
++		mvpp2_prs_shadow_set(port->priv, pe.index, MVPP2_PRS_LU_FLOWS);
++	} else {
++		mvpp2_prs_init_from_hw(port->priv, &pe, tid);
+ 	}
+ 
+-	mvpp2_prs_tcam_port_map_set(pe, (1 << port->id));
+-	mvpp2_prs_hw_write(port->priv, pe);
+-	kfree(pe);
++	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
++	mvpp2_prs_tcam_port_map_set(&pe, (1 << port->id));
++	mvpp2_prs_hw_write(port->priv, &pe);
+ 
+ 	return 0;
+ }
+-- 
+2.7.4
+
diff --git a/SOURCES/0041-net-mvpp2-Use-relaxed-I-O-in-data-path.patch b/SOURCES/0041-net-mvpp2-Use-relaxed-I-O-in-data-path.patch
new file mode 100644
index 0000000..95694fc
--- /dev/null
+++ b/SOURCES/0041-net-mvpp2-Use-relaxed-I-O-in-data-path.patch
@@ -0,0 +1,127 @@
+From 76fae3a0458b958e4478ba485e9d71b2ee6a5667 Mon Sep 17 00:00:00 2001
+From: Yan Markman <ymarkman@marvell.com>
+Date: Tue, 27 Mar 2018 16:49:05 +0200
+Subject: [PATCH 41/46] net: mvpp2: Use relaxed I/O in data path
+
+Use relaxed I/O on the hot path. This achieves significant performance
+improvements. On a 10G link, this makes a basic iperf TCP test go from
+an average of 4.5 Gbits/sec to about 9.40 Gbits/sec.
+
+Signed-off-by: Yan Markman <ymarkman@marvell.com>
+[Maxime: Commit message, cosmetic changes]
+Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+
+(cherry picked from commit cdcfeb0fb473e34e012b9a78b5cb377a6ad1434d)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 43 +++++++++++++++++++++++++-----------
+ 1 file changed, 30 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 7075e5a..7fc1bbf 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -1359,6 +1359,10 @@ static u32 mvpp2_read(struct mvpp2 *priv, u32 offset)
+ 	return readl(priv->swth_base[0] + offset);
+ }
+ 
++static u32 mvpp2_read_relaxed(struct mvpp2 *priv, u32 offset)
++{
++	return readl_relaxed(priv->swth_base[0] + offset);
++}
+ /* These accessors should be used to access:
+  *
+  * - per-CPU registers, where each CPU has its own copy of the
+@@ -1407,6 +1411,18 @@ static u32 mvpp2_percpu_read(struct mvpp2 *priv, int cpu,
+ 	return readl(priv->swth_base[cpu] + offset);
+ }
+ 
++static void mvpp2_percpu_write_relaxed(struct mvpp2 *priv, int cpu,
++				       u32 offset, u32 data)
++{
++	writel_relaxed(data, priv->swth_base[cpu] + offset);
++}
++
++static u32 mvpp2_percpu_read_relaxed(struct mvpp2 *priv, int cpu,
++				     u32 offset)
++{
++	return readl_relaxed(priv->swth_base[cpu] + offset);
++}
++
+ static dma_addr_t mvpp2_txdesc_dma_addr_get(struct mvpp2_port *port,
+ 					    struct mvpp2_tx_desc *tx_desc)
+ {
+@@ -4442,8 +4458,8 @@ static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,
+ 				<< MVPP22_BM_ADDR_HIGH_VIRT_RLS_SHIFT) &
+ 				MVPP22_BM_ADDR_HIGH_VIRT_RLS_MASK;
+ 
+-		mvpp2_percpu_write(port->priv, cpu,
+-				   MVPP22_BM_ADDR_HIGH_RLS_REG, val);
++		mvpp2_percpu_write_relaxed(port->priv, cpu,
++					   MVPP22_BM_ADDR_HIGH_RLS_REG, val);
+ 	}
+ 
+ 	/* MVPP2_BM_VIRT_RLS_REG is not interpreted by HW, and simply
+@@ -4451,10 +4467,10 @@ static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,
+ 	 * descriptor. Instead of storing the virtual address, we
+ 	 * store the physical address
+ 	 */
+-	mvpp2_percpu_write(port->priv, cpu,
+-			   MVPP2_BM_VIRT_RLS_REG, buf_phys_addr);
+-	mvpp2_percpu_write(port->priv, cpu,
+-			   MVPP2_BM_PHY_RLS_REG(pool), buf_dma_addr);
++	mvpp2_percpu_write_relaxed(port->priv, cpu,
++				   MVPP2_BM_VIRT_RLS_REG, buf_phys_addr);
++	mvpp2_percpu_write_relaxed(port->priv, cpu,
++				   MVPP2_BM_PHY_RLS_REG(pool), buf_dma_addr);
+ 
+ 	put_cpu();
+ }
+@@ -5546,7 +5562,8 @@ static int mvpp2_aggr_desc_num_check(struct mvpp2 *priv,
+ 	if ((aggr_txq->count + num) > MVPP2_AGGR_TXQ_SIZE) {
+ 		/* Update number of occupied aggregated Tx descriptors */
+ 		int cpu = smp_processor_id();
+-		u32 val = mvpp2_read(priv, MVPP2_AGGR_TXQ_STATUS_REG(cpu));
++		u32 val = mvpp2_read_relaxed(priv,
++					     MVPP2_AGGR_TXQ_STATUS_REG(cpu));
+ 
+ 		aggr_txq->count = val & MVPP2_AGGR_TXQ_PENDING_MASK;
+ 	}
+@@ -5570,9 +5587,9 @@ static int mvpp2_txq_alloc_reserved_desc(struct mvpp2 *priv,
+ 	int cpu = smp_processor_id();
+ 
+ 	val = (txq->id << MVPP2_TXQ_RSVD_REQ_Q_OFFSET) | num;
+-	mvpp2_percpu_write(priv, cpu, MVPP2_TXQ_RSVD_REQ_REG, val);
++	mvpp2_percpu_write_relaxed(priv, cpu, MVPP2_TXQ_RSVD_REQ_REG, val);
+ 
+-	val = mvpp2_percpu_read(priv, cpu, MVPP2_TXQ_RSVD_RSLT_REG);
++	val = mvpp2_percpu_read_relaxed(priv, cpu, MVPP2_TXQ_RSVD_RSLT_REG);
+ 
+ 	return val & MVPP2_TXQ_RSVD_RSLT_MASK;
+ }
+@@ -5677,8 +5694,8 @@ static inline int mvpp2_txq_sent_desc_proc(struct mvpp2_port *port,
+ 	u32 val;
+ 
+ 	/* Reading status reg resets transmitted descriptor counter */
+-	val = mvpp2_percpu_read(port->priv, smp_processor_id(),
+-				MVPP2_TXQ_SENT_REG(txq->id));
++	val = mvpp2_percpu_read_relaxed(port->priv, smp_processor_id(),
++					MVPP2_TXQ_SENT_REG(txq->id));
+ 
+ 	return (val & MVPP2_TRANSMITTED_COUNT_MASK) >>
+ 		MVPP2_TRANSMITTED_COUNT_OFFSET;
+@@ -7044,8 +7061,8 @@ static int mvpp2_poll(struct napi_struct *napi, int budget)
+ 	 *
+ 	 * Each CPU has its own Rx/Tx cause register
+ 	 */
+-	cause_rx_tx = mvpp2_percpu_read(port->priv, qv->sw_thread_id,
+-					MVPP2_ISR_RX_TX_CAUSE_REG(port->id));
++	cause_rx_tx = mvpp2_percpu_read_relaxed(port->priv, qv->sw_thread_id,
++						MVPP2_ISR_RX_TX_CAUSE_REG(port->id));
+ 
+ 	cause_misc = cause_rx_tx & MVPP2_CAUSE_MISC_SUM_MASK;
+ 	if (cause_misc) {
+-- 
+2.7.4
+
diff --git a/SOURCES/0042-net-mvpp2-Fix-parser-entry-init-boundary-check.patch b/SOURCES/0042-net-mvpp2-Fix-parser-entry-init-boundary-check.patch
new file mode 100644
index 0000000..b66f1a0
--- /dev/null
+++ b/SOURCES/0042-net-mvpp2-Fix-parser-entry-init-boundary-check.patch
@@ -0,0 +1,34 @@
+From 83d75929647f7f8a4c66c684e9962e497e58a5e4 Mon Sep 17 00:00:00 2001
+From: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Date: Thu, 5 Apr 2018 11:55:48 +0200
+Subject: [PATCH 42/46] net: mvpp2: Fix parser entry init boundary check
+
+Boundary check in mvpp2_prs_init_from_hw must be done according to the
+passed "tid" parameter, not the mvpp2_prs_entry index, which is not yet
+initialized at the time of the check.
+
+Fixes: 47e0e14eb1a6 ("net: mvpp2: Make mvpp2_prs_hw_read a parser entry init function")
+Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 3d92f0b582062127026af1fb5e86eda4a3b01783)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 7fc1bbf..54a0389 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -1604,7 +1604,7 @@ static int mvpp2_prs_init_from_hw(struct mvpp2 *priv,
+ {
+ 	int i;
+ 
+-	if (pe->index > MVPP2_PRS_TCAM_SRAM_SIZE - 1)
++	if (tid > MVPP2_PRS_TCAM_SRAM_SIZE - 1)
+ 		return -EINVAL;
+ 
+ 	memset(pe, 0, sizeof(*pe));
+-- 
+2.7.4
+
diff --git a/SOURCES/0043-net-mvpp2-Fix-TCAM-filter-reserved-range.patch b/SOURCES/0043-net-mvpp2-Fix-TCAM-filter-reserved-range.patch
new file mode 100644
index 0000000..7b0ba81
--- /dev/null
+++ b/SOURCES/0043-net-mvpp2-Fix-TCAM-filter-reserved-range.patch
@@ -0,0 +1,43 @@
+From 261ee18d8d5c66562421ad207c482fa17b62a567 Mon Sep 17 00:00:00 2001
+From: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Date: Mon, 16 Apr 2018 10:07:23 +0200
+Subject: [PATCH 43/46] net: mvpp2: Fix TCAM filter reserved range
+
+Marvell's PPv2 controller has a Packet Header parser, which uses a
+fixed-size TCAM array of filter entries.
+
+The mvpp2 driver reserves some ranges among the 256 TCAM entries to
+perform MAC and VID filtering. The rest of the TCAM ids are freely usable
+for other features, such as IPv4 proto matching.
+
+This commit fixes the MVPP2_PE_LAST_FREE_TID define that sets the end of
+the "free range", which included the MAC range. This could therefore allow
+some other features to use entries dedicated to MAC filtering,
+lowering the number of unicast/multicast addresses that could be allowed
+before switching to promiscuous mode.
+
+Fixes: 10fea26ce2aa ("net: mvpp2: Add support for unicast filtering")
+Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 982e05001c472066ab288e4269ad6cab48889f0d)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 54a0389..9deb79b 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -663,7 +663,7 @@ enum mvpp2_tag_type {
+ #define MVPP2_PE_VID_FILT_RANGE_END     (MVPP2_PRS_TCAM_SRAM_SIZE - 31)
+ #define MVPP2_PE_VID_FILT_RANGE_START   (MVPP2_PE_VID_FILT_RANGE_END - \
+ 					 MVPP2_PRS_VLAN_FILT_RANGE_SIZE + 1)
+-#define MVPP2_PE_LAST_FREE_TID          (MVPP2_PE_VID_FILT_RANGE_START - 1)
++#define MVPP2_PE_LAST_FREE_TID          (MVPP2_PE_MAC_RANGE_START - 1)
+ #define MVPP2_PE_IP6_EXT_PROTO_UN	(MVPP2_PRS_TCAM_SRAM_SIZE - 30)
+ #define MVPP2_PE_IP6_ADDR_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 29)
+ #define MVPP2_PE_IP4_ADDR_UN		(MVPP2_PRS_TCAM_SRAM_SIZE - 28)
+-- 
+2.7.4
+
diff --git a/SOURCES/0044-net-mvpp2-Fix-DMA-address-mask-size.patch b/SOURCES/0044-net-mvpp2-Fix-DMA-address-mask-size.patch
new file mode 100644
index 0000000..2804802
--- /dev/null
+++ b/SOURCES/0044-net-mvpp2-Fix-DMA-address-mask-size.patch
@@ -0,0 +1,80 @@
+From 329959e4e0ed9e8658ab84fa1df5b2225a623a3d Mon Sep 17 00:00:00 2001
+From: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Date: Wed, 18 Apr 2018 11:14:44 +0200
+Subject: [PATCH 44/46] net: mvpp2: Fix DMA address mask size
+
+PPv2 TX/RX descriptors uses 40bits DMA addresses, but 41 bits masks were
+used (GENMASK_ULL(40, 0)).
+
+This commit fixes that by using the correct mask.
+
+Fixes: e7c5359f2eed ("net: mvpp2: introduce PPv2.2 HW descriptors and adapt accessors")
+Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit da42bb271305d68df6cbf99eed90542f1f1ee1c9)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 9deb79b..4202f9b 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -916,6 +916,8 @@ static struct {
+ 
+ #define MVPP2_MIB_COUNTERS_STATS_DELAY		(1 * HZ)
+ 
++#define MVPP2_DESC_DMA_MASK	DMA_BIT_MASK(40)
++
+ /* Definitions */
+ 
+ /* Shared Packet Processor resources */
+@@ -1429,7 +1431,7 @@ static dma_addr_t mvpp2_txdesc_dma_addr_get(struct mvpp2_port *port,
+ 	if (port->priv->hw_version == MVPP21)
+ 		return tx_desc->pp21.buf_dma_addr;
+ 	else
+-		return tx_desc->pp22.buf_dma_addr_ptp & GENMASK_ULL(40, 0);
++		return tx_desc->pp22.buf_dma_addr_ptp & MVPP2_DESC_DMA_MASK;
+ }
+ 
+ static void mvpp2_txdesc_dma_addr_set(struct mvpp2_port *port,
+@@ -1447,7 +1449,7 @@ static void mvpp2_txdesc_dma_addr_set(struct mvpp2_port *port,
+ 	} else {
+ 		u64 val = (u64)addr;
+ 
+-		tx_desc->pp22.buf_dma_addr_ptp &= ~GENMASK_ULL(40, 0);
++		tx_desc->pp22.buf_dma_addr_ptp &= ~MVPP2_DESC_DMA_MASK;
+ 		tx_desc->pp22.buf_dma_addr_ptp |= val;
+ 		tx_desc->pp22.packet_offset = offset;
+ 	}
+@@ -1507,7 +1509,7 @@ static dma_addr_t mvpp2_rxdesc_dma_addr_get(struct mvpp2_port *port,
+ 	if (port->priv->hw_version == MVPP21)
+ 		return rx_desc->pp21.buf_dma_addr;
+ 	else
+-		return rx_desc->pp22.buf_dma_addr_key_hash & GENMASK_ULL(40, 0);
++		return rx_desc->pp22.buf_dma_addr_key_hash & MVPP2_DESC_DMA_MASK;
+ }
+ 
+ static unsigned long mvpp2_rxdesc_cookie_get(struct mvpp2_port *port,
+@@ -1516,7 +1518,7 @@ static unsigned long mvpp2_rxdesc_cookie_get(struct mvpp2_port *port,
+ 	if (port->priv->hw_version == MVPP21)
+ 		return rx_desc->pp21.buf_cookie;
+ 	else
+-		return rx_desc->pp22.buf_cookie_misc & GENMASK_ULL(40, 0);
++		return rx_desc->pp22.buf_cookie_misc & MVPP2_DESC_DMA_MASK;
+ }
+ 
+ static size_t mvpp2_rxdesc_size_get(struct mvpp2_port *port,
+@@ -8789,7 +8791,7 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	if (priv->hw_version == MVPP22) {
+-		err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(40));
++		err = dma_set_mask(&pdev->dev, MVPP2_DESC_DMA_MASK);
+ 		if (err)
+ 			goto err_mg_clk;
+ 		/* Sadly, the BM pools all share the same register to
+-- 
+2.7.4
+
diff --git a/SOURCES/0045-net-mvpp2-Fix-clk-error-path-in-mvpp2_probe.patch b/SOURCES/0045-net-mvpp2-Fix-clk-error-path-in-mvpp2_probe.patch
new file mode 100644
index 0000000..7bfc50c
--- /dev/null
+++ b/SOURCES/0045-net-mvpp2-Fix-clk-error-path-in-mvpp2_probe.patch
@@ -0,0 +1,87 @@
+From b3caf78626b230ecd05182b56884f682ac1e43b2 Mon Sep 17 00:00:00 2001
+From: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Date: Wed, 25 Apr 2018 20:21:16 +0200
+Subject: [PATCH 45/46] net: mvpp2: Fix clk error path in mvpp2_probe
+
+When clk_prepare_enable fails for the axi_clk, the mg_clk isn't properly
+cleaned up. Add another jump label to handle that case, and make sure we
+jump to it in the later error cases.
+
+Fixes: 4792ea04bcd0 ("net: mvpp2: Fix clock resource by adding an optional bus clock")
+Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 45f972adb7f4db2d7f02af728ccd104113336074)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 4202f9b..0c2f048 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -8774,12 +8774,12 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 		if (IS_ERR(priv->axi_clk)) {
+ 			err = PTR_ERR(priv->axi_clk);
+ 			if (err == -EPROBE_DEFER)
+-				goto err_gop_clk;
++				goto err_mg_clk;
+ 			priv->axi_clk = NULL;
+ 		} else {
+ 			err = clk_prepare_enable(priv->axi_clk);
+ 			if (err < 0)
+-				goto err_gop_clk;
++				goto err_mg_clk;
+ 		}
+ 
+ 		/* Get system's tclk rate */
+@@ -8793,7 +8793,7 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 	if (priv->hw_version == MVPP22) {
+ 		err = dma_set_mask(&pdev->dev, MVPP2_DESC_DMA_MASK);
+ 		if (err)
+-			goto err_mg_clk;
++			goto err_axi_clk;
+ 		/* Sadly, the BM pools all share the same register to
+ 		 * store the high 32 bits of their address. So they
+ 		 * must all have the same high 32 bits, which forces
+@@ -8801,14 +8801,14 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 		 */
+ 		err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+ 		if (err)
+-			goto err_mg_clk;
++			goto err_axi_clk;
+ 	}
+ 
+ 	/* Initialize network controller */
+ 	err = mvpp2_init(pdev, priv);
+ 	if (err < 0) {
+ 		dev_err(&pdev->dev, "failed to initialize controller\n");
+-		goto err_mg_clk;
++		goto err_axi_clk;
+ 	}
+ 
+ 	/* Initialize ports */
+@@ -8821,7 +8821,7 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 	if (priv->port_count == 0) {
+ 		dev_err(&pdev->dev, "no ports enabled\n");
+ 		err = -ENODEV;
+-		goto err_mg_clk;
++		goto err_axi_clk;
+ 	}
+ 
+ 	/* Statistics must be gathered regularly because some of them (like
+@@ -8849,8 +8849,9 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 			mvpp2_port_remove(priv->port_list[i]);
+ 		i++;
+ 	}
+-err_mg_clk:
++err_axi_clk:
+ 	clk_disable_unprepare(priv->axi_clk);
++err_mg_clk:
+ 	if (priv->hw_version == MVPP22)
+ 		clk_disable_unprepare(priv->mg_clk);
+ err_gop_clk:
+-- 
+2.7.4
+
diff --git a/SOURCES/0046-net-mvpp2-Fix-clock-resource-by-adding-missing-mg_co.patch b/SOURCES/0046-net-mvpp2-Fix-clock-resource-by-adding-missing-mg_co.patch
new file mode 100644
index 0000000..cdd3aa0
--- /dev/null
+++ b/SOURCES/0046-net-mvpp2-Fix-clock-resource-by-adding-missing-mg_co.patch
@@ -0,0 +1,85 @@
+From d8d511c8d065b531effcf478af68112d4502001c Mon Sep 17 00:00:00 2001
+From: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Date: Wed, 25 Apr 2018 20:21:17 +0200
+Subject: [PATCH 46/46] net: mvpp2: Fix clock resource by adding missing
+ mg_core_clk
+
+Marvell's PPv2.2 IP needs an additional clock named "MG Core clock".
+This is required on Armada 7K and 8K.
+
+This commit adds the required clock in mvpp2, making sure it's only
+used on PPv2.2.
+
+Fixes: c7e92def1ef4 ("clk: mvebu: cp110: Fix clock tree representation")
+Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 9af771ced473f92b5e57d086a0c2453fc0cb149c)
+Signed-off-by: Marcin Wojtas <mw@semihalf.com>
+---
+ drivers/net/ethernet/marvell/mvpp2.c | 19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
+index 0c2f048..6f41023 100644
+--- a/drivers/net/ethernet/marvell/mvpp2.c
++++ b/drivers/net/ethernet/marvell/mvpp2.c
+@@ -942,6 +942,7 @@ struct mvpp2 {
+ 	struct clk *pp_clk;
+ 	struct clk *gop_clk;
+ 	struct clk *mg_clk;
++	struct clk *mg_core_clk;
+ 	struct clk *axi_clk;
+ 
+ 	/* List of pointers to port structures */
+@@ -8768,18 +8769,27 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 			err = clk_prepare_enable(priv->mg_clk);
+ 			if (err < 0)
+ 				goto err_gop_clk;
++
++			priv->mg_core_clk = devm_clk_get(&pdev->dev, "mg_core_clk");
++			if (IS_ERR(priv->mg_core_clk)) {
++				priv->mg_core_clk = NULL;
++			} else {
++				err = clk_prepare_enable(priv->mg_core_clk);
++				if (err < 0)
++					goto err_mg_clk;
++			}
+ 		}
+ 
+ 		priv->axi_clk = devm_clk_get(&pdev->dev, "axi_clk");
+ 		if (IS_ERR(priv->axi_clk)) {
+ 			err = PTR_ERR(priv->axi_clk);
+ 			if (err == -EPROBE_DEFER)
+-				goto err_mg_clk;
++				goto err_mg_core_clk;
+ 			priv->axi_clk = NULL;
+ 		} else {
+ 			err = clk_prepare_enable(priv->axi_clk);
+ 			if (err < 0)
+-				goto err_mg_clk;
++				goto err_mg_core_clk;
+ 		}
+ 
+ 		/* Get system's tclk rate */
+@@ -8851,6 +8861,10 @@ static int mvpp2_probe(struct platform_device *pdev)
+ 	}
+ err_axi_clk:
+ 	clk_disable_unprepare(priv->axi_clk);
++
++err_mg_core_clk:
++	if (priv->hw_version == MVPP22)
++		clk_disable_unprepare(priv->mg_core_clk);
+ err_mg_clk:
+ 	if (priv->hw_version == MVPP22)
+ 		clk_disable_unprepare(priv->mg_clk);
+@@ -8898,6 +8912,7 @@ static int mvpp2_remove(struct platform_device *pdev)
+ 		return 0;
+ 
+ 	clk_disable_unprepare(priv->axi_clk);
++	clk_disable_unprepare(priv->mg_core_clk);
+ 	clk_disable_unprepare(priv->mg_clk);
+ 	clk_disable_unprepare(priv->pp_clk);
+ 	clk_disable_unprepare(priv->gop_clk);
+-- 
+2.7.4
+
diff --git a/SOURCES/centos-ca-secureboot.der b/SOURCES/centos-ca-secureboot.der
new file mode 100644
index 0000000..44a2563
--- /dev/null
+++ b/SOURCES/centos-ca-secureboot.der
Binary files differ
diff --git a/SOURCES/centos-kpatch.x509 b/SOURCES/centos-kpatch.x509
new file mode 100644
index 0000000..ca57a43
--- /dev/null
+++ b/SOURCES/centos-kpatch.x509
Binary files differ
diff --git a/SOURCES/centos-ldup.x509 b/SOURCES/centos-ldup.x509
new file mode 100644
index 0000000..9c65dd3
--- /dev/null
+++ b/SOURCES/centos-ldup.x509
Binary files differ
diff --git a/SOURCES/centossecureboot001.crt b/SOURCES/centossecureboot001.crt
new file mode 100644
index 0000000..c67b0f3
--- /dev/null
+++ b/SOURCES/centossecureboot001.crt
@@ -0,0 +1,81 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            b6:16:15:71:72:fb:31:7e
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: CN=CentOS Secure Boot (CA key 1)/emailAddress=security@centos.org
+        Validity
+            Not Before: Aug  1 11:47:30 2018 GMT
+            Not After : Dec 31 11:47:30 2037 GMT
+        Subject: CN=CentOS Secure Boot (key 1)/emailAddress=security@centos.org
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:c1:a3:6a:f4:2d:71:83:6c:21:ca:0c:b7:ac:fa:
+                    76:80:43:03:40:87:5d:de:e9:1e:df:ad:e7:2b:51:
+                    cb:f8:31:0f:9a:db:ab:23:25:04:11:05:57:7d:f2:
+                    4b:8d:1e:b3:75:78:1d:b9:57:8b:18:0b:bb:7e:e3:
+                    24:0f:6a:40:5f:2b:4f:03:a5:85:94:d2:f9:08:a0:
+                    bc:db:a5:ea:4f:7f:e8:7c:d1:a9:f8:f0:9c:25:18:
+                    00:14:c4:c4:35:7d:1d:4c:8a:8d:95:f8:ed:65:97:
+                    a5:a4:da:7d:cb:f0:33:3b:b7:03:94:68:47:05:57:
+                    6c:96:91:ac:14:f2:e3:f6:6d:4a:18:cf:68:8a:35:
+                    6f:8e:26:99:7f:db:c9:83:54:c2:c3:bf:ad:45:a0:
+                    aa:a0:86:5f:20:b1:86:1b:ae:b7:28:15:11:f9:65:
+                    53:5d:70:33:9b:a3:c7:b5:c8:11:ff:55:3b:e7:46:
+                    f1:6c:6b:8c:bb:f2:9f:36:23:b1:2d:23:2f:8f:4f:
+                    6c:a8:cc:ae:f5:56:9e:22:6c:0e:9a:4a:b1:bd:b2:
+                    76:15:5c:05:85:b8:5e:dc:8c:a5:c3:e0:75:51:a4:
+                    94:9b:03:2e:7b:f8:d3:b9:dd:7f:88:ce:2e:2f:28:
+                    4c:b4:92:2f:e6:e0:67:0a:d0:ff:c5:d2:79:a6:ef:
+                    94:0f
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Key Usage: 
+                Digital Signature
+            X509v3 Subject Key Identifier: 
+                F0:37:C6:EA:EC:36:D4:05:7A:52:6C:0E:C6:D5:A9:5B:32:4E:E1:29
+            X509v3 Authority Key Identifier: 
+                keyid:54:EC:81:85:89:3E:E9:1A:DB:08:F7:44:88:54:7E:8E:3F:74:3A:F3
+
+    Signature Algorithm: sha256WithRSAEncryption
+        97:97:ba:a6:0b:5b:bb:84:39:2e:ef:8b:51:9a:89:bb:65:3c:
+        dc:15:d0:5a:88:c5:af:ce:93:f5:c1:74:98:15:59:a9:38:da:
+        11:fd:46:d5:4f:23:7c:03:1f:ae:0c:70:93:94:a7:61:2f:4b:
+        2f:5f:bb:cc:8a:d7:4a:24:66:73:85:b4:19:13:fc:6a:61:4a:
+        28:1f:a2:38:f4:72:90:03:c4:3e:64:63:8b:fb:15:22:22:4e:
+        b9:43:d9:b4:3d:3a:60:c1:4d:3a:09:85:68:7a:bc:3b:f9:ef:
+        f3:f5:e9:c9:4f:80:8c:c6:e9:cb:ef:28:44:b0:5d:d4:9e:4f:
+        0f:02:9a:65:aa:98:35:b4:6f:d2:80:e3:08:ef:12:d0:17:56:
+        a6:a1:42:1e:1d:ab:e5:33:c0:fd:88:0d:40:42:81:c8:27:30:
+        17:07:57:3e:05:9d:aa:05:0e:5b:3a:79:b4:29:aa:7c:42:5a:
+        ad:43:59:fb:34:4d:dc:62:58:63:e4:fb:de:bb:fd:6c:4e:97:
+        58:f4:b9:99:4a:71:fe:7f:16:50:55:25:46:39:96:9b:88:6c:
+        75:19:33:9e:70:b3:04:82:fe:16:a8:8e:22:47:83:6d:16:77:
+        da:26:ad:31:d8:06:6d:c5:7e:46:4b:21:ab:ae:ec:2a:93:71:
+        da:7f:89:1d
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgIJALYWFXFy+zF+MA0GCSqGSIb3DQEBCwUAMEwxJjAkBgNV
+BAMMHUNlbnRPUyBTZWN1cmUgQm9vdCAoQ0Ega2V5IDEpMSIwIAYJKoZIhvcNAQkB
+FhNzZWN1cml0eUBjZW50b3Mub3JnMB4XDTE4MDgwMTExNDczMFoXDTM3MTIzMTEx
+NDczMFowSTEjMCEGA1UEAxMaQ2VudE9TIFNlY3VyZSBCb290IChrZXkgMSkxIjAg
+BgkqhkiG9w0BCQEWE3NlY3VyaXR5QGNlbnRvcy5vcmcwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDBo2r0LXGDbCHKDLes+naAQwNAh13e6R7frecrUcv4
+MQ+a26sjJQQRBVd98kuNHrN1eB25V4sYC7t+4yQPakBfK08DpYWU0vkIoLzbpepP
+f+h80an48JwlGAAUxMQ1fR1Mio2V+O1ll6Wk2n3L8DM7twOUaEcFV2yWkawU8uP2
+bUoYz2iKNW+OJpl/28mDVMLDv61FoKqghl8gsYYbrrcoFRH5ZVNdcDObo8e1yBH/
+VTvnRvFsa4y78p82I7EtIy+PT2yozK71Vp4ibA6aSrG9snYVXAWFuF7cjKXD4HVR
+pJSbAy57+NO53X+Izi4vKEy0ki/m4GcK0P/F0nmm75QPAgMBAAGjXTBbMAwGA1Ud
+EwEB/wQCMAAwCwYDVR0PBAQDAgeAMB0GA1UdDgQWBBTwN8bq7DbUBXpSbA7G1alb
+Mk7hKTAfBgNVHSMEGDAWgBRU7IGFiT7pGtsI90SIVH6OP3Q68zANBgkqhkiG9w0B
+AQsFAAOCAQEAl5e6pgtbu4Q5Lu+LUZqJu2U83BXQWojFr86T9cF0mBVZqTjaEf1G
+1U8jfAMfrgxwk5SnYS9LL1+7zIrXSiRmc4W0GRP8amFKKB+iOPRykAPEPmRji/sV
+IiJOuUPZtD06YMFNOgmFaHq8O/nv8/XpyU+AjMbpy+8oRLBd1J5PDwKaZaqYNbRv
+0oDjCO8S0BdWpqFCHh2r5TPA/YgNQEKByCcwFwdXPgWdqgUOWzp5tCmqfEJarUNZ
++zRN3GJYY+T73rv9bE6XWPS5mUpx/n8WUFUlRjmWm4hsdRkznnCzBIL+FqiOIkeD
+bRZ32iatMdgGbcV+Rkshq67sKpNx2n+JHQ==
+-----END CERTIFICATE-----

--
Gitblit v1.8.0