From: Rafael J. Wysocki <rjw@xxxxxxx> Introduce a function allowing the caller to obtain a mask of _OSC control bits the BIOS will allow the kernel to control for a given PCI root bridge. Signed-off-by: Rafael J. Wysocki <rjw@xxxxxxx> --- drivers/acpi/pci_root.c | 56 +++++++++++++++++++++++++++++++++++++++++------- include/linux/acpi.h | 1 2 files changed, 49 insertions(+), 8 deletions(-) Index: linux-2.6/drivers/acpi/pci_root.c =================================================================== --- linux-2.6.orig/drivers/acpi/pci_root.c +++ linux-2.6/drivers/acpi/pci_root.c @@ -224,21 +224,32 @@ static acpi_status acpi_pci_run_osc(acpi return status; } -static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 flags) +static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, + u32 support, + u32 *control) { acpi_status status; - u32 support_set, capbuf[3]; + u32 capbuf[3]; + + support &= OSC_PCI_SUPPORT_MASKS; + support |= root->osc_support_set; /* do _OSC query for all possible controls */ - support_set = root->osc_support_set | (flags & OSC_PCI_SUPPORT_MASKS); capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; - capbuf[OSC_SUPPORT_TYPE] = support_set; - capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; + capbuf[OSC_SUPPORT_TYPE] = support; + if (control) { + *control &= OSC_PCI_CONTROL_MASKS; + capbuf[OSC_CONTROL_TYPE] = *control; + } else { + capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; + } status = acpi_pci_run_osc(root->device->handle, capbuf); if (ACPI_SUCCESS(status)) { - root->osc_support_set = support_set; + root->osc_support_set = support; root->osc_control_qry = capbuf[OSC_CONTROL_TYPE]; + if (control) + *control = capbuf[OSC_CONTROL_TYPE]; root->osc_queried = 1; } return status; @@ -253,7 +264,7 @@ static acpi_status acpi_pci_osc_support( if (ACPI_FAILURE(status)) return status; mutex_lock(&osc_lock); - status = acpi_pci_query_osc(root, flags); + status = acpi_pci_query_osc(root, flags, NULL); mutex_unlock(&osc_lock); return status; } @@ -362,6 +373,35 @@ out: } EXPORT_SYMBOL_GPL(acpi_get_pci_dev); + /** + * acpi_pci_root_osc_query - Get the _OSC bits the kernel can control. + * @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex). + * @ctrl_mask: Mask of _OSC bits to query and the place to put the result into. + **/ +acpi_status acpi_pci_root_osc_query(acpi_handle handle, u32 *ctrl_mask) +{ + acpi_status status; + acpi_handle tmp; + struct acpi_pci_root *root; + + if (!ctrl_mask || !(*ctrl_mask & OSC_PCI_CONTROL_MASKS)) + return AE_BAD_PARAMETER; + + root = acpi_pci_find_root(handle); + if (!root) + return AE_NOT_EXIST; + + status = acpi_get_handle(handle, "_OSC", &tmp); + if (ACPI_FAILURE(status)) + return status; + + mutex_lock(&osc_lock); + status = acpi_pci_query_osc(root, root->osc_support_set, ctrl_mask); + mutex_unlock(&osc_lock); + + return status; +} + /** * acpi_pci_osc_control_set - commit requested control to Firmware * @handle: acpi_handle for the target ACPI object @@ -395,7 +435,7 @@ acpi_status acpi_pci_osc_control_set(acp /* Need to query controls first before requesting them */ if (!root->osc_queried) { - status = acpi_pci_query_osc(root, root->osc_support_set); + status = acpi_pci_query_osc(root, root->osc_support_set, NULL); if (ACPI_FAILURE(status)) goto out; } Index: linux-2.6/include/linux/acpi.h =================================================================== --- linux-2.6.orig/include/linux/acpi.h +++ linux-2.6/include/linux/acpi.h @@ -305,6 +305,7 @@ acpi_status acpi_run_osc(acpi_handle han OSC_PCI_EXPRESS_AER_CONTROL | \ OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL) +extern acpi_status acpi_pci_root_osc_query(acpi_handle handle, u32 *ctrl_mask); extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags); extern void acpi_early_init(void); -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html