Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/acpi An _ADR object is not required for PCI root bri...
details: https://anonhg.NetBSD.org/src/rev/e3ddb29c2153
branches: trunk
changeset: 758213:e3ddb29c2153
user: gsutre <gsutre%NetBSD.org@localhost>
date: Tue Oct 26 22:27:44 2010 +0000
description:
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@
diffstat:
sys/dev/acpi/acpi_display.c | 8 +++--
sys/dev/acpi/acpi_pci.c | 60 ++++++++++++++++++++++++++++++---------------
sys/dev/acpi/acpi_verbose.c | 28 ++++++++++++--------
sys/dev/acpi/acpivar.h | 18 +++++++++++--
4 files changed, 77 insertions(+), 37 deletions(-)
diffs (284 lines):
diff -r 082355f079d2 -r e3ddb29c2153 sys/dev/acpi/acpi_display.c
--- a/sys/dev/acpi/acpi_display.c Tue Oct 26 11:44:53 2010 +0000
+++ b/sys/dev/acpi/acpi_display.c Tue Oct 26 22:27:44 2010 +0000
@@ -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);
diff -r 082355f079d2 -r e3ddb29c2153 sys/dev/acpi/acpi_pci.c
--- a/sys/dev/acpi/acpi_pci.c Tue Oct 26 11:44:53 2010 +0000
+++ b/sys/dev/acpi/acpi_pci.c Tue Oct 26 22:27:44 2010 +0000
@@ -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 &&
diff -r 082355f079d2 -r e3ddb29c2153 sys/dev/acpi/acpi_verbose.c
--- a/sys/dev/acpi/acpi_verbose.c Tue Oct 26 11:44:53 2010 +0000
+++ b/sys/dev/acpi/acpi_verbose.c Tue Oct 26 22:27:44 2010 +0000
@@ -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");
diff -r 082355f079d2 -r e3ddb29c2153 sys/dev/acpi/acpivar.h
--- a/sys/dev/acpi/acpivar.h Tue Oct 26 11:44:53 2010 +0000
+++ b/sys/dev/acpi/acpivar.h Tue Oct 26 22:27:44 2010 +0000
@@ -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:
Home |
Main Index |
Thread Index |
Old Index