diff options
Diffstat (limited to 'drivers/acpi/tables')
-rw-r--r-- | drivers/acpi/tables/tbfadt.c | 32 | ||||
-rw-r--r-- | drivers/acpi/tables/tbinstal.c | 61 |
2 files changed, 75 insertions, 18 deletions
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c index a4a41ba2484b..2c7885e7ffba 100644 --- a/drivers/acpi/tables/tbfadt.c +++ b/drivers/acpi/tables/tbfadt.c | |||
@@ -50,7 +50,7 @@ ACPI_MODULE_NAME("tbfadt") | |||
50 | /* Local prototypes */ | 50 | /* Local prototypes */ |
51 | static void inline | 51 | static void inline |
52 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, | 52 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, |
53 | u8 bit_width, u64 address); | 53 | u8 byte_width, u64 address); |
54 | 54 | ||
55 | static void acpi_tb_convert_fadt(void); | 55 | static void acpi_tb_convert_fadt(void); |
56 | 56 | ||
@@ -111,7 +111,7 @@ static struct acpi_fadt_info fadt_info_table[] = { | |||
111 | * FUNCTION: acpi_tb_init_generic_address | 111 | * FUNCTION: acpi_tb_init_generic_address |
112 | * | 112 | * |
113 | * PARAMETERS: generic_address - GAS struct to be initialized | 113 | * PARAMETERS: generic_address - GAS struct to be initialized |
114 | * bit_width - Width of this register | 114 | * byte_width - Width of this register |
115 | * Address - Address of the register | 115 | * Address - Address of the register |
116 | * | 116 | * |
117 | * RETURN: None | 117 | * RETURN: None |
@@ -124,7 +124,7 @@ static struct acpi_fadt_info fadt_info_table[] = { | |||
124 | 124 | ||
125 | static void inline | 125 | static void inline |
126 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, | 126 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, |
127 | u8 bit_width, u64 address) | 127 | u8 byte_width, u64 address) |
128 | { | 128 | { |
129 | 129 | ||
130 | /* | 130 | /* |
@@ -136,7 +136,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, | |||
136 | /* All other fields are byte-wide */ | 136 | /* All other fields are byte-wide */ |
137 | 137 | ||
138 | generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO; | 138 | generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO; |
139 | generic_address->bit_width = bit_width; | 139 | generic_address->bit_width = byte_width << 3; |
140 | generic_address->bit_offset = 0; | 140 | generic_address->bit_offset = 0; |
141 | generic_address->access_width = 0; | 141 | generic_address->access_width = 0; |
142 | } | 142 | } |
@@ -342,9 +342,20 @@ static void acpi_tb_convert_fadt(void) | |||
342 | * useful to calculate them once, here. | 342 | * useful to calculate them once, here. |
343 | * | 343 | * |
344 | * The PM event blocks are split into two register blocks, first is the | 344 | * The PM event blocks are split into two register blocks, first is the |
345 | * PM Status Register block, followed immediately by the PM Enable Register | 345 | * PM Status Register block, followed immediately by the PM Enable |
346 | * block. Each is of length (pm1_event_length/2) | 346 | * Register block. Each is of length (xpm1x_event_block.bit_width/2). |
347 | * | ||
348 | * On various systems the v2 fields (and particularly the bit widths) | ||
349 | * cannot be relied upon, though. Hence resort to using the v1 length | ||
350 | * here (and warn about the inconsistency). | ||
347 | */ | 351 | */ |
352 | if (acpi_gbl_FADT.xpm1a_event_block.bit_width | ||
353 | != acpi_gbl_FADT.pm1_event_length * 8) | ||
354 | printk(KERN_WARNING "FADT: " | ||
355 | "X_PM1a_EVT_BLK.bit_width (%u) does not match" | ||
356 | " PM1_EVT_LEN (%u)\n", | ||
357 | acpi_gbl_FADT.xpm1a_event_block.bit_width, | ||
358 | acpi_gbl_FADT.pm1_event_length); | ||
348 | pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length); | 359 | pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length); |
349 | 360 | ||
350 | /* The PM1A register block is required */ | 361 | /* The PM1A register block is required */ |
@@ -360,13 +371,20 @@ static void acpi_tb_convert_fadt(void) | |||
360 | /* The PM1B register block is optional, ignore if not present */ | 371 | /* The PM1B register block is optional, ignore if not present */ |
361 | 372 | ||
362 | if (acpi_gbl_FADT.xpm1b_event_block.address) { | 373 | if (acpi_gbl_FADT.xpm1b_event_block.address) { |
374 | if (acpi_gbl_FADT.xpm1b_event_block.bit_width | ||
375 | != acpi_gbl_FADT.pm1_event_length * 8) | ||
376 | printk(KERN_WARNING "FADT: " | ||
377 | "X_PM1b_EVT_BLK.bit_width (%u) does not match" | ||
378 | " PM1_EVT_LEN (%u)\n", | ||
379 | acpi_gbl_FADT.xpm1b_event_block.bit_width, | ||
380 | acpi_gbl_FADT.pm1_event_length); | ||
363 | acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, | 381 | acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, |
364 | pm1_register_length, | 382 | pm1_register_length, |
365 | (acpi_gbl_FADT.xpm1b_event_block. | 383 | (acpi_gbl_FADT.xpm1b_event_block. |
366 | address + pm1_register_length)); | 384 | address + pm1_register_length)); |
367 | /* Don't forget to copy space_id of the GAS */ | 385 | /* Don't forget to copy space_id of the GAS */ |
368 | acpi_gbl_xpm1b_enable.space_id = | 386 | acpi_gbl_xpm1b_enable.space_id = |
369 | acpi_gbl_FADT.xpm1a_event_block.space_id; | 387 | acpi_gbl_FADT.xpm1b_event_block.space_id; |
370 | 388 | ||
371 | } | 389 | } |
372 | } | 390 | } |
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index b22185f55a16..18747ce8dd2f 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c | |||
@@ -110,7 +110,6 @@ acpi_status | |||
110 | acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) | 110 | acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) |
111 | { | 111 | { |
112 | u32 i; | 112 | u32 i; |
113 | u32 length; | ||
114 | acpi_status status = AE_OK; | 113 | acpi_status status = AE_OK; |
115 | 114 | ||
116 | ACPI_FUNCTION_TRACE(tb_add_table); | 115 | ACPI_FUNCTION_TRACE(tb_add_table); |
@@ -145,25 +144,64 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) | |||
145 | } | 144 | } |
146 | } | 145 | } |
147 | 146 | ||
148 | length = ACPI_MIN(table_desc->length, | 147 | /* |
149 | acpi_gbl_root_table_list.tables[i].length); | 148 | * Check for a table match on the entire table length, |
149 | * not just the header. | ||
150 | */ | ||
151 | if (table_desc->length != | ||
152 | acpi_gbl_root_table_list.tables[i].length) { | ||
153 | continue; | ||
154 | } | ||
155 | |||
150 | if (ACPI_MEMCMP(table_desc->pointer, | 156 | if (ACPI_MEMCMP(table_desc->pointer, |
151 | acpi_gbl_root_table_list.tables[i].pointer, | 157 | acpi_gbl_root_table_list.tables[i].pointer, |
152 | length)) { | 158 | acpi_gbl_root_table_list.tables[i].length)) { |
153 | continue; | 159 | continue; |
154 | } | 160 | } |
155 | 161 | ||
156 | /* Table is already registered */ | 162 | /* |
157 | 163 | * Note: the current mechanism does not unregister a table if it is | |
164 | * dynamically unloaded. The related namespace entries are deleted, | ||
165 | * but the table remains in the root table list. | ||
166 | * | ||
167 | * The assumption here is that the number of different tables that | ||
168 | * will be loaded is actually small, and there is minimal overhead | ||
169 | * in just keeping the table in case it is needed again. | ||
170 | * | ||
171 | * If this assumption changes in the future (perhaps on large | ||
172 | * machines with many table load/unload operations), tables will | ||
173 | * need to be unregistered when they are unloaded, and slots in the | ||
174 | * root table list should be reused when empty. | ||
175 | */ | ||
176 | |||
177 | /* | ||
178 | * Table is already registered. | ||
179 | * We can delete the table that was passed as a parameter. | ||
180 | */ | ||
158 | acpi_tb_delete_table(table_desc); | 181 | acpi_tb_delete_table(table_desc); |
159 | *table_index = i; | 182 | *table_index = i; |
160 | status = AE_ALREADY_EXISTS; | 183 | |
161 | goto release; | 184 | if (acpi_gbl_root_table_list.tables[i]. |
185 | flags & ACPI_TABLE_IS_LOADED) { | ||
186 | |||
187 | /* Table is still loaded, this is an error */ | ||
188 | |||
189 | status = AE_ALREADY_EXISTS; | ||
190 | goto release; | ||
191 | } else { | ||
192 | /* Table was unloaded, allow it to be reloaded */ | ||
193 | |||
194 | table_desc->pointer = | ||
195 | acpi_gbl_root_table_list.tables[i].pointer; | ||
196 | table_desc->address = | ||
197 | acpi_gbl_root_table_list.tables[i].address; | ||
198 | status = AE_OK; | ||
199 | goto print_header; | ||
200 | } | ||
162 | } | 201 | } |
163 | 202 | ||
164 | /* | 203 | /* Add the table to the global root table list */ |
165 | * Add the table to the global table list | 204 | |
166 | */ | ||
167 | status = acpi_tb_store_table(table_desc->address, table_desc->pointer, | 205 | status = acpi_tb_store_table(table_desc->address, table_desc->pointer, |
168 | table_desc->length, table_desc->flags, | 206 | table_desc->length, table_desc->flags, |
169 | table_index); | 207 | table_index); |
@@ -171,6 +209,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) | |||
171 | goto release; | 209 | goto release; |
172 | } | 210 | } |
173 | 211 | ||
212 | print_header: | ||
174 | acpi_tb_print_table_header(table_desc->address, table_desc->pointer); | 213 | acpi_tb_print_table_header(table_desc->address, table_desc->pointer); |
175 | 214 | ||
176 | release: | 215 | release: |