kernel: bump 4.14 to 4.14.51

The sender domain has a DMARC Reject/Quarantine policy which disallows
sending mailing list messages using the original "From" header.

To mitigate this problem, the original message has been wrapped
automatically by the mailing list software.
Refresh patches.

Remove patch that can be reverse applied:
mvebu/patches-4.14/530-ATA-ahci_mvebu-enable-stop_engine-override.patch
mvebu/patches-4.14/531-ATA-ahci_mvebu-pmp-stop-errata-226.patch

Update patch that no longer applied:
ipq806x/patches-4.14/0035-clk-mux-Split-out-register-accessors-for-reuse.patch

Compiled-tested-for: lantiq, ramips
Run-tested-on: lantiq BT hh5a, ramips MIR3g

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Tested-by: Michael Yartys <michael.yartys@protonmail.com>
Tested-by: Rosen Penev <rosenp@gmail.com>
This commit is contained in:
Kevin Darbyshire-Bryant 2018-06-21 19:24:05 +00:00 committed by John Crispin
parent 31c26cece3
commit 094d49cddf
13 changed files with 21 additions and 360 deletions

View File

@ -5,12 +5,12 @@ LINUX_RELEASE?=1
LINUX_VERSION-3.18 = .71 LINUX_VERSION-3.18 = .71
LINUX_VERSION-4.4 = .121 LINUX_VERSION-4.4 = .121
LINUX_VERSION-4.9 = .109 LINUX_VERSION-4.9 = .109
LINUX_VERSION-4.14 = .50 LINUX_VERSION-4.14 = .51
LINUX_KERNEL_HASH-3.18.71 = 5abc9778ad44ce02ed6c8ab52ece8a21c6d20d21f6ed8a19287b4a38a50c1240 LINUX_KERNEL_HASH-3.18.71 = 5abc9778ad44ce02ed6c8ab52ece8a21c6d20d21f6ed8a19287b4a38a50c1240
LINUX_KERNEL_HASH-4.4.121 = 44a88268b5088dc326b30c9b9133ac35a9a200b636b7268d08f32abeae6ca729 LINUX_KERNEL_HASH-4.4.121 = 44a88268b5088dc326b30c9b9133ac35a9a200b636b7268d08f32abeae6ca729
LINUX_KERNEL_HASH-4.9.109 = 3dcd5654a553432119492b69e649c4ed117781bfd571edcb02346c945be359b0 LINUX_KERNEL_HASH-4.9.109 = 3dcd5654a553432119492b69e649c4ed117781bfd571edcb02346c945be359b0
LINUX_KERNEL_HASH-4.14.50 = 703a8d013b25dc428d936f72858fa0c702c22cb3114a040fb9bb47562e4ea2ac LINUX_KERNEL_HASH-4.14.51 = dab2402baa2444348f9b3c354e8f65382a466d1766942a57441209f9a2df972b
remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1)))) remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1))))
sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1))))))) sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1)))))))

View File

@ -20,7 +20,7 @@ Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
--- a/drivers/net/ethernet/stmicro/stmmac/common.h --- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -49,7 +49,7 @@ @@ -46,7 +46,7 @@
#define STMMAC_GET_ENTRY(x, size) ((x + 1) & (size - 1)) #define STMMAC_GET_ENTRY(x, size) ((x + 1) & (size - 1))
#undef FRAME_FILTER_DEBUG #undef FRAME_FILTER_DEBUG

View File

@ -45,7 +45,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
{ {
--- a/net/ipv6/netfilter/Kconfig --- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig
@@ -71,6 +71,14 @@ config NFT_FIB_IPV6 @@ -99,6 +99,14 @@ config NFT_FIB_IPV6
endif # NF_TABLES_IPV6 endif # NF_TABLES_IPV6
endif # NF_TABLES endif # NF_TABLES

View File

@ -72,7 +72,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
--- a/net/ipv6/netfilter/Kconfig --- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig
@@ -72,8 +72,9 @@ endif # NF_TABLES_IPV6 @@ -100,8 +100,9 @@ endif # NF_TABLES_IPV6
endif # NF_TABLES endif # NF_TABLES
config NF_FLOW_TABLE_IPV6 config NF_FLOW_TABLE_IPV6

View File

@ -37,7 +37,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
--- a/net/ipv6/netfilter/Kconfig --- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig
@@ -73,8 +73,7 @@ endif # NF_TABLES @@ -101,8 +101,7 @@ endif # NF_TABLES
config NF_FLOW_TABLE_IPV6 config NF_FLOW_TABLE_IPV6
tristate "Netfilter flow table IPv6 module" tristate "Netfilter flow table IPv6 module"

View File

@ -28,7 +28,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
depends on !NF_CONNTRACK || NF_CONNTRACK depends on !NF_CONNTRACK || NF_CONNTRACK
--- a/net/ipv6/netfilter/Kconfig --- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig
@@ -69,7 +69,6 @@ config NFT_FIB_IPV6 @@ -97,7 +97,6 @@ config NFT_FIB_IPV6
multicast or blackhole. multicast or blackhole.
endif # NF_TABLES_IPV6 endif # NF_TABLES_IPV6
@ -36,7 +36,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
config NF_FLOW_TABLE_IPV6 config NF_FLOW_TABLE_IPV6
tristate "Netfilter flow table IPv6 module" tristate "Netfilter flow table IPv6 module"
@@ -79,6 +78,8 @@ config NF_FLOW_TABLE_IPV6 @@ -107,6 +106,8 @@ config NF_FLOW_TABLE_IPV6
To compile it as a module, choose M here. To compile it as a module, choose M here.

View File

@ -8,11 +8,9 @@ Signed-off-by: Chen Minqiang <ptpt52@gmail.com>
drivers/net/ethernet/qualcomm/essedma/edma.c | 2 +- drivers/net/ethernet/qualcomm/essedma/edma.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-) 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qualcomm/essedma/edma.c b/drivers/net/ethernet/qualcomm/essedma/edma.c
index a3c0d66..29bc9f8 100644
--- a/drivers/net/ethernet/qualcomm/essedma/edma.c --- a/drivers/net/ethernet/qualcomm/essedma/edma.c
+++ b/drivers/net/ethernet/qualcomm/essedma/edma.c +++ b/drivers/net/ethernet/qualcomm/essedma/edma.c
@@ -193,7 +193,7 @@ static int edma_alloc_rx_buf(struct edma_common_info @@ -201,7 +201,7 @@ static int edma_alloc_rx_buf(struct edma
skb = sw_desc->skb; skb = sw_desc->skb;
} else { } else {
/* alloc skb */ /* alloc skb */
@ -21,6 +19,3 @@ index a3c0d66..29bc9f8 100644
if (!skb) { if (!skb) {
/* Better luck next round */ /* Better luck next round */
break; break;
--
2.17.1

View File

@ -1,12 +1,12 @@
--- a/drivers/of/fdt.c --- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c +++ b/drivers/of/fdt.c
@@ -1127,6 +1127,9 @@ int __init early_init_dt_scan_chosen(uns @@ -1130,6 +1130,9 @@ int __init early_init_dt_scan_chosen(uns
p = of_get_flat_dt_prop(node, "bootargs", &l); p = of_get_flat_dt_prop(node, "bootargs", &l);
if (p != NULL && l > 0) if (p != NULL && l > 0)
strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));
+ p = of_get_flat_dt_prop(node, "bootargs-append", &l); + p = of_get_flat_dt_prop(node, "bootargs-append", &l);
+ if (p != NULL && l > 0) + if (p != NULL && l > 0)
+ strlcat(data, p, min_t(int, strlen(data) + (int)l, COMMAND_LINE_SIZE)); + strlcat(data, p, min_t(int, strlen(data) + (int)l, COMMAND_LINE_SIZE));
/* /*
* CONFIG_CMDLINE is meant to be a default in case nothing else * CONFIG_CMDLINE is meant to be a default in case nothing else

View File

@ -135,14 +135,14 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
if (mux->lock) if (mux->lock)
spin_lock_irqsave(mux->lock, flags); spin_lock_irqsave(mux->lock, flags);
else else
@@ -102,14 +121,14 @@ static int clk_mux_set_parent(struct clk @@ -110,14 +129,14 @@ static int clk_mux_determine_rate(struct
} }
const struct clk_ops clk_mux_ops = { const struct clk_ops clk_mux_ops = {
- .get_parent = clk_mux_get_parent, - .get_parent = clk_mux_get_parent,
+ .get_parent = _clk_mux_get_parent, + .get_parent = _clk_mux_get_parent,
.set_parent = clk_mux_set_parent, .set_parent = clk_mux_set_parent,
.determine_rate = __clk_mux_determine_rate, .determine_rate = clk_mux_determine_rate,
}; };
EXPORT_SYMBOL_GPL(clk_mux_ops); EXPORT_SYMBOL_GPL(clk_mux_ops);
@ -152,7 +152,7 @@ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
}; };
EXPORT_SYMBOL_GPL(clk_mux_ro_ops); EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
@@ -117,7 +136,7 @@ struct clk_hw *clk_hw_register_mux_table @@ -125,7 +144,7 @@ struct clk_hw *clk_hw_register_mux_table
const char * const *parent_names, u8 num_parents, const char * const *parent_names, u8 num_parents,
unsigned long flags, unsigned long flags,
void __iomem *reg, u8 shift, u32 mask, void __iomem *reg, u8 shift, u32 mask,

View File

@ -11,9 +11,9 @@ Signed-off-by: John Crispin <john@phrozen.org>
--- a/arch/arm/boot/dts/Makefile --- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile
@@ -699,6 +699,16 @@ dtb-$(CONFIG_ARCH_QCOM) += \ @@ -699,6 +699,16 @@ dtb-$(CONFIG_ARCH_QCOM) += \
qcom-apq8084-mtp.dtb \ qcom-apq8084-mtp.dtb \
qcom-ipq4019-ap.dk01.1-c1.dtb \ qcom-ipq4019-ap.dk01.1-c1.dtb \
qcom-ipq8064-ap148.dtb \ qcom-ipq8064-ap148.dtb \
+ qcom-ipq8064-c2600.dtb \ + qcom-ipq8064-c2600.dtb \
+ qcom-ipq8064-d7800.dtb \ + qcom-ipq8064-d7800.dtb \
+ qcom-ipq8064-db149.dtb \ + qcom-ipq8064-db149.dtb \
@ -24,6 +24,6 @@ Signed-off-by: John Crispin <john@phrozen.org>
+ qcom-ipq8064-wpq864.dtb \ + qcom-ipq8064-wpq864.dtb \
+ qcom-ipq8065-nbg6817.dtb \ + qcom-ipq8065-nbg6817.dtb \
+ qcom-ipq8065-r7800.dtb \ + qcom-ipq8065-r7800.dtb \
qcom-msm8660-surf.dtb \ qcom-msm8660-surf.dtb \
qcom-msm8960-cdp.dtb \ qcom-msm8960-cdp.dtb \
qcom-msm8974-lge-nexus5-hammerhead.dtb \ qcom-msm8974-lge-nexus5-hammerhead.dtb \

View File

@ -10,7 +10,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
--- a/drivers/clk/clk.c --- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c +++ b/drivers/clk/clk.c
@@ -796,7 +796,7 @@ unlock_out: @@ -797,7 +797,7 @@ unlock_out:
clk_core_disable_unprepare(core->parent); clk_core_disable_unprepare(core->parent);
} }

View File

@ -1,224 +0,0 @@
From fa89f53bd7288d6aa7a982841119e7123faf5a53 Mon Sep 17 00:00:00 2001
From: Evan Wang <xswang@marvell.com>
Date: Fri, 13 Apr 2018 12:32:30 +0800
Subject: [PATCH] libahci: Allow drivers to override stop_engine
Marvell armada37xx, armada7k and armada8k share the same
AHCI sata controller IP, and currently there is an issue
(Errata Ref#226)that the SATA can not be detected via SATA
Port-MultiPlayer(PMP). After debugging, the reason is
found that the value of Port-x FIS-based Switching Control
(PxFBS@0x40) became wrong.
According to design, the bits[11:8, 0] of register PxFBS
are cleared when Port Command and Status (0x18) bit[0]
changes its value from 1 to 0, i.e. falling edge of Port
Command and Status bit[0] sends PULSE that resets PxFBS
bits[11:8; 0].
So it needs save the port PxFBS register before PxCMD
ST write and restore the port PxFBS register afterwards
in ahci_stop_engine().
This commit allows drivers to override ahci_stop_engine
behavior for use by the Marvell AHCI driver(and potentially
other drivers in the future).
Signed-off-by: Evan Wang <xswang@marvell.com>
Cc: Ofer Heifetz <oferh@marvell.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
---
drivers/ata/ahci.c | 6 +++---
drivers/ata/ahci.h | 7 +++++++
drivers/ata/ahci_qoriq.c | 2 +-
drivers/ata/ahci_xgene.c | 4 ++--
drivers/ata/libahci.c | 20 ++++++++++++--------
drivers/ata/sata_highbank.c | 2 +-
6 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 1ff17799769d0..6389c88b3500a 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -698,7 +698,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
DPRINTK("ENTER\n");
- ahci_stop_engine(ap);
+ hpriv->stop_engine(ap);
rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
deadline, &online, NULL);
@@ -724,7 +724,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
bool online;
int rc;
- ahci_stop_engine(ap);
+ hpriv->stop_engine(ap);
/* clear D2H reception area to properly wait for D2H FIS */
ata_tf_init(link->device, &tf);
@@ -788,7 +788,7 @@ static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
DPRINTK("ENTER\n");
- ahci_stop_engine(ap);
+ hpriv->stop_engine(ap);
for (i = 0; i < 2; i++) {
u16 val;
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index a9d996e17d75e..824bd399f02ea 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -365,6 +365,13 @@ struct ahci_host_priv {
* be overridden anytime before the host is activated.
*/
void (*start_engine)(struct ata_port *ap);
+ /*
+ * Optional ahci_stop_engine override, if not set this gets set to the
+ * default ahci_stop_engine during ahci_save_initial_config, this can
+ * be overridden anytime before the host is activated.
+ */
+ int (*stop_engine)(struct ata_port *ap);
+
irqreturn_t (*irq_handler)(int irq, void *dev_instance);
/* only required for per-port MSI(-X) support */
diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
index 2685f28160f70..cfdef4d44ae92 100644
--- a/drivers/ata/ahci_qoriq.c
+++ b/drivers/ata/ahci_qoriq.c
@@ -96,7 +96,7 @@ static int ahci_qoriq_hardreset(struct ata_link *link, unsigned int *class,
DPRINTK("ENTER\n");
- ahci_stop_engine(ap);
+ hpriv->stop_engine(ap);
/*
* There is a errata on ls1021a Rev1.0 and Rev2.0 which is:
diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
index c2b5941d9184d..ad58da7c9affd 100644
--- a/drivers/ata/ahci_xgene.c
+++ b/drivers/ata/ahci_xgene.c
@@ -165,7 +165,7 @@ static int xgene_ahci_restart_engine(struct ata_port *ap)
PORT_CMD_ISSUE, 0x0, 1, 100))
return -EBUSY;
- ahci_stop_engine(ap);
+ hpriv->stop_engine(ap);
ahci_start_fis_rx(ap);
/*
@@ -421,7 +421,7 @@ static int xgene_ahci_hardreset(struct ata_link *link, unsigned int *class,
portrxfis_saved = readl(port_mmio + PORT_FIS_ADDR);
portrxfishi_saved = readl(port_mmio + PORT_FIS_ADDR_HI);
- ahci_stop_engine(ap);
+ hpriv->stop_engine(ap);
rc = xgene_ahci_do_hardreset(link, deadline, &online);
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 7adcf3caabd00..e5d90977caec2 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -560,6 +560,9 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
if (!hpriv->start_engine)
hpriv->start_engine = ahci_start_engine;
+ if (!hpriv->stop_engine)
+ hpriv->stop_engine = ahci_stop_engine;
+
if (!hpriv->irq_handler)
hpriv->irq_handler = ahci_single_level_irq_intr;
}
@@ -897,9 +900,10 @@ static void ahci_start_port(struct ata_port *ap)
static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
{
int rc;
+ struct ahci_host_priv *hpriv = ap->host->private_data;
/* disable DMA */
- rc = ahci_stop_engine(ap);
+ rc = hpriv->stop_engine(ap);
if (rc) {
*emsg = "failed to stop engine";
return rc;
@@ -1310,7 +1314,7 @@ int ahci_kick_engine(struct ata_port *ap)
int busy, rc;
/* stop engine */
- rc = ahci_stop_engine(ap);
+ rc = hpriv->stop_engine(ap);
if (rc)
goto out_restart;
@@ -1549,7 +1553,7 @@ int ahci_do_hardreset(struct ata_link *link, unsigned int *class,
DPRINTK("ENTER\n");
- ahci_stop_engine(ap);
+ hpriv->stop_engine(ap);
/* clear D2H reception area to properly wait for D2H FIS */
ata_tf_init(link->device, &tf);
@@ -2075,14 +2079,14 @@ void ahci_error_handler(struct ata_port *ap)
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
/* restart engine */
- ahci_stop_engine(ap);
+ hpriv->stop_engine(ap);
hpriv->start_engine(ap);
}
sata_pmp_error_handler(ap);
if (!ata_dev_enabled(ap->link.device))
- ahci_stop_engine(ap);
+ hpriv->stop_engine(ap);
}
EXPORT_SYMBOL_GPL(ahci_error_handler);
@@ -2129,7 +2133,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
return;
/* set DITO, MDAT, DETO and enable DevSlp, need to stop engine first */
- rc = ahci_stop_engine(ap);
+ rc = hpriv->stop_engine(ap);
if (rc)
return;
@@ -2189,7 +2193,7 @@ static void ahci_enable_fbs(struct ata_port *ap)
return;
}
- rc = ahci_stop_engine(ap);
+ rc = hpriv->stop_engine(ap);
if (rc)
return;
@@ -2222,7 +2226,7 @@ static void ahci_disable_fbs(struct ata_port *ap)
return;
}
- rc = ahci_stop_engine(ap);
+ rc = hpriv->stop_engine(ap);
if (rc)
return;
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index aafb8cc035232..e67815b896fcc 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -410,7 +410,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
int rc;
int retry = 100;
- ahci_stop_engine(ap);
+ hpriv->stop_engine(ap);
/* clear D2H reception area to properly wait for D2H FIS */
ata_tf_init(link->device, &tf);

View File

@ -1,110 +0,0 @@
From daa2e3bdbb0b3e691cf20a042350817310cb8cb5 Mon Sep 17 00:00:00 2001
From: Evan Wang <xswang@marvell.com>
Date: Fri, 13 Apr 2018 12:32:31 +0800
Subject: [PATCH] ata: ahci: mvebu: override ahci_stop_engine for mvebu AHCI
There is an issue(Errata Ref#226) that the SATA can not be
detected via SATA Port-MultiPlayer(PMP) with following
error log:
ata1.15: PMP product ID mismatch
ata1.15: SATA link up 6.0 Gbps (SStatus 133 SControl 300)
ata1.15: Port Multiplier vendor mismatch '0x1b4b'!='0x0'
ata1.15: PMP revalidation failed (errno=-19)
After debugging, the reason is found that the value Port-x
FIS-based Switching Control(PxFBS@0x40) become wrong.
According to design, the bits[11:8, 0] of register PxFBS
are cleared when Port Command and Status (0x18) bit[0]
changes its value from 1 to 0, i.e. falling edge of Port
Command and Status bit[0] sends PULSE that resets PxFBS
bits[11:8; 0].
So it needs a mvebu SATA WA to save the port PxFBS register
before PxCMD ST write and restore it afterwards.
This patch implements the WA in a separate function of
ahci_mvebu_stop_engine to override ahci_stop_gngine.
Signed-off-by: Evan Wang <xswang@marvell.com>
Cc: Ofer Heifetz <oferh@marvell.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
---
drivers/ata/ahci_mvebu.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c
index de7128d81e9cc..0045dacd814b4 100644
--- a/drivers/ata/ahci_mvebu.c
+++ b/drivers/ata/ahci_mvebu.c
@@ -62,6 +62,60 @@ static void ahci_mvebu_regret_option(struct ahci_host_priv *hpriv)
writel(0x80, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA);
}
+/**
+ * ahci_mvebu_stop_engine
+ *
+ * @ap: Target ata port
+ *
+ * Errata Ref#226 - SATA Disk HOT swap issue when connected through
+ * Port Multiplier in FIS-based Switching mode.
+ *
+ * To avoid the issue, according to design, the bits[11:8, 0] of
+ * register PxFBS are cleared when Port Command and Status (0x18) bit[0]
+ * changes its value from 1 to 0, i.e. falling edge of Port
+ * Command and Status bit[0] sends PULSE that resets PxFBS
+ * bits[11:8; 0].
+ *
+ * This function is used to override function of "ahci_stop_engine"
+ * from libahci.c by adding the mvebu work around(WA) to save PxFBS
+ * value before the PxCMD ST write of 0, then restore PxFBS value.
+ *
+ * Return: 0 on success; Error code otherwise.
+ */
+int ahci_mvebu_stop_engine(struct ata_port *ap)
+{
+ void __iomem *port_mmio = ahci_port_base(ap);
+ u32 tmp, port_fbs;
+
+ tmp = readl(port_mmio + PORT_CMD);
+
+ /* check if the HBA is idle */
+ if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
+ return 0;
+
+ /* save the port PxFBS register for later restore */
+ port_fbs = readl(port_mmio + PORT_FBS);
+
+ /* setting HBA to idle */
+ tmp &= ~PORT_CMD_START;
+ writel(tmp, port_mmio + PORT_CMD);
+
+ /*
+ * bit #15 PxCMD signal doesn't clear PxFBS,
+ * restore the PxFBS register right after clearing the PxCMD ST,
+ * no need to wait for the PxCMD bit #15.
+ */
+ writel(port_fbs, port_mmio + PORT_FBS);
+
+ /* wait for engine to stop. This could be as long as 500 msec */
+ tmp = ata_wait_register(ap, port_mmio + PORT_CMD,
+ PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
+ if (tmp & PORT_CMD_LIST_ON)
+ return -EIO;
+
+ return 0;
+}
+
#ifdef CONFIG_PM_SLEEP
static int ahci_mvebu_suspend(struct platform_device *pdev, pm_message_t state)
{
@@ -112,6 +166,8 @@ static int ahci_mvebu_probe(struct platform_device *pdev)
if (rc)
return rc;
+ hpriv->stop_engine = ahci_mvebu_stop_engine;
+
if (of_device_is_compatible(pdev->dev.of_node,
"marvell,armada-380-ahci")) {
dram = mv_mbus_dram_info();