Subject: port-hp300/18849: open of dcm modem port sometimes hangs
To: None <gnats-bugs@gnats.netbsd.org>
From: None <swp@alumni.rice.edu>
List: netbsd-bugs
Date: 10/29/2002 01:39:01
>Number:         18849
>Category:       port-hp300
>Synopsis:       open of dcm modem port sometimes hangs
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    port-hp300-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Oct 29 00:40:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Steve Peurifoy
>Release:        NetBSD 1.5.2
>Organization:
>Environment:
System: NetBSD loop.home 1.5.2 NetBSD 1.5.2 (loop) #2: Fri Oct 25 23:49:35 MDT 2002 root@loop.home:/usr/obj/sys/arch/hp300/compile/loop hp300


>Description:
	Occasionally a blocking open of dcm port 0 will hang in ttyopen()
	waiting for carrier detect to be asserted when it's already
	present.
>How-To-Repeat:
	I've encountered this at random times wth a couple of different
	modems.
>Fix:
	The problem is that dcmmint() will return before updating the
	value of sc->sc_mcndlast if the device is not open.  If carrier
	detect drops after the device is closed, sc->sc_mcndlast will
	no longer correctly represent the "previous" state of the
	signals when the next transition of carrier detect occurs.
	A subsequent blocking open will wait forever for an event
	which has in fact taken place.

Index: dcm.c
===================================================================
RCS file: /cvs/src/sys/arch/hp300/dev/dcm.c,v
retrieving revision 1.2
diff -c -r1.2 dcm.c
*** dcm.c	2002/10/21 08:36:57	1.2
--- dcm.c	2002/10/26 05:46:09
***************
*** 908,917 ****
  	struct tty *tp;
  	struct dcmdevice *dcm = sc->sc_dcm;
  
- 	tp = sc->sc_tty[port];
- 	if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
- 		return;
- 
  #ifdef DEBUG
  	if (dcmdebug & DDB_MODEM)
  		printf("%s port %d: dcmmint: mcnd %x mcndlast %x\n",
--- 908,913 ----
***************
*** 919,924 ****
--- 915,924 ----
  #endif
  	delta = mcnd ^ sc->sc_mcndlast[port];
  	sc->sc_mcndlast[port] = mcnd;
+ 	tp = sc->sc_tty[port];
+ 	if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
+ 		return;
+ 
  	if ((delta & MI_CTS) && (tp->t_state & TS_ISOPEN) &&
  	    (tp->t_cflag & CCTS_OFLOW)) {
  		if (mcnd & MI_CTS) {

>Release-Note:
>Audit-Trail:
>Unformatted: