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 */ |