Skip to contentSkip to conversation

serial: 8250: unlock port for uart_write_wakeup()

PATCH NAK John Ogness 2 participants 3 messages Jul 30, 2015 TTY layer and serial drivers

lore
Share & tools
lore
#0 lore raw

PATCH 1/3 serial: 8250: unlock port for uart_write_wakeup()

uart_write_wakeup() should be called without holding the port lock. Otherwise a possible recursive spinlock issue can occur, such as the following callchain:

8250_core.c:serial8250_tx_chars() - called with port locked
serial_core.c:uart_write_wakeup()
tty_io.c:tty_wakeup()
st_core.c:st_tty_wakeup()

    st_core.c:st_tx_wakeup()
     st_core.c:st_int_write()
      serial_core.c:uart_write() - locks port
---
 drivers/tty/serial/8250/8250_core.c |    6 +++++-
 drivers/tty/serial/8250/8250_omap.c |    6 +++++-
 2 files changed, 10 insertions(+), 2 deletions(-)
drivers/tty/serial/8250/8250_core.c +5 -1
index 37fff12..5ac2425 100644
@@ -1559,8 +1559,12 @@ void serial8250_tx_chars(struct uart_8250_port *up)
 		}
 	} while (--count > 0);
 
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
+		/* do not hold lock for call to uart_write_wakeup() */
+		spin_unlock(&port->lock);
 		uart_write_wakeup(port);
+		spin_lock(&port->lock);
+	}
 
 	DEBUG_INTR("THRE...");
 
drivers/tty/serial/8250/8250_omap.c +5 -1
index d75a66c..5b39892 100644
@@ -861,8 +861,12 @@ static void omap_8250_dma_tx_complete(void *param)
 		omap8250_restore_regs(p);
 	}
 
-	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
+		/* do not hold lock for call to uart_write_wakeup() */
+		spin_unlock(&p->port.lock);
 		uart_write_wakeup(&p->port);
+		spin_lock(&p->port.lock);
+	}
 
 	if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) {
 		int ret;
Signature · 1 line
1.7.10.4
#1 lore raw
Quoted 11 lines · John Ogness

uart_write_wakeup() should be called without holding the port lock. Otherwise a possible recursive spinlock issue can occur, such as the following callchain:

8250_core.c:serial8250_tx_chars() - called with port locked
serial_core.c:uart_write_wakeup()
tty_io.c:tty_wakeup()
st_core.c:st_tty_wakeup()

    st_core.c:st_tx_wakeup()
     st_core.c:st_int_write()
      serial_core.c:uart_write() - locks port

NAK.

This is a bug in the N_TI_WL line discipline, specifically in the st_tx_wakeup() function, which cannot perform the write synchronously.

This is a common line discipline bug, and typically fixed by performing the wakeup operations from a kworker instead.

Regards,
Peter Hurley

#2 lore raw
Quoted 13 lines · Peter Hurley
Quoted 11 lines · John Ogness

uart_write_wakeup() should be called without holding the port lock. Otherwise a possible recursive spinlock issue can occur, such as the following callchain:

8250_core.c:serial8250_tx_chars() - called with port locked
serial_core.c:uart_write_wakeup()
tty_io.c:tty_wakeup()
st_core.c:st_tty_wakeup()

    st_core.c:st_tx_wakeup()
     st_core.c:st_int_write()
      serial_core.c:uart_write() - locks port
Quoted 7 lines

NAK.

This is a bug in the N_TI_WL line discipline, specifically in the st_tx_wakeup() function, which cannot perform the write synchronously.

This is a common line discipline bug, and typically fixed by performing the wakeup operations from a kworker instead.

Also, seriously consider if you want to use that TI line discipline at all.

If you're using it only for bluetooth w/ kernel bluetooth stack, you don't need btwilink + st_drv anyway.

Regards,
Peter Hurley