diff options
Diffstat (limited to 'drivers/acpi/pci_root.c')
| -rw-r--r-- | drivers/acpi/pci_root.c | 85 |
1 files changed, 44 insertions, 41 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 0ac546d5e53f..6ae5e440436e 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
| @@ -415,7 +415,6 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
| 415 | struct acpi_pci_root *root; | 415 | struct acpi_pci_root *root; |
| 416 | struct acpi_pci_driver *driver; | 416 | struct acpi_pci_driver *driver; |
| 417 | u32 flags, base_flags; | 417 | u32 flags, base_flags; |
| 418 | bool is_osc_granted = false; | ||
| 419 | 418 | ||
| 420 | root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); | 419 | root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); |
| 421 | if (!root) | 420 | if (!root) |
| @@ -476,6 +475,30 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
| 476 | flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; | 475 | flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; |
| 477 | acpi_pci_osc_support(root, flags); | 476 | acpi_pci_osc_support(root, flags); |
| 478 | 477 | ||
| 478 | /* | ||
| 479 | * TBD: Need PCI interface for enumeration/configuration of roots. | ||
| 480 | */ | ||
| 481 | |||
| 482 | mutex_lock(&acpi_pci_root_lock); | ||
| 483 | list_add_tail(&root->node, &acpi_pci_roots); | ||
| 484 | mutex_unlock(&acpi_pci_root_lock); | ||
| 485 | |||
| 486 | /* | ||
| 487 | * Scan the Root Bridge | ||
| 488 | * -------------------- | ||
| 489 | * Must do this prior to any attempt to bind the root device, as the | ||
| 490 | * PCI namespace does not get created until this call is made (and | ||
| 491 | * thus the root bridge's pci_dev does not exist). | ||
| 492 | */ | ||
| 493 | root->bus = pci_acpi_scan_root(root); | ||
| 494 | if (!root->bus) { | ||
| 495 | printk(KERN_ERR PREFIX | ||
| 496 | "Bus %04x:%02x not present in PCI namespace\n", | ||
| 497 | root->segment, (unsigned int)root->secondary.start); | ||
| 498 | result = -ENODEV; | ||
| 499 | goto out_del_root; | ||
| 500 | } | ||
| 501 | |||
| 479 | /* Indicate support for various _OSC capabilities. */ | 502 | /* Indicate support for various _OSC capabilities. */ |
| 480 | if (pci_ext_cfg_avail()) | 503 | if (pci_ext_cfg_avail()) |
| 481 | flags |= OSC_EXT_PCI_CONFIG_SUPPORT; | 504 | flags |= OSC_EXT_PCI_CONFIG_SUPPORT; |
| @@ -494,6 +517,7 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
| 494 | flags = base_flags; | 517 | flags = base_flags; |
| 495 | } | 518 | } |
| 496 | } | 519 | } |
| 520 | |||
| 497 | if (!pcie_ports_disabled | 521 | if (!pcie_ports_disabled |
| 498 | && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { | 522 | && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { |
| 499 | flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL | 523 | flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL |
| @@ -514,54 +538,28 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
| 514 | status = acpi_pci_osc_control_set(device->handle, &flags, | 538 | status = acpi_pci_osc_control_set(device->handle, &flags, |
| 515 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | 539 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); |
| 516 | if (ACPI_SUCCESS(status)) { | 540 | if (ACPI_SUCCESS(status)) { |
| 517 | is_osc_granted = true; | ||
| 518 | dev_info(&device->dev, | 541 | dev_info(&device->dev, |
| 519 | "ACPI _OSC control (0x%02x) granted\n", flags); | 542 | "ACPI _OSC control (0x%02x) granted\n", flags); |
| 543 | if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { | ||
| 544 | /* | ||
| 545 | * We have ASPM control, but the FADT indicates | ||
| 546 | * that it's unsupported. Clear it. | ||
| 547 | */ | ||
| 548 | pcie_clear_aspm(root->bus); | ||
| 549 | } | ||
| 520 | } else { | 550 | } else { |
| 521 | is_osc_granted = false; | ||
| 522 | dev_info(&device->dev, | 551 | dev_info(&device->dev, |
| 523 | "ACPI _OSC request failed (%s), " | 552 | "ACPI _OSC request failed (%s), " |
| 524 | "returned control mask: 0x%02x\n", | 553 | "returned control mask: 0x%02x\n", |
| 525 | acpi_format_exception(status), flags); | 554 | acpi_format_exception(status), flags); |
| 555 | pr_info("ACPI _OSC control for PCIe not granted, " | ||
| 556 | "disabling ASPM\n"); | ||
| 557 | pcie_no_aspm(); | ||
| 526 | } | 558 | } |
| 527 | } else { | 559 | } else { |
| 528 | dev_info(&device->dev, | 560 | dev_info(&device->dev, |
| 529 | "Unable to request _OSC control " | 561 | "Unable to request _OSC control " |
| 530 | "(_OSC support mask: 0x%02x)\n", flags); | 562 | "(_OSC support mask: 0x%02x)\n", flags); |
| 531 | } | ||
| 532 | |||
| 533 | /* | ||
| 534 | * TBD: Need PCI interface for enumeration/configuration of roots. | ||
| 535 | */ | ||
| 536 | |||
| 537 | mutex_lock(&acpi_pci_root_lock); | ||
| 538 | list_add_tail(&root->node, &acpi_pci_roots); | ||
| 539 | mutex_unlock(&acpi_pci_root_lock); | ||
| 540 | |||
| 541 | /* | ||
| 542 | * Scan the Root Bridge | ||
| 543 | * -------------------- | ||
| 544 | * Must do this prior to any attempt to bind the root device, as the | ||
| 545 | * PCI namespace does not get created until this call is made (and | ||
| 546 | * thus the root bridge's pci_dev does not exist). | ||
| 547 | */ | ||
| 548 | root->bus = pci_acpi_scan_root(root); | ||
| 549 | if (!root->bus) { | ||
| 550 | printk(KERN_ERR PREFIX | ||
| 551 | "Bus %04x:%02x not present in PCI namespace\n", | ||
| 552 | root->segment, (unsigned int)root->secondary.start); | ||
| 553 | result = -ENODEV; | ||
| 554 | goto out_del_root; | ||
| 555 | } | ||
| 556 | |||
| 557 | /* ASPM setting */ | ||
| 558 | if (is_osc_granted) { | ||
| 559 | if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) | ||
| 560 | pcie_clear_aspm(root->bus); | ||
| 561 | } else { | ||
| 562 | pr_info("ACPI _OSC control for PCIe not granted, " | ||
| 563 | "disabling ASPM\n"); | ||
| 564 | pcie_no_aspm(); | ||
| 565 | } | 563 | } |
| 566 | 564 | ||
| 567 | pci_acpi_add_bus_pm_notifier(device, root->bus); | 565 | pci_acpi_add_bus_pm_notifier(device, root->bus); |
| @@ -646,6 +644,7 @@ static void handle_root_bridge_insertion(acpi_handle handle) | |||
| 646 | 644 | ||
| 647 | static void handle_root_bridge_removal(struct acpi_device *device) | 645 | static void handle_root_bridge_removal(struct acpi_device *device) |
| 648 | { | 646 | { |
| 647 | acpi_status status; | ||
| 649 | struct acpi_eject_event *ej_event; | 648 | struct acpi_eject_event *ej_event; |
| 650 | 649 | ||
| 651 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); | 650 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); |
| @@ -661,7 +660,9 @@ static void handle_root_bridge_removal(struct acpi_device *device) | |||
| 661 | ej_event->device = device; | 660 | ej_event->device = device; |
| 662 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; | 661 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; |
| 663 | 662 | ||
| 664 | acpi_bus_hot_remove_device(ej_event); | 663 | status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); |
| 664 | if (ACPI_FAILURE(status)) | ||
| 665 | kfree(ej_event); | ||
| 665 | } | 666 | } |
| 666 | 667 | ||
| 667 | static void _handle_hotplug_event_root(struct work_struct *work) | 668 | static void _handle_hotplug_event_root(struct work_struct *work) |
| @@ -676,8 +677,9 @@ static void _handle_hotplug_event_root(struct work_struct *work) | |||
| 676 | handle = hp_work->handle; | 677 | handle = hp_work->handle; |
| 677 | type = hp_work->type; | 678 | type = hp_work->type; |
| 678 | 679 | ||
| 679 | root = acpi_pci_find_root(handle); | 680 | acpi_scan_lock_acquire(); |
| 680 | 681 | ||
| 682 | root = acpi_pci_find_root(handle); | ||
| 681 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | 683 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); |
| 682 | 684 | ||
| 683 | switch (type) { | 685 | switch (type) { |
| @@ -711,6 +713,7 @@ static void _handle_hotplug_event_root(struct work_struct *work) | |||
| 711 | break; | 713 | break; |
| 712 | } | 714 | } |
| 713 | 715 | ||
| 716 | acpi_scan_lock_release(); | ||
| 714 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ | 717 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ |
| 715 | kfree(buffer.pointer); | 718 | kfree(buffer.pointer); |
| 716 | } | 719 | } |
