Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/acpi/acpica AcpiOsDerivePciId: make sure that we onl...



details:   https://anonhg.NetBSD.org/src/rev/5eef9d0b79b4
branches:  trunk
changeset: 756287:5eef9d0b79b4
user:      gsutre <gsutre%NetBSD.org@localhost>
date:      Sat Jul 10 21:31:00 2010 +0000

description:
AcpiOsDerivePciId: make sure that we only update the PCI bus number,
and that we do so only if it was succesfully derived.

ok jruoho@, kochi@

diffstat:

 sys/dev/acpi/acpica/OsdHardware.c |  139 +++++++++++++++++++++++++------------
 1 files changed, 92 insertions(+), 47 deletions(-)

diffs (187 lines):

diff -r 86001369faab -r 5eef9d0b79b4 sys/dev/acpi/acpica/OsdHardware.c
--- a/sys/dev/acpi/acpica/OsdHardware.c Sat Jul 10 19:37:38 2010 +0000
+++ b/sys/dev/acpi/acpica/OsdHardware.c Sat Jul 10 21:31:00 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: OsdHardware.c,v 1.5 2009/09/15 19:41:30 drochner Exp $ */
+/*     $NetBSD: OsdHardware.c,v 1.6 2010/07/10 21:31:00 gsutre Exp $   */
 
 /*
  * Copyright 2001 Wasabi Systems, Inc.
@@ -44,13 +44,14 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: OsdHardware.c,v 1.5 2009/09/15 19:41:30 drochner Exp $");
+__KERNEL_RCSID(0, "$NetBSD: OsdHardware.c,v 1.6 2010/07/10 21:31:00 gsutre Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
 
 #include <dev/acpi/acpica.h>
 #include <dev/acpi/acpivar.h>
+#include <dev/acpi/acpi_pci.h>
 
 #include <machine/acpi_machdep.h>
 
@@ -276,66 +277,99 @@
        return AE_OK;
 }
 
-/* get PCI bus# from root bridge recursively */
-static int
-get_bus_number(
-    ACPI_HANDLE        rhandle,
-    ACPI_HANDLE        chandle,
-    ACPI_PCI_ID        **PciId)
+/*
+ * acpi_os_derive_pciid_rec:
+ *
+ *     Helper function for AcpiOsDerivePciId.  The parameters are:
+ *     - chandle:      a handle to the node whose PCI id shall be derived.
+ *     - rhandle:      a handle the PCI root bridge upstream of chandle.
+ *     - pciid:        where the derived PCI id is returned.
+ *
+ *     This function assumes that rhandle is a proper ancestor of chandle,
+ *     and that pciid has already been filled by ACPICA:
+ *     - segment# and bus# obtained from _SEG and _BBN on rhandle,
+ *     - device# and function# obtained from _ADR on the ACPI device node
+ *       whose scope chandle is in).
+ */
+static ACPI_STATUS
+acpi_os_derive_pciid_rec(ACPI_HANDLE chandle, ACPI_HANDLE rhandle, ACPI_PCI_ID *pciid)
 {
-       ACPI_HANDLE handle;
+       ACPI_HANDLE phandle;
+       ACPI_INTEGER address;
+       ACPI_OBJECT_TYPE objtype;
        ACPI_STATUS rv;
-       ACPI_OBJECT_TYPE type;
-       ACPI_PCI_ID *id;
-       ACPI_INTEGER v;
-       int bus;
+       uint16_t valb;
 
-       id = *PciId;
-
-       rv = AcpiGetParent(chandle, &handle);
-       if (ACPI_FAILURE(rv))
-               return 0;
+       KASSERT(chandle != rhandle);
 
        /*
-        * When handle == rhandle, we have valid PciId->Bus
-        * which was obtained from _BBN in evrgnini.c
-        * so we don't have to reevaluate _BBN.
+        * Get parent device node.  This is should not fail since chandle has
+        * at least one ancestor that is a device node: rhandle.
         */
-       if (handle != rhandle) {
-               bus = get_bus_number(rhandle, handle, PciId);
+       phandle = chandle;
+       do {
+               rv = AcpiGetParent(phandle, &phandle);
+               if (ACPI_FAILURE(rv))
+                       return rv;
+               rv = AcpiGetType(phandle, &objtype);
+               if (ACPI_FAILURE(rv))
+                       return rv;
+       }
+       while (objtype != ACPI_TYPE_DEVICE);
 
-               rv = AcpiGetType(handle, &type);
-               if (ACPI_FAILURE(rv) || type != ACPI_TYPE_DEVICE)
-                       return bus;
+       /*
+        * If the parent is rhandle then we have nothing to do since ACPICA
+        * has pre-filled the PCI id to the best it could.
+        */
+       if (phandle == rhandle)
+               return AE_OK;
 
-               rv = acpi_eval_integer(handle, METHOD_NAME__ADR, &v);
-
-               if (ACPI_FAILURE(rv))
-                       return bus;
+       /* Recursive call to get PCI id of the parent */
+       rv = acpi_os_derive_pciid_rec(phandle, rhandle, pciid);
+       if (ACPI_FAILURE(rv))
+               return rv;
 
-               id->Bus = bus;
-               id->Device = ACPI_HIWORD((ACPI_INTEGER)v);
-               id->Function = ACPI_LOWORD((ACPI_INTEGER)v);
+       /*
+        * If this is not an ACPI device, return the PCI id of its parent.
+        */
+       rv = AcpiGetType(chandle, &objtype);
+       if (ACPI_FAILURE(rv))
+               return rv;
+       if (objtype != ACPI_TYPE_DEVICE)
+               return AE_OK;
 
-               /* read HDR_TYPE register */
-               rv = AcpiOsReadPciConfiguration(id, 0x0e, &v, 8);
-               if (ACPI_SUCCESS(rv) &&
-                       /* mask multifunction bit & check bridge type */
-                       ((v & 0x7f) == 1 || (v & 0x7f) == 2)) {
-                       /* read SECONDARY_BUS register */
-                       rv = AcpiOsReadPciConfiguration(id, 0x19, &v, 8);
-                       if (ACPI_SUCCESS(rv))
-                               id->Bus = v;
-               }
-       }
+       /*
+        * This is an ACPI device node.  Its parent device node is not a PCI
+        * root bridge.  Check that it is a PCI-to-PCI bridge and get its
+        * secondary bus#.
+        */
+       rv = acpi_pcidev_ppb_downbus(pciid->Segment, pciid->Bus, pciid->Device,
+           pciid->Function, &valb);
+       if (ACPI_FAILURE(rv))
+               return rv;
 
-       return id->Bus;
+       /* Get address (contains dev# and fun# for PCI devices). */
+       rv = acpi_eval_integer(chandle, METHOD_NAME__ADR, &address);
+       if (ACPI_FAILURE(rv))
+               return rv;
+
+       pciid->Bus = valb;
+       pciid->Device = ACPI_HIWORD(ACPI_LODWORD(address));
+       pciid->Function = ACPI_LOWORD(ACPI_LODWORD(address));
+       return AE_OK;
 }
 
 /*
  * AcpiOsDerivePciId:
  *
- * Derive correct PCI bus# by traversing bridges
+ *     Derive correct PCI bus# by traversing bridges.
+ *
+ *     In ACPICA release 20100331 (as well as older versions), the interface
+ *     of this function is not correctly documented in the ACPICA programmer
+ *     reference.  The correct interface parameters to this function are:
+ *     - rhandle:      a handle the PCI root bridge upstream of handle.
+ *     - chandle:      a handle to the PCI_Config operation region.
+ *     - PciId:        where the derived PCI id is returned.
  */
 void
 AcpiOsDerivePciId(
@@ -343,5 +377,16 @@
     ACPI_HANDLE        chandle,
     ACPI_PCI_ID        **PciId)
 {
-       (*PciId)->Bus = get_bus_number(rhandle, chandle, PciId);
+       ACPI_PCI_ID pciid;
+       ACPI_STATUS rv;
+
+       if (chandle == rhandle)
+               return;
+
+       pciid = **PciId;
+       rv = acpi_os_derive_pciid_rec(chandle, rhandle, &pciid);
+       if (ACPI_FAILURE(rv))
+               return;
+
+       (*PciId)->Bus = pciid.Bus;
 }



Home | Main Index | Thread Index | Old Index