Skip to content

Commit abcd863

Browse files
andy-shevgregkh
authored andcommitted
serial: core: Extract uart_alloc_xmit_buf() and uart_free_xmit_buf()
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 5f1149d commit abcd863

File tree

1 file changed

+54
-44
lines changed

1 file changed

+54
-44
lines changed

drivers/tty/serial/serial_core.c

Lines changed: 54 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -243,25 +243,12 @@ static void uart_change_line_settings(struct tty_struct *tty, struct uart_state
243243
uart_port_unlock_irq(uport);
244244
}
245245

246-
/*
247-
* Startup the port. This will be called once per open. All calls
248-
* will be serialised by the per-port mutex.
249-
*/
250-
static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
251-
bool init_hw)
246+
static int uart_alloc_xmit_buf(struct tty_port *port)
252247
{
253-
struct uart_port *uport = uart_port_check(state);
248+
struct uart_state *state = container_of(port, struct uart_state, port);
249+
struct uart_port *uport;
254250
unsigned long flags;
255251
unsigned long page;
256-
int retval = 0;
257-
258-
if (uport->type == PORT_UNKNOWN)
259-
return 1;
260-
261-
/*
262-
* Make sure the device is in D0 state.
263-
*/
264-
uart_change_pm(state, UART_PM_STATE_ON);
265252

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

274-
uart_port_lock(state, flags);
261+
uport = uart_port_lock(state, flags);
275262
if (!state->port.xmit_buf) {
276263
state->port.xmit_buf = (unsigned char *)page;
277264
kfifo_init(&state->port.xmit_fifo, state->port.xmit_buf,
@@ -281,11 +268,58 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
281268
uart_port_unlock(uport, flags);
282269
/*
283270
* Do not free() the page under the port lock, see
284-
* uart_shutdown().
271+
* uart_free_xmit_buf().
285272
*/
286273
free_page(page);
287274
}
288275

276+
return 0;
277+
}
278+
279+
static void uart_free_xmit_buf(struct tty_port *port)
280+
{
281+
struct uart_state *state = container_of(port, struct uart_state, port);
282+
struct uart_port *uport;
283+
unsigned long flags;
284+
char *xmit_buf;
285+
286+
/*
287+
* Do not free() the transmit buffer page under the port lock since
288+
* this can create various circular locking scenarios. For instance,
289+
* console driver may need to allocate/free a debug object, which
290+
* can end up in printk() recursion.
291+
*/
292+
uport = uart_port_lock(state, flags);
293+
xmit_buf = port->xmit_buf;
294+
port->xmit_buf = NULL;
295+
INIT_KFIFO(port->xmit_fifo);
296+
uart_port_unlock(uport, flags);
297+
298+
free_page((unsigned long)xmit_buf);
299+
}
300+
301+
/*
302+
* Startup the port. This will be called once per open. All calls
303+
* will be serialised by the per-port mutex.
304+
*/
305+
static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,
306+
bool init_hw)
307+
{
308+
struct uart_port *uport = uart_port_check(state);
309+
int retval;
310+
311+
if (uport->type == PORT_UNKNOWN)
312+
return 1;
313+
314+
/*
315+
* Make sure the device is in D0 state.
316+
*/
317+
uart_change_pm(state, UART_PM_STATE_ON);
318+
319+
retval = uart_alloc_xmit_buf(&state->port);
320+
if (retval)
321+
return retval;
322+
289323
retval = uport->ops->startup(uport);
290324
if (retval == 0) {
291325
if (uart_console(uport) && uport->cons->cflag) {
@@ -347,8 +381,6 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
347381
{
348382
struct uart_port *uport = uart_port_check(state);
349383
struct tty_port *port = &state->port;
350-
unsigned long flags;
351-
char *xmit_buf = NULL;
352384

353385
/*
354386
* Set the TTY IO error marker
@@ -381,19 +413,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
381413
*/
382414
tty_port_set_suspended(port, false);
383415

384-
/*
385-
* Do not free() the transmit buffer page under the port lock since
386-
* this can create various circular locking scenarios. For instance,
387-
* console driver may need to allocate/free a debug object, which
388-
* can endup in printk() recursion.
389-
*/
390-
uart_port_lock(state, flags);
391-
xmit_buf = port->xmit_buf;
392-
port->xmit_buf = NULL;
393-
INIT_KFIFO(port->xmit_fifo);
394-
uart_port_unlock(uport, flags);
395-
396-
free_page((unsigned long)xmit_buf);
416+
uart_free_xmit_buf(port);
397417
}
398418

399419
/**
@@ -1747,7 +1767,6 @@ static void uart_tty_port_shutdown(struct tty_port *port)
17471767
{
17481768
struct uart_state *state = container_of(port, struct uart_state, port);
17491769
struct uart_port *uport = uart_port_check(state);
1750-
char *buf;
17511770

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

1772-
/*
1773-
* Free the transmit buffer.
1774-
*/
1775-
uart_port_lock_irq(uport);
1776-
buf = port->xmit_buf;
1777-
port->xmit_buf = NULL;
1778-
INIT_KFIFO(port->xmit_fifo);
1779-
uart_port_unlock_irq(uport);
1780-
1781-
free_page((unsigned long)buf);
1791+
uart_free_xmit_buf(port);
17821792

17831793
uart_change_pm(state, UART_PM_STATE_OFF);
17841794
}

0 commit comments

Comments
 (0)