Skip to content

Commit

Permalink
serial: core: Extract uart_alloc_xmit_buf() and uart_free_xmit_buf()
Browse files Browse the repository at this point in the history
After conversion to the kfifo, it becomes possible to extract two helper
functions for better maintenance and code deduplication. Do it here.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20240409174057.1104262-1-andriy.shevchenko@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Andy Shevchenko authored and Greg Kroah-Hartman committed Apr 17, 2024
1 parent 5f1149d commit abcd863
Showing 1 changed file with 54 additions and 44 deletions.
98 changes: 54 additions & 44 deletions drivers/tty/serial/serial_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,25 +243,12 @@ static void uart_change_line_settings(struct tty_struct *tty, struct uart_state
uart_port_unlock_irq(uport);
}

/*
* Startup the port. This will be called once per open. All calls
* will be serialised by the per-port mutex.
*/
static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
bool init_hw)
static int uart_alloc_xmit_buf(struct tty_port *port)
{
struct uart_port *uport = uart_port_check(state);
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport;
unsigned long flags;
unsigned long page;
int retval = 0;

if (uport->type == PORT_UNKNOWN)
return 1;

/*
* Make sure the device is in D0 state.
*/
uart_change_pm(state, UART_PM_STATE_ON);

/*
* Initialise and allocate the transmit and temporary
Expand All @@ -271,7 +258,7 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
if (!page)
return -ENOMEM;

uart_port_lock(state, flags);
uport = uart_port_lock(state, flags);
if (!state->port.xmit_buf) {
state->port.xmit_buf = (unsigned char *)page;
kfifo_init(&state->port.xmit_fifo, state->port.xmit_buf,
Expand All @@ -281,11 +268,58 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
uart_port_unlock(uport, flags);
/*
* Do not free() the page under the port lock, see
* uart_shutdown().
* uart_free_xmit_buf().
*/
free_page(page);
}

return 0;
}

static void uart_free_xmit_buf(struct tty_port *port)
{
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport;
unsigned long flags;
char *xmit_buf;

/*
* 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 end up in printk() recursion.
*/
uport = uart_port_lock(state, flags);
xmit_buf = port->xmit_buf;
port->xmit_buf = NULL;
INIT_KFIFO(port->xmit_fifo);
uart_port_unlock(uport, flags);

free_page((unsigned long)xmit_buf);
}

/*
* Startup the port. This will be called once per open. All calls
* will be serialised by the per-port mutex.
*/
static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
bool init_hw)
{
struct uart_port *uport = uart_port_check(state);
int retval;

if (uport->type == PORT_UNKNOWN)
return 1;

/*
* Make sure the device is in D0 state.
*/
uart_change_pm(state, UART_PM_STATE_ON);

retval = uart_alloc_xmit_buf(&state->port);
if (retval)
return retval;

retval = uport->ops->startup(uport);
if (retval == 0) {
if (uart_console(uport) && uport->cons->cflag) {
Expand Down Expand Up @@ -347,8 +381,6 @@ 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;
char *xmit_buf = NULL;

/*
* Set the TTY IO error marker
Expand Down Expand Up @@ -381,19 +413,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
*/
tty_port_set_suspended(port, false);

/*
* 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);
xmit_buf = port->xmit_buf;
port->xmit_buf = NULL;
INIT_KFIFO(port->xmit_fifo);
uart_port_unlock(uport, flags);

free_page((unsigned long)xmit_buf);
uart_free_xmit_buf(port);
}

/**
Expand Down Expand Up @@ -1747,7 +1767,6 @@ static void uart_tty_port_shutdown(struct tty_port *port)
{
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport = uart_port_check(state);
char *buf;

/*
* At this point, we stop accepting input. To do this, we
Expand All @@ -1769,16 +1788,7 @@ static void uart_tty_port_shutdown(struct tty_port *port)
*/
tty_port_set_suspended(port, false);

/*
* Free the transmit buffer.
*/
uart_port_lock_irq(uport);
buf = port->xmit_buf;
port->xmit_buf = NULL;
INIT_KFIFO(port->xmit_fifo);
uart_port_unlock_irq(uport);

free_page((unsigned long)buf);
uart_free_xmit_buf(port);

uart_change_pm(state, UART_PM_STATE_OFF);
}
Expand Down

0 comments on commit abcd863

Please sign in to comment.