diff options
Diffstat (limited to 'drivers/acpi/processor_core.c')
-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, | |||
83 | return 0; | 83 | return 0; |
84 | } | 84 | } |
85 | 85 | ||
86 | /* | ||
87 | * Retrieve the ARM CPU physical identifier (MPIDR) | ||
88 | */ | ||
89 | static int map_gicc_mpidr(struct acpi_subtable_header *entry, | ||
90 | int device_declaration, u32 acpi_id, phys_cpuid_t *mpidr) | ||
91 | { | ||
92 | struct acpi_madt_generic_interrupt *gicc = | ||
93 | container_of(entry, struct acpi_madt_generic_interrupt, header); | ||
94 | |||
95 | if (!(gicc->flags & ACPI_MADT_ENABLED)) | ||
96 | return -ENODEV; | ||
97 | |||
98 | /* device_declaration means Device object in DSDT, in the | ||
99 | * GIC interrupt model, logical processors are required to | ||
100 | * have a Processor Device object in the DSDT, so we should | ||
101 | * check device_declaration here | ||
102 | */ | ||
103 | if (device_declaration && (gicc->uid == acpi_id)) { | ||
104 | *mpidr = gicc->arm_mpidr; | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | return -EINVAL; | ||
109 | } | ||
110 | |||
86 | static phys_cpuid_t map_madt_entry(int type, u32 acpi_id) | 111 | static phys_cpuid_t map_madt_entry(int type, u32 acpi_id) |
87 | { | 112 | { |
88 | unsigned long madt_end, entry; | 113 | unsigned long madt_end, entry; |
@@ -111,6 +136,9 @@ static phys_cpuid_t map_madt_entry(int type, u32 acpi_id) | |||
111 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { | 136 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { |
112 | if (!map_lsapic_id(header, type, acpi_id, &phys_id)) | 137 | if (!map_lsapic_id(header, type, acpi_id, &phys_id)) |
113 | break; | 138 | break; |
139 | } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) { | ||
140 | if (!map_gicc_mpidr(header, type, acpi_id, &phys_id)) | ||
141 | break; | ||
114 | } | 142 | } |
115 | entry += header->length; | 143 | entry += header->length; |
116 | } | 144 | } |
@@ -143,6 +171,8 @@ static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id) | |||
143 | map_lsapic_id(header, type, acpi_id, &phys_id); | 171 | map_lsapic_id(header, type, acpi_id, &phys_id); |
144 | else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) | 172 | else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) |
145 | map_x2apic_id(header, type, acpi_id, &phys_id); | 173 | map_x2apic_id(header, type, acpi_id, &phys_id); |
174 | else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) | ||
175 | map_gicc_mpidr(header, type, acpi_id, &phys_id); | ||
146 | 176 | ||
147 | exit: | 177 | exit: |
148 | kfree(buffer.pointer); | 178 | kfree(buffer.pointer); |