aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2012-02-14 05:31:56 -0500
committerLen Brown <len.brown@intel.com>2012-03-22 01:44:59 -0400
commitf7b004a17c9183f023796dea0d70284684ec000d (patch)
tree885f0b9b00d2592b3bb0ee90c7b1f74aaff5e9b3 /drivers/acpi/acpica
parentea143604c5c8426923bbed7cd389fdaed7d58a2e (diff)
ACPICA: Add acpi_os_physical_table_override interface
This interface allows the host to override a table via a physical address, instead of the logical address required by acpi_os_table_override. This simplifies the host implementation. Initial implementation by Thomas Renninger. ACPICA implementation creates a single function for table overrides that attempts both a logical and a physical override. Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Thomas Renninger <trenn@suse.de> Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/acpica')
-rw-r--r--drivers/acpi/acpica/actables.h5
-rw-r--r--drivers/acpi/acpica/tbinstal.c117
-rw-r--r--drivers/acpi/acpica/tbutils.c93
3 files changed, 152 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
68acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc); 68acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc);
69 69
70struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
71 *table_header,
72 struct acpi_table_desc
73 *table_desc);
74
70acpi_status 75acpi_status
71acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index); 76acpi_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
266struct 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
456acpi_tb_install_table(acpi_physical_address address, 456acpi_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/*******************************************************************************