]>
Commit | Line | Data |
---|---|---|
1b52f688 GKH |
1 | From 4a7e625ce50412a7711efa0f2ef0b96ce3826759 Mon Sep 17 00:00:00 2001 |
2 | From: Dave Martin <Dave.Martin@arm.com> | |
3 | Date: Thu, 10 May 2018 18:08:23 +0100 | |
4 | Subject: tty: pl011: Avoid spuriously stuck-off interrupts | |
5 | ||
6 | From: Dave Martin <Dave.Martin@arm.com> | |
7 | ||
8 | commit 4a7e625ce50412a7711efa0f2ef0b96ce3826759 upstream. | |
9 | ||
10 | Commit 9b96fbacda34 ("serial: PL011: clear pending interrupts") | |
11 | clears the RX and receive timeout interrupts on pl011 startup, to | |
12 | avoid a screaming-interrupt scenario that can occur when the | |
13 | firmware or bootloader leaves these interrupts asserted. | |
14 | ||
15 | This has been noted as an issue when running Linux on qemu [1]. | |
16 | ||
17 | Unfortunately, the above fix seems to lead to potential | |
18 | misbehaviour if the RX FIFO interrupt is asserted _non_ spuriously | |
19 | on driver startup, if the RX FIFO is also already full to the | |
20 | trigger level. | |
21 | ||
22 | Clearing the RX FIFO interrupt does not change the FIFO fill level. | |
23 | In this scenario, because the interrupt is now clear and because | |
24 | the FIFO is already full to the trigger level, no new assertion of | |
25 | the RX FIFO interrupt can occur unless the FIFO is drained back | |
26 | below the trigger level. This never occurs because the pl011 | |
27 | driver is waiting for an RX FIFO interrupt to tell it that there is | |
28 | something to read, and does not read the FIFO at all until that | |
29 | interrupt occurs. | |
30 | ||
31 | Thus, simply clearing "spurious" interrupts on startup may be | |
32 | misguided, since there is no way to be sure that the interrupts are | |
33 | truly spurious, and things can go wrong if they are not. | |
34 | ||
35 | This patch instead clears the interrupt condition by draining the | |
36 | RX FIFO during UART startup, after clearing any potentially | |
37 | spurious interrupt. This should ensure that an interrupt will | |
38 | definitely be asserted if the RX FIFO subsequently becomes | |
39 | sufficiently full. | |
40 | ||
41 | The drain is done at the point of enabling interrupts only. This | |
42 | means that it will occur any time the UART is newly opened through | |
43 | the tty layer. It will not apply to polled-mode use of the UART by | |
44 | kgdboc: since that scenario cannot use interrupts by design, this | |
45 | should not matter. kgdboc will interact badly with "normal" use of | |
46 | the UART in any case: this patch makes no attempt to paper over | |
47 | such issues. | |
48 | ||
49 | This patch does not attempt to address the case where the RX FIFO | |
50 | fills faster than it can be drained: that is a pathological | |
51 | hardware design problem that is beyond the scope of the driver to | |
52 | work around. As a failsafe, the number of poll iterations for | |
53 | draining the FIFO is limited to twice the FIFO size. This will | |
54 | ensure that the kernel at least boots even if it is impossible to | |
55 | drain the FIFO for some reason. | |
56 | ||
57 | [1] [Qemu-devel] [Qemu-arm] [PATCH] pl011: do not put into fifo | |
58 | before enabled the interruption | |
59 | https://lists.gnu.org/archive/html/qemu-devel/2018-01/msg06446.html | |
60 | ||
61 | Reported-by: Wei Xu <xuwei5@hisilicon.com> | |
62 | Cc: Russell King <linux@armlinux.org.uk> | |
63 | Cc: Linus Walleij <linus.walleij@linaro.org> | |
64 | Cc: Peter Maydell <peter.maydell@linaro.org> | |
65 | Fixes: 9b96fbacda34 ("serial: PL011: clear pending interrupts") | |
66 | Signed-off-by: Dave Martin <Dave.Martin@arm.com> | |
67 | Cc: stable <stable@vger.kernel.org> | |
68 | Tested-by: Wei Xu <xuwei5@hisilicon.com> | |
69 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
70 | ||
71 | --- | |
72 | drivers/tty/serial/amba-pl011.c | 16 ++++++++++++++++ | |
73 | 1 file changed, 16 insertions(+) | |
74 | ||
75 | --- a/drivers/tty/serial/amba-pl011.c | |
76 | +++ b/drivers/tty/serial/amba-pl011.c | |
77 | @@ -1726,10 +1726,26 @@ static int pl011_allocate_irq(struct uar | |
78 | */ | |
79 | static void pl011_enable_interrupts(struct uart_amba_port *uap) | |
80 | { | |
81 | + unsigned int i; | |
82 | + | |
83 | spin_lock_irq(&uap->port.lock); | |
84 | ||
85 | /* Clear out any spuriously appearing RX interrupts */ | |
86 | pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR); | |
87 | + | |
88 | + /* | |
89 | + * RXIS is asserted only when the RX FIFO transitions from below | |
90 | + * to above the trigger threshold. If the RX FIFO is already | |
91 | + * full to the threshold this can't happen and RXIS will now be | |
92 | + * stuck off. Drain the RX FIFO explicitly to fix this: | |
93 | + */ | |
94 | + for (i = 0; i < uap->fifosize * 2; ++i) { | |
95 | + if (pl011_read(uap, REG_FR) & UART01x_FR_RXFE) | |
96 | + break; | |
97 | + | |
98 | + pl011_read(uap, REG_DR); | |
99 | + } | |
100 | + | |
101 | uap->im = UART011_RTIM; | |
102 | if (!pl011_dma_rx_running(uap)) | |
103 | uap->im |= UART011_RXIM; |