summaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/serial_core.c
diff options
context:
space:
mode:
authorJames Morris <james.morris@microsoft.com>2019-01-10 11:41:59 -0800
committerJames Morris <james.morris@microsoft.com>2019-01-10 11:41:59 -0800
commit49e41801b335f64610bbfd23e8f2bbaf34d46276 (patch)
tree4fbedacd1de1bbd4054f07f93031aebcb7b7a919 /drivers/tty/serial/serial_core.c
parentb49d564344f773d8afee982153c8493e5f2eaf38 (diff)
parentbfeffd155283772bbe78c6a05dec7c0128ee500c (diff)
downloadtalos-op-linux-49e41801b335f64610bbfd23e8f2bbaf34d46276.tar.gz
talos-op-linux-49e41801b335f64610bbfd23e8f2bbaf34d46276.zip
Merge tag 'v5.0-rc1' into next-general
Linux 5.0-rc1 Sync to pick up LSM stacking work (which is based on -rc1).
Diffstat (limited to 'drivers/tty/serial/serial_core.c')
-rw-r--r--drivers/tty/serial/serial_core.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index c439a5a1e6c0..d4cca5bdaf1c 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -205,10 +205,15 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
if (!state->xmit.buf) {
state->xmit.buf = (unsigned char *) page;
uart_circ_clear(&state->xmit);
+ uart_port_unlock(uport, flags);
} else {
+ uart_port_unlock(uport, flags);
+ /*
+ * Do not free() the page under the port lock, see
+ * uart_shutdown().
+ */
free_page(page);
}
- uart_port_unlock(uport, flags);
retval = uport->ops->startup(uport);
if (retval == 0) {
@@ -268,6 +273,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
@@ -298,14 +304,18 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
tty_port_set_suspended(port, 0);
/*
- * Free the transmit buffer page.
+ * Do not free() the transmit buffer page under the port lock since
+ * this can create various circular locking scenarios. For instance,
+ * console driver may need to allocate/free a debug object, which
+ * can endup in printk() recursion.
*/
uart_port_lock(state, flags);
- if (state->xmit.buf) {
- free_page((unsigned long)state->xmit.buf);
- state->xmit.buf = NULL;
- }
+ xmit_buf = state->xmit.buf;
+ state->xmit.buf = NULL;
uart_port_unlock(uport, flags);
+
+ if (xmit_buf)
+ free_page((unsigned long)xmit_buf);
}
/**
OpenPOWER on IntegriCloud