diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 01823ce87801..82a1770dd808 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -338,15 +339,18 @@ void uart_update_timeout(struct uart_port *port, unsigned int cflag, unsigned int baud) { - unsigned int size; + unsigned int size = tty_get_frame_size(cflag); + u64 frame_time; - size = tty_get_frame_size(cflag) * port->fifosize; + 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); @@ -1643,10 +1647,8 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) * Note: we have to use pretty tight timings here to satisfy * the NIST-PCTS. */ - char_time = (port->timeout - HZ/50) / port->fifosize; - char_time = char_time / 5; - if (char_time == 0) - char_time = 1; + char_time = max(nsecs_to_jiffies(port->frame_time / 5), 1UL); + if (timeout && timeout < char_time) char_time = timeout; diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index d4828e69087a..cbd5070bc87f 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -232,6 +232,7 @@ 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; unsigned int custom_divisor;