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