Message ID | 1505828334-29109-3-git-send-email-awais.masood@vadion.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
>>> On 19.09.17 at 15:38, <awais.masood@vadion.com> wrote: > --- a/xen/drivers/char/ns16550.c > +++ b/xen/drivers/char/ns16550.c > @@ -521,6 +521,18 @@ static void ns16550_interrupt( > serial_tx_interrupt(port, regs); > if ( lsr & UART_LSR_DR ) > serial_rx_interrupt(port, regs); > + if ( uart->dw_usr_bsy && > + (ns_read_reg(uart, UART_IIR) & UART_IIR_BSY) == UART_IIR_BSY ) > + { > + /* If DesignWare 8250 UART became busy again when LCR was written > + * earlier, it can raise a "busy detect" again. > + * Read the UART Status Register to clear this state or we'll end up > + * in an infinte loop because UART_IIR_NOINT is not true. > + * Placing this check in setup_preirq after LCR write does not work > + * probably due to a delayed interrupt. > + */ > + ns_read_reg(uart, UART_USR); > + } This same code already exists in ns16550_setup_preirq() - please introduce a helper function. It would also help if you referred to the commit introducing that other instance of the code, explaining why what was done there was not enough (because pretty clearly the author must have assumed that change to be sufficient). Jan
diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c index 6ab5ec3..6630720 100644 --- a/xen/drivers/char/ns16550.c +++ b/xen/drivers/char/ns16550.c @@ -521,6 +521,18 @@ static void ns16550_interrupt( serial_tx_interrupt(port, regs); if ( lsr & UART_LSR_DR ) serial_rx_interrupt(port, regs); + if ( uart->dw_usr_bsy && + (ns_read_reg(uart, UART_IIR) & UART_IIR_BSY) == UART_IIR_BSY ) + { + /* If DesignWare 8250 UART became busy again when LCR was written + * earlier, it can raise a "busy detect" again. + * Read the UART Status Register to clear this state or we'll end up + * in an infinte loop because UART_IIR_NOINT is not true. + * Placing this check in setup_preirq after LCR write does not work + * probably due to a delayed interrupt. + */ + ns_read_reg(uart, UART_USR); + } } }
On H5 (Orange Pi PC2) serial driver goes into an infinite loop as soon as interrupts are enabled. The reason being a residual "busy detect" interrupt. Since the condition UART_IIR_NOINT is not true, we'll remain in this while loop forever. A check has been added to detect "busy detect" interrupt condition and UART_USR register is read to clear the condition. Conditonal for dw_usr_busy ensures this hw quirk fix affects only designware uarts. The check during ns16550_setup_preirq call does not help on H5 because its called before LCR is set and if the busy condition appears again during subsequent LCR writes, we end up in this situation. Tested on Orange Pi PC2 Signed-off-by: Awais Masood <awais.masood@vadion.com> --- xen/drivers/char/ns16550.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)