[PATCH] add delay between port write and port read

From: Mikulas Patocka (mpatocka@xxxxxxxxxx)
Date: Tue Feb 19 2019 - 08:43:54 EST


The patches cd0e00c106722eca40b38ebf11cf134c01901086 and
92d7223a74235054f2aa7227d207d9c57f84dca0 fix a theoretical issue where the
code didn't follow the specification. Unfortunatelly, they also reduce
timing when port write is followed by a port read.

These reduced timing cause hang on boot on the Avanti platform when
probing serial ports. This patch adds memory barrier after the outb, outw,
outl functions, so that there is delay between port write and subsequent
port read - just like before.

Fixes: cd0e00c10672 ("alpha: io: reorder barriers to guarantee writeX() and iowriteX() ordering")
Cc: stable@xxxxxxxxxxxxxxx # v4.17+

---
arch/alpha/kernel/io.c | 6 ++++++
1 file changed, 6 insertions(+)

Index: linux-stable/arch/alpha/kernel/io.c
===================================================================
--- linux-stable.orig/arch/alpha/kernel/io.c 2019-02-19 14:06:03.000000000 +0100
+++ linux-stable/arch/alpha/kernel/io.c 2019-02-19 14:12:29.000000000 +0100
@@ -78,16 +78,19 @@ u32 inl(unsigned long port)
void outb(u8 b, unsigned long port)
{
iowrite8(b, ioport_map(port, 1));
+ mb();
}

void outw(u16 b, unsigned long port)
{
iowrite16(b, ioport_map(port, 2));
+ mb();
}

void outl(u32 b, unsigned long port)
{
iowrite32(b, ioport_map(port, 4));
+ mb();
}

EXPORT_SYMBOL(inb);
@@ -336,6 +339,7 @@ void iowrite8_rep(void __iomem *port, co
void outsb(unsigned long port, const void *src, unsigned long count)
{
iowrite8_rep(ioport_map(port, 1), src, count);
+ mb();
}

EXPORT_SYMBOL(iowrite8_rep);
@@ -376,6 +380,7 @@ void iowrite16_rep(void __iomem *port, c
void outsw(unsigned long port, const void *src, unsigned long count)
{
iowrite16_rep(ioport_map(port, 2), src, count);
+ mb();
}

EXPORT_SYMBOL(iowrite16_rep);
@@ -408,6 +413,7 @@ void iowrite32_rep(void __iomem *port, c
void outsl(unsigned long port, const void *src, unsigned long count)
{
iowrite32_rep(ioport_map(port, 4), src, count);
+ mb();
}

EXPORT_SYMBOL(iowrite32_rep);