diff options
| -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 | ||
