The ACPI bus driver currently adds a device node (device_t) for every Device() 
object in the ACPI namespace.  However, the ACPI namespace enumerates devices 
on other buses (such as PCI) that are self-enumerating.  In fact, we have code 
in the ACPI PCI bus driver to reclaim the device nodes for PCI devices and 
associate the PCI-enumerated device nodes with ACPI handles instead.

In practice no device driver can attach to an ACPI device node unless it has 
_HID or _CID methods, so having ACPI device_t objects for nodes without an ID 
isn't really useful.  My changes to make the ACPI bus driver reserve resources 
for devices has turned up some cases where it is actually harmful as well.  It 
seems a few BIOSes actually use _CRS to list resources for a PCI device that 
are not managed via a BAR.  (I've see this at least twice so far.)  Two things 
happen as a result: 1) the resources are "orphaned" when the ACPI device_t is 
removed and replaced by the PCI device_t.  As a result, devinfo -r claims they 
are associated with some other device (whatever happens to reuse that device_t 
pointer).  2) The resources can be allocated at the wrong place in the tree.

I had a recent thread on current@ where 2) interacted badly with the NEW_PCIB 
changes to the PCI-PCI bridge driver.  Because the ACPI-enumerated device_t 
hangs off acpi0, it is not "behind" the PCI-PCI bridges.  In the case of the 
thread, a PCI device behind a bridge was allocating some IO port resources via 
_CRS that were in the parent bridge's window.  However, because the ACPI 
device_t was off of acpi0, it turned into a resource conflict since the 
resources were not allocated from the PCI-PCI bridge but from nexus0 directly.

What I am proposing to do is to change the ACPI bus driver to only add 
device_t objects for Device() nodes that have a _HID or _CID.  This should not 
break any devices that have a current driver, but it will avoid having ACPI 
attach to PCI devices.  This does mean that _CRS is currently ignored for PCI 
devices.  My feeling on that is that if we do feel that is important to 
reserve those resources, we should handle that in the ACPI PCI bus driver 
itself instead (it can examine _CRS for those devices and allocate resources
if we so choose).

It does strike me as odd that BIOSes are assigning resources to PCI devices 
via _CRS and I wonder if it is truly valid or it it should just be ignored.

The patch in question:

Index: acpi.c
===================================================================
--- acpi.c      (revision 223082)
+++ acpi.c      (working copy)
@@ -151,6 +151,7 @@
 static ACPI_STATUS acpi_EnterSleepState(struct acpi_softc *sc, int state);
 static void    acpi_shutdown_final(void *arg, int howto);
 static void    acpi_enable_fixed_events(struct acpi_softc *sc);
+static BOOLEAN acpi_has_hid(ACPI_HANDLE handle);
 static int     acpi_wake_sleep_prep(ACPI_HANDLE handle, int sstate);
 static int     acpi_wake_run_prep(ACPI_HANDLE handle, int sstate);
 static int     acpi_wake_prep_walk(int sstate);
@@ -1855,6 +1856,13 @@
                break;
            if (acpi_parse_prw(handle, &prw) == 0)
                AcpiSetupGpeForWake(handle, prw.gpe_handle, prw.gpe_bit);
+
+           /*
+            * Ignore devices that do not have a _HID or _CID.  They should
+            * be discovered by other buses (e.g. the PCI bus driver).
+            */
+           if (!acpi_has_hid(handle))
+               break;
            /* FALLTHROUGH */
        case ACPI_TYPE_PROCESSOR:
        case ACPI_TYPE_THERMAL:
@@ -2043,6 +2051,30 @@
 }
 
 /*
+ * Returns true if a device has at least one valid device ID.
+ */
+static BOOLEAN
+acpi_has_hid(ACPI_HANDLE h)
+{
+    ACPI_DEVICE_INFO   *devinfo;
+    BOOLEAN            ret;
+
+    if (h == NULL ||
+       ACPI_FAILURE(AcpiGetObjectInfo(h, &devinfo)))
+       return (FALSE);
+
+    ret = FALSE;
+    if ((devinfo->Valid & ACPI_VALID_HID) != 0)
+       ret = TRUE;
+    else if ((devinfo->Valid & ACPI_VALID_CID) != 0)
+       if (devinfo->CompatibleIdList.Count > 0)
+           ret = TRUE;
+
+    AcpiOsFree(devinfo);
+    return (ret);
+}
+
+/*
  * Match a HID string against a handle
  */
 BOOLEAN
Index: acpi_pci.c
===================================================================
--- acpi_pci.c  (revision 223082)
+++ acpi_pci.c  (working copy)
@@ -209,38 +209,24 @@
        device_t child;
 
        /*
-        * Lookup and remove the unused device that acpi0 creates when it walks
-        * the namespace creating devices.
+        * Occasionally a PCI device may show up as an ACPI device
+        * with a _HID.  (For example, the TabletPC TC1000 has a
+        * second PCI-ISA bridge that has a _HID for an
+        * acpi_sysresource device.)  In that case, leave ACPI-CA's
+        * device data pointing at the ACPI-enumerated device.
         */
        child = acpi_get_device(handle);
        if (child != NULL) {
-               if (device_is_alive(child)) {
-                       /*
-                        * The TabletPC TC1000 has a second PCI-ISA bridge
-                        * that has a _HID for an acpi_sysresource device.
-                        * In that case, leave ACPI-CA's device data pointing
-                        * at the ACPI-enumerated device.
-                        */
-                       device_printf(child,
-                           "Conflicts with PCI device %d:%d:%d\n",
-                           pci_get_bus(pci_child), pci_get_slot(pci_child),
-                           pci_get_function(pci_child));
-                       return;
-               }
                KASSERT(device_get_parent(child) ==
                    devclass_get_device(devclass_find("acpi"), 0),
                    ("%s: child (%s)'s parent is not acpi0", __func__,
                    acpi_name(handle)));
-               device_delete_child(device_get_parent(child), child);
+               return;
        }
 
        /*
         * Update ACPI-CA to use the PCI enumerated device_t for this handle.
         */
-       status = AcpiDetachData(handle, acpi_fake_objhandler);
-       if (ACPI_FAILURE(status))
-               printf("WARNING: Unable to detach object data from %s - %s\n",
-                   acpi_name(handle), AcpiFormatException(status));
        status = AcpiAttachData(handle, acpi_fake_objhandler, pci_child);
        if (ACPI_FAILURE(status))
                printf("WARNING: Unable to attach object data to %s - %s\n",


-- 
John Baldwin
_______________________________________________
freebsd-acpi@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-acpi
To unsubscribe, send any mail to "freebsd-acpi-unsubscr...@freebsd.org"

Reply via email to