|
[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 |