On Wed, Dec 12, 2018 at 12:42:52PM +0900, Sergey Senozhatsky wrote: > Something like this (not tested): > > --- > > drivers/tty/serial/serial_core.c | 14 ++++++++------ > 1 file changed, 8 insertions(+), 6 deletions(-) > > diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c > index c439a5a1e6c0..64050f506348 100644 > --- a/drivers/tty/serial/serial_core.c > +++ b/drivers/tty/serial/serial_core.c > @@ -268,6 +268,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) > struct uart_port *uport = uart_port_check(state); > struct tty_port *port = &state->port; > unsigned long flags = 0; > + char *xmit_buf = NULL; > > /* > * Set the TTY IO error marker > @@ -297,15 +298,16 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) > */ > tty_port_set_suspended(port, 0); > > + uart_port_lock(state, flags); > + xmit_buf = state->xmit.buf; > + state->xmit.buf = NULL; > + uart_port_unlock(uport, flags); > + > /* > * Free the transmit buffer page. > */ > - uart_port_lock(state, flags); > - if (state->xmit.buf) { > - free_page((unsigned long)state->xmit.buf); > - state->xmit.buf = NULL; > - } > - uart_port_unlock(uport, flags); > + if (xmit_buf) > + free_page((unsigned long)xmit_buf); > } That looks sensible anyhow. One should strive to not do alloc or free under locks as much as possible anyway.