summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/tbinstal.c
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2014-04-04 06:38:26 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-04-20 22:59:38 +0200
commitdc156adf0d1b9d9ea54a86ca803ac5202ab139c7 (patch)
treefd87853be65ce947c2f3aa01b3dfec7743a9f031 /drivers/acpi/acpica/tbinstal.c
parentACPICA: Remove indent divergences to reduce maintenance overhead. (diff)
downloadlinux-dc156adf0d1b9d9ea54a86ca803ac5202ab139c7.tar.xz
linux-dc156adf0d1b9d9ea54a86ca803ac5202ab139c7.zip
ACPICA: Tables: Fix the issues in handling virtual addressed tables.
When table is overridden or reloaded, acpi_tb_delete_table() is called where struct acpi_table_desc.Pointer will be NULL. It thus is impossible for virtual addressed tables to obtain the .Pointer again in acpi_tb_verify_table(). This patch stores virtual table addresses (ACPI_TABLE_ORIGIN_ALLOCATED, ACPI_TABLE_ORIGIN_UNKNOWN, ACPI_TABLE_ORIGIN_OVERRIDE) in the struct acpi_table_desc.Address field and refills the struct acpi_table_desc.Pointer using these addresses in acpi_tb_verify_table(). Note that if a table with ACPI_TABLE_ORIGIN_ALLOCATED set is actually freed, the .Address field should be invalidated and thus must be replaced with NULL to avoid wrong future validations occuring in acpi_tb_verify_table(). Signed-off-by: Lv Zheng <lv.zheng@intel.com> Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/acpica/tbinstal.c')
-rw-r--r--drivers/acpi/acpica/tbinstal.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c
index 73fffb0f3dd3..144076ac21f0 100644
--- a/drivers/acpi/acpica/tbinstal.c
+++ b/drivers/acpi/acpica/tbinstal.c
@@ -69,11 +69,26 @@ acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
/* Map the table if necessary */
if (!table_desc->pointer) {
- if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
- ACPI_TABLE_ORIGIN_MAPPED) {
+ switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
+ case ACPI_TABLE_ORIGIN_MAPPED:
+
table_desc->pointer =
acpi_os_map_memory(table_desc->address,
table_desc->length);
+ break;
+
+ case ACPI_TABLE_ORIGIN_ALLOCATED:
+ case ACPI_TABLE_ORIGIN_UNKNOWN:
+ case ACPI_TABLE_ORIGIN_OVERRIDE:
+
+ table_desc->pointer =
+ ACPI_CAST_PTR(struct acpi_table_header,
+ table_desc->address);
+ break;
+
+ default:
+
+ break;
}
if (!table_desc->pointer) {
@@ -476,6 +491,7 @@ void acpi_tb_delete_table(struct acpi_table_desc *table_desc)
case ACPI_TABLE_ORIGIN_ALLOCATED:
ACPI_FREE(table_desc->pointer);
+ table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL);
break;
/* Not mapped or allocated, there is nothing we can do */