diff options
| -rw-r--r-- | drivers/acpi/pci_root.c | 59 | ||||
| -rw-r--r-- | drivers/pci/hotplug/acpi_pcihp.c | 2 | ||||
| -rw-r--r-- | drivers/pci/pcie/aer/aerdrv_acpi.c | 6 | ||||
| -rw-r--r-- | drivers/pci/pcie/pme/pcie_pme_acpi.c | 8 | ||||
| -rw-r--r-- | include/linux/acpi.h | 4 |
5 files changed, 49 insertions, 30 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 77cd19697b1e..c34713112520 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
| @@ -374,21 +374,32 @@ out: | |||
| 374 | EXPORT_SYMBOL_GPL(acpi_get_pci_dev); | 374 | EXPORT_SYMBOL_GPL(acpi_get_pci_dev); |
| 375 | 375 | ||
| 376 | /** | 376 | /** |
| 377 | * acpi_pci_osc_control_set - commit requested control to Firmware | 377 | * acpi_pci_osc_control_set - Request control of PCI root _OSC features. |
| 378 | * @handle: acpi_handle for the target ACPI object | 378 | * @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex). |
| 379 | * @flags: driver's requested control bits | 379 | * @mask: Mask of _OSC bits to request control of, place to store control mask. |
| 380 | * @req: Mask of _OSC bits the control of is essential to the caller. | ||
| 380 | * | 381 | * |
| 381 | * Attempt to take control from Firmware on requested control bits. | 382 | * Run _OSC query for @mask and if that is successful, compare the returned |
| 383 | * mask of control bits with @req. If all of the @req bits are set in the | ||
| 384 | * returned mask, run _OSC request for it. | ||
| 385 | * | ||
| 386 | * The variable at the @mask address may be modified regardless of whether or | ||
| 387 | * not the function returns success. On success it will contain the mask of | ||
| 388 | * _OSC bits the BIOS has granted control of, but its contents are meaningless | ||
| 389 | * on failure. | ||
| 382 | **/ | 390 | **/ |
| 383 | acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) | 391 | acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req) |
| 384 | { | 392 | { |
| 393 | struct acpi_pci_root *root; | ||
| 385 | acpi_status status; | 394 | acpi_status status; |
| 386 | u32 control_req, result, capbuf[3]; | 395 | u32 ctrl, capbuf[3]; |
| 387 | acpi_handle tmp; | 396 | acpi_handle tmp; |
| 388 | struct acpi_pci_root *root; | ||
| 389 | 397 | ||
| 390 | control_req = (flags & OSC_PCI_CONTROL_MASKS); | 398 | if (!mask) |
| 391 | if (!control_req) | 399 | return AE_BAD_PARAMETER; |
| 400 | |||
| 401 | ctrl = *mask & OSC_PCI_CONTROL_MASKS; | ||
| 402 | if ((ctrl & req) != req) | ||
| 392 | return AE_TYPE; | 403 | return AE_TYPE; |
| 393 | 404 | ||
| 394 | root = acpi_pci_find_root(handle); | 405 | root = acpi_pci_find_root(handle); |
| @@ -400,27 +411,33 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) | |||
| 400 | return status; | 411 | return status; |
| 401 | 412 | ||
| 402 | mutex_lock(&osc_lock); | 413 | mutex_lock(&osc_lock); |
| 414 | |||
| 415 | *mask = ctrl | root->osc_control_set; | ||
| 403 | /* No need to evaluate _OSC if the control was already granted. */ | 416 | /* No need to evaluate _OSC if the control was already granted. */ |
| 404 | if ((root->osc_control_set & control_req) == control_req) | 417 | if ((root->osc_control_set & ctrl) == ctrl) |
| 405 | goto out; | 418 | goto out; |
| 406 | 419 | ||
| 407 | /* Need to query controls first before requesting them */ | 420 | /* Need to check the available controls bits before requesting them. */ |
| 408 | flags = control_req; | 421 | while (*mask) { |
| 409 | status = acpi_pci_query_osc(root, root->osc_support_set, &flags); | 422 | status = acpi_pci_query_osc(root, root->osc_support_set, mask); |
| 410 | if (ACPI_FAILURE(status)) | 423 | if (ACPI_FAILURE(status)) |
| 411 | goto out; | 424 | goto out; |
| 425 | if (ctrl == *mask) | ||
| 426 | break; | ||
| 427 | ctrl = *mask; | ||
| 428 | } | ||
| 412 | 429 | ||
| 413 | if (flags != control_req) { | 430 | if ((ctrl & req) != req) { |
| 414 | status = AE_SUPPORT; | 431 | status = AE_SUPPORT; |
| 415 | goto out; | 432 | goto out; |
| 416 | } | 433 | } |
| 417 | 434 | ||
| 418 | capbuf[OSC_QUERY_TYPE] = 0; | 435 | capbuf[OSC_QUERY_TYPE] = 0; |
| 419 | capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set; | 436 | capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set; |
| 420 | capbuf[OSC_CONTROL_TYPE] = root->osc_control_set | control_req; | 437 | capbuf[OSC_CONTROL_TYPE] = ctrl; |
| 421 | status = acpi_pci_run_osc(handle, capbuf, &result); | 438 | status = acpi_pci_run_osc(handle, capbuf, mask); |
| 422 | if (ACPI_SUCCESS(status)) | 439 | if (ACPI_SUCCESS(status)) |
| 423 | root->osc_control_set = result; | 440 | root->osc_control_set = *mask; |
| 424 | out: | 441 | out: |
| 425 | mutex_unlock(&osc_lock); | 442 | mutex_unlock(&osc_lock); |
| 426 | return status; | 443 | return status; |
| @@ -551,8 +568,8 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 551 | if (flags != base_flags) | 568 | if (flags != base_flags) |
| 552 | acpi_pci_osc_support(root, flags); | 569 | acpi_pci_osc_support(root, flags); |
| 553 | 570 | ||
| 554 | status = acpi_pci_osc_control_set(root->device->handle, | 571 | flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL; |
| 555 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | 572 | status = acpi_pci_osc_control_set(root->device->handle, &flags, flags); |
| 556 | 573 | ||
| 557 | if (ACPI_FAILURE(status)) { | 574 | if (ACPI_FAILURE(status)) { |
| 558 | printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n"); | 575 | printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n"); |
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 45fcc1e96df9..3d93d529a7bd 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
| @@ -360,7 +360,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) | |||
| 360 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | 360 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); |
| 361 | dbg("Trying to get hotplug control for %s\n", | 361 | dbg("Trying to get hotplug control for %s\n", |
| 362 | (char *)string.pointer); | 362 | (char *)string.pointer); |
| 363 | status = acpi_pci_osc_control_set(handle, flags); | 363 | status = acpi_pci_osc_control_set(handle, &flags, flags); |
| 364 | if (ACPI_SUCCESS(status)) | 364 | if (ACPI_SUCCESS(status)) |
| 365 | goto got_one; | 365 | goto got_one; |
| 366 | if (status == AE_SUPPORT) | 366 | if (status == AE_SUPPORT) |
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index f278d7b0d95d..3a276a0cea93 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) | |||
| 39 | 39 | ||
| 40 | handle = acpi_find_root_bridge_handle(pdev); | 40 | handle = acpi_find_root_bridge_handle(pdev); |
| 41 | if (handle) { | 41 | if (handle) { |
| 42 | status = acpi_pci_osc_control_set(handle, | 42 | u32 flags = OSC_PCI_EXPRESS_AER_CONTROL | |
| 43 | OSC_PCI_EXPRESS_AER_CONTROL | | 43 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL; |
| 44 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | 44 | status = acpi_pci_osc_control_set(handle, &flags, flags); |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | if (ACPI_FAILURE(status)) { | 47 | 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 83ab2287ae3f..be20222b12d3 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) | |||
| 28 | acpi_status status = AE_NOT_FOUND; | 28 | acpi_status status = AE_NOT_FOUND; |
| 29 | struct pci_dev *port = srv->port; | 29 | struct pci_dev *port = srv->port; |
| 30 | acpi_handle handle; | 30 | acpi_handle handle; |
| 31 | u32 flags; | ||
| 31 | int error = 0; | 32 | int error = 0; |
| 32 | 33 | ||
| 33 | if (acpi_pci_disabled) | 34 | if (acpi_pci_disabled) |
| @@ -39,9 +40,10 @@ int pcie_pme_acpi_setup(struct pcie_device *srv) | |||
| 39 | if (!handle) | 40 | if (!handle) |
| 40 | return -EINVAL; | 41 | return -EINVAL; |
| 41 | 42 | ||
| 42 | status = acpi_pci_osc_control_set(handle, | 43 | flags = OSC_PCI_EXPRESS_PME_CONTROL | |
| 43 | OSC_PCI_EXPRESS_PME_CONTROL | | 44 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL; |
| 44 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | 45 | |
| 46 | status = acpi_pci_osc_control_set(handle, &flags, flags); | ||
| 45 | if (ACPI_FAILURE(status)) { | 47 | if (ACPI_FAILURE(status)) { |
| 46 | dev_info(&port->dev, | 48 | dev_info(&port->dev, |
| 47 | "Failed to receive control of PCIe PME service: %s\n", | 49 | "Failed to receive control of PCIe PME service: %s\n", |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index ccf94dc5acdf..c227757feb06 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
| @@ -304,8 +304,8 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); | |||
| 304 | OSC_PCI_EXPRESS_PME_CONTROL | \ | 304 | OSC_PCI_EXPRESS_PME_CONTROL | \ |
| 305 | OSC_PCI_EXPRESS_AER_CONTROL | \ | 305 | OSC_PCI_EXPRESS_AER_CONTROL | \ |
| 306 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL) | 306 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL) |
| 307 | 307 | extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, | |
| 308 | extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags); | 308 | u32 *mask, u32 req); |
| 309 | extern void acpi_early_init(void); | 309 | extern void acpi_early_init(void); |
| 310 | 310 | ||
| 311 | #else /* !CONFIG_ACPI */ | 311 | #else /* !CONFIG_ACPI */ |
