diff options
author | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | 2015-03-25 11:13:56 -0400 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2015-03-26 11:13:10 -0400 |
commit | 54971e43b9d6cb37366d2da64cc5a2d8f8102bc4 (patch) | |
tree | 69b963c2aa097e0fec371272dda3020e25bb3272 | |
parent | d9895571877e965a9f3e18a2a30611322099ae30 (diff) |
ARM64: kernel: acpi: refactor ACPI tables init and checks
Current ACPI init code on ARM64 relies on acpi_table_parse() API to
check if the FADT is present and to carry out sanity checks on that.
The handler passed to the acpi_table_parse() function and used to
carry out the parsing on the requested table returns a value that is
ignored by the acpi_table_parse() function, so it is not possible
to propagate errors back to the acpi_table_parse() caller through
the handler.
This forces ARM64 ACPI init code to have disable_acpi() calls scattered
all over the place that makes code unwieldy and not easy to follow.
This patch refactors the ARM64 ACPI init code, by creating a
self-contained function (ie acpi_fadt_sanity_check()) that carries
out the required checks on FADT and returns an adequate return value
to the caller. This allows creating a common error path that disables
ACPI and makes code more readable and easy to parse and change were
further checks FADT to be added in the future.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r-- | arch/arm64/kernel/acpi.c | 95 |
1 files changed, 59 insertions, 36 deletions
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c index a70f7141c0f6..172b7c9f6881 100644 --- a/arch/arm64/kernel/acpi.c +++ b/arch/arm64/kernel/acpi.c | |||
@@ -218,43 +218,60 @@ void __init acpi_init_cpus(void) | |||
218 | pr_info("%d CPUs enabled, %d CPUs total\n", enabled_cpus, total_cpus); | 218 | pr_info("%d CPUs enabled, %d CPUs total\n", enabled_cpus, total_cpus); |
219 | } | 219 | } |
220 | 220 | ||
221 | static int __init acpi_parse_fadt(struct acpi_table_header *table) | 221 | /* |
222 | * acpi_fadt_sanity_check() - Check FADT presence and carry out sanity | ||
223 | * checks on it | ||
224 | * | ||
225 | * Return 0 on success, <0 on failure | ||
226 | */ | ||
227 | static int __init acpi_fadt_sanity_check(void) | ||
222 | { | 228 | { |
223 | struct acpi_table_fadt *fadt = (struct acpi_table_fadt *)table; | 229 | struct acpi_table_header *table; |
230 | struct acpi_table_fadt *fadt; | ||
231 | acpi_status status; | ||
232 | acpi_size tbl_size; | ||
233 | int ret = 0; | ||
234 | |||
235 | /* | ||
236 | * FADT is required on arm64; retrieve it to check its presence | ||
237 | * and carry out revision and ACPI HW reduced compliancy tests | ||
238 | */ | ||
239 | status = acpi_get_table_with_size(ACPI_SIG_FADT, 0, &table, &tbl_size); | ||
240 | if (ACPI_FAILURE(status)) { | ||
241 | const char *msg = acpi_format_exception(status); | ||
242 | |||
243 | pr_err("Failed to get FADT table, %s\n", msg); | ||
244 | return -ENODEV; | ||
245 | } | ||
246 | |||
247 | fadt = (struct acpi_table_fadt *)table; | ||
224 | 248 | ||
225 | /* | 249 | /* |
226 | * Revision in table header is the FADT Major revision, and there | 250 | * Revision in table header is the FADT Major revision, and there |
227 | * is a minor revision of FADT which was introduced by ACPI 5.1, | 251 | * is a minor revision of FADT which was introduced by ACPI 5.1, |
228 | * we only deal with ACPI 5.1 or newer revision to get GIC and SMP | 252 | * we only deal with ACPI 5.1 or newer revision to get GIC and SMP |
229 | * boot protocol configuration data, or we will disable ACPI. | 253 | * boot protocol configuration data. |
230 | */ | 254 | */ |
231 | if (table->revision > 5 || | 255 | if (table->revision < 5 || |
232 | (table->revision == 5 && fadt->minor_revision >= 1)) { | 256 | (table->revision == 5 && fadt->minor_revision < 1)) { |
233 | if (!acpi_gbl_reduced_hardware) { | 257 | pr_err("Unsupported FADT revision %d.%d, should be 5.1+\n", |
234 | pr_err("Not hardware reduced ACPI mode, will not be supported\n"); | 258 | table->revision, fadt->minor_revision); |
235 | goto disable_acpi; | 259 | ret = -EINVAL; |
236 | } | 260 | goto out; |
237 | |||
238 | /* | ||
239 | * ACPI 5.1 only has two explicit methods to boot up SMP, | ||
240 | * PSCI and Parking protocol, but the Parking protocol is | ||
241 | * only specified for ARMv7 now, so make PSCI as the only | ||
242 | * way for the SMP boot protocol before some updates for | ||
243 | * the Parking protocol spec. | ||
244 | */ | ||
245 | if (acpi_psci_present()) | ||
246 | return 0; | ||
247 | |||
248 | pr_warn("No PSCI support, will not bring up secondary CPUs\n"); | ||
249 | return -EOPNOTSUPP; | ||
250 | } | 261 | } |
251 | 262 | ||
252 | pr_warn("Unsupported FADT revision %d.%d, should be 5.1+, will disable ACPI\n", | 263 | if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) { |
253 | table->revision, fadt->minor_revision); | 264 | pr_err("FADT not ACPI hardware reduced compliant\n"); |
265 | ret = -EINVAL; | ||
266 | } | ||
254 | 267 | ||
255 | disable_acpi: | 268 | out: |
256 | disable_acpi(); | 269 | /* |
257 | return -EINVAL; | 270 | * acpi_get_table_with_size() creates FADT table mapping that |
271 | * should be released after parsing and before resuming boot | ||
272 | */ | ||
273 | early_acpi_os_unmap_memory(table, tbl_size); | ||
274 | return ret; | ||
258 | } | 275 | } |
259 | 276 | ||
260 | /* | 277 | /* |
@@ -262,9 +279,13 @@ disable_acpi: | |||
262 | * 1. find RSDP and get its address, and then find XSDT | 279 | * 1. find RSDP and get its address, and then find XSDT |
263 | * 2. extract all tables and checksums them all | 280 | * 2. extract all tables and checksums them all |
264 | * 3. check ACPI FADT revision | 281 | * 3. check ACPI FADT revision |
282 | * 4. check ACPI FADT HW reduced flag | ||
265 | * | 283 | * |
266 | * We can parse ACPI boot-time tables such as MADT after | 284 | * We can parse ACPI boot-time tables such as MADT after |
267 | * this function is called. | 285 | * this function is called. |
286 | * | ||
287 | * ACPI is enabled on return if ACPI tables initialized and sanity checks | ||
288 | * passed, disabled otherwise | ||
268 | */ | 289 | */ |
269 | void __init acpi_boot_table_init(void) | 290 | void __init acpi_boot_table_init(void) |
270 | { | 291 | { |
@@ -278,18 +299,20 @@ void __init acpi_boot_table_init(void) | |||
278 | (!param_acpi_force && of_scan_flat_dt(dt_scan_depth1_nodes, NULL))) | 299 | (!param_acpi_force && of_scan_flat_dt(dt_scan_depth1_nodes, NULL))) |
279 | return; | 300 | return; |
280 | 301 | ||
302 | /* | ||
303 | * ACPI is disabled at this point. Enable it in order to parse | ||
304 | * the ACPI tables and carry out sanity checks | ||
305 | */ | ||
281 | enable_acpi(); | 306 | enable_acpi(); |
282 | 307 | ||
283 | /* Initialize the ACPI boot-time table parser. */ | 308 | /* |
284 | if (acpi_table_init()) { | 309 | * If ACPI tables are initialized and FADT sanity checks passed, |
285 | disable_acpi(); | 310 | * leave ACPI enabled and carry on booting; otherwise disable ACPI |
286 | return; | 311 | * on initialization error. |
287 | } | 312 | */ |
288 | 313 | if (acpi_table_init() || acpi_fadt_sanity_check()) { | |
289 | if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt)) { | 314 | pr_err("Failed to init ACPI tables\n"); |
290 | /* disable ACPI if no FADT is found */ | ||
291 | disable_acpi(); | 315 | disable_acpi(); |
292 | pr_err("Can't find FADT\n"); | ||
293 | } | 316 | } |
294 | } | 317 | } |
295 | 318 | ||