Subject: kern/37538: Problems with ACPI and BIOS interrupts on some laptops
To: None <email@example.com, firstname.lastname@example.org,>
From: None <email@example.com>
Date: 12/14/2007 06:20:00
>Synopsis: The BIOS on Dell D400 laptops routes interrupts properly, but doesn't report it to the ACPI tables.
>Arrival-Date: Fri Dec 14 06:20:00 +0000 2007
>Originator: Brian Buhrow
>Release: NetBSD 3.0, 3.1, 4.x and -current up to i and including 2007-12-13
NFB of California
On the Dell D400 laptop computer, if ACPI is enabled, the wireless
card and the sound card share irq 9. If the interrupt load gets too high,
where too high is defined as something over 100 interupts/second, all
interrupts to irq 9 cease, and the sound card and the wireless network
card both become unusable until the application using the audio device
Another symptom of this problem is that during the boot sequence,
you'll see something like:
. . .
LNKB: BIOS IRQ 11 for 0.31.INTB is invalid
LNKA: ACPI: Found matching pin for 0.29.INTA at func 0: 11
LNKD: ACPI: Found matching pin for 0.29.INTB at func 1: 11
LNKC: ACPI: Found matching pin for 0.29.INTC at func 2: 11
LNKH: ACPI: Found matching pin for 0.29.INTD at func 7: 11
LNKA: ACPI: Found matching pin for 0.2.INTA at func 0: 11
LNKD: ACPI: Found matching pin for 1.1.INTA at func 0: 255
LNKD: ACPI: Found matching pin for 1.1.INTA at func 1: 11
LNKB: ACPI: Found matching pin for 1.3.INTA at func 0: 11
LNKB: BIOS IRQ 11 for 1.3.INTA is invalid
LNKC: ACPI: Found matching pin for 1.0.INTA at func 0: 11
. . .
If you look on the Net, you'll find that other folks have described
this behavior with Ubuntu Linux as well. Their solution is to disable
ACPI, which works, but means you can't do things like monitor the
temperature of the machine, sleep the computer, check the battery status,
etc. Fortunately, there is another way.
When an ACPI-enabled NetBSD kernel boots, it consults the BIOS on the
host computer to find out what interrupts the BIOS has enabled for which
devices. Once that's done, it then checks to make sure the ACPI tables
from the BIOS designate the assigned interrupts as being available for
ACPI-enabled devices, at least I think this is how things work. In the
case of the Dell D400, and I suspect in other laptop cases, the BIOS sets
up the interrupt for the wireless and audio cards, but doesn't note that
the indicated interrupt can be used by those devices in its interrupt
tables. NetBSD, being unavle to verify that the IRQ's are really valid,
reroutes the interrupts for these devices to other, available, irq's.
If you apply the patch below, and add
to your kernel config and rebuild, the ACPI subsystem will not question what
the BIOS has done and will permit the BIOS mappings to stay in force.
Since the mappings were really valid, all works well, and you get sound,
wireless, which you can use together again, and ACPI all in one tidy
lightweight computer. I wouldn't recommend this option be on by default,
but it would be nice to have it available for those of us with BIOS's which
do the right thing, but don't advertise their good deeds. This patch
should work for NetBSD-3.x, 4.x and -current. I've tested it under 4.x,
but verified the problem exists on 3.x and -current.
Boot an ACPI enabled kernel on a Dell D400, or another computer with a
similarly broken BIOS, and try to use the devices indicated by the invalid
messages above simultaneously. After a while, you'll either notice all
interrupts for those devices stop, and/or they'll become intermittent.
RCS file: /cvsroot/src/sys/dev/acpi/acpi_pci_link.c,v
retrieving revision 1.7
diff -u -r1.7 acpi_pci_link.c
--- acpi_pci_link.c 24 Sep 2006 06:03:20 -0000 1.7
+++ acpi_pci_link.c 14 Dec 2007 06:03:25 -0000
@@ -369,6 +369,17 @@
+ *Some BIOS's route the interrupts correctly for the devices
+ *they configure, but don't report that those interrupts are valid in
+ *their interrupt table. If this option is true, assume the BIOS
+ *did the right thing, and always return valid.
+ *Fixes interrupt problems with ACPI and the Dell D400 laptop
/* Invalid interrupts are never valid. */