Subject: kern/10974: Infinite Interrupt loop in com.c
To: None <gnats-bugs@gnats.netbsd.org>
From: Andreas Wrede <andreas@planix.com>
List: netbsd-bugs
Date: 09/07/2000 14:42:15
>Number:         10974
>Category:       kern
>Synopsis:       Infinite interrupt loop in com.c
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu Sep 07 14:43:00 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     Andreas Wrede
>Release:        <NetBSD-current source date>
>Organization:
Planix, Inc
>Environment:
	
System: NetBSD woffi.planix.com 1.5_ALPHA2 NetBSD 1.5_ALPHA2 (PLANIX-IPv6) #0: Thu Sep 7 12:21:01 EDT 2000 root@woffi.planix.com:/usr/src/sys/arch/i386/compile/WOFFI i386


>Description:
The comintr routine in sys/dev/ic/com.c checks for and services additional
interrupts requests before exiting. This can cause the system to freeze
with interrupts disabled if the com device produces an interrupt strom,
as it did for me with a Lava Quattro-PCI 4-port serial card. 

>How-To-Repeat:
Install faulty com hardware. Boot. Observe that machine is non-reponsive
after the "Setting tty flags." message.
>Fix:
The patch below forces the loop to exit every 10000 interrupts. It produces
a message if we reach that limit and more importantly, it lets the you 
get into the kernel debugger :-). The number is 10000 is magic, maybe 100
is more appropriate?


Index: com.c
===================================================================
RCS file: //u5/NetBSD-CVS/main//syssrc/sys/dev/ic/com.c,v
retrieving revision 1.175
diff -c -r1.175 com.c
*** com.c	2000/08/18 13:22:39	1.175
--- com.c	2000/09/07 21:17:22
***************
*** 1929,1934 ****
--- 1929,1935 ----
  	u_char *put, *end;
  	u_int cc;
  	u_char lsr, iir;
+ 	int looplim = 10000;
  
  	if (COM_ISALIVE(sc) == 0)
  		return (0);
***************
*** 2099,2106 ****
  
  			sc->sc_st_check = 1;
  		}
! 	} while (!ISSET((iir = bus_space_read_1(iot, ioh, com_iir)), IIR_NOPEND));
  
  	/*
  	 * Done handling any receive interrupts. See if data can be
  	 * transmitted as well. Schedule tx done event if no data left
--- 2100,2110 ----
  
  			sc->sc_st_check = 1;
  		}
! 		looplim--;
! 	} while (!ISSET((iir = bus_space_read_1(iot, ioh, com_iir)), IIR_NOPEND) && looplim);
  
+ 	if (!looplim) 
+ 		printf("%s: excessive interrupts\n", sc->sc_dev.dv_xname);
  	/*
  	 * Done handling any receive interrupts. See if data can be
  	 * transmitted as well. Schedule tx done event if no data left
>Release-Note:
>Audit-Trail:
>Unformatted: