From 63e32a69f23a2ef5543ae204991a7936d0aaeb2a Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Fri, 18 Apr 1997 18:28:09 +0000 Subject: [PATCH] Don't call timeout() for DTR wakeup or busy check if the relevant timeout is already active. This fixes "timeout table full" panics under 100% interrupt load and other weird conditions. --- sys/dev/sio/sio.c | 16 +++++++++++----- sys/i386/isa/sio.c | 16 +++++++++++----- sys/isa/sio.c | 16 +++++++++++----- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/sys/dev/sio/sio.c b/sys/dev/sio/sio.c index c07c411d4391..7d5e78db1be2 100644 --- a/sys/dev/sio/sio.c +++ b/sys/dev/sio/sio.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)com.c 7.5 (Berkeley) 5/16/91 - * $Id: sio.c,v 1.161 1997/03/24 11:24:04 bde Exp $ + * $Id: sio.c,v 1.162 1997/04/05 13:11:27 bde Exp $ */ #include "opt_comconsole.h" @@ -148,6 +148,7 @@ #define CS_DTR_OFF 0x10 /* DTR held off */ #define CS_ODONE 4 /* output completed */ #define CS_RTS_IFLOW 8 /* use RTS input flow control */ +#define CSE_BUSYCHECK 1 /* siobusycheck() scheduled */ static char const * const error_desc[] = { #define CE_OVERRUN 0 @@ -181,6 +182,7 @@ struct com_s { #ifdef COM_ESP bool_t esp; /* is this unit a hayes esp board? */ #endif + u_char extra_state; /* more flag bits, separate for order trick */ u_char fifo_image; /* copy of value written to FIFO */ bool_t hasfifo; /* nonzero for 16550 UARTs */ bool_t loses_outints; /* nonzero if device loses output interrupts */ @@ -1230,7 +1232,7 @@ comhardclose(com) && !(com->it_in.c_cflag & CLOCAL) || !(tp->t_state & TS_ISOPEN)) { (void)commctl(com, TIOCM_DTR, DMBIC); - if (com->dtr_wait != 0) { + if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { timeout(siodtrwakeup, com, com->dtr_wait); com->state |= CS_DTR_OFF; } @@ -1311,18 +1313,19 @@ siobusycheck(chan) /* * Clear TS_BUSY if low-level output is complete. * spl locking is sufficient because siointr1() does not set CS_BUSY. - * If siointr() clears CS_BUSY after we look at it, then we'll get + * If siointr1() clears CS_BUSY after we look at it, then we'll get * called again. Reading the line status port outside of siointr1() * is safe because CS_BUSY is clear so there are no output interrupts * to lose. */ s = spltty(); if (com->state & CS_BUSY) - ; /* False alarm. */ + com->extra_state &= ~CSE_BUSYCHECK; /* False alarm. */ else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) == (LSR_TSRE | LSR_TXRDY)) { com->tp->t_state &= ~TS_BUSY; ttwwakeup(com->tp); + com->extra_state &= ~CSE_BUSYCHECK; } else timeout(siobusycheck, com, hz / 100); splx(s); @@ -1813,8 +1816,11 @@ repeat: com_events -= LOTS_OF_EVENTS; com->state &= ~CS_ODONE; enable_intr(); - if (!(com->state & CS_BUSY)) + if (!(com->state & CS_BUSY) + && !(com->extra_state & CSE_BUSYCHECK)) { timeout(siobusycheck, com, hz / 100); + com->extra_state |= CSE_BUSYCHECK; + } (*linesw[tp->t_line].l_start)(tp); } if (incc <= 0 || !(tp->t_state & TS_ISOPEN) || diff --git a/sys/i386/isa/sio.c b/sys/i386/isa/sio.c index c07c411d4391..7d5e78db1be2 100644 --- a/sys/i386/isa/sio.c +++ b/sys/i386/isa/sio.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)com.c 7.5 (Berkeley) 5/16/91 - * $Id: sio.c,v 1.161 1997/03/24 11:24:04 bde Exp $ + * $Id: sio.c,v 1.162 1997/04/05 13:11:27 bde Exp $ */ #include "opt_comconsole.h" @@ -148,6 +148,7 @@ #define CS_DTR_OFF 0x10 /* DTR held off */ #define CS_ODONE 4 /* output completed */ #define CS_RTS_IFLOW 8 /* use RTS input flow control */ +#define CSE_BUSYCHECK 1 /* siobusycheck() scheduled */ static char const * const error_desc[] = { #define CE_OVERRUN 0 @@ -181,6 +182,7 @@ struct com_s { #ifdef COM_ESP bool_t esp; /* is this unit a hayes esp board? */ #endif + u_char extra_state; /* more flag bits, separate for order trick */ u_char fifo_image; /* copy of value written to FIFO */ bool_t hasfifo; /* nonzero for 16550 UARTs */ bool_t loses_outints; /* nonzero if device loses output interrupts */ @@ -1230,7 +1232,7 @@ comhardclose(com) && !(com->it_in.c_cflag & CLOCAL) || !(tp->t_state & TS_ISOPEN)) { (void)commctl(com, TIOCM_DTR, DMBIC); - if (com->dtr_wait != 0) { + if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { timeout(siodtrwakeup, com, com->dtr_wait); com->state |= CS_DTR_OFF; } @@ -1311,18 +1313,19 @@ siobusycheck(chan) /* * Clear TS_BUSY if low-level output is complete. * spl locking is sufficient because siointr1() does not set CS_BUSY. - * If siointr() clears CS_BUSY after we look at it, then we'll get + * If siointr1() clears CS_BUSY after we look at it, then we'll get * called again. Reading the line status port outside of siointr1() * is safe because CS_BUSY is clear so there are no output interrupts * to lose. */ s = spltty(); if (com->state & CS_BUSY) - ; /* False alarm. */ + com->extra_state &= ~CSE_BUSYCHECK; /* False alarm. */ else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) == (LSR_TSRE | LSR_TXRDY)) { com->tp->t_state &= ~TS_BUSY; ttwwakeup(com->tp); + com->extra_state &= ~CSE_BUSYCHECK; } else timeout(siobusycheck, com, hz / 100); splx(s); @@ -1813,8 +1816,11 @@ repeat: com_events -= LOTS_OF_EVENTS; com->state &= ~CS_ODONE; enable_intr(); - if (!(com->state & CS_BUSY)) + if (!(com->state & CS_BUSY) + && !(com->extra_state & CSE_BUSYCHECK)) { timeout(siobusycheck, com, hz / 100); + com->extra_state |= CSE_BUSYCHECK; + } (*linesw[tp->t_line].l_start)(tp); } if (incc <= 0 || !(tp->t_state & TS_ISOPEN) || diff --git a/sys/isa/sio.c b/sys/isa/sio.c index c07c411d4391..7d5e78db1be2 100644 --- a/sys/isa/sio.c +++ b/sys/isa/sio.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)com.c 7.5 (Berkeley) 5/16/91 - * $Id: sio.c,v 1.161 1997/03/24 11:24:04 bde Exp $ + * $Id: sio.c,v 1.162 1997/04/05 13:11:27 bde Exp $ */ #include "opt_comconsole.h" @@ -148,6 +148,7 @@ #define CS_DTR_OFF 0x10 /* DTR held off */ #define CS_ODONE 4 /* output completed */ #define CS_RTS_IFLOW 8 /* use RTS input flow control */ +#define CSE_BUSYCHECK 1 /* siobusycheck() scheduled */ static char const * const error_desc[] = { #define CE_OVERRUN 0 @@ -181,6 +182,7 @@ struct com_s { #ifdef COM_ESP bool_t esp; /* is this unit a hayes esp board? */ #endif + u_char extra_state; /* more flag bits, separate for order trick */ u_char fifo_image; /* copy of value written to FIFO */ bool_t hasfifo; /* nonzero for 16550 UARTs */ bool_t loses_outints; /* nonzero if device loses output interrupts */ @@ -1230,7 +1232,7 @@ comhardclose(com) && !(com->it_in.c_cflag & CLOCAL) || !(tp->t_state & TS_ISOPEN)) { (void)commctl(com, TIOCM_DTR, DMBIC); - if (com->dtr_wait != 0) { + if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { timeout(siodtrwakeup, com, com->dtr_wait); com->state |= CS_DTR_OFF; } @@ -1311,18 +1313,19 @@ siobusycheck(chan) /* * Clear TS_BUSY if low-level output is complete. * spl locking is sufficient because siointr1() does not set CS_BUSY. - * If siointr() clears CS_BUSY after we look at it, then we'll get + * If siointr1() clears CS_BUSY after we look at it, then we'll get * called again. Reading the line status port outside of siointr1() * is safe because CS_BUSY is clear so there are no output interrupts * to lose. */ s = spltty(); if (com->state & CS_BUSY) - ; /* False alarm. */ + com->extra_state &= ~CSE_BUSYCHECK; /* False alarm. */ else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) == (LSR_TSRE | LSR_TXRDY)) { com->tp->t_state &= ~TS_BUSY; ttwwakeup(com->tp); + com->extra_state &= ~CSE_BUSYCHECK; } else timeout(siobusycheck, com, hz / 100); splx(s); @@ -1813,8 +1816,11 @@ repeat: com_events -= LOTS_OF_EVENTS; com->state &= ~CS_ODONE; enable_intr(); - if (!(com->state & CS_BUSY)) + if (!(com->state & CS_BUSY) + && !(com->extra_state & CSE_BUSYCHECK)) { timeout(siobusycheck, com, hz / 100); + com->extra_state |= CSE_BUSYCHECK; + } (*linesw[tp->t_line].l_start)(tp); } if (incc <= 0 || !(tp->t_state & TS_ISOPEN) ||