[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.