aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2013-08-29 16:17:05 -0400
committerBjorn Helgaas <bhelgaas@google.com>2013-08-29 17:34:53 -0400
commit3dc48af310709b85d07c8b0d3aa8f1ead02829d3 (patch)
tree4c5042c3c98f935edf06e6e1118102627c1008bc /drivers/acpi
parent058dd016a1ed43d0d8e0c6c10a472d560a3299b4 (diff)
PCI/ACPI: Fix _OSC ordering to allow PCIe hotplug use when available
This fixes the problem of acpiphp claiming slots that should be managed by pciehp, which may keep ExpressCard slots from working. The acpiphp driver claims PCIe slots unless the BIOS has granted us control of PCIe native hotplug via _OSC. Prior to v3.10, the acpiphp .add method (add_bridge()) was always called *after* we had requested native hotplug control with _OSC. But after 3b63aaa70e ("PCI: acpiphp: Do not use ACPI PCI subdriver mechanism"), which appeared in v3.10, acpiphp initialization is done during the bus scan via the pcibios_add_bus() hook, and this happens *before* we request native hotplug control. Therefore, acpiphp doesn't know yet whether the BIOS will grant control, and it claims slots that we should be handling with native hotplug. This patch requests native hotplug control earlier, so we know whether the BIOS granted it to us before we initialize acpiphp. To avoid reintroducing the ASPM issue fixed by b8178f130e ('Revert "PCI/ACPI: Request _OSC control before scanning PCI root bus"'), we run _OSC earlier but defer the actual ASPM calls until after the bus scan is complete. Tested successfully by myself. [bhelgaas: changelog, mark for stable] Reference: https://bugzilla.kernel.org/show_bug.cgi?id=60736 Signed-off-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Yinghai Lu <yinghai@kernel.org> CC: stable@vger.kernel.org # v3.10+ CC: Len Brown <lenb@kernel.org> CC: "Rafael J. Wysocki" <rjw@sisk.pl>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/pci_root.c62
1 files changed, 38 insertions, 24 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 5917839321b8..a67853e3c419 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -378,6 +378,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
378 struct acpi_pci_root *root; 378 struct acpi_pci_root *root;
379 u32 flags, base_flags; 379 u32 flags, base_flags;
380 acpi_handle handle = device->handle; 380 acpi_handle handle = device->handle;
381 bool no_aspm = false, clear_aspm = false;
381 382
382 root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); 383 root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
383 if (!root) 384 if (!root)
@@ -437,27 +438,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
437 flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; 438 flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
438 acpi_pci_osc_support(root, flags); 439 acpi_pci_osc_support(root, flags);
439 440
440 /*
441 * TBD: Need PCI interface for enumeration/configuration of roots.
442 */
443
444 /*
445 * Scan the Root Bridge
446 * --------------------
447 * Must do this prior to any attempt to bind the root device, as the
448 * PCI namespace does not get created until this call is made (and
449 * thus the root bridge's pci_dev does not exist).
450 */
451 root->bus = pci_acpi_scan_root(root);
452 if (!root->bus) {
453 dev_err(&device->dev,
454 "Bus %04x:%02x not present in PCI namespace\n",
455 root->segment, (unsigned int)root->secondary.start);
456 result = -ENODEV;
457 goto end;
458 }
459
460 /* Indicate support for various _OSC capabilities. */
461 if (pci_ext_cfg_avail()) 441 if (pci_ext_cfg_avail())
462 flags |= OSC_EXT_PCI_CONFIG_SUPPORT; 442 flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
463 if (pcie_aspm_support_enabled()) { 443 if (pcie_aspm_support_enabled()) {
@@ -471,7 +451,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
471 if (ACPI_FAILURE(status)) { 451 if (ACPI_FAILURE(status)) {
472 dev_info(&device->dev, "ACPI _OSC support " 452 dev_info(&device->dev, "ACPI _OSC support "
473 "notification failed, disabling PCIe ASPM\n"); 453 "notification failed, disabling PCIe ASPM\n");
474 pcie_no_aspm(); 454 no_aspm = true;
475 flags = base_flags; 455 flags = base_flags;
476 } 456 }
477 } 457 }
@@ -503,7 +483,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
503 * We have ASPM control, but the FADT indicates 483 * We have ASPM control, but the FADT indicates
504 * that it's unsupported. Clear it. 484 * that it's unsupported. Clear it.
505 */ 485 */
506 pcie_clear_aspm(root->bus); 486 clear_aspm = true;
507 } 487 }
508 } else { 488 } else {
509 dev_info(&device->dev, 489 dev_info(&device->dev,
@@ -512,7 +492,14 @@ static int acpi_pci_root_add(struct acpi_device *device,
512 acpi_format_exception(status), flags); 492 acpi_format_exception(status), flags);
513 dev_info(&device->dev, 493 dev_info(&device->dev,
514 "ACPI _OSC control for PCIe not granted, disabling ASPM\n"); 494 "ACPI _OSC control for PCIe not granted, disabling ASPM\n");
515 pcie_no_aspm(); 495 /*
496 * We want to disable ASPM here, but aspm_disabled
497 * needs to remain in its state from boot so that we
498 * properly handle PCIe 1.1 devices. So we set this
499 * flag here, to defer the action until after the ACPI
500 * root scan.
501 */
502 no_aspm = true;
516 } 503 }
517 } else { 504 } else {
518 dev_info(&device->dev, 505 dev_info(&device->dev,
@@ -520,6 +507,33 @@ static int acpi_pci_root_add(struct acpi_device *device,
520 "(_OSC support mask: 0x%02x)\n", flags); 507 "(_OSC support mask: 0x%02x)\n", flags);
521 } 508 }
522 509
510 /*
511 * TBD: Need PCI interface for enumeration/configuration of roots.
512 */
513
514 /*
515 * Scan the Root Bridge
516 * --------------------
517 * Must do this prior to any attempt to bind the root device, as the
518 * PCI namespace does not get created until this call is made (and
519 * thus the root bridge's pci_dev does not exist).
520 */
521 root->bus = pci_acpi_scan_root(root);
522 if (!root->bus) {
523 dev_err(&device->dev,
524 "Bus %04x:%02x not present in PCI namespace\n",
525 root->segment, (unsigned int)root->secondary.start);
526 result = -ENODEV;
527 goto end;
528 }
529
530 if (clear_aspm) {
531 dev_info(&device->dev, "Disabling ASPM (FADT indicates it is unsupported)\n");
532 pcie_clear_aspm(root->bus);
533 }
534 if (no_aspm)
535 pcie_no_aspm();
536
523 pci_acpi_add_bus_pm_notifier(device, root->bus); 537 pci_acpi_add_bus_pm_notifier(device, root->bus);
524 if (device->wakeup.flags.run_wake) 538 if (device->wakeup.flags.run_wake)
525 device_set_run_wake(root->bus->bridge, true); 539 device_set_run_wake(root->bus->bridge, true);