ACPI Problems: IRQ conflicts on USB controllers and SATA controller

John Baldwin jhb at freebsd.org
Fri Oct 13 18:49:52 UTC 2006


On Friday 13 October 2006 12:58, Erik Norgaard wrote:
> Thanks, I tried but no luck... :(
> 
> John Baldwin wrote:
> 
> > Ok, so get vmstat -i output.  There's not much flexibility here though as 
all 
> > the APIC IRQ's are hardcoded, so to guess which ones are routed 
incorrectly 
> > will be a pain.
> 
> For boot-v with empty loader.conf:
> 
> interrupt                          total       rate
> irq1: atkbd0                         410          1
> irq9: acpi0                     17173212      50959
> irq14: ata0                         1296          3
> irq15: ata1                           47          0
> irq18: uhci0 uhci+                     2          0
> irq22: fwohci0+                        1          0
> cpu0: timer                       673315       1997
> Total                           17848283      52962

So whatever is storming is storming on IRQ 9.  Can you figure out which device 
is causing the interrupt?  That is, see what triggers it starting, or hack
drivers to selectively disable devices to help narrow things down.

> >> I will try to see if I can get the debugger when apic is disabled and 
> >> pci_link enabled.
> > 
> > Actually, I think I know what that is already.
> 
> Didn't get that...

When you disable pci_link two of your USB devices don't have interrupts 
assigned at all so they are just going to cause storms.

> >>>> boot -v, acpi disabled:
> >>> Doesn't detect APIC.  BIOS is too dumb to provide $PIR.  That's a new
> >>> low for incompetence on the part of BIOS writers.
> >> Strange - is ACPI required on this box to find APIC? Sounds wierd when 
> >> they are both enabled they each seem to fight for control over the 
> >> devices...
> > 
> > ACPI and APIC are two _entirely_ different things.  On your box, yes, ACPI 
is 
> > required to find APICs.
> 
> That's what I understood from the documentation, but if both handles 
> IRQs then I don't understand how they can coexist.

Interrupt controllers (APIC and 8259A) are hardware devices with pins that
you hook interrupt lines from other devices up to.  They then alert the CPU
when there is an interrupt.  BIOS tables (ACPI, MPTable, $PIR, etc.) provide
information to tell you what the interrupt line for a given device is hooked
up to.  On x86 it is complicated since you have two sets of interrupt 
controllers and the OS can use either one (though not all machines have 
APIC).

> > You really shouldn't use that hint, you should route an entire link 
> > (hw.pci.link.LNKD.irq = 5 for example) when using links.  First try just 
> > fixing your ASL w/o using any settings in loader.conf.
> > 
> > Hmm, you can also try just doing this w/o having to hack your ASL which 
might 
> > fix things:
> > 
> > hw.pci.link.LNKB.irq=10
> > hw.pci.link.LNKD.irq=10
> > hw.pci.link.LNKF.irq=10
> > 
> > It will emit warnings about the IRQs not being valid but still use them, 
and 
> > this matches what your BIOS used.
> 
> Tried that but no change. I have added the dmesg etc to the same path as 
> the previous: http://www.locolomo.org/src/acpi/

Ah, I didn't MFC the patch to let you specify invalid links.  Try the patch 
below (MFC of 1.54 of acpi_pci_link.c):

Index: acpi_pci_link.c
===================================================================
RCS file: /usr/cvs/src/sys/dev/acpica/acpi_pci_link.c,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -r1.53 -r1.54
--- acpi_pci_link.c	6 Jan 2006 16:14:32 -0000	1.53
+++ acpi_pci_link.c	7 Aug 2006 19:52:30 -0000	1.54
@@ -941,19 +941,27 @@
 	KASSERT(!PCI_INTERRUPT_VALID(link->l_irq),
 	    ("%s: link already has an IRQ", __func__));
 
-	/* Check for a tunable override and use it if it is valid. */
+	/* Check for a tunable override. */
 	if (ACPI_SUCCESS(acpi_short_name(acpi_get_handle(dev), link_name,
 	    sizeof(link_name)))) {
 		snprintf(tunable_buffer, sizeof(tunable_buffer),
 		    "hw.pci.link.%s.%d.irq", link_name, link->l_res_index);
-		if (getenv_int(tunable_buffer, &i) &&
-		    PCI_INTERRUPT_VALID(i) && link_valid_irq(link, i))
+		if (getenv_int(tunable_buffer, &i) && PCI_INTERRUPT_VALID(i)) {
+			if (!link_valid_irq(link, i))
+				device_printf(dev,
+				    "Warning, IRQ %d is not listed as valid\n",
+				    i);
 			return (i);
+		}
 		snprintf(tunable_buffer, sizeof(tunable_buffer),
 		    "hw.pci.link.%s.irq", link_name);
-		if (getenv_int(tunable_buffer, &i) &&
-		    PCI_INTERRUPT_VALID(i) && link_valid_irq(link, i))
+		if (getenv_int(tunable_buffer, &i) && PCI_INTERRUPT_VALID(i)) {
+			if (!link_valid_irq(link, i))
+				device_printf(dev,
+				    "Warning, IRQ %d is not listed as valid\n",
+				    i);
 			return (i);
+		}
 	}
 
 	/*

-- 
John Baldwin


More information about the freebsd-mobile mailing list