From: Peter Hurley Date: Wed, 5 Nov 2014 18:11:45 +0000 (-0500) Subject: serial: Test/disable MSIs if switching from N_PPS X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=cab68f89546ba5a04bf28aaeaca841d4ccc2fd52;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git serial: Test/disable MSIs if switching from N_PPS Switching to the N_PPS line discipline may require enabling modem status interrupts; conversely switching from N_PPS may require disabling modem status interrupts. Affected drivers: 8250 amba-pl010 atmel Cc: Nicolas Ferre Cc: Russell King Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index f0f35e782bc3..25eb8e93615d 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1402,6 +1402,19 @@ static void serial8250_stop_rx(struct uart_port *port) serial8250_rpm_put(up); } +static void serial8250_disable_ms(struct uart_port *port) +{ + struct uart_8250_port *up = + container_of(port, struct uart_8250_port, port); + + /* no MSR capabilities */ + if (up->bugs & UART_BUG_NOMSR) + return; + + up->ier &= ~UART_IER_MSI; + serial_port_out(port, UART_IER, up->ier); +} + static void serial8250_enable_ms(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); @@ -2616,8 +2629,14 @@ serial8250_set_ldisc(struct uart_port *port, struct ktermios *termios) spin_lock_irq(&port->lock); serial8250_enable_ms(port); spin_unlock_irq(&port->lock); - } else + } else { port->flags &= ~UPF_HARDPPS_CD; + if (!UART_ENABLE_MS(port, termios->c_cflag)) { + spin_lock_irq(&port->lock); + serial8250_disable_ms(port); + spin_unlock_irq(&port->lock); + } + } } diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c index 194108b0de84..5d41d5b92619 100644 --- a/drivers/tty/serial/amba-pl010.c +++ b/drivers/tty/serial/amba-pl010.c @@ -106,6 +106,16 @@ static void pl010_stop_rx(struct uart_port *port) writel(cr, uap->port.membase + UART010_CR); } +static void pl010_disable_ms(struct uart_port *port) +{ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + unsigned int cr; + + cr = readb(uap->port.membase + UART010_CR); + cr &= ~UART010_CR_MSIE; + writel(cr, uap->port.membase + UART010_CR); +} + static void pl010_enable_ms(struct uart_port *port) { struct uart_amba_port *uap = @@ -486,8 +496,14 @@ static void pl010_set_ldisc(struct uart_port *port, struct ktermios *termios) spin_lock_irq(&port->lock); pl010_enable_ms(port); spin_unlock_irq(&port->lock); - } else + } else { port->flags &= ~UPF_HARDPPS_CD; + if (!UART_ENABLE_MS(port, termios->c_cflag)) { + spin_lock_irq(&port->lock); + pl010_disable_ms(port); + spin_unlock_irq(&port->lock); + } + } } static const char *pl010_type(struct uart_port *port) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index e67cb3831280..b1d61dc3fc1b 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2065,6 +2065,11 @@ static void atmel_set_ldisc(struct uart_port *port, struct ktermios *termios) spin_unlock_irq(&port->lock); } else { port->flags &= ~UPF_HARDPPS_CD; + if (!UART_ENABLE_MS(port, termios->c_cflag)) { + spin_lock_irq(&port->lock); + atmel_disable_ms(port); + spin_unlock_irq(&port->lock); + } } }