mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-17 01:34:00 +08:00
serial: Drop timeout from uart_port
Since commit 31f6bd7fad
("serial: Store character timing information
to uart_port"), per frame timing information is available on uart_port.
Uart port's timeout can be derived from frame_time by multiplying with
fifosize.
Most callers of uart_poll_timeout are not made under port's lock. To be
on the safe side, make sure frame_time is only accessed once. As
fifo_size is effectively a constant, it shouldn't cause any issues.
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Link: https://lore.kernel.org/r/20220613113905.22962-1-ilpo.jarvinen@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
ab24a01b27
commit
f9008285bb
@ -422,8 +422,9 @@ Other functions
|
||||
---------------
|
||||
|
||||
uart_update_timeout(port,cflag,baud)
|
||||
Update the FIFO drain timeout, port->timeout, according to the
|
||||
number of bits, parity, stop bits and baud rate.
|
||||
Update the frame timing information according to the number of bits,
|
||||
parity, stop bits and baud rate. The FIFO drain timeout is derived
|
||||
from the frame timing information.
|
||||
|
||||
Locking: caller is expected to take port->lock
|
||||
|
||||
|
@ -481,12 +481,6 @@ static int __init mux_probe(struct parisc_device *dev)
|
||||
port->line = port_cnt;
|
||||
port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MUX_CONSOLE);
|
||||
|
||||
/* The port->timeout needs to match what is present in
|
||||
* uart_wait_until_sent in serial_core.c. Otherwise
|
||||
* the time spent in msleep_interruptable will be very
|
||||
* long, causing the appearance of a console hang.
|
||||
*/
|
||||
port->timeout = HZ / 50;
|
||||
spin_lock_init(&port->lock);
|
||||
|
||||
status = uart_add_one_port(&mux_driver, port);
|
||||
|
@ -327,13 +327,14 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
|
||||
}
|
||||
|
||||
/**
|
||||
* uart_update_timeout - update per-port FIFO timeout.
|
||||
* uart_update_timeout - update per-port frame timing information.
|
||||
* @port: uart_port structure describing the port
|
||||
* @cflag: termios cflag value
|
||||
* @baud: speed of the port
|
||||
*
|
||||
* Set the port FIFO timeout value. The @cflag value should
|
||||
* reflect the actual hardware settings.
|
||||
* Set the port frame timing information from which the FIFO timeout
|
||||
* value is derived. The @cflag value should reflect the actual hardware
|
||||
* settings.
|
||||
*/
|
||||
void
|
||||
uart_update_timeout(struct uart_port *port, unsigned int cflag,
|
||||
@ -343,13 +344,6 @@ uart_update_timeout(struct uart_port *port, unsigned int cflag,
|
||||
u64 frame_time;
|
||||
|
||||
frame_time = (u64)size * NSEC_PER_SEC;
|
||||
size *= port->fifosize;
|
||||
|
||||
/*
|
||||
* Figure the timeout to send the above number of bits.
|
||||
* Add .02 seconds of slop
|
||||
*/
|
||||
port->timeout = (HZ * size) / baud + HZ/50;
|
||||
port->frame_time = DIV64_U64_ROUND_UP(frame_time, baud);
|
||||
}
|
||||
EXPORT_SYMBOL(uart_update_timeout);
|
||||
@ -1698,7 +1692,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
|
||||
{
|
||||
struct uart_state *state = tty->driver_data;
|
||||
struct uart_port *port;
|
||||
unsigned long char_time, expire;
|
||||
unsigned long char_time, expire, fifo_timeout;
|
||||
|
||||
port = uart_port_ref(state);
|
||||
if (!port)
|
||||
@ -1728,12 +1722,13 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
|
||||
* amount of time to send the entire FIFO, it probably won't
|
||||
* ever clear. This assumes the UART isn't doing flow
|
||||
* control, which is currently the case. Hence, if it ever
|
||||
* takes longer than port->timeout, this is probably due to a
|
||||
* takes longer than FIFO timeout, this is probably due to a
|
||||
* UART bug of some kind. So, we clamp the timeout parameter at
|
||||
* 2*port->timeout.
|
||||
* 2 * FIFO timeout.
|
||||
*/
|
||||
if (timeout == 0 || timeout > 2 * port->timeout)
|
||||
timeout = 2 * port->timeout;
|
||||
fifo_timeout = uart_fifo_timeout(port);
|
||||
if (timeout == 0 || timeout > 2 * fifo_timeout)
|
||||
timeout = 2 * fifo_timeout;
|
||||
}
|
||||
|
||||
expire = jiffies + timeout;
|
||||
|
@ -232,7 +232,6 @@ struct uart_port {
|
||||
|
||||
int hw_stopped; /* sw-assisted CTS flow state */
|
||||
unsigned int mctrl; /* current modem ctrl settings */
|
||||
unsigned int timeout; /* character-based timeout */
|
||||
unsigned int frame_time; /* frame timing in ns */
|
||||
unsigned int type; /* port type */
|
||||
const struct uart_ops *ops;
|
||||
@ -335,10 +334,23 @@ unsigned int uart_get_baud_rate(struct uart_port *port, struct ktermios *termios
|
||||
unsigned int max);
|
||||
unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud);
|
||||
|
||||
/*
|
||||
* Calculates FIFO drain time.
|
||||
*/
|
||||
static inline unsigned long uart_fifo_timeout(struct uart_port *port)
|
||||
{
|
||||
u64 fifo_timeout = (u64)READ_ONCE(port->frame_time) * port->fifosize;
|
||||
|
||||
/* Add .02 seconds of slop */
|
||||
fifo_timeout += 20 * NSEC_PER_MSEC;
|
||||
|
||||
return max(nsecs_to_jiffies(fifo_timeout), 1UL);
|
||||
}
|
||||
|
||||
/* Base timer interval for polling */
|
||||
static inline int uart_poll_timeout(struct uart_port *port)
|
||||
{
|
||||
int timeout = port->timeout;
|
||||
int timeout = uart_fifo_timeout(port);
|
||||
|
||||
return timeout > 6 ? (timeout / 2 - 2) : 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user