[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] ns16550: mask transmit holding register empty interrupt when tx is stopped
commit b42a30f3f90370828e68fa5324d561d0b2df9ef9 Author: Chris Patterson <pattersonc@xxxxxxxxxxxx> AuthorDate: Thu Aug 25 09:00:59 2016 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Thu Aug 25 09:00:59 2016 +0200 ns16550: mask transmit holding register empty interrupt when tx is stopped The uart generates an interrupt whenever the transmit holding register is empty and UART_IER_ETHREI is set in UART_IER. Currently, Xen's ns16550 driver does not currently mask this interrupt when transmit is stopped, unlike other platforms such as Linux [1]. Toggle UART_IER_ETHREI flag in the UART_IER according to the state dictated by stop_tx and start_tx hooks. On the Tegra platform (forthcoming series), the reset via reading IIR does not prevent re-assertion of THRE. This causes Xen to hang in the interrupt handler's while loop whenever there is no data to transmit. This behavior (bug?) is addressed by utilizing the start & stop tx hooks. This has been tested on various x86 PCs for any obvious signs of regressions. [1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/tty/serial/8250/8250_port.c?id=refs/tags/v4.8-rc2#n1518 Signed-off-by: Chris Patterson <pattersonc@xxxxxxxxxxxx> Acked-by: Jan Beulich <jbeulich@xxxxxxxx> --- xen/drivers/char/ns16550.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c index b2b5f56..1da103a 100644 --- a/xen/drivers/char/ns16550.c +++ b/xen/drivers/char/ns16550.c @@ -656,8 +656,8 @@ static void ns16550_setup_postirq(struct ns16550 *uart) ns_write_reg(uart, UART_MCR, UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS); - /* Enable receive and transmit interrupts. */ - ns_write_reg(uart, UART_IER, UART_IER_ERDAI | UART_IER_ETHREI); + /* Enable receive interrupts. */ + ns_write_reg(uart, UART_IER, UART_IER_ERDAI); } if ( uart->irq >= 0 ) @@ -813,6 +813,26 @@ static int __init ns16550_irq(struct serial_port *port) return ((uart->irq > 0) ? uart->irq : -1); } +static void ns16550_start_tx(struct serial_port *port) +{ + struct ns16550 *uart = port->uart; + u8 ier = ns_read_reg(uart, UART_IER); + + /* Unmask transmit holding register empty interrupt if currently masked. */ + if ( !(ier & UART_IER_ETHREI) ) + ns_write_reg(uart, UART_IER, ier | UART_IER_ETHREI); +} + +static void ns16550_stop_tx(struct serial_port *port) +{ + struct ns16550 *uart = port->uart; + u8 ier = ns_read_reg(uart, UART_IER); + + /* Mask off transmit holding register empty interrupt if currently unmasked. */ + if ( ier & UART_IER_ETHREI ) + ns_write_reg(uart, UART_IER, ier & ~UART_IER_ETHREI); +} + #ifdef CONFIG_ARM static const struct vuart_info *ns16550_vuart_info(struct serial_port *port) { @@ -832,6 +852,8 @@ static struct uart_driver __read_mostly ns16550_driver = { .putc = ns16550_putc, .getc = ns16550_getc, .irq = ns16550_irq, + .start_tx = ns16550_start_tx, + .stop_tx = ns16550_stop_tx, #ifdef CONFIG_ARM .vuart_info = ns16550_vuart_info, #endif -- generated by git-patchbot for /home/xen/git/xen.git#master _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |