Subject: Re: ACPI and invalid devices
To: Quentin Garnier <cube@cubidou.net>
From: Manuel Bouyer <bouyer@antioche.eu.org>
List: port-i386
Date: 03/28/2007 22:14:19
--6c2NcOVqGQ03X4Wi
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Fri, Mar 09, 2007 at 06:24:59PM +0100, Quentin Garnier wrote:
> On Fri, Mar 09, 2007 at 05:51:09PM +0100, Manuel Bouyer wrote:
> > Hi,
> > an ACPI kernel doesn't boot on the dell 2950, it panics in pci_make_tag()
> > because this function is called with bus 0 device 0xffff function 0xffff.
> > With the attached patch it boots and I didn't notice any bad effects.
> > Does it make sense ?
> 
> The low word encodes the function, thus the test should against 8.
> 
> The reason why this happens is found in DSDT, in method INIS (in scope
> \_SB):  it is called by _INI method of \_SB (thus very early), and aims
> at deactivating PCIe-to-PCI bridges under some condition.
> 
> While it's not a bad idea to sanity check the values we pass to
> pci_make_tag, it's probably better to skip the device if it is not
> active.  When dev_list is populated in that function, there is a call to
> AcpiGetObjectInfo():  you should immediately test for its status before
> you go on with it, using the same test you can find in mpacpi_pcibus_cb
> (look for ACPI_STA_OK).
> 
> That means re-organising the for loop a bit, malloc'ing dev after that
> test.

OK, so what about the attached patch ? It works for me.

-- 
Manuel Bouyer <bouyer@antioche.eu.org>
     NetBSD: 26 ans d'experience feront toujours la difference
--

--6c2NcOVqGQ03X4Wi
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff

Index: x86/mpacpi.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/mpacpi.c,v
retrieving revision 1.46
diff -u -r1.46 mpacpi.c
--- x86/mpacpi.c	5 Mar 2007 16:51:03 -0000	1.46
+++ x86/mpacpi.c	28 Mar 2007 20:04:14 -0000
@@ -80,6 +80,8 @@
 
 #include "locators.h"
 
+#define ACPI_STA_OK (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|ACPI_STA_DEV_OK)
+
 /* XXX room for PCI-to-PCI bus */
 #define BUS_BUFFER (16)
 
@@ -475,11 +477,25 @@
 
 	/* first, search parent root bus */
 	for (current = handle;; current = parent) {
-		dev = malloc(sizeof(struct ac_dev), M_TEMP, M_WAITOK|M_ZERO);
-		if (dev == NULL)
+		buf.Pointer = NULL;
+		buf.Length = ACPI_ALLOCATE_BUFFER;
+		rv = AcpiGetObjectInfo(current, &buf);
+		if (ACPI_FAILURE(rv))
 			return -1;
-		dev->handle = current;
-		TAILQ_INSERT_HEAD(&dev_list, dev, list);
+
+		devinfo = buf.Pointer;
+		/* add this device to the list only if it's active */
+		if ((devinfo->Valid & ACPI_VALID_STA) == 0 ||
+		    (devinfo->CurrentStatus & ACPI_STA_OK) == ACPI_STA_OK) {
+			AcpiOsFree(buf.Pointer);
+			dev = malloc(sizeof(struct ac_dev), M_TEMP,
+			    M_WAITOK|M_ZERO);
+			if (dev == NULL)
+				return -1;
+			dev->handle = current;
+			TAILQ_INSERT_HEAD(&dev_list, dev, list);
+		}
+		AcpiOsFree(buf.Pointer);
 
 		rv = AcpiGetParent(current, &parent);
 		if (ACPI_FAILURE(rv))
@@ -492,6 +508,7 @@
 			return -1;
 
 		devinfo = buf.Pointer;
+
 		if (acpi_match_hid(devinfo, pciroot_hid)) {
 			rv = acpi_eval_integer(parent, METHOD_NAME__BBN, &val);
 			AcpiOsFree(buf.Pointer);
@@ -570,8 +587,6 @@
 
 	devinfo = buf.Pointer;
 
-#define ACPI_STA_OK (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|ACPI_STA_DEV_OK)
-
 	/* if this device is not active, ignore it */
 	if ((devinfo->Valid & ACPI_VALID_STA) &&
 	    (devinfo->CurrentStatus & ACPI_STA_OK) != ACPI_STA_OK)

--6c2NcOVqGQ03X4Wi--