Module Name:    src
Committed By:   gsutre
Date:           Tue Oct 26 22:27:44 UTC 2010

Modified Files:
        src/sys/dev/acpi: acpi_display.c acpi_pci.c acpi_verbose.c acpivar.h

Log Message:
An _ADR object is not required for PCI root bridges.  To solve
this, the structure acpi_pciinfo now tells whether the ACPI
device node is a PCI bridge, a regular PCI device, or both.

Problem reported by jmcneill@, who also suggested the solution.

ok jmcneill@, jruoho@


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/acpi/acpi_display.c
cvs rdiff -u -r1.15 -r1.16 src/sys/dev/acpi/acpi_pci.c
cvs rdiff -u -r1.11 -r1.12 src/sys/dev/acpi/acpi_verbose.c
cvs rdiff -u -r1.64 -r1.65 src/sys/dev/acpi/acpivar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/acpi/acpi_display.c
diff -u src/sys/dev/acpi/acpi_display.c:1.2 src/sys/dev/acpi/acpi_display.c:1.3
--- src/sys/dev/acpi/acpi_display.c:1.2	Mon Oct 25 17:06:58 2010
+++ src/sys/dev/acpi/acpi_display.c	Tue Oct 26 22:27:44 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: acpi_display.c,v 1.2 2010/10/25 17:06:58 jruoho Exp $	*/
+/*	$NetBSD: acpi_display.c,v 1.3 2010/10/26 22:27:44 gsutre Exp $	*/
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_display.c,v 1.2 2010/10/25 17:06:58 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_display.c,v 1.3 2010/10/26 22:27:44 gsutre Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -406,7 +406,9 @@
 		return 0;
 
 	ap = ad->ad_pciinfo;
-	if ((ap == NULL) || (ap->ap_function == 0xffff))
+	if ((ap == NULL) ||
+	    !(ap->ap_flags & ACPI_PCI_INFO_DEVICE) ||
+	    (ap->ap_function == 0xffff))
 		return 0;
 
 	KASSERT(ap->ap_bus < 256 && ap->ap_device < 32 && ap->ap_function < 8);

Index: src/sys/dev/acpi/acpi_pci.c
diff -u src/sys/dev/acpi/acpi_pci.c:1.15 src/sys/dev/acpi/acpi_pci.c:1.16
--- src/sys/dev/acpi/acpi_pci.c:1.15	Fri Sep 24 07:48:59 2010
+++ src/sys/dev/acpi/acpi_pci.c	Tue Oct 26 22:27:44 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_pci.c,v 1.15 2010/09/24 07:48:59 gsutre Exp $ */
+/* $NetBSD: acpi_pci.c,v 1.16 2010/10/26 22:27:44 gsutre Exp $ */
 
 /*
  * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_pci.c,v 1.15 2010/09/24 07:48:59 gsutre Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_pci.c,v 1.16 2010/10/26 22:27:44 gsutre Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -158,6 +158,10 @@
  *	PCI device if it has an ancestor that is a PCI root bridge and such
  *	that all intermediate nodes are PCI-to-PCI bridges.  Depth-first
  *	recursive implementation.
+ *
+ *	PCI root bridges do not necessarily contain an _ADR, since they already
+ *	contain an _HID (ACPI 4.0a, p. 197).  However we require an _ADR for
+ *	all non-root PCI devices.
  */
 ACPI_STATUS
 acpi_pcidev_scan(struct acpi_devnode *ad)
@@ -169,16 +173,14 @@
 
 	ad->ad_pciinfo = NULL;
 
-	if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE ||
-	    !(ad->ad_devinfo->Valid & ACPI_VALID_ADR))
-		goto rec;
-
 	/*
 	 * We attach PCI information only to devices that are present,
 	 * enabled, and functioning properly.
 	 * Note: there is a possible race condition, because _STA may
 	 * have changed since ad->ad_devinfo->CurrentStatus was set.
 	 */
+	if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE)
+		goto rec;
 	if ((ad->ad_devinfo->Valid & ACPI_VALID_STA) != 0 &&
 	    (ad->ad_devinfo->CurrentStatus & ACPI_STA_OK) != ACPI_STA_OK)
 		goto rec;
@@ -201,29 +203,43 @@
 		if (ACPI_SUCCESS(rv))
 			ap->ap_segment = ACPI_LOWORD(val);
 
-		/* Try to get bus number using _CRS first. */
-		rv = acpi_pcidev_pciroot_bus(ad->ad_handle, &ap->ap_bus);
+		/* Try to get downstream bus number using _CRS first. */
+		rv = acpi_pcidev_pciroot_bus(ad->ad_handle, &ap->ap_downbus);
 
 		if (ACPI_FAILURE(rv)) {
 			rv = acpi_eval_integer(ad->ad_handle, "_BBN", &val);
 
 			if (ACPI_SUCCESS(rv))
-				ap->ap_bus = ACPI_LOWORD(val);
+				ap->ap_downbus = ACPI_LOWORD(val);
 		}
 
-		ap->ap_device = ACPI_HILODWORD(ad->ad_devinfo->Address);
-		ap->ap_function = ACPI_LOLODWORD(ad->ad_devinfo->Address);
-
-		if (ap->ap_bus > 255 || ap->ap_device > 31 ||
-		    (ap->ap_function > 7 && ap->ap_function != 0xFFFF)) {
+		if (ap->ap_downbus > 255) {
 			aprint_error_dev(ad->ad_root,
-			    "invalid PCI address for %s\n", ad->ad_name);
+			    "invalid PCI downstream bus for %s\n", ad->ad_name);
 			kmem_free(ap, sizeof(*ap));
 			goto rec;
 		}
 
-		ap->ap_bridge = true;
-		ap->ap_downbus = ap->ap_bus;
+		ap->ap_flags |= ACPI_PCI_INFO_BRIDGE;
+
+		/*
+		 * This ACPI node denotes a PCI root bridge, but it may also
+		 * denote a PCI device on the bridge's downstream bus segment.
+		 */
+		if (ad->ad_devinfo->Valid & ACPI_VALID_ADR) {
+			ap->ap_bus = ap->ap_downbus;
+			ap->ap_device =
+			    ACPI_HILODWORD(ad->ad_devinfo->Address);
+			ap->ap_function =
+			    ACPI_LOLODWORD(ad->ad_devinfo->Address);
+
+			if (ap->ap_device > 31 ||
+			    (ap->ap_function > 7 && ap->ap_function != 0xFFFF))
+				aprint_error_dev(ad->ad_root,
+				    "invalid PCI address for %s\n", ad->ad_name);
+			else
+				ap->ap_flags |= ACPI_PCI_INFO_DEVICE;
+		}
 
 		ad->ad_pciinfo = ap;
 
@@ -232,7 +248,8 @@
 
 	if ((ad->ad_parent != NULL) &&
 	    (ad->ad_parent->ad_pciinfo != NULL) &&
-	    (ad->ad_parent->ad_pciinfo->ap_bridge)) {
+	    (ad->ad_parent->ad_pciinfo->ap_flags & ACPI_PCI_INFO_BRIDGE) &&
+	    (ad->ad_devinfo->Valid & ACPI_VALID_ADR)) {
 
 		/*
 		 * Our parent is a PCI root bridge or a PCI-to-PCI
@@ -258,12 +275,13 @@
 			goto rec;
 		}
 
+		ap->ap_flags |= ACPI_PCI_INFO_DEVICE;
+
 		if (ap->ap_function == 0xFFFF) {
 			/*
 			 * Assume that this device is not a PCI-to-PCI bridge.
 			 * XXX: Do we need to be smarter?
 			 */
-			ap->ap_bridge = false;
 		} else {
 			/*
 			 * Check whether this device is a PCI-to-PCI
@@ -272,7 +290,8 @@
 			rv = acpi_pcidev_ppb_downbus(ap->ap_segment, ap->ap_bus,
 			    ap->ap_device, ap->ap_function, &ap->ap_downbus);
 
-			ap->ap_bridge = (rv != AE_OK) ? false : true;
+			if (ACPI_SUCCESS(rv))
+				ap->ap_flags |= ACPI_PCI_INFO_BRIDGE;
 		}
 
 		ad->ad_pciinfo = ap;
@@ -356,6 +375,7 @@
 	SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
 
 		if (ad->ad_pciinfo != NULL &&
+		    (ad->ad_pciinfo->ap_flags & ACPI_PCI_INFO_DEVICE) &&
 		    ad->ad_pciinfo->ap_segment == segment &&
 		    ad->ad_pciinfo->ap_bus == bus &&
 		    ad->ad_pciinfo->ap_device == device &&

Index: src/sys/dev/acpi/acpi_verbose.c
diff -u src/sys/dev/acpi/acpi_verbose.c:1.11 src/sys/dev/acpi/acpi_verbose.c:1.12
--- src/sys/dev/acpi/acpi_verbose.c:1.11	Fri Sep 24 07:48:59 2010
+++ src/sys/dev/acpi/acpi_verbose.c	Tue Oct 26 22:27:44 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: acpi_verbose.c,v 1.11 2010/09/24 07:48:59 gsutre Exp $ */
+/*	$NetBSD: acpi_verbose.c,v 1.12 2010/10/26 22:27:44 gsutre Exp $ */
 
 /*-
  * Copyright (c) 2003, 2007, 2010 The NetBSD Foundation, Inc.
@@ -65,7 +65,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_verbose.c,v 1.11 2010/09/24 07:48:59 gsutre Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_verbose.c,v 1.12 2010/10/26 22:27:44 gsutre Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -466,29 +466,35 @@
 	for (i = 0; i < level; i++)
 		aprint_normal("    ");
 
-	aprint_normal("%-5s [%02u] [%c%c] ", ad->ad_name, ad->ad_type,
+	aprint_normal("%-5s [%02u] [%c%c]", ad->ad_name, ad->ad_type,
 	    ((ad->ad_flags & ACPI_DEVICE_POWER)  != 0) ? 'P' : ' ',
 	    ((ad->ad_flags & ACPI_DEVICE_WAKEUP) != 0) ? 'W' : ' ');
 
 	if (ad->ad_device != NULL)
-		aprint_normal("<%s> ", device_xname(ad->ad_device));
+		aprint_normal(" <%s>", device_xname(ad->ad_device));
 
 	if (ad->ad_pciinfo != NULL) {
 
-		aprint_normal("(PCI) @ 0x%02X:0x%02X:0x%02X:0x%02X ",
-		    ad->ad_pciinfo->ap_segment, ad->ad_pciinfo->ap_bus,
-		    ad->ad_pciinfo->ap_device, ad->ad_pciinfo->ap_function);
+		aprint_normal(" (PCI)");
+
+		if ((ad->ad_pciinfo->ap_flags & ACPI_PCI_INFO_DEVICE) != 0)
+			aprint_normal(" @ 0x%02X:0x%02X:0x%02X:0x%02X",
+			    ad->ad_pciinfo->ap_segment,
+			    ad->ad_pciinfo->ap_bus,
+			    ad->ad_pciinfo->ap_device,
+			    ad->ad_pciinfo->ap_function);
 
 		if ((ad->ad_devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0)
-			aprint_normal("[R] ");
+			aprint_normal(" [R]");
 
-		if (ad->ad_pciinfo->ap_bridge != false)
-			aprint_normal("[B] -> 0x%02X ",
+		if ((ad->ad_pciinfo->ap_flags & ACPI_PCI_INFO_BRIDGE) != 0)
+			aprint_normal(" [B] -> 0x%02X:0x%02X",
+			    ad->ad_pciinfo->ap_segment,
 			    ad->ad_pciinfo->ap_downbus);
 
 		pcidev = device_find_by_acpi_pci_info(ad->ad_pciinfo);
 		if (pcidev != NULL)
-			aprint_normal("<%s>", device_xname(pcidev));
+			aprint_normal(" <%s>", device_xname(pcidev));
 	}
 
 	aprint_normal("\n");

Index: src/sys/dev/acpi/acpivar.h
diff -u src/sys/dev/acpi/acpivar.h:1.64 src/sys/dev/acpi/acpivar.h:1.65
--- src/sys/dev/acpi/acpivar.h:1.64	Sun Oct 24 07:53:04 2010
+++ src/sys/dev/acpi/acpivar.h	Tue Oct 26 22:27:44 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: acpivar.h,v 1.64 2010/10/24 07:53:04 jruoho Exp $	*/
+/*	$NetBSD: acpivar.h,v 1.65 2010/10/26 22:27:44 gsutre Exp $	*/
 
 /*
  * Copyright 2001 Wasabi Systems, Inc.
@@ -72,22 +72,34 @@
  *	ap_bus		<= 255
  *	ap_device	<= 31
  *	ap_function	<= 7		or	ap_function == 0xFFFF
- *	ap_downbus	<= 255		if	ap_bridge == true
+ *	ap_downbus	<= 255
+ *
+ * Validity of some fields depends on the value of ap_flags:
+ *
+ *	ap_segment				always valid
+ *	ap_bus, ap_device, ap_function		valid for PCI devices
+ *	ap_downbus				valid for PCI bridges
  *
  * The device and function numbers are encoded in the value returned by
  * _ADR.  A function number of 0xFFFF is used to refer to all the
  * functions on a PCI device (ACPI 4.0a, p. 200).
  */
 struct acpi_pci_info {
+	uint16_t		 ap_flags;	/* Flags (cf. below) */
 	uint16_t		 ap_segment;	/* PCI segment group */
 	uint16_t		 ap_bus;	/* PCI bus */
 	uint16_t		 ap_device;	/* PCI device */
 	uint16_t		 ap_function;	/* PCI function */
-	bool			 ap_bridge;	/* PCI bridge (PHB or PPB) */
 	uint16_t		 ap_downbus;	/* PCI bridge downstream bus */
 };
 
 /*
+ * Flags for PCI information.
+ */
+#define ACPI_PCI_INFO_DEVICE	__BIT(0)	/* PCI device */
+#define ACPI_PCI_INFO_BRIDGE	__BIT(1)	/* PCI bridge */
+
+/*
  * An ACPI device node.
  *
  * Remarks:

Reply via email to