ar71xx: fix nondeterministic hangs during bootconsole/console handover

Reconfiguring the UART when the FIFO is not empty may cause the boot to
hang. This hang is extremely suspectible to timing differences; recompiling
the kernel with the same configuration, but different UTS_VERSION
timestamps can yield images that hang more or less often. Sometimes images
are produced that hang reproducibly.

This patch should also make it into one of the next linux-stable releases,
but it's better to get this fixed as soon as possible.

Fixes #21773, #21857.

Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>

Backport of r49156

git-svn-id: svn://svn.openwrt.org/openwrt/branches/chaos_calmer@49202 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
Rafał Miłecki 2016-04-20 06:05:56 +00:00
parent 877ee7d7f5
commit dfcf8a8dbe
4 changed files with 57 additions and 8 deletions

View File

@ -0,0 +1,49 @@
From f1ba020af5076172c9d29006a747ccf40027fedc Mon Sep 17 00:00:00 2001
Message-Id: <f1ba020af5076172c9d29006a747ccf40027fedc.1458840219.git.mschiffer@universe-factory.net>
From: Matthias Schiffer <mschiffer@universe-factory.net>
Date: Thu, 24 Mar 2016 15:34:05 +0100
Subject: [PATCH] MIPS: ath79: make bootconsole wait for both THRE and TEMT
This makes the ath79 bootconsole behave the same way as the generic 8250
bootconsole.
Also waiting for TEMT (transmit buffer is empty) instead of just THRE
(transmit buffer is not full) ensures that all characters have been
transmitted before the real serial driver starts reconfiguring the serial
controller (which would sometimes result in garbage being transmitted.)
This change does not cause a visible performance loss.
In addition, this seems to fix a hang observed in certain configurations on
many AR7xxx/AR9xxx SoCs during autoconfig of the real serial driver.
A more complete follow-up patch will disable 8250 autoconfig for ath79
altogether (the serial controller is detected as a 16550A, which is not
fully compatible with the ath79 serial, and the autoconfig may lead to
undefined behavior on ath79.)
Cc: <stable@vger.kernel.org>
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
---
arch/mips/ath79/early_printk.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/arch/mips/ath79/early_printk.c
+++ b/arch/mips/ath79/early_printk.c
@@ -31,13 +31,15 @@ static inline void prom_putchar_wait(voi
} while (1);
}
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
static void prom_putchar_ar71xx(unsigned char ch)
{
void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE));
- prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE);
+ prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY);
__raw_writel(ch, base + UART_TX * 4);
- prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE);
+ prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY);
}
static void prom_putchar_ar933x(unsigned char ch)

View File

@ -1,6 +1,6 @@
--- a/arch/mips/ath79/early_printk.c
+++ b/arch/mips/ath79/early_printk.c
@@ -56,6 +56,46 @@ static void prom_putchar_dummy(unsigned
@@ -58,6 +58,46 @@ static void prom_putchar_dummy(unsigned
/* nothing to do */
}
@ -47,7 +47,7 @@
static void prom_putchar_init(void)
{
void __iomem *base;
@@ -86,8 +126,10 @@ static void prom_putchar_init(void)
@@ -88,8 +128,10 @@ static void prom_putchar_init(void)
default:
_prom_putchar = prom_putchar_dummy;

View File

@ -22,7 +22,7 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed.
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -1257,6 +1257,10 @@ config SOC_AR934X
@@ -1266,6 +1266,10 @@ config SOC_AR934X
select PCI_AR724X if PCI
def_bool n
@ -33,7 +33,7 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed.
config SOC_QCA955X
select HW_HAS_PCI
select PCI_AR724X if PCI
@@ -1299,7 +1303,7 @@ config ATH79_DEV_USB
@@ -1308,7 +1312,7 @@ config ATH79_DEV_USB
def_bool n
config ATH79_DEV_WMAC
@ -275,7 +275,7 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed.
else
--- a/arch/mips/ath79/early_printk.c
+++ b/arch/mips/ath79/early_printk.c
@@ -114,6 +114,8 @@ static void prom_putchar_init(void)
@@ -116,6 +116,8 @@ static void prom_putchar_init(void)
case REV_ID_MAJOR_AR9341:
case REV_ID_MAJOR_AR9342:
case REV_ID_MAJOR_AR9344:

View File

@ -211,7 +211,7 @@
--- a/arch/mips/ath79/early_printk.c
+++ b/arch/mips/ath79/early_printk.c
@@ -118,6 +118,8 @@ static void prom_putchar_init(void)
@@ -120,6 +120,8 @@ static void prom_putchar_init(void)
case REV_ID_MAJOR_QCA9533_V2:
case REV_ID_MAJOR_QCA9556:
case REV_ID_MAJOR_QCA9558:
@ -378,7 +378,7 @@
}
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -1277,6 +1277,12 @@ config SOC_QCA955X
@@ -1286,6 +1286,12 @@ config SOC_QCA955X
select PCI_AR724X if PCI
def_bool n
@ -391,7 +391,7 @@
config ATH79_DEV_M25P80
select ATH79_DEV_SPI
def_bool n
@@ -1314,7 +1320,7 @@ config ATH79_DEV_USB
@@ -1323,7 +1329,7 @@ config ATH79_DEV_USB
def_bool n
config ATH79_DEV_WMAC