NetBSD Problem Report #19011

Received: (qmail 8973 invoked by uid 605); 11 Nov 2002 07:28:34 -0000
Message-Id: <20021111072833.6CAB211124@narn.netbsd.org>
Date: Sun, 10 Nov 2002 23:28:33 -0800 (PST)
From: umezawa@iij.ad.jp
Sender: gnats-bugs-owner@netbsd.org
Reply-To: umezawa@iij.ad.jp
To: gnats-bugs@gnats.netbsd.org
Subject: Interrupt from serial device is sometimes lost
X-Send-Pr-Version: www-1.0

>Number:         19011
>Category:       kern
>Synopsis:       Interrupt from serial device is sometimes lost
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Nov 11 07:29:00 +0000 2002
>Closed-Date:    
>Last-Modified:  Mon Nov 11 11:41:02 +0000 2002
>Originator:     UMEZAWA Takeshi
>Release:        1.5.3
>Organization:
Internet Initiative Japan (IIJ)
>Environment:
NetBSD netbsdtest 1.5.3 NetBSD 1.5.3 (GENERIC) #34: Mon Jul  1 21:36:06 CEST 2002
    he@hamster.urc.uninett.no:/usr/src/sys/arch/i386/compile/GENERIC i386

>Description:
On certain machine and certain condition, an interrupt from a serial device is lost.
Once lost, that serial device seems to be hung up. But if the kernel itself output a message to the serial console device (that is hung up), this situation is corrected and the device works normally.

>How-To-Repeat:
1. Boot with serial console.
2. Repeat plugging/unplugging serial cable some times.
3. You will find that serial console is hung up. If not, that machine does not cause this problem.

>Fix:
Apply following patch (against NetBSD 1.5.3).
If applied, comintr() is periodically called in order to recover lost interrupt(s). Recovery interval is COM_INTR_RECOVERY_INTERVAL second(s), and it is defiend as 1 (second).
Similar workaround is found in /usr/src/sys/dev/sio/sio.c of FreeBSD.

*** comvar.h-	Mon Nov 11 15:26:02 2002
--- comvar.h	Mon Nov 11 15:26:23 2002
***************
*** 125,130 ****
--- 125,132 ----
  #if NRND > 0 && defined(RND_COM)
  	rndsource_element_t  rnd_source;
  #endif
+ 
+ 	struct callout sc_intr_recover_callout;
  };

  /* Macros to clear/set/test flags. */
*** com.c-	Mon Nov 11 15:25:50 2002
--- com.c	Mon Nov 11 15:26:23 2002
***************
*** 168,173 ****
--- 168,174 ----
  integrate void com_stsoft	__P((struct com_softc *, struct tty *));
  integrate void com_schedrx	__P((struct com_softc *));
  void	comdiag		__P((void *));
+ void	comintr_recover __P((void *));

  extern struct cfdriver com_cd;

***************
*** 228,233 ****
--- 229,238 ----
  #define	BW	BUS_SPACE_BARRIER_WRITE
  #define COM_BARRIER(t, h, f) bus_space_barrier((t), (h), 0, COM_NPORTS, (f))

+ /* interval (in seconds) to recover lost interrupts */
+ #define COM_INTR_RECOVERY_INTERVAL 1
+ 
+ 
  int
  comspeed(speed, frequency)
  	long speed, frequency;
***************
*** 399,404 ****
--- 404,410 ----
  #endif

  	callout_init(&sc->sc_diag_callout);
+ 	callout_init(&sc->sc_intr_recover_callout);

  	/* Disable interrupts before configuring the device. */
  	sc->sc_ier = 0;
***************
*** 556,561 ****
--- 562,570 ----
  	com_config(sc);

  	SET(sc->sc_hwflags, COM_HW_DEV_OK);
+ 
+ 	callout_reset(&sc->sc_intr_recover_callout,
+ 	    hz*COM_INTR_RECOVERY_INTERVAL, comintr_recover, sc);
  }

  void
***************
*** 626,631 ****
--- 635,642 ----
  	struct com_softc *sc = (struct com_softc *)self;
  	int maj, mn;

+ 	callout_stop(&sc->sc_intr_recover_callout);
+ 
  	/* locate the major number */
  	for (maj = 0; maj < nchrdev; maj++)
  		if (cdevsw[maj].d_open == comopen)
***************
*** 2145,2150 ****
--- 2156,2173 ----

  	return (1);
  }
+ 
+ void
+ comintr_recover(arg)
+ 	void * arg;
+ {
+ 	struct com_softc *sc = arg;
+ 
+ 	comintr(sc);
+ 	callout_reset(&sc->sc_intr_recover_callout,
+ 	    hz*COM_INTR_RECOVERY_INTERVAL, comintr_recover, arg);
+ }
+ 

  /*
   * The following functions are polled getc and putc routines, shared

>Release-Note:
>Audit-Trail:

From: =?ISO-2022-JP?B?GyRCR19fNxsoQiAbJEIwUjtWGyhCIA==?= <umezawa@iij.ad.jp>
To: gnats-bugs@netbsd.org
Cc:  
Subject: Re: kern/19011
Date: Mon, 11 Nov 2002 20:40:34 +0900

 Oops, I have forgot calling splserial() in comintr_recover().

 The following one should be correct...


 *** comvar.h-	Mon Nov 11 15:26:02 2002
 --- comvar.h	Mon Nov 11 15:26:23 2002
 ***************
 *** 125,130 ****
 --- 125,132 ----
   #if NRND > 0 && defined(RND_COM)
   	rndsource_element_t  rnd_source;
   #endif
 + 
 + 	struct callout sc_intr_recover_callout;
   };

   /* Macros to clear/set/test flags. */
 *** com.c-	Mon Nov 11 15:25:50 2002
 --- com.c	Mon Nov 11 20:35:18 2002
 ***************
 *** 168,173 ****
 --- 168,174 ----
   integrate void com_stsoft	__P((struct com_softc *, struct tty *));
   integrate void com_schedrx	__P((struct com_softc *));
   void	comdiag		__P((void *));
 + void	comintr_recover __P((void *));

   extern struct cfdriver com_cd;

 ***************
 *** 228,233 ****
 --- 229,238 ----
   #define	BW	BUS_SPACE_BARRIER_WRITE
   #define COM_BARRIER(t, h, f) bus_space_barrier((t), (h), 0, COM_NPORTS, (f))

 + /* interval (in seconds) to recover lost interrupts */
 + #define COM_INTR_RECOVERY_INTERVAL 1
 + 
 + 
   int
   comspeed(speed, frequency)
   	long speed, frequency;
 ***************
 *** 399,404 ****
 --- 404,410 ----
   #endif

   	callout_init(&sc->sc_diag_callout);
 + 	callout_init(&sc->sc_intr_recover_callout);

   	/* Disable interrupts before configuring the device. */
   	sc->sc_ier = 0;
 ***************
 *** 556,561 ****
 --- 562,570 ----
   	com_config(sc);

   	SET(sc->sc_hwflags, COM_HW_DEV_OK);
 + 
 + 	callout_reset(&sc->sc_intr_recover_callout,
 + 	    hz*COM_INTR_RECOVERY_INTERVAL, comintr_recover, sc);
   }

   void
 ***************
 *** 626,631 ****
 --- 635,642 ----
   	struct com_softc *sc = (struct com_softc *)self;
   	int maj, mn;

 + 	callout_stop(&sc->sc_intr_recover_callout);
 + 
   	/* locate the major number */
   	for (maj = 0; maj < nchrdev; maj++)
   		if (cdevsw[maj].d_open == comopen)
 ***************
 *** 2145,2150 ****
 --- 2156,2176 ----

   	return (1);
   }
 + 
 + void
 + comintr_recover(arg)
 + 	void * arg;
 + {
 + 	struct com_softc *sc = arg;
 + 	int s;
 + 
 + 	s = splserial();
 + 	comintr(sc);
 + 	splx(s);
 + 	callout_reset(&sc->sc_intr_recover_callout,
 + 	    hz*COM_INTR_RECOVERY_INTERVAL, comintr_recover, arg);
 + }
 + 

   /*
    * The following functions are polled getc and putc routines, shared



 -----------------------------------
 UMEZAWA Takeshi <umezawa@iij.ad.jp>

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(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.