diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/processor_core.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 51cc29909e08..b1ec78b8a645 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -83,6 +83,31 @@ static int map_lsapic_id(struct acpi_subtable_header *entry, return 0; } +/* + * Retrieve the ARM CPU physical identifier (MPIDR) + */ +static int map_gicc_mpidr(struct acpi_subtable_header *entry, + int device_declaration, u32 acpi_id, phys_cpuid_t *mpidr) +{ + struct acpi_madt_generic_interrupt *gicc = + container_of(entry, struct acpi_madt_generic_interrupt, header); + + if (!(gicc->flags & ACPI_MADT_ENABLED)) + return -ENODEV; + + /* device_declaration means Device object in DSDT, in the + * GIC interrupt model, logical processors are required to + * have a Processor Device object in the DSDT, so we should + * check device_declaration here + */ + if (device_declaration && (gicc->uid == acpi_id)) { + *mpidr = gicc->arm_mpidr; + return 0; + } + + return -EINVAL; +} + static phys_cpuid_t map_madt_entry(int type, u32 acpi_id) { unsigned long madt_end, entry; @@ -111,6 +136,9 @@ static phys_cpuid_t map_madt_entry(int type, u32 acpi_id) } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { if (!map_lsapic_id(header, type, acpi_id, &phys_id)) break; + } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) { + if (!map_gicc_mpidr(header, type, acpi_id, &phys_id)) + break; } entry += header->length; } @@ -143,6 +171,8 @@ static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id) map_lsapic_id(header, type, acpi_id, &phys_id); else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) map_x2apic_id(header, type, acpi_id, &phys_id); + else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) + map_gicc_mpidr(header, type, acpi_id, &phys_id); exit: kfree(buffer.pointer); |