3.2-stable review patch. If anyone has any objections, please let me know.
------------------ From: Linus Walleij <[email protected]> commit 9b96fbacda34079dea0638ee1e92c56286f6114a upstream. Chanho Min reported that when the boot loader transfers control to the kernel, there may be pending interrupts causing the UART to lock up in an eternal loop trying to pick tokens from the FIFO (since the RX interrupt flag indicates there are tokens) while in practice there are no tokens - in fact there is only a pending IRQ flag. This patch address the issue with a combination of two patches suggested by Russell King that clears and mask all interrupts at probe() and clears any pending error and RX interrupts at port startup time. We suspect the spurious interrupts are a side-effect of switching the UART from FIFO to non-FIFO mode. Cc: Shreshtha Kumar Sahu <[email protected]> Reported-by: Chanho Min <[email protected]> Suggested-by: Russell King <[email protected]> Signed-off-by: Linus Walleij <[email protected]> Reviewed-by: Jong-Sung Kim <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> --- drivers/tty/serial/amba-pl011.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1380,6 +1380,10 @@ static int pl011_startup(struct uart_por uap->port.uartclk = clk_get_rate(uap->clk); + /* Clear pending error and receive interrupts */ + writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | + UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); + /* * Allocate the IRQ */ @@ -1414,10 +1418,6 @@ static int pl011_startup(struct uart_por cr = UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; writew(cr, uap->port.membase + UART011_CR); - /* Clear pending error interrupts */ - writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS, - uap->port.membase + UART011_ICR); - /* * initialise the old status of the modem signals */ @@ -1432,6 +1432,9 @@ static int pl011_startup(struct uart_por * as well. */ spin_lock_irq(&uap->port.lock); + /* Clear out any spuriously appearing RX interrupts */ + writew(UART011_RTIS | UART011_RXIS, + uap->port.membase + UART011_ICR); uap->im = UART011_RTIM; if (!pl011_dma_rx_running(uap)) uap->im |= UART011_RXIM; @@ -1916,6 +1919,10 @@ static int pl011_probe(struct amba_devic goto unmap; } + /* Ensure interrupts from this UART are masked and cleared */ + writew(0, uap->port.membase + UART011_IMSC); + writew(0xffff, uap->port.membase + UART011_ICR); + uap->vendor = vendor; uap->lcrh_rx = vendor->lcrh_rx; uap->lcrh_tx = vendor->lcrh_tx; -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
