diff options
-rw-r--r-- | drivers/acpi/acpica/actables.h | 5 | ||||
-rw-r--r-- | drivers/acpi/acpica/tbinstal.c | 117 | ||||
-rw-r--r-- | drivers/acpi/acpica/tbutils.c | 93 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 9 | ||||
-rw-r--r-- | include/acpi/acpiosxf.h | 5 |
5 files changed, 166 insertions, 63 deletions
diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index d5bec304c823..6712965ba8ae 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h | |||
@@ -67,6 +67,11 @@ acpi_status acpi_tb_resize_root_table_list(void); | |||
67 | 67 | ||
68 | acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc); | 68 | acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc); |
69 | 69 | ||
70 | struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header | ||
71 | *table_header, | ||
72 | struct acpi_table_desc | ||
73 | *table_desc); | ||
74 | |||
70 | acpi_status | 75 | acpi_status |
71 | acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index); | 76 | acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index); |
72 | 77 | ||
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 1aecf7baa4e0..c03500b4cc7a 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c | |||
@@ -114,7 +114,6 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) | |||
114 | { | 114 | { |
115 | u32 i; | 115 | u32 i; |
116 | acpi_status status = AE_OK; | 116 | acpi_status status = AE_OK; |
117 | struct acpi_table_header *override_table = NULL; | ||
118 | 117 | ||
119 | ACPI_FUNCTION_TRACE(tb_add_table); | 118 | ACPI_FUNCTION_TRACE(tb_add_table); |
120 | 119 | ||
@@ -224,25 +223,10 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) | |||
224 | /* | 223 | /* |
225 | * ACPI Table Override: | 224 | * ACPI Table Override: |
226 | * Allow the host to override dynamically loaded tables. | 225 | * Allow the host to override dynamically loaded tables. |
226 | * NOTE: the table is fully mapped at this point, and the mapping will | ||
227 | * be deleted by tb_table_override if the table is actually overridden. | ||
227 | */ | 228 | */ |
228 | status = acpi_os_table_override(table_desc->pointer, &override_table); | 229 | (void)acpi_tb_table_override(table_desc->pointer, table_desc); |
229 | if (ACPI_SUCCESS(status) && override_table) { | ||
230 | ACPI_INFO((AE_INFO, | ||
231 | "%4.4s @ 0x%p Table override, replaced with:", | ||
232 | table_desc->pointer->signature, | ||
233 | ACPI_CAST_PTR(void, table_desc->address))); | ||
234 | |||
235 | /* We can delete the table that was passed as a parameter */ | ||
236 | |||
237 | acpi_tb_delete_table(table_desc); | ||
238 | |||
239 | /* Setup descriptor for the new table */ | ||
240 | |||
241 | table_desc->address = ACPI_PTR_TO_PHYSADDR(override_table); | ||
242 | table_desc->pointer = override_table; | ||
243 | table_desc->length = override_table->length; | ||
244 | table_desc->flags = ACPI_TABLE_ORIGIN_OVERRIDE; | ||
245 | } | ||
246 | 230 | ||
247 | /* Add the table to the global root table list */ | 231 | /* Add the table to the global root table list */ |
248 | 232 | ||
@@ -263,6 +247,95 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) | |||
263 | 247 | ||
264 | /******************************************************************************* | 248 | /******************************************************************************* |
265 | * | 249 | * |
250 | * FUNCTION: acpi_tb_table_override | ||
251 | * | ||
252 | * PARAMETERS: table_header - Header for the original table | ||
253 | * table_desc - Table descriptor initialized for the | ||
254 | * original table. May or may not be mapped. | ||
255 | * | ||
256 | * RETURN: Pointer to the entire new table. NULL if table not overridden. | ||
257 | * If overridden, installs the new table within the input table | ||
258 | * descriptor. | ||
259 | * | ||
260 | * DESCRIPTION: Attempt table override by calling the OSL override functions. | ||
261 | * Note: If the table is overridden, then the entire new table | ||
262 | * is mapped and returned by this function. | ||
263 | * | ||
264 | ******************************************************************************/ | ||
265 | |||
266 | struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header | ||
267 | *table_header, | ||
268 | struct acpi_table_desc | ||
269 | *table_desc) | ||
270 | { | ||
271 | acpi_status status; | ||
272 | struct acpi_table_header *new_table = NULL; | ||
273 | acpi_physical_address new_address = 0; | ||
274 | u32 new_table_length = 0; | ||
275 | u8 new_flags; | ||
276 | char *override_type; | ||
277 | |||
278 | /* (1) Attempt logical override (returns a logical address) */ | ||
279 | |||
280 | status = acpi_os_table_override(table_header, &new_table); | ||
281 | if (ACPI_SUCCESS(status) && new_table) { | ||
282 | new_address = ACPI_PTR_TO_PHYSADDR(new_table); | ||
283 | new_table_length = new_table->length; | ||
284 | new_flags = ACPI_TABLE_ORIGIN_OVERRIDE; | ||
285 | override_type = "Logical"; | ||
286 | goto finish_override; | ||
287 | } | ||
288 | |||
289 | /* (2) Attempt physical override (returns a physical address) */ | ||
290 | |||
291 | status = acpi_os_physical_table_override(table_header, | ||
292 | &new_address, | ||
293 | &new_table_length); | ||
294 | if (ACPI_SUCCESS(status) && new_address && new_table_length) { | ||
295 | |||
296 | /* Map the entire new table */ | ||
297 | |||
298 | new_table = acpi_os_map_memory(new_address, new_table_length); | ||
299 | if (!new_table) { | ||
300 | ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, | ||
301 | "%4.4s %p Attempted physical table override failed", | ||
302 | table_header->signature, | ||
303 | ACPI_CAST_PTR(void, | ||
304 | table_desc->address))); | ||
305 | return (NULL); | ||
306 | } | ||
307 | |||
308 | override_type = "Physical"; | ||
309 | new_flags = ACPI_TABLE_ORIGIN_MAPPED; | ||
310 | goto finish_override; | ||
311 | } | ||
312 | |||
313 | return (NULL); /* There was no override */ | ||
314 | |||
315 | finish_override: | ||
316 | |||
317 | ACPI_INFO((AE_INFO, | ||
318 | "%4.4s %p %s table override, new table: %p", | ||
319 | table_header->signature, | ||
320 | ACPI_CAST_PTR(void, table_desc->address), | ||
321 | override_type, new_table)); | ||
322 | |||
323 | /* We can now unmap/delete the original table (if fully mapped) */ | ||
324 | |||
325 | acpi_tb_delete_table(table_desc); | ||
326 | |||
327 | /* Setup descriptor for the new table */ | ||
328 | |||
329 | table_desc->address = new_address; | ||
330 | table_desc->pointer = new_table; | ||
331 | table_desc->length = new_table_length; | ||
332 | table_desc->flags = new_flags; | ||
333 | |||
334 | return (new_table); | ||
335 | } | ||
336 | |||
337 | /******************************************************************************* | ||
338 | * | ||
266 | * FUNCTION: acpi_tb_resize_root_table_list | 339 | * FUNCTION: acpi_tb_resize_root_table_list |
267 | * | 340 | * |
268 | * PARAMETERS: None | 341 | * PARAMETERS: None |
@@ -396,7 +469,11 @@ void acpi_tb_delete_table(struct acpi_table_desc *table_desc) | |||
396 | case ACPI_TABLE_ORIGIN_ALLOCATED: | 469 | case ACPI_TABLE_ORIGIN_ALLOCATED: |
397 | ACPI_FREE(table_desc->pointer); | 470 | ACPI_FREE(table_desc->pointer); |
398 | break; | 471 | break; |
399 | default:; | 472 | |
473 | /* Not mapped or allocated, there is nothing we can do */ | ||
474 | |||
475 | default: | ||
476 | return; | ||
400 | } | 477 | } |
401 | 478 | ||
402 | table_desc->pointer = NULL; | 479 | table_desc->pointer = NULL; |
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 1347c084fc2b..0a706cac37de 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c | |||
@@ -446,7 +446,7 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index) | |||
446 | * RETURN: None | 446 | * RETURN: None |
447 | * | 447 | * |
448 | * DESCRIPTION: Install an ACPI table into the global data structure. The | 448 | * DESCRIPTION: Install an ACPI table into the global data structure. The |
449 | * table override mechanism is implemented here to allow the host | 449 | * table override mechanism is called to allow the host |
450 | * OS to replace any table before it is installed in the root | 450 | * OS to replace any table before it is installed in the root |
451 | * table array. | 451 | * table array. |
452 | * | 452 | * |
@@ -456,11 +456,9 @@ void | |||
456 | acpi_tb_install_table(acpi_physical_address address, | 456 | acpi_tb_install_table(acpi_physical_address address, |
457 | char *signature, u32 table_index) | 457 | char *signature, u32 table_index) |
458 | { | 458 | { |
459 | u8 flags; | 459 | struct acpi_table_header *table; |
460 | acpi_status status; | 460 | struct acpi_table_header *final_table; |
461 | struct acpi_table_header *table_to_install; | 461 | struct acpi_table_desc *table_desc; |
462 | struct acpi_table_header *mapped_table; | ||
463 | struct acpi_table_header *override_table = NULL; | ||
464 | 462 | ||
465 | if (!address) { | 463 | if (!address) { |
466 | ACPI_ERROR((AE_INFO, | 464 | ACPI_ERROR((AE_INFO, |
@@ -471,69 +469,78 @@ acpi_tb_install_table(acpi_physical_address address, | |||
471 | 469 | ||
472 | /* Map just the table header */ | 470 | /* Map just the table header */ |
473 | 471 | ||
474 | mapped_table = | 472 | table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); |
475 | acpi_os_map_memory(address, sizeof(struct acpi_table_header)); | 473 | if (!table) { |
476 | if (!mapped_table) { | 474 | ACPI_ERROR((AE_INFO, |
475 | "Could not map memory for table [%s] at %p", | ||
476 | signature, ACPI_CAST_PTR(void, address))); | ||
477 | return; | 477 | return; |
478 | } | 478 | } |
479 | 479 | ||
480 | /* If a particular signature is expected (DSDT/FACS), it must match */ | 480 | /* If a particular signature is expected (DSDT/FACS), it must match */ |
481 | 481 | ||
482 | if (signature && !ACPI_COMPARE_NAME(mapped_table->signature, signature)) { | 482 | if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) { |
483 | ACPI_ERROR((AE_INFO, | 483 | ACPI_ERROR((AE_INFO, |
484 | "Invalid signature 0x%X for ACPI table, expected [%s]", | 484 | "Invalid signature 0x%X for ACPI table, expected [%s]", |
485 | *ACPI_CAST_PTR(u32, mapped_table->signature), | 485 | *ACPI_CAST_PTR(u32, table->signature), signature)); |
486 | signature)); | ||
487 | goto unmap_and_exit; | 486 | goto unmap_and_exit; |
488 | } | 487 | } |
489 | 488 | ||
490 | /* | 489 | /* |
490 | * Initialize the table entry. Set the pointer to NULL, since the | ||
491 | * table is not fully mapped at this time. | ||
492 | */ | ||
493 | table_desc = &acpi_gbl_root_table_list.tables[table_index]; | ||
494 | |||
495 | table_desc->address = address; | ||
496 | table_desc->pointer = NULL; | ||
497 | table_desc->length = table->length; | ||
498 | table_desc->flags = ACPI_TABLE_ORIGIN_MAPPED; | ||
499 | ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature); | ||
500 | |||
501 | /* | ||
491 | * ACPI Table Override: | 502 | * ACPI Table Override: |
492 | * | 503 | * |
493 | * Before we install the table, let the host OS override it with a new | 504 | * Before we install the table, let the host OS override it with a new |
494 | * one if desired. Any table within the RSDT/XSDT can be replaced, | 505 | * one if desired. Any table within the RSDT/XSDT can be replaced, |
495 | * including the DSDT which is pointed to by the FADT. | 506 | * including the DSDT which is pointed to by the FADT. |
507 | * | ||
508 | * NOTE: If the table is overridden, then final_table will contain a | ||
509 | * mapped pointer to the full new table. If the table is not overridden, | ||
510 | * or if there has been a physical override, then the table will be | ||
511 | * fully mapped later (in verify table). In any case, we must | ||
512 | * unmap the header that was mapped above. | ||
496 | */ | 513 | */ |
497 | status = acpi_os_table_override(mapped_table, &override_table); | 514 | final_table = acpi_tb_table_override(table, table_desc); |
498 | if (ACPI_SUCCESS(status) && override_table) { | 515 | if (!final_table) { |
499 | ACPI_INFO((AE_INFO, | 516 | final_table = table; /* There was no override */ |
500 | "%4.4s @ 0x%p Table override, replaced with:", | ||
501 | mapped_table->signature, ACPI_CAST_PTR(void, | ||
502 | address))); | ||
503 | |||
504 | acpi_gbl_root_table_list.tables[table_index].pointer = | ||
505 | override_table; | ||
506 | address = ACPI_PTR_TO_PHYSADDR(override_table); | ||
507 | |||
508 | table_to_install = override_table; | ||
509 | flags = ACPI_TABLE_ORIGIN_OVERRIDE; | ||
510 | } else { | ||
511 | table_to_install = mapped_table; | ||
512 | flags = ACPI_TABLE_ORIGIN_MAPPED; | ||
513 | } | 517 | } |
514 | 518 | ||
515 | /* Initialize the table entry */ | 519 | acpi_tb_print_table_header(table_desc->address, final_table); |
516 | 520 | ||
517 | acpi_gbl_root_table_list.tables[table_index].address = address; | 521 | /* Set the global integer width (based upon revision of the DSDT) */ |
518 | acpi_gbl_root_table_list.tables[table_index].length = | ||
519 | table_to_install->length; | ||
520 | acpi_gbl_root_table_list.tables[table_index].flags = flags; | ||
521 | |||
522 | ACPI_MOVE_32_TO_32(& | ||
523 | (acpi_gbl_root_table_list.tables[table_index]. | ||
524 | signature), table_to_install->signature); | ||
525 | |||
526 | acpi_tb_print_table_header(address, table_to_install); | ||
527 | 522 | ||
528 | if (table_index == ACPI_TABLE_INDEX_DSDT) { | 523 | if (table_index == ACPI_TABLE_INDEX_DSDT) { |
524 | acpi_ut_set_integer_width(final_table->revision); | ||
525 | } | ||
529 | 526 | ||
530 | /* Global integer width is based upon revision of the DSDT */ | 527 | /* |
531 | 528 | * If we have a physical override during this early loading of the ACPI | |
532 | acpi_ut_set_integer_width(table_to_install->revision); | 529 | * tables, unmap the table for now. It will be mapped again later when |
530 | * it is actually used. This supports very early loading of ACPI tables, | ||
531 | * before virtual memory is fully initialized and running within the | ||
532 | * host OS. Note: A logical override has the ACPI_TABLE_ORIGIN_OVERRIDE | ||
533 | * flag set and will not be deleted below. | ||
534 | */ | ||
535 | if (final_table != table) { | ||
536 | acpi_tb_delete_table(table_desc); | ||
533 | } | 537 | } |
534 | 538 | ||
535 | unmap_and_exit: | 539 | unmap_and_exit: |
536 | acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header)); | 540 | |
541 | /* Always unmap the table header that we mapped above */ | ||
542 | |||
543 | acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); | ||
537 | } | 544 | } |
538 | 545 | ||
539 | /******************************************************************************* | 546 | /******************************************************************************* |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 1dea025e4e98..07d426425b59 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -554,6 +554,15 @@ acpi_os_table_override(struct acpi_table_header * existing_table, | |||
554 | return AE_OK; | 554 | return AE_OK; |
555 | } | 555 | } |
556 | 556 | ||
557 | acpi_status | ||
558 | acpi_os_physical_table_override(struct acpi_table_header *existing_table, | ||
559 | acpi_physical_address * new_address, | ||
560 | u32 *new_table_length) | ||
561 | { | ||
562 | return AE_SUPPORT; | ||
563 | } | ||
564 | |||
565 | |||
557 | static irqreturn_t acpi_irq(int irq, void *dev_id) | 566 | static irqreturn_t acpi_irq(int irq, void *dev_id) |
558 | { | 567 | { |
559 | u32 handled; | 568 | u32 handled; |
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index 1cd22045fbd4..21a5548c6686 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h | |||
@@ -95,6 +95,11 @@ acpi_status | |||
95 | acpi_os_table_override(struct acpi_table_header *existing_table, | 95 | acpi_os_table_override(struct acpi_table_header *existing_table, |
96 | struct acpi_table_header **new_table); | 96 | struct acpi_table_header **new_table); |
97 | 97 | ||
98 | acpi_status | ||
99 | acpi_os_physical_table_override(struct acpi_table_header *existing_table, | ||
100 | acpi_physical_address * new_address, | ||
101 | u32 *new_table_length); | ||
102 | |||
98 | /* | 103 | /* |
99 | * Spinlock primitives | 104 | * Spinlock primitives |
100 | */ | 105 | */ |