aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Slaby <jslaby@suse.cz>2017-09-12 06:39:54 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-09-18 12:19:20 -0400
commit104583b504da8a3ad86d033b497cb6e58941a9a1 (patch)
treebd26ede2093fe93714d6d49aff4e28f3ac0aa591
parent432219fd002ada95d2f45dd3a25c3f7c73f27864 (diff)
mxser: fix timeout calculation for low rates
Paul reported, that low rates like B300 make the driver to hang in mxser_wait_until_sent. His debugging tackled the issue down to the info->timeout computation in mxser_set_baud. Obviously, ints are used there and they easily overflow with these low rates: B300 makes info->timeout to be -373. So switch all these types to unsigned as it ought to be. And use the u64 domain to perform the computation as in the worst case, we need 35 bits to store the computed value (before division). And use do_div not to break 32 bit kernels. [v2] make it actually build Signed-off-by: Jiri Slaby <jslaby@suse.cz> Cc: Paul <Paul@abelian.netcom.co.uk> Tested-by: <Paul@abelian.netcom.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/mxser.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index 1c0c9553bc05..7dd38047ba23 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -246,11 +246,11 @@ struct mxser_port {
246 unsigned char err_shadow; 246 unsigned char err_shadow;
247 247
248 struct async_icount icount; /* kernel counters for 4 input interrupts */ 248 struct async_icount icount; /* kernel counters for 4 input interrupts */
249 int timeout; 249 unsigned int timeout;
250 250
251 int read_status_mask; 251 int read_status_mask;
252 int ignore_status_mask; 252 int ignore_status_mask;
253 int xmit_fifo_size; 253 unsigned int xmit_fifo_size;
254 int xmit_head; 254 int xmit_head;
255 int xmit_tail; 255 int xmit_tail;
256 int xmit_cnt; 256 int xmit_cnt;
@@ -572,8 +572,9 @@ static void mxser_dtr_rts(struct tty_port *port, int on)
572static int mxser_set_baud(struct tty_struct *tty, long newspd) 572static int mxser_set_baud(struct tty_struct *tty, long newspd)
573{ 573{
574 struct mxser_port *info = tty->driver_data; 574 struct mxser_port *info = tty->driver_data;
575 int quot = 0, baud; 575 unsigned int quot = 0, baud;
576 unsigned char cval; 576 unsigned char cval;
577 u64 timeout;
577 578
578 if (!info->ioaddr) 579 if (!info->ioaddr)
579 return -1; 580 return -1;
@@ -594,8 +595,13 @@ static int mxser_set_baud(struct tty_struct *tty, long newspd)
594 quot = 0; 595 quot = 0;
595 } 596 }
596 597
597 info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base); 598 /*
598 info->timeout += HZ / 50; /* Add .02 seconds of slop */ 599 * worst case (128 * 1000 * 10 * 18432) needs 35 bits, so divide in the
600 * u64 domain
601 */
602 timeout = (u64)info->xmit_fifo_size * HZ * 10 * quot;
603 do_div(timeout, info->baud_base);
604 info->timeout = timeout + HZ / 50; /* Add .02 seconds of slop */
599 605
600 if (quot) { 606 if (quot) {
601 info->MCR |= UART_MCR_DTR; 607 info->MCR |= UART_MCR_DTR;