ACPI/PCI: call _OSC support during root bridge discovery
Andrew Patterson [Mon, 10 Nov 2008 22:30:45 +0000 (15:30 -0700)]
Add pci_acpi_osc_support() and call it when a PCI bridge is added.  This
allows us to avoid having every individual PCI root bridge driver call
_OSC support for every root bridge in their probe functions, a
significant savings in boot time.

Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

drivers/acpi/pci_root.c
drivers/pci/pci-acpi.c
include/linux/pci-acpi.h

index 642554b..de4d571 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/spinlock.h>
 #include <linux/pm.h>
 #include <linux/pci.h>
+#include <linux/pci-acpi.h>
 #include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
@@ -193,6 +194,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
        unsigned long long value = 0;
        acpi_handle handle = NULL;
        struct acpi_device *child;
+       u32 flags;
 
 
        if (!device)
@@ -210,6 +212,13 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 
        device->ops.bind = acpi_pci_bind;
 
+       /*
+        * All supported architectures that use ACPI have support for
+        * PCI domains, so we indicate this in _OSC support capabilities.
+        */
+       flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
+       pci_acpi_osc_support(device->handle, flags);
+
        /* 
         * Segment
         * -------
index 2ed3f10..8a1f02c 100644 (file)
@@ -143,28 +143,42 @@ static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data,
        return status;
 }
 
-static acpi_status acpi_query_osc(acpi_handle handle,
-                                 u32 level, void *context, void **retval)
+/*
+ * pci_acpi_osc_support: Invoke _OSC indicating support for the given feature
+ * @flags: Bitmask of flags to support
+ *
+ * See the ACPI spec for the definition of the flags
+ */
+int pci_acpi_osc_support(acpi_handle handle, u32 flags)
 {
+       u32 dummy;
        acpi_status status;
-       struct acpi_osc_data *osc_data;
-       u32 flags = (unsigned long)context, dummy;
        acpi_handle tmp;
+       struct acpi_osc_data *osc_data;
+       int rc = 0;
 
        status = acpi_get_handle(handle, "_OSC", &tmp);
        if (ACPI_FAILURE(status))
-               return AE_OK;
+               return -ENOTTY;
 
        mutex_lock(&pci_acpi_lock);
        osc_data = acpi_get_osc_data(handle);
        if (!osc_data) {
                printk(KERN_ERR "acpi osc data array is full\n");
+               rc = -ENOMEM;
                goto out;
        }
 
        __acpi_query_osc(flags, osc_data, &dummy);
 out:
        mutex_unlock(&pci_acpi_lock);
+       return rc;
+}
+
+static acpi_status acpi_query_osc(acpi_handle handle, u32 level,
+                                 void *context, void **retval)
+{
+       pci_acpi_osc_support(handle, (unsigned long)context);
        return AE_OK;
 }
 
index a9e4c34..424f06f 100644 (file)
@@ -51,6 +51,7 @@
 #ifdef CONFIG_ACPI
 extern acpi_status pci_osc_control_set(acpi_handle handle, u32 flags);
 extern acpi_status __pci_osc_support_set(u32 flags, const char *hid);
+int pci_acpi_osc_support(acpi_handle handle, u32 flags);
 static inline acpi_status pci_osc_support_set(u32 flags)
 {
        return __pci_osc_support_set(flags, PCI_ROOT_HID_STRING);