aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pcie
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-08-23 23:53:11 +0200
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-08-24 13:44:40 -0700
commit75fb60f26befb59dbfa05cb122972642b7bdd219 (patch)
treebe015dd00e7748e45f3691f04a16c204546b3026 /drivers/pci/pcie
parent2b8fd9186d9275b07aef43e5bb4e98cd571f9a7d (diff)
downloadkernel_samsung_smdk4412-75fb60f26befb59dbfa05cb122972642b7bdd219.zip
kernel_samsung_smdk4412-75fb60f26befb59dbfa05cb122972642b7bdd219.tar.gz
kernel_samsung_smdk4412-75fb60f26befb59dbfa05cb122972642b7bdd219.tar.bz2
ACPI/PCI: Negotiate _OSC control bits before requesting them
It is possible that the BIOS will not grant control of all _OSC features requested via acpi_pci_osc_control_set(), so it is recommended to negotiate the final set of _OSC features with the query flag set before calling _OSC to request control of these features. To implement it, rework acpi_pci_osc_control_set() so that the caller can specify the mask of _OSC control bits to negotiate and the mask of _OSC control bits that are absolutely necessary to it. Then, acpi_pci_osc_control_set() will run _OSC queries in a loop until the mask of _OSC control bits returned by the BIOS is equal to the mask passed to it. Also, before running the _OSC request acpi_pci_osc_control_set() will check if the caller's required control bits are present in the final mask. Using this mechanism we will be able to avoid situations in which the BIOS doesn't grant control of certain _OSC features, because they depend on some other _OSC features that have not been requested. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/pcie')
-rw-r--r--drivers/pci/pcie/aer/aerdrv_acpi.c6
-rw-r--r--drivers/pci/pcie/pme/pcie_pme_acpi.c8
2 files changed, 8 insertions, 6 deletions
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
index f278d7b..3a276a0 100644
--- a/drivers/pci/pcie/aer/aerdrv_acpi.c
+++ b/drivers/pci/pcie/aer/aerdrv_acpi.c
@@ -39,9 +39,9 @@ int aer_osc_setup(struct pcie_device *pciedev)
handle = acpi_find_root_bridge_handle(pdev);
if (handle) {
- status = acpi_pci_osc_control_set(handle,
- OSC_PCI_EXPRESS_AER_CONTROL |
- OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
+ u32 flags = OSC_PCI_EXPRESS_AER_CONTROL |
+ OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL;
+ status = acpi_pci_osc_control_set(handle, &flags, flags);
}
if (ACPI_FAILURE(status)) {
diff --git a/drivers/pci/pcie/pme/pcie_pme_acpi.c b/drivers/pci/pcie/pme/pcie_pme_acpi.c
index 83ab228..be20222 100644
--- a/drivers/pci/pcie/pme/pcie_pme_acpi.c
+++ b/drivers/pci/pcie/pme/pcie_pme_acpi.c
@@ -28,6 +28,7 @@ int pcie_pme_acpi_setup(struct pcie_device *srv)
acpi_status status = AE_NOT_FOUND;
struct pci_dev *port = srv->port;
acpi_handle handle;
+ u32 flags;
int error = 0;
if (acpi_pci_disabled)
@@ -39,9 +40,10 @@ int pcie_pme_acpi_setup(struct pcie_device *srv)
if (!handle)
return -EINVAL;
- status = acpi_pci_osc_control_set(handle,
- OSC_PCI_EXPRESS_PME_CONTROL |
- OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
+ flags = OSC_PCI_EXPRESS_PME_CONTROL |
+ OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL;
+
+ status = acpi_pci_osc_control_set(handle, &flags, flags);
if (ACPI_FAILURE(status)) {
dev_info(&port->dev,
"Failed to receive control of PCIe PME service: %s\n",