]> git.baikalelectronics.ru Git - kernel.git/commitdiff
serial: Store character timing information to uart_port
authorIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Mon, 25 Apr 2022 14:33:58 +0000 (17:33 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 26 Apr 2022 11:28:32 +0000 (13:28 +0200)
Struct uart_port currently stores FIFO timeout. Having character timing
information readily available is useful. Even serial core itself
determines char_time from port->timeout using inverse calculation.

Store frame_time directly into uart_port. Character time is stored in
nanoseconds to have reasonable precision with high rates. To avoid
overflow, 64-bit math is necessary.

It might be possible to determine timeout from frame_time by
multiplying it with fifosize as needed but only part of the users seem
to be protected by a lock. Thus, this patch does not pursue storing
only frame_time in uart_port.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Link: https://lore.kernel.org/r/20220425143410.12703-2-ilpo.jarvinen@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/serial_core.c
include/linux/serial_core.h

index 01823ce87801960356ed8e6a8bf0d24b815223b0..82a1770dd8085f7ebeef2005874627cc08079dc2 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/sysrq.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
+#include <linux/math64.h>
 #include <linux/security.h>
 
 #include <linux/irq.h>
@@ -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;
 
index d4828e69087a405ed748a70034ac5551d2b58379..cbd5070bc87f42aa450c4ca7af8a9b59fbe88574 100644 (file)
@@ -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;