Subject: port-i386/1047: rs232c/ns16450 hang up problem & fix
To: None <gnats-admin@sun-lamp.cs.berkeley.edu>
From: Noriyuki Soda <soda@sra.co.jp>
List: netbsd-bugs
Date: 05/14/1995 08:20:04
>Number: 1047
>Category: port-i386
>Synopsis: rs232c/ns16450 hang up problem & fix
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: gnats-admin (GNATS administrator)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun May 14 08:20:02 1995
>Originator: Noriyuki Soda
>Organization:
Software Research Associates, Inc.
>Release: 1.0A
>Environment:
System: NetBSD james 1.0A NetBSD 1.0A (JAMES) #0: Sat Mar 4 08:21:18 JST 1995 soda@james:/usr/src/sys/arch/i386/compile/JAMES i386
Machine:
486DX2/66MHz, 8MB RAM, IDE 520MB disk, NS16450 serial chip.
com1 at isa0 port 0x2f8-0x2ff irq 3: ns82450 or ns16450, no fifo
>Description:
When using PPPD or TIP, RS-232 is sometimes stopped up, and it
doesn't recover until rebooting NetBSD.
When hangs on PPPD, "ps agxl" shows WCHAR="ttyout".
Note: my serial chip is NS16450.
>How-To-Repeat:
% find / -print >& /dev/null &
% ping -s 1400 ppp-peer-address
>Fix:
After applying following patch, problem goes away, with following message.
-> May 14 20:11:35 james /netbsd: com1: lost tx interrupt
May 14 20:12:20 james /netbsd: com1: 2 silo overflows
May 14 20:13:26 james /netbsd: com1: 1 silo overflow
-> May 14 20:14:55 james /netbsd: com1: lost tx interrupt
(This patch is based on NetBSD-current 1995/05/13)
----------------------------------------------------------------------------
--- 1.1.1.1 1995/05/13 10:25:50
+++ com.c 1995/05/14 09:48:45
@@ -62,6 +62,9 @@
#include <dev/isa/comreg.h>
#include <dev/ic/ns16550.h>
+#define COM_DETECT_LOST_TXINTR
+#define COM_TX_TIMEOUT 2 /* should be > 1 */
+
struct com_softc {
struct device sc_dev;
void *sc_ih;
@@ -79,6 +82,10 @@
#define COM_SW_CRTSCTS 0x04
#define COM_SW_MDMBUF 0x08
u_char sc_msr, sc_mcr;
+#ifdef COM_DETECT_LOST_TXINTR
+ int32_t sc_transmit_time;
+ u_char sc_txintr_pending;
+#endif
};
int comprobe __P((struct device *, void *, void *));
@@ -86,6 +93,9 @@
int comopen __P((dev_t, int, int, struct proc *));
int comclose __P((dev_t, int, int, struct proc *));
void comdiag __P((void *));
+#ifdef COM_DETECT_LOST_TXINTR
+void comwatchdog __P((void *));
+#endif
int comintr __P((void *));
int comparam __P((struct tty *, struct termios *));
void comstart __P((struct tty *));
@@ -295,6 +305,13 @@
outb(iobase + com_fifo,
FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
(tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
+#ifdef COM_DETECT_LOST_TXINTR
+ else {
+ /* for buggy chip */
+ sc->sc_txintr_pending = 0;
+ timeout(comwatchdog, sc, hz);
+ }
+#endif
/* flush any pending I/O */
(void) inb(iobase + com_lsr);
(void) inb(iobase + com_data);
@@ -359,6 +376,12 @@
(sc->sc_swflags & COM_SW_SOFTCAR) == 0)
/* XXX perhaps only clear DTR */
outb(iobase + com_mcr, 0);
+#ifdef COM_DETECT_LOST_TXINTR
+ if ((sc->sc_hwflags & COM_HW_FIFO) == 0) {
+ sc->sc_txintr_pending = 0;
+ untimeout(comwatchdog, sc);
+ }
+#endif
}
ttyclose(tp);
#ifdef notyet /* XXXX */
@@ -674,6 +697,10 @@
} while (--n);
} else
outb(iobase + com_data, getc(&tp->t_outq));
+#ifdef COM_DETECT_LOST_TXINTR
+ sc->sc_txintr_pending = 1;
+ sc->sc_transmit_time = time.tv_sec;
+#endif
out:
splx(s);
}
@@ -778,6 +805,46 @@
sc->sc_dev.dv_xname, overflows, overflows == 1 ? "" : "s");
}
+static inline void
+comtint(sc)
+ struct com_softc *sc;
+{
+ struct tty *tp = tp = sc->sc_tty;
+
+#ifdef COM_DETECT_LOST_TXINTR
+ sc->sc_txintr_pending = 0;
+#endif
+ tp->t_state &= ~TS_BUSY;
+ if (tp->t_state & TS_FLUSH)
+ tp->t_state &= ~TS_FLUSH;
+ else if (tp->t_line)
+ (*linesw[tp->t_line].l_start)(tp);
+ else
+ comstart(tp);
+}
+
+#ifdef COM_DETECT_LOST_TXINTR
+void
+comwatchdog(arg)
+ void *arg;
+{
+ struct com_softc *sc = arg;
+ int iobase = sc->sc_iobase;
+ int s;
+
+ if (sc->sc_txintr_pending &&
+ time.tv_sec - sc->sc_transmit_time >= COM_TX_TIMEOUT &&
+ (inb(iobase + com_lsr) & LSR_TXRDY)) {
+ s = spltty();
+ comtint(sc);
+ splx(s);
+ log(LOG_WARNING, "%s: lost tx interrupt\n",
+ sc->sc_dev.dv_xname);
+ }
+ timeout(comwatchdog, sc, hz);
+}
+#endif
+
int
comintr(arg)
void *arg;
@@ -811,15 +878,7 @@
comeint(sc, code);
}
} else if (code == IIR_TXRDY) {
- tp = sc->sc_tty;
- tp->t_state &= ~TS_BUSY;
- if (tp->t_state & TS_FLUSH)
- tp->t_state &= ~TS_FLUSH;
- else
- if (tp->t_line)
- (*linesw[tp->t_line].l_start)(tp);
- else
- comstart(tp);
+ comtint(sc);
} else if (code == IIR_MLSC) {
commint(sc);
} else {
----------------------------------------------------------------------------
P.S.
Sorry for my poor English.
--
soda@sra.co.jp Software Research Associates, Inc., Japan
(Noriyuki Soda) software tools and technology group
>Audit-Trail:
>Unformatted: