aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/pci_root.c59
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c2
-rw-r--r--drivers/pci/pcie/aer/aerdrv_acpi.c6
-rw-r--r--drivers/pci/pcie/pme/pcie_pme_acpi.c8
-rw-r--r--include/linux/acpi.h4
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:
374EXPORT_SYMBOL_GPL(acpi_get_pci_dev); 374EXPORT_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 **/
383acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) 391acpi_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;
424out: 441out:
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 307extern acpi_status acpi_pci_osc_control_set(acpi_handle handle,
308extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags); 308 u32 *mask, u32 req);
309extern void acpi_early_init(void); 309extern void acpi_early_init(void);
310 310
311#else /* !CONFIG_ACPI */ 311#else /* !CONFIG_ACPI */