diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/acpi/acpi_processor.c | 104 | ||||
| -rw-r--r-- | drivers/acpi/bus.c | 1 | ||||
| -rw-r--r-- | drivers/acpi/internal.h | 2 | ||||
| -rw-r--r-- | drivers/acpi/ioapic.c | 46 | ||||
| -rw-r--r-- | drivers/acpi/pci_root.c | 12 | ||||
| -rw-r--r-- | drivers/acpi/processor_core.c | 133 | ||||
| -rw-r--r-- | drivers/pci/setup-bus.c | 8 |
7 files changed, 259 insertions, 47 deletions
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index c7ba948d253c..3de3b6b8f0f1 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c | |||
| @@ -182,6 +182,11 @@ int __weak arch_register_cpu(int cpu) | |||
| 182 | 182 | ||
| 183 | void __weak arch_unregister_cpu(int cpu) {} | 183 | void __weak arch_unregister_cpu(int cpu) {} |
| 184 | 184 | ||
| 185 | int __weak acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) | ||
| 186 | { | ||
| 187 | return -ENODEV; | ||
| 188 | } | ||
| 189 | |||
| 185 | static int acpi_processor_hotadd_init(struct acpi_processor *pr) | 190 | static int acpi_processor_hotadd_init(struct acpi_processor *pr) |
| 186 | { | 191 | { |
| 187 | unsigned long long sta; | 192 | unsigned long long sta; |
| @@ -300,8 +305,11 @@ static int acpi_processor_get_info(struct acpi_device *device) | |||
| 300 | * Extra Processor objects may be enumerated on MP systems with | 305 | * Extra Processor objects may be enumerated on MP systems with |
| 301 | * less than the max # of CPUs. They should be ignored _iff | 306 | * less than the max # of CPUs. They should be ignored _iff |
| 302 | * they are physically not present. | 307 | * they are physically not present. |
| 308 | * | ||
| 309 | * NOTE: Even if the processor has a cpuid, it may not be present | ||
| 310 | * because cpuid <-> apicid mapping is persistent now. | ||
| 303 | */ | 311 | */ |
| 304 | if (invalid_logical_cpuid(pr->id)) { | 312 | if (invalid_logical_cpuid(pr->id) || !cpu_present(pr->id)) { |
| 305 | int ret = acpi_processor_hotadd_init(pr); | 313 | int ret = acpi_processor_hotadd_init(pr); |
| 306 | if (ret) | 314 | if (ret) |
| 307 | return ret; | 315 | return ret; |
| @@ -573,8 +581,102 @@ static struct acpi_scan_handler processor_container_handler = { | |||
| 573 | .attach = acpi_processor_container_attach, | 581 | .attach = acpi_processor_container_attach, |
| 574 | }; | 582 | }; |
| 575 | 583 | ||
| 584 | /* The number of the unique processor IDs */ | ||
| 585 | static int nr_unique_ids __initdata; | ||
| 586 | |||
| 587 | /* The number of the duplicate processor IDs */ | ||
| 588 | static int nr_duplicate_ids __initdata; | ||
| 589 | |||
| 590 | /* Used to store the unique processor IDs */ | ||
| 591 | static int unique_processor_ids[] __initdata = { | ||
| 592 | [0 ... NR_CPUS - 1] = -1, | ||
| 593 | }; | ||
| 594 | |||
| 595 | /* Used to store the duplicate processor IDs */ | ||
| 596 | static int duplicate_processor_ids[] __initdata = { | ||
| 597 | [0 ... NR_CPUS - 1] = -1, | ||
| 598 | }; | ||
| 599 | |||
| 600 | static void __init processor_validated_ids_update(int proc_id) | ||
| 601 | { | ||
| 602 | int i; | ||
| 603 | |||
| 604 | if (nr_unique_ids == NR_CPUS||nr_duplicate_ids == NR_CPUS) | ||
| 605 | return; | ||
| 606 | |||
| 607 | /* | ||
| 608 | * Firstly, compare the proc_id with duplicate IDs, if the proc_id is | ||
| 609 | * already in the IDs, do nothing. | ||
| 610 | */ | ||
| 611 | for (i = 0; i < nr_duplicate_ids; i++) { | ||
| 612 | if (duplicate_processor_ids[i] == proc_id) | ||
| 613 | return; | ||
| 614 | } | ||
| 615 | |||
| 616 | /* | ||
| 617 | * Secondly, compare the proc_id with unique IDs, if the proc_id is in | ||
| 618 | * the IDs, put it in the duplicate IDs. | ||
| 619 | */ | ||
| 620 | for (i = 0; i < nr_unique_ids; i++) { | ||
| 621 | if (unique_processor_ids[i] == proc_id) { | ||
| 622 | duplicate_processor_ids[nr_duplicate_ids] = proc_id; | ||
| 623 | nr_duplicate_ids++; | ||
| 624 | return; | ||
| 625 | } | ||
| 626 | } | ||
| 627 | |||
| 628 | /* | ||
| 629 | * Lastly, the proc_id is a unique ID, put it in the unique IDs. | ||
| 630 | */ | ||
| 631 | unique_processor_ids[nr_unique_ids] = proc_id; | ||
| 632 | nr_unique_ids++; | ||
| 633 | } | ||
| 634 | |||
| 635 | static acpi_status __init acpi_processor_ids_walk(acpi_handle handle, | ||
| 636 | u32 lvl, | ||
| 637 | void *context, | ||
| 638 | void **rv) | ||
| 639 | { | ||
| 640 | acpi_status status; | ||
| 641 | union acpi_object object = { 0 }; | ||
| 642 | struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; | ||
| 643 | |||
| 644 | status = acpi_evaluate_object(handle, NULL, NULL, &buffer); | ||
| 645 | if (ACPI_FAILURE(status)) | ||
| 646 | acpi_handle_info(handle, "Not get the processor object\n"); | ||
| 647 | else | ||
| 648 | processor_validated_ids_update(object.processor.proc_id); | ||
| 649 | |||
| 650 | return AE_OK; | ||
| 651 | } | ||
| 652 | |||
| 653 | static void __init acpi_processor_check_duplicates(void) | ||
| 654 | { | ||
| 655 | /* Search all processor nodes in ACPI namespace */ | ||
| 656 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, | ||
| 657 | ACPI_UINT32_MAX, | ||
| 658 | acpi_processor_ids_walk, | ||
| 659 | NULL, NULL, NULL); | ||
| 660 | } | ||
| 661 | |||
| 662 | bool __init acpi_processor_validate_proc_id(int proc_id) | ||
| 663 | { | ||
| 664 | int i; | ||
| 665 | |||
| 666 | /* | ||
| 667 | * compare the proc_id with duplicate IDs, if the proc_id is already | ||
| 668 | * in the duplicate IDs, return true, otherwise, return false. | ||
| 669 | */ | ||
| 670 | for (i = 0; i < nr_duplicate_ids; i++) { | ||
| 671 | if (duplicate_processor_ids[i] == proc_id) | ||
| 672 | return true; | ||
| 673 | } | ||
| 674 | return false; | ||
| 675 | } | ||
| 676 | |||
| 576 | void __init acpi_processor_init(void) | 677 | void __init acpi_processor_init(void) |
| 577 | { | 678 | { |
| 679 | acpi_processor_check_duplicates(); | ||
| 578 | acpi_scan_add_handler_with_hotplug(&processor_handler, "processor"); | 680 | acpi_scan_add_handler_with_hotplug(&processor_handler, "processor"); |
| 579 | acpi_scan_add_handler(&processor_container_handler); | 681 | acpi_scan_add_handler(&processor_container_handler); |
| 580 | } | 682 | } |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 658b4c4f169f..8df0afad35a9 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
| @@ -1195,6 +1195,7 @@ static int __init acpi_init(void) | |||
| 1195 | acpi_wakeup_device_init(); | 1195 | acpi_wakeup_device_init(); |
| 1196 | acpi_debugger_init(); | 1196 | acpi_debugger_init(); |
| 1197 | acpi_setup_sb_notify_handler(); | 1197 | acpi_setup_sb_notify_handler(); |
| 1198 | acpi_set_processor_mapping(); | ||
| 1198 | return 0; | 1199 | return 0; |
| 1199 | } | 1200 | } |
| 1200 | 1201 | ||
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 4bf8bf16d096..1b41a2739dac 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
| @@ -40,10 +40,8 @@ int acpi_sysfs_init(void); | |||
| 40 | void acpi_container_init(void); | 40 | void acpi_container_init(void); |
| 41 | void acpi_memory_hotplug_init(void); | 41 | void acpi_memory_hotplug_init(void); |
| 42 | #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC | 42 | #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC |
| 43 | int acpi_ioapic_add(struct acpi_pci_root *root); | ||
| 44 | int acpi_ioapic_remove(struct acpi_pci_root *root); | 43 | int acpi_ioapic_remove(struct acpi_pci_root *root); |
| 45 | #else | 44 | #else |
| 46 | static inline int acpi_ioapic_add(struct acpi_pci_root *root) { return 0; } | ||
| 47 | static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { return 0; } | 45 | static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { return 0; } |
| 48 | #endif | 46 | #endif |
| 49 | #ifdef CONFIG_ACPI_DOCK | 47 | #ifdef CONFIG_ACPI_DOCK |
diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c index ccdc8db16bb8..6d7ce6e12aaa 100644 --- a/drivers/acpi/ioapic.c +++ b/drivers/acpi/ioapic.c | |||
| @@ -46,7 +46,7 @@ static acpi_status setup_res(struct acpi_resource *acpi_res, void *data) | |||
| 46 | struct resource_win win; | 46 | struct resource_win win; |
| 47 | 47 | ||
| 48 | res->flags = 0; | 48 | res->flags = 0; |
| 49 | if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM) == 0) | 49 | if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM)) |
| 50 | return AE_OK; | 50 | return AE_OK; |
| 51 | 51 | ||
| 52 | if (!acpi_dev_resource_memory(acpi_res, res)) { | 52 | if (!acpi_dev_resource_memory(acpi_res, res)) { |
| @@ -97,7 +97,7 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, | |||
| 97 | unsigned long long gsi_base; | 97 | unsigned long long gsi_base; |
| 98 | struct acpi_pci_ioapic *ioapic; | 98 | struct acpi_pci_ioapic *ioapic; |
| 99 | struct pci_dev *dev = NULL; | 99 | struct pci_dev *dev = NULL; |
| 100 | struct resource *res = NULL; | 100 | struct resource *res = NULL, *pci_res = NULL, *crs_res; |
| 101 | char *type = NULL; | 101 | char *type = NULL; |
| 102 | 102 | ||
| 103 | if (!acpi_is_ioapic(handle, &type)) | 103 | if (!acpi_is_ioapic(handle, &type)) |
| @@ -137,23 +137,30 @@ static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl, | |||
| 137 | pci_set_master(dev); | 137 | pci_set_master(dev); |
| 138 | if (pci_request_region(dev, 0, type)) | 138 | if (pci_request_region(dev, 0, type)) |
| 139 | goto exit_disable; | 139 | goto exit_disable; |
| 140 | res = &dev->resource[0]; | 140 | pci_res = &dev->resource[0]; |
| 141 | ioapic->pdev = dev; | 141 | ioapic->pdev = dev; |
| 142 | } else { | 142 | } else { |
| 143 | pci_dev_put(dev); | 143 | pci_dev_put(dev); |
| 144 | dev = NULL; | 144 | dev = NULL; |
| 145 | } | ||
| 145 | 146 | ||
| 146 | res = &ioapic->res; | 147 | crs_res = &ioapic->res; |
| 147 | acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, res); | 148 | acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, crs_res); |
| 148 | if (res->flags == 0) { | 149 | crs_res->name = type; |
| 149 | acpi_handle_warn(handle, "failed to get resource\n"); | 150 | crs_res->flags |= IORESOURCE_BUSY; |
| 150 | goto exit_free; | 151 | if (crs_res->flags == 0) { |
| 151 | } else if (request_resource(&iomem_resource, res)) { | 152 | acpi_handle_warn(handle, "failed to get resource\n"); |
| 152 | acpi_handle_warn(handle, "failed to insert resource\n"); | 153 | goto exit_release; |
| 153 | goto exit_free; | 154 | } else if (insert_resource(&iomem_resource, crs_res)) { |
| 154 | } | 155 | acpi_handle_warn(handle, "failed to insert resource\n"); |
| 156 | goto exit_release; | ||
| 155 | } | 157 | } |
| 156 | 158 | ||
| 159 | /* try pci resource first, then "_CRS" resource */ | ||
| 160 | res = pci_res; | ||
| 161 | if (!res || !res->flags) | ||
| 162 | res = crs_res; | ||
| 163 | |||
| 157 | if (acpi_register_ioapic(handle, res->start, (u32)gsi_base)) { | 164 | if (acpi_register_ioapic(handle, res->start, (u32)gsi_base)) { |
| 158 | acpi_handle_warn(handle, "failed to register IOAPIC\n"); | 165 | acpi_handle_warn(handle, "failed to register IOAPIC\n"); |
| 159 | goto exit_release; | 166 | goto exit_release; |
| @@ -174,14 +181,13 @@ done: | |||
| 174 | exit_release: | 181 | exit_release: |
| 175 | if (dev) | 182 | if (dev) |
| 176 | pci_release_region(dev, 0); | 183 | pci_release_region(dev, 0); |
| 177 | else | 184 | if (ioapic->res.flags && ioapic->res.parent) |
| 178 | release_resource(res); | 185 | release_resource(&ioapic->res); |
| 179 | exit_disable: | 186 | exit_disable: |
| 180 | if (dev) | 187 | if (dev) |
| 181 | pci_disable_device(dev); | 188 | pci_disable_device(dev); |
| 182 | exit_put: | 189 | exit_put: |
| 183 | pci_dev_put(dev); | 190 | pci_dev_put(dev); |
| 184 | exit_free: | ||
| 185 | kfree(ioapic); | 191 | kfree(ioapic); |
| 186 | exit: | 192 | exit: |
| 187 | mutex_unlock(&ioapic_list_lock); | 193 | mutex_unlock(&ioapic_list_lock); |
| @@ -189,13 +195,13 @@ exit: | |||
| 189 | return AE_OK; | 195 | return AE_OK; |
| 190 | } | 196 | } |
| 191 | 197 | ||
| 192 | int acpi_ioapic_add(struct acpi_pci_root *root) | 198 | int acpi_ioapic_add(acpi_handle root_handle) |
| 193 | { | 199 | { |
| 194 | acpi_status status, retval = AE_OK; | 200 | acpi_status status, retval = AE_OK; |
| 195 | 201 | ||
| 196 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle, | 202 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root_handle, |
| 197 | UINT_MAX, handle_ioapic_add, NULL, | 203 | UINT_MAX, handle_ioapic_add, NULL, |
| 198 | root->device->handle, (void **)&retval); | 204 | root_handle, (void **)&retval); |
| 199 | 205 | ||
| 200 | return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; | 206 | return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV; |
| 201 | } | 207 | } |
| @@ -217,9 +223,9 @@ int acpi_ioapic_remove(struct acpi_pci_root *root) | |||
| 217 | pci_release_region(ioapic->pdev, 0); | 223 | pci_release_region(ioapic->pdev, 0); |
| 218 | pci_disable_device(ioapic->pdev); | 224 | pci_disable_device(ioapic->pdev); |
| 219 | pci_dev_put(ioapic->pdev); | 225 | pci_dev_put(ioapic->pdev); |
| 220 | } else if (ioapic->res.flags && ioapic->res.parent) { | ||
| 221 | release_resource(&ioapic->res); | ||
| 222 | } | 226 | } |
| 227 | if (ioapic->res.flags && ioapic->res.parent) | ||
| 228 | release_resource(&ioapic->res); | ||
| 223 | list_del(&ioapic->list); | 229 | list_del(&ioapic->list); |
| 224 | kfree(ioapic); | 230 | kfree(ioapic); |
| 225 | } | 231 | } |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d144168d4ef9..bf601d4df8cf 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
| @@ -614,7 +614,17 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
| 614 | if (hotadd) { | 614 | if (hotadd) { |
| 615 | pcibios_resource_survey_bus(root->bus); | 615 | pcibios_resource_survey_bus(root->bus); |
| 616 | pci_assign_unassigned_root_bus_resources(root->bus); | 616 | pci_assign_unassigned_root_bus_resources(root->bus); |
| 617 | acpi_ioapic_add(root); | 617 | /* |
| 618 | * This is only called for the hotadd case. For the boot-time | ||
| 619 | * case, we need to wait until after PCI initialization in | ||
| 620 | * order to deal with IOAPICs mapped in on a PCI BAR. | ||
| 621 | * | ||
| 622 | * This is currently x86-specific, because acpi_ioapic_add() | ||
| 623 | * is an empty function without CONFIG_ACPI_HOTPLUG_IOAPIC. | ||
| 624 | * And CONFIG_ACPI_HOTPLUG_IOAPIC depends on CONFIG_X86_IO_APIC | ||
| 625 | * (see drivers/acpi/Kconfig). | ||
| 626 | */ | ||
| 627 | acpi_ioapic_add(root->device->handle); | ||
| 618 | } | 628 | } |
| 619 | 629 | ||
| 620 | pci_lock_rescan_remove(); | 630 | pci_lock_rescan_remove(); |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 9125d7d96372..5c78ee1860b0 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
| @@ -32,12 +32,12 @@ static struct acpi_table_madt *get_madt_table(void) | |||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | static int map_lapic_id(struct acpi_subtable_header *entry, | 34 | static int map_lapic_id(struct acpi_subtable_header *entry, |
| 35 | u32 acpi_id, phys_cpuid_t *apic_id) | 35 | u32 acpi_id, phys_cpuid_t *apic_id, bool ignore_disabled) |
| 36 | { | 36 | { |
| 37 | struct acpi_madt_local_apic *lapic = | 37 | struct acpi_madt_local_apic *lapic = |
| 38 | container_of(entry, struct acpi_madt_local_apic, header); | 38 | container_of(entry, struct acpi_madt_local_apic, header); |
| 39 | 39 | ||
| 40 | if (!(lapic->lapic_flags & ACPI_MADT_ENABLED)) | 40 | if (ignore_disabled && !(lapic->lapic_flags & ACPI_MADT_ENABLED)) |
| 41 | return -ENODEV; | 41 | return -ENODEV; |
| 42 | 42 | ||
| 43 | if (lapic->processor_id != acpi_id) | 43 | if (lapic->processor_id != acpi_id) |
| @@ -48,12 +48,13 @@ static int map_lapic_id(struct acpi_subtable_header *entry, | |||
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | static int map_x2apic_id(struct acpi_subtable_header *entry, | 50 | static int map_x2apic_id(struct acpi_subtable_header *entry, |
| 51 | int device_declaration, u32 acpi_id, phys_cpuid_t *apic_id) | 51 | int device_declaration, u32 acpi_id, phys_cpuid_t *apic_id, |
| 52 | bool ignore_disabled) | ||
| 52 | { | 53 | { |
| 53 | struct acpi_madt_local_x2apic *apic = | 54 | struct acpi_madt_local_x2apic *apic = |
| 54 | container_of(entry, struct acpi_madt_local_x2apic, header); | 55 | container_of(entry, struct acpi_madt_local_x2apic, header); |
| 55 | 56 | ||
| 56 | if (!(apic->lapic_flags & ACPI_MADT_ENABLED)) | 57 | if (ignore_disabled && !(apic->lapic_flags & ACPI_MADT_ENABLED)) |
| 57 | return -ENODEV; | 58 | return -ENODEV; |
| 58 | 59 | ||
| 59 | if (device_declaration && (apic->uid == acpi_id)) { | 60 | if (device_declaration && (apic->uid == acpi_id)) { |
| @@ -65,12 +66,13 @@ static int map_x2apic_id(struct acpi_subtable_header *entry, | |||
| 65 | } | 66 | } |
| 66 | 67 | ||
| 67 | static int map_lsapic_id(struct acpi_subtable_header *entry, | 68 | static int map_lsapic_id(struct acpi_subtable_header *entry, |
| 68 | int device_declaration, u32 acpi_id, phys_cpuid_t *apic_id) | 69 | int device_declaration, u32 acpi_id, phys_cpuid_t *apic_id, |
| 70 | bool ignore_disabled) | ||
| 69 | { | 71 | { |
| 70 | struct acpi_madt_local_sapic *lsapic = | 72 | struct acpi_madt_local_sapic *lsapic = |
| 71 | container_of(entry, struct acpi_madt_local_sapic, header); | 73 | container_of(entry, struct acpi_madt_local_sapic, header); |
| 72 | 74 | ||
| 73 | if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED)) | 75 | if (ignore_disabled && !(lsapic->lapic_flags & ACPI_MADT_ENABLED)) |
| 74 | return -ENODEV; | 76 | return -ENODEV; |
| 75 | 77 | ||
| 76 | if (device_declaration) { | 78 | if (device_declaration) { |
| @@ -87,12 +89,13 @@ static int map_lsapic_id(struct acpi_subtable_header *entry, | |||
| 87 | * Retrieve the ARM CPU physical identifier (MPIDR) | 89 | * Retrieve the ARM CPU physical identifier (MPIDR) |
| 88 | */ | 90 | */ |
| 89 | static int map_gicc_mpidr(struct acpi_subtable_header *entry, | 91 | static int map_gicc_mpidr(struct acpi_subtable_header *entry, |
| 90 | int device_declaration, u32 acpi_id, phys_cpuid_t *mpidr) | 92 | int device_declaration, u32 acpi_id, phys_cpuid_t *mpidr, |
| 93 | bool ignore_disabled) | ||
| 91 | { | 94 | { |
| 92 | struct acpi_madt_generic_interrupt *gicc = | 95 | struct acpi_madt_generic_interrupt *gicc = |
| 93 | container_of(entry, struct acpi_madt_generic_interrupt, header); | 96 | container_of(entry, struct acpi_madt_generic_interrupt, header); |
| 94 | 97 | ||
| 95 | if (!(gicc->flags & ACPI_MADT_ENABLED)) | 98 | if (ignore_disabled && !(gicc->flags & ACPI_MADT_ENABLED)) |
| 96 | return -ENODEV; | 99 | return -ENODEV; |
| 97 | 100 | ||
| 98 | /* device_declaration means Device object in DSDT, in the | 101 | /* device_declaration means Device object in DSDT, in the |
| @@ -109,7 +112,7 @@ static int map_gicc_mpidr(struct acpi_subtable_header *entry, | |||
| 109 | } | 112 | } |
| 110 | 113 | ||
| 111 | static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt, | 114 | static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt, |
| 112 | int type, u32 acpi_id) | 115 | int type, u32 acpi_id, bool ignore_disabled) |
| 113 | { | 116 | { |
| 114 | unsigned long madt_end, entry; | 117 | unsigned long madt_end, entry; |
| 115 | phys_cpuid_t phys_id = PHYS_CPUID_INVALID; /* CPU hardware ID */ | 118 | phys_cpuid_t phys_id = PHYS_CPUID_INVALID; /* CPU hardware ID */ |
| @@ -127,16 +130,20 @@ static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt, | |||
| 127 | struct acpi_subtable_header *header = | 130 | struct acpi_subtable_header *header = |
| 128 | (struct acpi_subtable_header *)entry; | 131 | (struct acpi_subtable_header *)entry; |
| 129 | if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { | 132 | if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { |
| 130 | if (!map_lapic_id(header, acpi_id, &phys_id)) | 133 | if (!map_lapic_id(header, acpi_id, &phys_id, |
| 134 | ignore_disabled)) | ||
| 131 | break; | 135 | break; |
| 132 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) { | 136 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) { |
| 133 | if (!map_x2apic_id(header, type, acpi_id, &phys_id)) | 137 | if (!map_x2apic_id(header, type, acpi_id, &phys_id, |
| 138 | ignore_disabled)) | ||
| 134 | break; | 139 | break; |
| 135 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { | 140 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { |
| 136 | if (!map_lsapic_id(header, type, acpi_id, &phys_id)) | 141 | if (!map_lsapic_id(header, type, acpi_id, &phys_id, |
| 142 | ignore_disabled)) | ||
| 137 | break; | 143 | break; |
| 138 | } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) { | 144 | } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) { |
| 139 | if (!map_gicc_mpidr(header, type, acpi_id, &phys_id)) | 145 | if (!map_gicc_mpidr(header, type, acpi_id, &phys_id, |
| 146 | ignore_disabled)) | ||
| 140 | break; | 147 | break; |
| 141 | } | 148 | } |
| 142 | entry += header->length; | 149 | entry += header->length; |
| @@ -156,14 +163,15 @@ phys_cpuid_t __init acpi_map_madt_entry(u32 acpi_id) | |||
| 156 | if (!madt) | 163 | if (!madt) |
| 157 | return PHYS_CPUID_INVALID; | 164 | return PHYS_CPUID_INVALID; |
| 158 | 165 | ||
| 159 | rv = map_madt_entry(madt, 1, acpi_id); | 166 | rv = map_madt_entry(madt, 1, acpi_id, true); |
| 160 | 167 | ||
| 161 | early_acpi_os_unmap_memory(madt, tbl_size); | 168 | early_acpi_os_unmap_memory(madt, tbl_size); |
| 162 | 169 | ||
| 163 | return rv; | 170 | return rv; |
| 164 | } | 171 | } |
| 165 | 172 | ||
| 166 | static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id) | 173 | static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id, |
| 174 | bool ignore_disabled) | ||
| 167 | { | 175 | { |
| 168 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 176 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 169 | union acpi_object *obj; | 177 | union acpi_object *obj; |
| @@ -184,30 +192,38 @@ static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id) | |||
| 184 | 192 | ||
| 185 | header = (struct acpi_subtable_header *)obj->buffer.pointer; | 193 | header = (struct acpi_subtable_header *)obj->buffer.pointer; |
| 186 | if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) | 194 | if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) |
| 187 | map_lapic_id(header, acpi_id, &phys_id); | 195 | map_lapic_id(header, acpi_id, &phys_id, ignore_disabled); |
| 188 | else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) | 196 | else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) |
| 189 | map_lsapic_id(header, type, acpi_id, &phys_id); | 197 | map_lsapic_id(header, type, acpi_id, &phys_id, ignore_disabled); |
| 190 | else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) | 198 | else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) |
| 191 | map_x2apic_id(header, type, acpi_id, &phys_id); | 199 | map_x2apic_id(header, type, acpi_id, &phys_id, ignore_disabled); |
| 192 | else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) | 200 | else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) |
| 193 | map_gicc_mpidr(header, type, acpi_id, &phys_id); | 201 | map_gicc_mpidr(header, type, acpi_id, &phys_id, |
| 202 | ignore_disabled); | ||
| 194 | 203 | ||
| 195 | exit: | 204 | exit: |
| 196 | kfree(buffer.pointer); | 205 | kfree(buffer.pointer); |
| 197 | return phys_id; | 206 | return phys_id; |
| 198 | } | 207 | } |
| 199 | 208 | ||
| 200 | phys_cpuid_t acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id) | 209 | static phys_cpuid_t __acpi_get_phys_id(acpi_handle handle, int type, |
| 210 | u32 acpi_id, bool ignore_disabled) | ||
| 201 | { | 211 | { |
| 202 | phys_cpuid_t phys_id; | 212 | phys_cpuid_t phys_id; |
| 203 | 213 | ||
| 204 | phys_id = map_mat_entry(handle, type, acpi_id); | 214 | phys_id = map_mat_entry(handle, type, acpi_id, ignore_disabled); |
| 205 | if (invalid_phys_cpuid(phys_id)) | 215 | if (invalid_phys_cpuid(phys_id)) |
| 206 | phys_id = map_madt_entry(get_madt_table(), type, acpi_id); | 216 | phys_id = map_madt_entry(get_madt_table(), type, acpi_id, |
| 217 | ignore_disabled); | ||
| 207 | 218 | ||
| 208 | return phys_id; | 219 | return phys_id; |
| 209 | } | 220 | } |
| 210 | 221 | ||
| 222 | phys_cpuid_t acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id) | ||
| 223 | { | ||
| 224 | return __acpi_get_phys_id(handle, type, acpi_id, true); | ||
| 225 | } | ||
| 226 | |||
| 211 | int acpi_map_cpuid(phys_cpuid_t phys_id, u32 acpi_id) | 227 | int acpi_map_cpuid(phys_cpuid_t phys_id, u32 acpi_id) |
| 212 | { | 228 | { |
| 213 | #ifdef CONFIG_SMP | 229 | #ifdef CONFIG_SMP |
| @@ -264,6 +280,79 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) | |||
| 264 | } | 280 | } |
| 265 | EXPORT_SYMBOL_GPL(acpi_get_cpuid); | 281 | EXPORT_SYMBOL_GPL(acpi_get_cpuid); |
| 266 | 282 | ||
| 283 | #ifdef CONFIG_ACPI_HOTPLUG_CPU | ||
| 284 | static bool __init | ||
| 285 | map_processor(acpi_handle handle, phys_cpuid_t *phys_id, int *cpuid) | ||
| 286 | { | ||
| 287 | int type, id; | ||
| 288 | u32 acpi_id; | ||
| 289 | acpi_status status; | ||
| 290 | acpi_object_type acpi_type; | ||
| 291 | unsigned long long tmp; | ||
| 292 | union acpi_object object = { 0 }; | ||
| 293 | struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; | ||
| 294 | |||
| 295 | status = acpi_get_type(handle, &acpi_type); | ||
| 296 | if (ACPI_FAILURE(status)) | ||
| 297 | return false; | ||
| 298 | |||
| 299 | switch (acpi_type) { | ||
| 300 | case ACPI_TYPE_PROCESSOR: | ||
| 301 | status = acpi_evaluate_object(handle, NULL, NULL, &buffer); | ||
| 302 | if (ACPI_FAILURE(status)) | ||
| 303 | return false; | ||
| 304 | acpi_id = object.processor.proc_id; | ||
| 305 | |||
| 306 | /* validate the acpi_id */ | ||
| 307 | if(acpi_processor_validate_proc_id(acpi_id)) | ||
| 308 | return false; | ||
| 309 | break; | ||
| 310 | case ACPI_TYPE_DEVICE: | ||
| 311 | status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp); | ||
| 312 | if (ACPI_FAILURE(status)) | ||
| 313 | return false; | ||
| 314 | acpi_id = tmp; | ||
| 315 | break; | ||
| 316 | default: | ||
| 317 | return false; | ||
| 318 | } | ||
| 319 | |||
| 320 | type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0; | ||
| 321 | |||
| 322 | *phys_id = __acpi_get_phys_id(handle, type, acpi_id, false); | ||
| 323 | id = acpi_map_cpuid(*phys_id, acpi_id); | ||
| 324 | |||
| 325 | if (id < 0) | ||
| 326 | return false; | ||
| 327 | *cpuid = id; | ||
| 328 | return true; | ||
| 329 | } | ||
| 330 | |||
| 331 | static acpi_status __init | ||
| 332 | set_processor_node_mapping(acpi_handle handle, u32 lvl, void *context, | ||
| 333 | void **rv) | ||
| 334 | { | ||
| 335 | phys_cpuid_t phys_id; | ||
| 336 | int cpu_id; | ||
| 337 | |||
| 338 | if (!map_processor(handle, &phys_id, &cpu_id)) | ||
| 339 | return AE_ERROR; | ||
| 340 | |||
| 341 | acpi_map_cpu2node(handle, cpu_id, phys_id); | ||
| 342 | return AE_OK; | ||
| 343 | } | ||
| 344 | |||
| 345 | void __init acpi_set_processor_mapping(void) | ||
| 346 | { | ||
| 347 | /* Set persistent cpu <-> node mapping for all processors. */ | ||
| 348 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, | ||
| 349 | ACPI_UINT32_MAX, set_processor_node_mapping, | ||
| 350 | NULL, NULL, NULL); | ||
| 351 | } | ||
| 352 | #else | ||
| 353 | void __init acpi_set_processor_mapping(void) {} | ||
| 354 | #endif /* CONFIG_ACPI_HOTPLUG_CPU */ | ||
| 355 | |||
| 267 | #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC | 356 | #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC |
| 268 | static int get_ioapic_id(struct acpi_subtable_header *entry, u32 gsi_base, | 357 | static int get_ioapic_id(struct acpi_subtable_header *entry, u32 gsi_base, |
| 269 | u64 *phys_addr, int *ioapic_id) | 358 | u64 *phys_addr, int *ioapic_id) |
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index c74059e10a6d..f30ca75b5b6c 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/ioport.h> | 25 | #include <linux/ioport.h> |
| 26 | #include <linux/cache.h> | 26 | #include <linux/cache.h> |
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include <linux/acpi.h> | ||
| 28 | #include "pci.h" | 29 | #include "pci.h" |
| 29 | 30 | ||
| 30 | unsigned int pci_flags; | 31 | unsigned int pci_flags; |
| @@ -1852,8 +1853,13 @@ void __init pci_assign_unassigned_resources(void) | |||
| 1852 | { | 1853 | { |
| 1853 | struct pci_bus *root_bus; | 1854 | struct pci_bus *root_bus; |
| 1854 | 1855 | ||
| 1855 | list_for_each_entry(root_bus, &pci_root_buses, node) | 1856 | list_for_each_entry(root_bus, &pci_root_buses, node) { |
| 1856 | pci_assign_unassigned_root_bus_resources(root_bus); | 1857 | pci_assign_unassigned_root_bus_resources(root_bus); |
| 1858 | |||
| 1859 | /* Make sure the root bridge has a companion ACPI device: */ | ||
| 1860 | if (ACPI_HANDLE(root_bus->bridge)) | ||
| 1861 | acpi_ioapic_add(ACPI_HANDLE(root_bus->bridge)); | ||
| 1862 | } | ||
| 1857 | } | 1863 | } |
| 1858 | 1864 | ||
| 1859 | void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) | 1865 | void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) |
