diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-09-07 19:00:17 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-09-07 19:00:17 -0400 |
| commit | d56557af19867edb8c0e96f8e26399698a08857f (patch) | |
| tree | 2d98f87962a5a08839371ed90b9eaa7f256bea36 /drivers/acpi/pci_root.c | |
| parent | fa2925cf90e612cb9c10c45d0cb8a7c7332e56a7 (diff) | |
| parent | 17134d96735115644cc2f0e2b1bab51ca6e3ab95 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6:
PCI: bus speed strings should be const
PCI hotplug: Fix build with CONFIG_ACPI unset
PCI: PCIe: Remove the port driver module exit routine
PCI: PCIe: Move PCIe PME code to the pcie directory
PCI: PCIe: Disable PCIe port services during port initialization
PCI: PCIe: Ask BIOS for control of all native services at once
ACPI/PCI: Negotiate _OSC control bits before requesting them
ACPI/PCI: Do not preserve _OSC control bits returned by a query
ACPI/PCI: Make acpi_pci_query_osc() return control bits
ACPI/PCI: Reorder checks in acpi_pci_osc_control_set()
PCI: PCIe: Introduce commad line switch for disabling port services
PCI: PCIe AER: Introduce pci_aer_available()
x86/PCI: only define pci_domain_nr if PCI and PCI_DOMAINS are set
PCI: provide stub pci_domain_nr function for !CONFIG_PCI configs
Diffstat (limited to 'drivers/acpi/pci_root.c')
| -rw-r--r-- | drivers/acpi/pci_root.c | 97 |
1 files changed, 56 insertions, 41 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 1f67057af2a5..3ba8d1f44a73 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
| @@ -33,7 +33,6 @@ | |||
| 33 | #include <linux/pm_runtime.h> | 33 | #include <linux/pm_runtime.h> |
| 34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
| 35 | #include <linux/pci-acpi.h> | 35 | #include <linux/pci-acpi.h> |
| 36 | #include <linux/pci-aspm.h> | ||
| 37 | #include <linux/acpi.h> | 36 | #include <linux/acpi.h> |
| 38 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
| 39 | #include <acpi/acpi_bus.h> | 38 | #include <acpi/acpi_bus.h> |
| @@ -226,22 +225,31 @@ static acpi_status acpi_pci_run_osc(acpi_handle handle, | |||
| 226 | return status; | 225 | return status; |
| 227 | } | 226 | } |
| 228 | 227 | ||
| 229 | static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 flags) | 228 | static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, |
| 229 | u32 support, | ||
| 230 | u32 *control) | ||
| 230 | { | 231 | { |
| 231 | acpi_status status; | 232 | acpi_status status; |
| 232 | u32 support_set, result, capbuf[3]; | 233 | u32 result, capbuf[3]; |
| 234 | |||
| 235 | support &= OSC_PCI_SUPPORT_MASKS; | ||
| 236 | support |= root->osc_support_set; | ||
| 233 | 237 | ||
| 234 | /* do _OSC query for all possible controls */ | ||
| 235 | support_set = root->osc_support_set | (flags & OSC_PCI_SUPPORT_MASKS); | ||
| 236 | capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; | 238 | capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; |
| 237 | capbuf[OSC_SUPPORT_TYPE] = support_set; | 239 | capbuf[OSC_SUPPORT_TYPE] = support; |
| 238 | capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; | 240 | if (control) { |
| 241 | *control &= OSC_PCI_CONTROL_MASKS; | ||
| 242 | capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set; | ||
| 243 | } else { | ||
| 244 | /* Run _OSC query for all possible controls. */ | ||
| 245 | capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; | ||
| 246 | } | ||
| 239 | 247 | ||
| 240 | status = acpi_pci_run_osc(root->device->handle, capbuf, &result); | 248 | status = acpi_pci_run_osc(root->device->handle, capbuf, &result); |
| 241 | if (ACPI_SUCCESS(status)) { | 249 | if (ACPI_SUCCESS(status)) { |
| 242 | root->osc_support_set = support_set; | 250 | root->osc_support_set = support; |
| 243 | root->osc_control_qry = result; | 251 | if (control) |
| 244 | root->osc_queried = 1; | 252 | *control = result; |
| 245 | } | 253 | } |
| 246 | return status; | 254 | return status; |
| 247 | } | 255 | } |
| @@ -255,7 +263,7 @@ static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags) | |||
| 255 | if (ACPI_FAILURE(status)) | 263 | if (ACPI_FAILURE(status)) |
| 256 | return status; | 264 | return status; |
| 257 | mutex_lock(&osc_lock); | 265 | mutex_lock(&osc_lock); |
| 258 | status = acpi_pci_query_osc(root, flags); | 266 | status = acpi_pci_query_osc(root, flags, NULL); |
| 259 | mutex_unlock(&osc_lock); | 267 | mutex_unlock(&osc_lock); |
| 260 | return status; | 268 | return status; |
| 261 | } | 269 | } |
| @@ -365,55 +373,70 @@ out: | |||
| 365 | EXPORT_SYMBOL_GPL(acpi_get_pci_dev); | 373 | EXPORT_SYMBOL_GPL(acpi_get_pci_dev); |
| 366 | 374 | ||
| 367 | /** | 375 | /** |
| 368 | * acpi_pci_osc_control_set - commit requested control to Firmware | 376 | * acpi_pci_osc_control_set - Request control of PCI root _OSC features. |
| 369 | * @handle: acpi_handle for the target ACPI object | 377 | * @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex). |
| 370 | * @flags: driver's requested control bits | 378 | * @mask: Mask of _OSC bits to request control of, place to store control mask. |
| 379 | * @req: Mask of _OSC bits the control of is essential to the caller. | ||
| 380 | * | ||
| 381 | * Run _OSC query for @mask and if that is successful, compare the returned | ||
| 382 | * mask of control bits with @req. If all of the @req bits are set in the | ||
| 383 | * returned mask, run _OSC request for it. | ||
| 371 | * | 384 | * |
| 372 | * Attempt to take control from Firmware on requested control bits. | 385 | * The variable at the @mask address may be modified regardless of whether or |
| 386 | * not the function returns success. On success it will contain the mask of | ||
| 387 | * _OSC bits the BIOS has granted control of, but its contents are meaningless | ||
| 388 | * on failure. | ||
| 373 | **/ | 389 | **/ |
| 374 | acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) | 390 | acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req) |
| 375 | { | 391 | { |
| 392 | struct acpi_pci_root *root; | ||
| 376 | acpi_status status; | 393 | acpi_status status; |
| 377 | u32 control_req, result, capbuf[3]; | 394 | u32 ctrl, capbuf[3]; |
| 378 | acpi_handle tmp; | 395 | acpi_handle tmp; |
| 379 | struct acpi_pci_root *root; | ||
| 380 | 396 | ||
| 381 | status = acpi_get_handle(handle, "_OSC", &tmp); | 397 | if (!mask) |
| 382 | if (ACPI_FAILURE(status)) | 398 | return AE_BAD_PARAMETER; |
| 383 | return status; | ||
| 384 | 399 | ||
| 385 | control_req = (flags & OSC_PCI_CONTROL_MASKS); | 400 | ctrl = *mask & OSC_PCI_CONTROL_MASKS; |
| 386 | if (!control_req) | 401 | if ((ctrl & req) != req) |
| 387 | return AE_TYPE; | 402 | return AE_TYPE; |
| 388 | 403 | ||
| 389 | root = acpi_pci_find_root(handle); | 404 | root = acpi_pci_find_root(handle); |
| 390 | if (!root) | 405 | if (!root) |
| 391 | return AE_NOT_EXIST; | 406 | return AE_NOT_EXIST; |
| 392 | 407 | ||
| 408 | status = acpi_get_handle(handle, "_OSC", &tmp); | ||
| 409 | if (ACPI_FAILURE(status)) | ||
| 410 | return status; | ||
| 411 | |||
| 393 | mutex_lock(&osc_lock); | 412 | mutex_lock(&osc_lock); |
| 413 | |||
| 414 | *mask = ctrl | root->osc_control_set; | ||
| 394 | /* No need to evaluate _OSC if the control was already granted. */ | 415 | /* No need to evaluate _OSC if the control was already granted. */ |
| 395 | if ((root->osc_control_set & control_req) == control_req) | 416 | if ((root->osc_control_set & ctrl) == ctrl) |
| 396 | goto out; | 417 | goto out; |
| 397 | 418 | ||
| 398 | /* Need to query controls first before requesting them */ | 419 | /* Need to check the available controls bits before requesting them. */ |
| 399 | if (!root->osc_queried) { | 420 | while (*mask) { |
| 400 | status = acpi_pci_query_osc(root, root->osc_support_set); | 421 | status = acpi_pci_query_osc(root, root->osc_support_set, mask); |
| 401 | if (ACPI_FAILURE(status)) | 422 | if (ACPI_FAILURE(status)) |
| 402 | goto out; | 423 | goto out; |
| 424 | if (ctrl == *mask) | ||
| 425 | break; | ||
| 426 | ctrl = *mask; | ||
| 403 | } | 427 | } |
| 404 | if ((root->osc_control_qry & control_req) != control_req) { | 428 | |
| 405 | printk(KERN_DEBUG | 429 | if ((ctrl & req) != req) { |
| 406 | "Firmware did not grant requested _OSC control\n"); | ||
| 407 | status = AE_SUPPORT; | 430 | status = AE_SUPPORT; |
| 408 | goto out; | 431 | goto out; |
| 409 | } | 432 | } |
| 410 | 433 | ||
| 411 | capbuf[OSC_QUERY_TYPE] = 0; | 434 | capbuf[OSC_QUERY_TYPE] = 0; |
| 412 | capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set; | 435 | capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set; |
| 413 | capbuf[OSC_CONTROL_TYPE] = root->osc_control_set | control_req; | 436 | capbuf[OSC_CONTROL_TYPE] = ctrl; |
| 414 | status = acpi_pci_run_osc(handle, capbuf, &result); | 437 | status = acpi_pci_run_osc(handle, capbuf, mask); |
| 415 | if (ACPI_SUCCESS(status)) | 438 | if (ACPI_SUCCESS(status)) |
| 416 | root->osc_control_set = result; | 439 | root->osc_control_set = *mask; |
| 417 | out: | 440 | out: |
| 418 | mutex_unlock(&osc_lock); | 441 | mutex_unlock(&osc_lock); |
| 419 | return status; | 442 | return status; |
| @@ -544,14 +567,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 544 | if (flags != base_flags) | 567 | if (flags != base_flags) |
| 545 | acpi_pci_osc_support(root, flags); | 568 | acpi_pci_osc_support(root, flags); |
| 546 | 569 | ||
| 547 | status = acpi_pci_osc_control_set(root->device->handle, | ||
| 548 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | ||
| 549 | |||
| 550 | if (ACPI_FAILURE(status)) { | ||
| 551 | printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n"); | ||
| 552 | pcie_no_aspm(); | ||
| 553 | } | ||
| 554 | |||
| 555 | pci_acpi_add_bus_pm_notifier(device, root->bus); | 570 | pci_acpi_add_bus_pm_notifier(device, root->bus); |
| 556 | if (device->wakeup.flags.run_wake) | 571 | if (device->wakeup.flags.run_wake) |
| 557 | device_set_run_wake(root->bus->bridge, true); | 572 | device_set_run_wake(root->bus->bridge, true); |
