Subject: port-arm32/6421: Can't share interrupts on IOMD when IPLs differ
To: None <>
From: None <>
List: netbsd-bugs
Date: 11/10/1998 11:40:22
>Number:         6421
>Category:       port-arm32
>Synopsis:       Can't share interrupts on IOMD when IPLs differ
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Nov 10 03:50:00 1998
>Originator:     Richard Earnshaw (
>Release:        NetBSD-current Nov 1998<NetBSD-current source date>
System: NetBSD buzzard 1.3H NetBSD 1.3H (BUZZARD) #26: Sun Nov 8 23:49:19 GMT 1998 rearnsha@buzzard:/home/rearnsha/netbsd/sys/arch/arm32/compile/BUZZARD arm32

	A bug in the initialization of the interrupt masks for IOMD means that
	if there are multiple boards on the RISCPC podule bus at different
	IPL levels, the interrupt masks may be incorrectly initialized causing
	the board at the lower numbered IPL to take interrupts when it has
	tried to disable them.  This can happen, for example, if an ethernet
	card is in podule slot 0 and a hard disk interface in podule slot 1.

	The code to add an IRQ for a device currently works by scanning for
	the lowest numbered IPL on the IRQ and then only enabling interrupts
	for that IRQ when the priority is lower than that.  However, it does
	this as each interrupt is added and it doesn't clear any bits that
	may have been erroneously set on a previous itteration.

	A work-around would normally be to put the lowest IPL board in
	slot 0, but:
	i) This is fiddly for users to know and understand
	ii) The SCSI card has an on-board terminator which sticks up
	into the space above it (so the ethernet board won't fit).
	Put an Acorn Ether1 (if_ie) board in podule slot0 and an Acorn
	SCSI card (asc) in slot1, boot and then try to use the scsi card.
Patch below clears the now invalid bits in the interrupt masks when an extra 
device is added to an IRQ line but at a lower IPL.
Index: iomd_irqhandler.c
RCS file: /xx/rearnsha.old/netbsd/usr/cvs/src/sys/arch/arm32/iomd/iomd_irqhandler.c,v
retrieving revision
diff -p -p -r1.1.1.6 iomd_irqhandler.c
*** iomd_irqhandler.c	1998/09/08 16:45:59
--- iomd_irqhandler.c	1998/11/09 23:21:41
*************** irq_claim(irq, handler)
*** 217,227 ****
--- 217,237 ----
  		ptr = irqhandlers[irq];
  		if (ptr) {
+ 			int max_level;
  			level = ptr->ih_level - 1;
+ 			max_level = ptr->ih_level - 1;
  			while (ptr) {
  				if (ptr->ih_level - 1 < level)
  					level = ptr->ih_level - 1;
+ 				else if (ptr->ih_level - 1 > max_level)
+ 					max_level = ptr->ih_level - 1;
  				ptr = ptr->ih_next;
+ 			}
+ 			/* Clear out any levels that we cannot now allow */
+ 			while (max_level >=0 && max_level > level) {
+ 				irqmasks[max_level] &= ~(1 << irq);
+ 				--max_level;
  			while (level >= 0) {
  				irqmasks[level] |= (1 << irq);