NetBSD Problem Report #4227
Received: (qmail 19013 invoked from network); 6 Oct 1997 17:04:48 -0000
Message-Id: <199710061705.CAA03470@escar.shiota.imasy.or.jp>
Date: Tue, 7 Oct 1997 02:05:13 +0900 (JST)
From: Noriyuki Shiota <nori@shiota.imasy.or.jp>
Reply-To: nori@shiota.imasy.or.jp
To: gnats-bugs@gnats.netbsd.org
Subject: blocked state of hardware flow control is not cleared
X-Send-Pr-Version: 3.95
>Number: 4227
>Category: kern
>Synopsis: blocked state of hardware flow control is not cleared
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Oct 06 10:05:01 +0000 1997
>Closed-Date:
>Last-Modified: Sun Sep 03 01:16:18 +0000 2006
>Originator: Noriyuki Shiota
>Release: NetBSD-current as of October 6, 1997
>Organization:
Noriyuki Shiota nori@shiota.imasy.or.jp
>Environment:
System: NetBSD escar 1.2G NetBSD 1.2G (ESCAR_BT_BOCA) #15: Mon Oct 6 23:26:37 JST 1997 root@escar:/usr/src/sys/arch/i386/compile/ESCAR_BT_BOCA i386
>Description:
On establishing ppp connection, I used following command:
pppd `chat ...` ....
and chat script is done normally.
But if the host machine send the long motd message, serial driver
negates RTS signal line.
then pppd changes line descipline to ppp, RTS signal is still
low. (serial driver's state is still blocked.)
In this situation, pppd never receive PPP packet.
>How-To-Repeat:
Try to connect ppp to long motd ppp server.
or
f = open("/dev/tty00", O_RDWR);
<receive may characters from serial line.
(*tp->t_hwiflow)(tp, 1) is called.
serial driver clears RTS signal line and enter block state>
what = FREAD;
ioctl(f, TIOCFLUSH, &what); /* flush receive buffer */
read(f, buf, sizeof(buf)); <-- block forever...
receive no character because
RTS is still low.
or
f = open("/dev/tty00", O_RDWR);
<receive may characters from serial line.
(*tp->t_hwiflow)(tp, 1) is called.
serial driver clears RTS signal line and enter block state>
ldisc = PPPDISC;
ioctl(f, TIOCSETD, &ldisc); /* change to PPP line descipline */
read(f, buf, sizeof(buf)); <-- block forever...
receive no character because
RTS is still low.
>Fix:
*** tty.c.ORIG Fri Jun 20 20:33:34 1997
--- tty.c Tue Oct 7 02:04:29 1997
***************
*** 1057,1082 ****
--- 1057,1086 ----
ttyflush(tp, rw)
register struct tty *tp;
int rw;
{
register int s;
s = spltty();
if (rw & FREAD) {
FLUSHQ(&tp->t_canq);
FLUSHQ(&tp->t_rawq);
tp->t_rocount = 0;
tp->t_rocol = 0;
CLR(tp->t_state, TS_LOCAL);
+ if (ISSET(tp->t_state, TS_TBLOCK) &&
+ ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
+ (*tp->t_hwiflow)(tp, 0) != 0)
+ CLR(tp->t_state, TS_TBLOCK);
ttwakeup(tp);
}
if (rw & FWRITE) {
CLR(tp->t_state, TS_TTSTOP);
(*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
FLUSHQ(&tp->t_outq);
wakeup((caddr_t)&tp->t_outq);
selwakeup(&tp->t_wsel);
}
splx(s);
}
/*
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: kern-bug-people->mycroft
Responsible-Changed-By: mycroft
Responsible-Changed-When: Thu Oct 9 02:09:52 PDT 1997
Responsible-Changed-Why:
The patch isn't quite complete; it doesn't handle the IXOFF case. I'll fix it
shortly.
From: "Charles M. Hannum" <mycroft@mit.edu>
To: nori@shiota.imasy.or.jp
Cc: gnats-bugs@gnats.netbsd.org
Subject: Re: kern/4227: blocked state of hardware flow control is not cleared
Date: Thu, 9 Oct 1997 16:11:33 -0400 (EDT)
Your patch is more or less correct, but:
* It doesn't deal with the case of XON/XOFF flow control. (This also
requires a slight rearrangement so that we queue the XON character
*after* flushing the write side.)
* It could (if the case were actually possible, which it's not
currently) cause a fairly severe malfunction when an input ring
becomes full; the input will be unblocked and then immediately blocked
again.
* There is a remaining problem that I haven't solved in the following
patch. With your change, if the input ring is full, there will be a
glitch on RTS during close, as it's raised by foohwiflow() and then
immediately lowered again by fooclose(). This is actually a fairly
serious error, and needs to be fixed.
Index: tty.c
===================================================================
RCS file: /cvsroot/src/sys/kern/tty.c,v
retrieving revision 1.98
diff -c -2 -r1.98 tty.c
*** tty.c 1997/10/09 12:59:56 1.98
--- tty.c 1997/10/09 20:09:31
***************
*** 67,70 ****
--- 67,72 ----
static void ttyrubo __P((struct tty *, int));
static int proc_compare __P((struct proc *, struct proc *));
+ static __inline void ttblock __P((struct tty *));
+ static __inline void ttunblock __P((struct tty *));
/* Symbolic sleep message strings. */
***************
*** 1014,1017 ****
--- 1016,1055 ----
}
+ static __inline void
+ ttblock(tp)
+ struct tty *tp;
+ {
+
+ /* Try to block remote output via software (XON/XOFF) flow control. */
+ if (ISSET(tp->t_iflag, IXOFF) &&
+ tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
+ putc(tp->t_cc[VSTOP], &tp->t_outq) == 0) {
+ SET(tp->t_state, TS_TBLOCK);
+ ttstart(tp);
+ }
+ /* Try to block remote output via hardware (CTS/RTS) flow control. */
+ if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
+ (*tp->t_hwiflow)(tp, 1) != 0)
+ SET(tp->t_state, TS_TBLOCK);
+ }
+
+ static __inline void
+ ttunblock(tp)
+ struct tty *tp;
+ {
+
+ /* Try to unblock remote output via software (XON/XOFF) flow control. */
+ if (ISSET(tp->t_iflag, IXOFF) &&
+ tp->t_cc[VSTART] != _POSIX_VDISABLE &&
+ putc(tp->t_cc[VSTART], &tp->t_outq) == 0) {
+ CLR(tp->t_state, TS_TBLOCK);
+ ttstart(tp);
+ }
+ /* Try to unblock remote output via hardware (CTS/RTS) flow control. */
+ if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
+ (*tp->t_hwiflow)(tp, 0) != 0)
+ CLR(tp->t_state, TS_TBLOCK);
+ }
+
/*
* Wait for output to drain.
***************
*** 1062,1065 ****
--- 1100,1110 ----
s = spltty();
+ if (rw & FWRITE) {
+ CLR(tp->t_state, TS_TTSTOP);
+ (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
+ FLUSHQ(&tp->t_outq);
+ wakeup((caddr_t)&tp->t_outq);
+ selwakeup(&tp->t_wsel);
+ }
if (rw & FREAD) {
FLUSHQ(&tp->t_canq);
***************
*** 1068,1080 ****
tp->t_rocol = 0;
CLR(tp->t_state, TS_LOCAL);
ttwakeup(tp);
}
- if (rw & FWRITE) {
- CLR(tp->t_state, TS_TTSTOP);
- (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
- FLUSHQ(&tp->t_outq);
- wakeup((caddr_t)&tp->t_outq);
- selwakeup(&tp->t_wsel);
- }
splx(s);
}
--- 1113,1120 ----
tp->t_rocol = 0;
CLR(tp->t_state, TS_LOCAL);
+ if (ISSET(tp->t_state, TS_TBLOCK))
+ ttunblock(tp);
ttwakeup(tp);
}
splx(s);
}
***************
*** 1102,1107 ****
total = tp->t_rawq.c_cc + tp->t_canq.c_cc;
if (tp->t_rawq.c_cc > TTYHOG) {
- ttyflush(tp, FREAD | FWRITE);
CLR(tp->t_state, TS_TBLOCK);
}
/*
--- 1142,1147 ----
total = tp->t_rawq.c_cc + tp->t_canq.c_cc;
if (tp->t_rawq.c_cc > TTYHOG) {
CLR(tp->t_state, TS_TBLOCK);
+ ttyflush(tp, FREAD | FWRITE);
}
/*
***************
*** 1111,1126 ****
if ((total >= TTYHOG / 2 &&
!ISSET(tp->t_state, TS_TBLOCK) &&
! !ISSET(tp->t_lflag, ICANON)) || tp->t_canq.c_cc > 0) {
! if (ISSET(tp->t_iflag, IXOFF) &&
! tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
! putc(tp->t_cc[VSTOP], &tp->t_outq) == 0) {
! SET(tp->t_state, TS_TBLOCK);
! ttstart(tp);
! }
! /* Try to block remote output via hardware flow control. */
! if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
! (*tp->t_hwiflow)(tp, 1) != 0)
! SET(tp->t_state, TS_TBLOCK);
! }
}
--- 1151,1156 ----
if ((total >= TTYHOG / 2 &&
!ISSET(tp->t_state, TS_TBLOCK) &&
! !ISSET(tp->t_lflag, ICANON)) || tp->t_canq.c_cc > 0)
! ttblock(tp);
}
***************
*** 1189,1195 ****
CLR(tp->t_state, TS_CARR_ON);
if (ISSET(tp->t_state, TS_ISOPEN) && !CONNECTED(tp)) {
if (tp->t_session && tp->t_session->s_leader)
psignal(tp->t_session->s_leader, SIGHUP);
- ttyflush(tp, FREAD | FWRITE);
return (0);
}
--- 1219,1225 ----
CLR(tp->t_state, TS_CARR_ON);
if (ISSET(tp->t_state, TS_ISOPEN) && !CONNECTED(tp)) {
+ ttyflush(tp, FREAD | FWRITE);
if (tp->t_session && tp->t_session->s_leader)
psignal(tp->t_session->s_leader, SIGHUP);
return (0);
}
***************
*** 1435,1450 ****
*/
s = spltty();
! if (ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG/5) {
! if (ISSET(tp->t_iflag, IXOFF) &&
! cc[VSTART] != _POSIX_VDISABLE &&
! putc(cc[VSTART], &tp->t_outq) == 0) {
! CLR(tp->t_state, TS_TBLOCK);
! ttstart(tp);
! }
! /* Try to unblock remote output via hardware flow control. */
! if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
! (*tp->t_hwiflow)(tp, 0) != 0)
! CLR(tp->t_state, TS_TBLOCK);
! }
splx(s);
return (error);
--- 1465,1470 ----
*/
s = spltty();
! if (ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG/5)
! ttunblock(tp);
splx(s);
return (error);
From: Noriyuki Shiota <nori@shiota.imasy.or.jp>
To: mycroft@mit.edu
Cc: gnats-bugs@gnats.netbsd.org, nori@escar.shiota.imasy.or.jp
Subject: Re: kern/4227: blocked state of hardware flow control is not cleared
Date: Mon, 13 Oct 1997 06:08:27 +0900
> Your patch is more or less correct, but:
>
> * It doesn't deal with the case of XON/XOFF flow control. (This also
> requires a slight rearrangement so that we queue the XON character
> *after* flushing the write side.)
I didn't consider the XON/XOFF flow control case.
I understand the same treatment is requred for this case.
> * It could (if the case were actually possible, which it's not
> currently) cause a fairly severe malfunction when an input ring
> becomes full; the input will be unblocked and then immediately blocked
> again.
Is it a malfunction? I don't understand what you mean. After flushing,
if many characters are received, an input ring and **the line decipline queue**
are filled up, then to block immediately is normal behavior, isn't it?
But I think that to add foohwiflush() is ideal.
> * There is a remaining problem that I haven't solved in the following
> patch. With your change, if the input ring is full, there will be a
> glitch on RTS during close, as it's raised by foohwiflow() and then
> immediately lowered again by fooclose(). This is actually a fairly
> serious error, and needs to be fixed.
I see. It is necessary to add a mask FCLOSE or FUNBLOCK for the second
argument of ttyflush(), and if this mask is set then ttyflush() deson't
call foohwiflow(tp, 0). (in XON/XOFF case, I think it is better it send
cc[VSTART] on closing.)
---
Noriyuki Shiota nori@shiota.imasy.or.jp
Responsible-Changed-From-To: mycroft->kern-bug-people
Responsible-Changed-By: wiz@netbsd.org
Responsible-Changed-When: Sun, 03 Sep 2006 01:16:18 +0000
Responsible-Changed-Why:
Back to role account, mycroft doesn't have commit access any longer.
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.