diff options
Diffstat (limited to 'drivers/acpi/tables/tbinstal.c')
-rw-r--r-- | drivers/acpi/tables/tbinstal.c | 664 |
1 files changed, 326 insertions, 338 deletions
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 1668a232fb67..0e7b121a99ce 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2006, R. Byron Moore | 8 | * Copyright (C) 2000 - 2007, R. Byron Moore |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -42,510 +42,498 @@ | |||
42 | */ | 42 | */ |
43 | 43 | ||
44 | #include <acpi/acpi.h> | 44 | #include <acpi/acpi.h> |
45 | #include <acpi/acnamesp.h> | ||
45 | #include <acpi/actables.h> | 46 | #include <acpi/actables.h> |
46 | 47 | ||
47 | #define _COMPONENT ACPI_TABLES | 48 | #define _COMPONENT ACPI_TABLES |
48 | ACPI_MODULE_NAME("tbinstal") | 49 | ACPI_MODULE_NAME("tbinstal") |
49 | 50 | ||
50 | /* Local prototypes */ | 51 | /****************************************************************************** |
51 | static acpi_status | ||
52 | acpi_tb_match_signature(char *signature, | ||
53 | struct acpi_table_desc *table_info, u8 search_type); | ||
54 | |||
55 | /******************************************************************************* | ||
56 | * | 52 | * |
57 | * FUNCTION: acpi_tb_match_signature | 53 | * FUNCTION: acpi_tb_verify_table |
58 | * | 54 | * |
59 | * PARAMETERS: Signature - Table signature to match | 55 | * PARAMETERS: table_desc - table |
60 | * table_info - Return data | ||
61 | * search_type - Table type to match (primary/secondary) | ||
62 | * | 56 | * |
63 | * RETURN: Status | 57 | * RETURN: Status |
64 | * | 58 | * |
65 | * DESCRIPTION: Compare signature against the list of "ACPI-subsystem-owned" | 59 | * DESCRIPTION: this function is called to verify and map table |
66 | * tables (DSDT/FADT/SSDT, etc.) Returns the table_type_iD on match. | ||
67 | * | 60 | * |
68 | ******************************************************************************/ | 61 | *****************************************************************************/ |
69 | 62 | acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) | |
70 | static acpi_status | ||
71 | acpi_tb_match_signature(char *signature, | ||
72 | struct acpi_table_desc *table_info, u8 search_type) | ||
73 | { | 63 | { |
74 | acpi_native_uint i; | 64 | acpi_status status = AE_OK; |
75 | 65 | ||
76 | ACPI_FUNCTION_TRACE(tb_match_signature); | 66 | ACPI_FUNCTION_TRACE(tb_verify_table); |
77 | 67 | ||
78 | /* Search for a signature match among the known table types */ | 68 | /* Map the table if necessary */ |
79 | 69 | ||
80 | for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) { | 70 | if (!table_desc->pointer) { |
81 | if (!(acpi_gbl_table_data[i].flags & search_type)) { | 71 | if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == |
82 | continue; | 72 | ACPI_TABLE_ORIGIN_MAPPED) { |
73 | table_desc->pointer = | ||
74 | acpi_os_map_memory(table_desc->address, | ||
75 | table_desc->length); | ||
83 | } | 76 | } |
77 | if (!table_desc->pointer) { | ||
78 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
79 | } | ||
80 | } | ||
84 | 81 | ||
85 | if (!ACPI_STRNCMP(signature, acpi_gbl_table_data[i].signature, | 82 | /* FACS is the odd table, has no standard ACPI header and no checksum */ |
86 | acpi_gbl_table_data[i].sig_length)) { | ||
87 | |||
88 | /* Found a signature match, return index if requested */ | ||
89 | 83 | ||
90 | if (table_info) { | 84 | if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) { |
91 | table_info->type = (u8) i; | ||
92 | } | ||
93 | 85 | ||
94 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 86 | /* Always calculate checksum, ignore bad checksum if requested */ |
95 | "Table [%4.4s] is an ACPI table consumed by the core subsystem\n", | ||
96 | (char *)acpi_gbl_table_data[i]. | ||
97 | signature)); | ||
98 | 87 | ||
99 | return_ACPI_STATUS(AE_OK); | 88 | status = |
100 | } | 89 | acpi_tb_verify_checksum(table_desc->pointer, |
90 | table_desc->length); | ||
101 | } | 91 | } |
102 | 92 | ||
103 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 93 | return_ACPI_STATUS(status); |
104 | "Table [%4.4s] is not an ACPI table consumed by the core subsystem - ignored\n", | ||
105 | (char *)signature)); | ||
106 | |||
107 | return_ACPI_STATUS(AE_TABLE_NOT_SUPPORTED); | ||
108 | } | 94 | } |
109 | 95 | ||
110 | /******************************************************************************* | 96 | /******************************************************************************* |
111 | * | 97 | * |
112 | * FUNCTION: acpi_tb_install_table | 98 | * FUNCTION: acpi_tb_add_table |
113 | * | 99 | * |
114 | * PARAMETERS: table_info - Return value from acpi_tb_get_table_body | 100 | * PARAMETERS: table_desc - Table descriptor |
101 | * table_index - Where the table index is returned | ||
115 | * | 102 | * |
116 | * RETURN: Status | 103 | * RETURN: Status |
117 | * | 104 | * |
118 | * DESCRIPTION: Install the table into the global data structures. | 105 | * DESCRIPTION: This function is called to add the ACPI table |
119 | * | 106 | * |
120 | ******************************************************************************/ | 107 | ******************************************************************************/ |
121 | 108 | ||
122 | acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info) | 109 | acpi_status |
110 | acpi_tb_add_table(struct acpi_table_desc *table_desc, | ||
111 | acpi_native_uint * table_index) | ||
123 | { | 112 | { |
124 | acpi_status status; | 113 | acpi_native_uint i; |
125 | 114 | acpi_native_uint length; | |
126 | ACPI_FUNCTION_TRACE(tb_install_table); | 115 | acpi_status status = AE_OK; |
127 | 116 | ||
128 | /* Lock tables while installing */ | 117 | ACPI_FUNCTION_TRACE(tb_add_table); |
129 | 118 | ||
130 | status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | 119 | if (!table_desc->pointer) { |
131 | if (ACPI_FAILURE(status)) { | 120 | status = acpi_tb_verify_table(table_desc); |
132 | ACPI_EXCEPTION((AE_INFO, status, | 121 | if (ACPI_FAILURE(status) || !table_desc->pointer) { |
133 | "Could not acquire table mutex")); | 122 | return_ACPI_STATUS(status); |
134 | return_ACPI_STATUS(status); | 123 | } |
135 | } | 124 | } |
136 | 125 | ||
137 | /* | 126 | /* The table must be either an SSDT or a PSDT */ |
138 | * Ignore a table that is already installed. For example, some BIOS | 127 | |
139 | * ASL code will repeatedly attempt to load the same SSDT. | 128 | if ((!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)) |
140 | */ | 129 | && |
141 | status = acpi_tb_is_table_installed(table_info); | 130 | (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT))) |
142 | if (ACPI_FAILURE(status)) { | 131 | { |
143 | goto unlock_and_exit; | 132 | ACPI_ERROR((AE_INFO, |
133 | "Table has invalid signature [%4.4s], must be SSDT or PSDT", | ||
134 | table_desc->pointer->signature)); | ||
135 | return_ACPI_STATUS(AE_BAD_SIGNATURE); | ||
144 | } | 136 | } |
145 | 137 | ||
146 | /* Install the table into the global data structure */ | 138 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
139 | |||
140 | /* Check if table is already registered */ | ||
141 | |||
142 | for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { | ||
143 | if (!acpi_gbl_root_table_list.tables[i].pointer) { | ||
144 | status = | ||
145 | acpi_tb_verify_table(&acpi_gbl_root_table_list. | ||
146 | tables[i]); | ||
147 | if (ACPI_FAILURE(status) | ||
148 | || !acpi_gbl_root_table_list.tables[i].pointer) { | ||
149 | continue; | ||
150 | } | ||
151 | } | ||
152 | |||
153 | length = ACPI_MIN(table_desc->length, | ||
154 | acpi_gbl_root_table_list.tables[i].length); | ||
155 | if (ACPI_MEMCMP(table_desc->pointer, | ||
156 | acpi_gbl_root_table_list.tables[i].pointer, | ||
157 | length)) { | ||
158 | continue; | ||
159 | } | ||
160 | |||
161 | /* Table is already registered */ | ||
162 | |||
163 | acpi_tb_delete_table(table_desc); | ||
164 | *table_index = i; | ||
165 | goto release; | ||
166 | } | ||
147 | 167 | ||
148 | status = acpi_tb_init_table_descriptor(table_info->type, table_info); | 168 | /* |
169 | * Add the table to the global table list | ||
170 | */ | ||
171 | status = acpi_tb_store_table(table_desc->address, table_desc->pointer, | ||
172 | table_desc->length, table_desc->flags, | ||
173 | table_index); | ||
149 | if (ACPI_FAILURE(status)) { | 174 | if (ACPI_FAILURE(status)) { |
150 | ACPI_EXCEPTION((AE_INFO, status, | 175 | goto release; |
151 | "Could not install table [%4.4s]", | ||
152 | table_info->pointer->signature)); | ||
153 | } | 176 | } |
154 | 177 | ||
155 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s located at %p\n", | 178 | acpi_tb_print_table_header(table_desc->address, table_desc->pointer); |
156 | acpi_gbl_table_data[table_info->type].name, | ||
157 | table_info->pointer)); | ||
158 | 179 | ||
159 | unlock_and_exit: | 180 | release: |
160 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 181 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
161 | return_ACPI_STATUS(status); | 182 | return_ACPI_STATUS(status); |
162 | } | 183 | } |
163 | 184 | ||
164 | /******************************************************************************* | 185 | /******************************************************************************* |
165 | * | 186 | * |
166 | * FUNCTION: acpi_tb_recognize_table | 187 | * FUNCTION: acpi_tb_resize_root_table_list |
167 | * | 188 | * |
168 | * PARAMETERS: table_info - Return value from acpi_tb_get_table_body | 189 | * PARAMETERS: None |
169 | * search_type - Table type to match (primary/secondary) | ||
170 | * | 190 | * |
171 | * RETURN: Status | 191 | * RETURN: Status |
172 | * | 192 | * |
173 | * DESCRIPTION: Check a table signature for a match against known table types | 193 | * DESCRIPTION: Expand the size of global table array |
174 | * | ||
175 | * NOTE: All table pointers are validated as follows: | ||
176 | * 1) Table pointer must point to valid physical memory | ||
177 | * 2) Signature must be 4 ASCII chars, even if we don't recognize the | ||
178 | * name | ||
179 | * 3) Table must be readable for length specified in the header | ||
180 | * 4) Table checksum must be valid (with the exception of the FACS | ||
181 | * which has no checksum for some odd reason) | ||
182 | * | 194 | * |
183 | ******************************************************************************/ | 195 | ******************************************************************************/ |
184 | 196 | ||
185 | acpi_status | 197 | acpi_status acpi_tb_resize_root_table_list(void) |
186 | acpi_tb_recognize_table(struct acpi_table_desc *table_info, u8 search_type) | ||
187 | { | 198 | { |
188 | struct acpi_table_header *table_header; | 199 | struct acpi_table_desc *tables; |
189 | acpi_status status; | ||
190 | 200 | ||
191 | ACPI_FUNCTION_TRACE(tb_recognize_table); | 201 | ACPI_FUNCTION_TRACE(tb_resize_root_table_list); |
192 | 202 | ||
193 | /* Ensure that we have a valid table pointer */ | 203 | /* allow_resize flag is a parameter to acpi_initialize_tables */ |
194 | 204 | ||
195 | table_header = (struct acpi_table_header *)table_info->pointer; | 205 | if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) { |
196 | if (!table_header) { | 206 | ACPI_ERROR((AE_INFO, |
197 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 207 | "Resize of Root Table Array is not allowed")); |
208 | return_ACPI_STATUS(AE_SUPPORT); | ||
198 | } | 209 | } |
199 | 210 | ||
200 | /* | 211 | /* Increase the Table Array size */ |
201 | * We only "recognize" a limited number of ACPI tables -- namely, the | 212 | |
202 | * ones that are used by the subsystem (DSDT, FADT, etc.) | 213 | tables = ACPI_ALLOCATE_ZEROED((acpi_gbl_root_table_list.size + |
203 | * | 214 | ACPI_ROOT_TABLE_SIZE_INCREMENT) |
204 | * An AE_TABLE_NOT_SUPPORTED means that the table was not recognized. | 215 | * sizeof(struct acpi_table_desc)); |
205 | * This can be any one of many valid ACPI tables, it just isn't one of | 216 | if (!tables) { |
206 | * the tables that is consumed by the core subsystem | 217 | ACPI_ERROR((AE_INFO, |
207 | */ | 218 | "Could not allocate new root table array")); |
208 | status = acpi_tb_match_signature(table_header->signature, | 219 | return_ACPI_STATUS(AE_NO_MEMORY); |
209 | table_info, search_type); | ||
210 | if (ACPI_FAILURE(status)) { | ||
211 | return_ACPI_STATUS(status); | ||
212 | } | 220 | } |
213 | 221 | ||
214 | status = acpi_tb_validate_table_header(table_header); | 222 | /* Copy and free the previous table array */ |
215 | if (ACPI_FAILURE(status)) { | 223 | |
216 | return_ACPI_STATUS(status); | 224 | if (acpi_gbl_root_table_list.tables) { |
225 | ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, | ||
226 | acpi_gbl_root_table_list.size * | ||
227 | sizeof(struct acpi_table_desc)); | ||
228 | |||
229 | if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { | ||
230 | ACPI_FREE(acpi_gbl_root_table_list.tables); | ||
231 | } | ||
217 | } | 232 | } |
218 | 233 | ||
219 | /* Return the table type and length via the info struct */ | 234 | acpi_gbl_root_table_list.tables = tables; |
235 | acpi_gbl_root_table_list.size += ACPI_ROOT_TABLE_SIZE_INCREMENT; | ||
236 | acpi_gbl_root_table_list.flags |= (u8) ACPI_ROOT_ORIGIN_ALLOCATED; | ||
220 | 237 | ||
221 | table_info->length = (acpi_size) table_header->length; | 238 | return_ACPI_STATUS(AE_OK); |
222 | return_ACPI_STATUS(status); | ||
223 | } | 239 | } |
224 | 240 | ||
225 | /******************************************************************************* | 241 | /******************************************************************************* |
226 | * | 242 | * |
227 | * FUNCTION: acpi_tb_init_table_descriptor | 243 | * FUNCTION: acpi_tb_store_table |
228 | * | 244 | * |
229 | * PARAMETERS: table_type - The type of the table | 245 | * PARAMETERS: Address - Table address |
230 | * table_info - A table info struct | 246 | * Table - Table header |
247 | * Length - Table length | ||
248 | * Flags - flags | ||
231 | * | 249 | * |
232 | * RETURN: None. | 250 | * RETURN: Status and table index. |
233 | * | 251 | * |
234 | * DESCRIPTION: Install a table into the global data structs. | 252 | * DESCRIPTION: Add an ACPI table to the global table list |
235 | * | 253 | * |
236 | ******************************************************************************/ | 254 | ******************************************************************************/ |
237 | 255 | ||
238 | acpi_status | 256 | acpi_status |
239 | acpi_tb_init_table_descriptor(acpi_table_type table_type, | 257 | acpi_tb_store_table(acpi_physical_address address, |
240 | struct acpi_table_desc *table_info) | 258 | struct acpi_table_header *table, |
259 | u32 length, u8 flags, acpi_native_uint * table_index) | ||
241 | { | 260 | { |
242 | struct acpi_table_list *list_head; | 261 | acpi_status status = AE_OK; |
243 | struct acpi_table_desc *table_desc; | ||
244 | acpi_status status; | ||
245 | |||
246 | ACPI_FUNCTION_TRACE_U32(tb_init_table_descriptor, table_type); | ||
247 | 262 | ||
248 | /* Allocate a descriptor for this table */ | 263 | /* Ensure that there is room for the table in the Root Table List */ |
249 | 264 | ||
250 | table_desc = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc)); | 265 | if (acpi_gbl_root_table_list.count >= acpi_gbl_root_table_list.size) { |
251 | if (!table_desc) { | 266 | status = acpi_tb_resize_root_table_list(); |
252 | return_ACPI_STATUS(AE_NO_MEMORY); | 267 | if (ACPI_FAILURE(status)) { |
268 | return (status); | ||
269 | } | ||
253 | } | 270 | } |
254 | 271 | ||
255 | /* Get a new owner ID for the table */ | 272 | /* Initialize added table */ |
273 | |||
274 | acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. | ||
275 | address = address; | ||
276 | acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. | ||
277 | pointer = table; | ||
278 | acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].length = | ||
279 | length; | ||
280 | acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. | ||
281 | owner_id = 0; | ||
282 | acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].flags = | ||
283 | flags; | ||
284 | |||
285 | ACPI_MOVE_32_TO_32(& | ||
286 | (acpi_gbl_root_table_list. | ||
287 | tables[acpi_gbl_root_table_list.count].signature), | ||
288 | table->signature); | ||
289 | |||
290 | *table_index = acpi_gbl_root_table_list.count; | ||
291 | acpi_gbl_root_table_list.count++; | ||
292 | return (status); | ||
293 | } | ||
256 | 294 | ||
257 | status = acpi_ut_allocate_owner_id(&table_desc->owner_id); | 295 | /******************************************************************************* |
258 | if (ACPI_FAILURE(status)) { | 296 | * |
259 | goto error_exit1; | 297 | * FUNCTION: acpi_tb_delete_table |
260 | } | 298 | * |
299 | * PARAMETERS: table_index - Table index | ||
300 | * | ||
301 | * RETURN: None | ||
302 | * | ||
303 | * DESCRIPTION: Delete one internal ACPI table | ||
304 | * | ||
305 | ******************************************************************************/ | ||
261 | 306 | ||
262 | /* Install the table into the global data structure */ | 307 | void acpi_tb_delete_table(struct acpi_table_desc *table_desc) |
308 | { | ||
309 | /* Table must be mapped or allocated */ | ||
310 | if (!table_desc->pointer) { | ||
311 | return; | ||
312 | } | ||
313 | switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { | ||
314 | case ACPI_TABLE_ORIGIN_MAPPED: | ||
315 | acpi_os_unmap_memory(table_desc->pointer, table_desc->length); | ||
316 | break; | ||
317 | case ACPI_TABLE_ORIGIN_ALLOCATED: | ||
318 | ACPI_FREE(table_desc->pointer); | ||
319 | break; | ||
320 | default:; | ||
321 | } | ||
263 | 322 | ||
264 | list_head = &acpi_gbl_table_lists[table_type]; | 323 | table_desc->pointer = NULL; |
324 | } | ||
265 | 325 | ||
266 | /* | 326 | /******************************************************************************* |
267 | * Two major types of tables: 1) Only one instance is allowed. This | 327 | * |
268 | * includes most ACPI tables such as the DSDT. 2) Multiple instances of | 328 | * FUNCTION: acpi_tb_terminate |
269 | * the table are allowed. This includes SSDT and PSDTs. | 329 | * |
270 | */ | 330 | * PARAMETERS: None |
271 | if (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags)) { | 331 | * |
272 | /* | 332 | * RETURN: None |
273 | * Only one table allowed, and a table has alread been installed | 333 | * |
274 | * at this location, so return an error. | 334 | * DESCRIPTION: Delete all internal ACPI tables |
275 | */ | 335 | * |
276 | if (list_head->next) { | 336 | ******************************************************************************/ |
277 | status = AE_ALREADY_EXISTS; | ||
278 | goto error_exit2; | ||
279 | } | ||
280 | 337 | ||
281 | table_desc->next = list_head->next; | 338 | void acpi_tb_terminate(void) |
282 | list_head->next = table_desc; | 339 | { |
340 | acpi_native_uint i; | ||
283 | 341 | ||
284 | if (table_desc->next) { | 342 | ACPI_FUNCTION_TRACE(tb_terminate); |
285 | table_desc->next->prev = table_desc; | ||
286 | } | ||
287 | 343 | ||
288 | list_head->count++; | 344 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
289 | } else { | ||
290 | /* | ||
291 | * Link the new table in to the list of tables of this type. | ||
292 | * Insert at the end of the list, order IS IMPORTANT. | ||
293 | * | ||
294 | * table_desc->Prev & Next are already NULL from calloc() | ||
295 | */ | ||
296 | list_head->count++; | ||
297 | |||
298 | if (!list_head->next) { | ||
299 | list_head->next = table_desc; | ||
300 | } else { | ||
301 | table_desc->next = list_head->next; | ||
302 | 345 | ||
303 | while (table_desc->next->next) { | 346 | /* Delete the individual tables */ |
304 | table_desc->next = table_desc->next->next; | ||
305 | } | ||
306 | 347 | ||
307 | table_desc->next->next = table_desc; | 348 | for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { |
308 | table_desc->prev = table_desc->next; | 349 | acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]); |
309 | table_desc->next = NULL; | ||
310 | } | ||
311 | } | 350 | } |
312 | 351 | ||
313 | /* Finish initialization of the table descriptor */ | ||
314 | |||
315 | table_desc->loaded_into_namespace = FALSE; | ||
316 | table_desc->type = (u8) table_type; | ||
317 | table_desc->pointer = table_info->pointer; | ||
318 | table_desc->length = table_info->length; | ||
319 | table_desc->allocation = table_info->allocation; | ||
320 | table_desc->aml_start = (u8 *) (table_desc->pointer + 1), | ||
321 | table_desc->aml_length = (u32) | ||
322 | (table_desc->length - (u32) sizeof(struct acpi_table_header)); | ||
323 | |||
324 | /* | 352 | /* |
325 | * Set the appropriate global pointer (if there is one) to point to the | 353 | * Delete the root table array if allocated locally. Array cannot be |
326 | * newly installed table | 354 | * mapped, so we don't need to check for that flag. |
327 | */ | 355 | */ |
328 | if (acpi_gbl_table_data[table_type].global_ptr) { | 356 | if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { |
329 | *(acpi_gbl_table_data[table_type].global_ptr) = | 357 | ACPI_FREE(acpi_gbl_root_table_list.tables); |
330 | table_info->pointer; | ||
331 | } | 358 | } |
332 | 359 | ||
333 | /* Return Data */ | 360 | acpi_gbl_root_table_list.tables = NULL; |
334 | 361 | acpi_gbl_root_table_list.flags = 0; | |
335 | table_info->owner_id = table_desc->owner_id; | 362 | acpi_gbl_root_table_list.count = 0; |
336 | table_info->installed_desc = table_desc; | ||
337 | return_ACPI_STATUS(AE_OK); | ||
338 | |||
339 | /* Error exit with cleanup */ | ||
340 | |||
341 | error_exit2: | ||
342 | |||
343 | acpi_ut_release_owner_id(&table_desc->owner_id); | ||
344 | 363 | ||
345 | error_exit1: | 364 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); |
346 | 365 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | |
347 | ACPI_FREE(table_desc); | ||
348 | return_ACPI_STATUS(status); | ||
349 | } | 366 | } |
350 | 367 | ||
351 | /******************************************************************************* | 368 | /******************************************************************************* |
352 | * | 369 | * |
353 | * FUNCTION: acpi_tb_delete_all_tables | 370 | * FUNCTION: acpi_tb_delete_namespace_by_owner |
354 | * | 371 | * |
355 | * PARAMETERS: None. | 372 | * PARAMETERS: table_index - Table index |
356 | * | 373 | * |
357 | * RETURN: None. | 374 | * RETURN: None |
358 | * | 375 | * |
359 | * DESCRIPTION: Delete all internal ACPI tables | 376 | * DESCRIPTION: Delete all namespace objects created when this table was loaded. |
360 | * | 377 | * |
361 | ******************************************************************************/ | 378 | ******************************************************************************/ |
362 | 379 | ||
363 | void acpi_tb_delete_all_tables(void) | 380 | void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index) |
364 | { | 381 | { |
365 | acpi_table_type type; | 382 | acpi_owner_id owner_id; |
366 | 383 | ||
367 | /* | 384 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
368 | * Free memory allocated for ACPI tables | 385 | if (table_index < acpi_gbl_root_table_list.count) { |
369 | * Memory can either be mapped or allocated | 386 | owner_id = |
370 | */ | 387 | acpi_gbl_root_table_list.tables[table_index].owner_id; |
371 | for (type = 0; type < (ACPI_TABLE_ID_MAX + 1); type++) { | 388 | } else { |
372 | acpi_tb_delete_tables_by_type(type); | 389 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
390 | return; | ||
373 | } | 391 | } |
392 | |||
393 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
394 | acpi_ns_delete_namespace_by_owner(owner_id); | ||
374 | } | 395 | } |
375 | 396 | ||
376 | /******************************************************************************* | 397 | /******************************************************************************* |
377 | * | 398 | * |
378 | * FUNCTION: acpi_tb_delete_tables_by_type | 399 | * FUNCTION: acpi_tb_allocate_owner_id |
379 | * | 400 | * |
380 | * PARAMETERS: Type - The table type to be deleted | 401 | * PARAMETERS: table_index - Table index |
381 | * | 402 | * |
382 | * RETURN: None. | 403 | * RETURN: Status |
383 | * | 404 | * |
384 | * DESCRIPTION: Delete an internal ACPI table | 405 | * DESCRIPTION: Allocates owner_id in table_desc |
385 | * Locks the ACPI table mutex | ||
386 | * | 406 | * |
387 | ******************************************************************************/ | 407 | ******************************************************************************/ |
388 | 408 | ||
389 | void acpi_tb_delete_tables_by_type(acpi_table_type type) | 409 | acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index) |
390 | { | 410 | { |
391 | struct acpi_table_desc *table_desc; | 411 | acpi_status status = AE_BAD_PARAMETER; |
392 | u32 count; | ||
393 | u32 i; | ||
394 | 412 | ||
395 | ACPI_FUNCTION_TRACE_U32(tb_delete_tables_by_type, type); | 413 | ACPI_FUNCTION_TRACE(tb_allocate_owner_id); |
396 | 414 | ||
397 | if (type > ACPI_TABLE_ID_MAX) { | 415 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
398 | return_VOID; | 416 | if (table_index < acpi_gbl_root_table_list.count) { |
399 | } | 417 | status = acpi_ut_allocate_owner_id |
400 | 418 | (&(acpi_gbl_root_table_list.tables[table_index].owner_id)); | |
401 | if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_TABLES))) { | ||
402 | return; | ||
403 | } | ||
404 | |||
405 | /* Clear the appropriate "typed" global table pointer */ | ||
406 | |||
407 | switch (type) { | ||
408 | case ACPI_TABLE_ID_RSDP: | ||
409 | acpi_gbl_RSDP = NULL; | ||
410 | break; | ||
411 | |||
412 | case ACPI_TABLE_ID_DSDT: | ||
413 | acpi_gbl_DSDT = NULL; | ||
414 | break; | ||
415 | |||
416 | case ACPI_TABLE_ID_FADT: | ||
417 | acpi_gbl_FADT = NULL; | ||
418 | break; | ||
419 | |||
420 | case ACPI_TABLE_ID_FACS: | ||
421 | acpi_gbl_FACS = NULL; | ||
422 | break; | ||
423 | |||
424 | case ACPI_TABLE_ID_XSDT: | ||
425 | acpi_gbl_XSDT = NULL; | ||
426 | break; | ||
427 | |||
428 | case ACPI_TABLE_ID_SSDT: | ||
429 | case ACPI_TABLE_ID_PSDT: | ||
430 | default: | ||
431 | break; | ||
432 | } | ||
433 | |||
434 | /* | ||
435 | * Free the table | ||
436 | * 1) Get the head of the list | ||
437 | */ | ||
438 | table_desc = acpi_gbl_table_lists[type].next; | ||
439 | count = acpi_gbl_table_lists[type].count; | ||
440 | |||
441 | /* | ||
442 | * 2) Walk the entire list, deleting both the allocated tables | ||
443 | * and the table descriptors | ||
444 | */ | ||
445 | for (i = 0; i < count; i++) { | ||
446 | table_desc = acpi_tb_uninstall_table(table_desc); | ||
447 | } | 419 | } |
448 | 420 | ||
449 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 421 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
450 | return_VOID; | 422 | return_ACPI_STATUS(status); |
451 | } | 423 | } |
452 | 424 | ||
453 | /******************************************************************************* | 425 | /******************************************************************************* |
454 | * | 426 | * |
455 | * FUNCTION: acpi_tb_delete_single_table | 427 | * FUNCTION: acpi_tb_release_owner_id |
456 | * | 428 | * |
457 | * PARAMETERS: table_info - A table info struct | 429 | * PARAMETERS: table_index - Table index |
458 | * | 430 | * |
459 | * RETURN: None. | 431 | * RETURN: Status |
460 | * | 432 | * |
461 | * DESCRIPTION: Low-level free for a single ACPI table. Handles cases where | 433 | * DESCRIPTION: Releases owner_id in table_desc |
462 | * the table was allocated a buffer or was mapped. | ||
463 | * | 434 | * |
464 | ******************************************************************************/ | 435 | ******************************************************************************/ |
465 | 436 | ||
466 | void acpi_tb_delete_single_table(struct acpi_table_desc *table_desc) | 437 | acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index) |
467 | { | 438 | { |
439 | acpi_status status = AE_BAD_PARAMETER; | ||
468 | 440 | ||
469 | /* Must have a valid table descriptor and pointer */ | 441 | ACPI_FUNCTION_TRACE(tb_release_owner_id); |
470 | 442 | ||
471 | if ((!table_desc) || (!table_desc->pointer)) { | 443 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
472 | return; | 444 | if (table_index < acpi_gbl_root_table_list.count) { |
445 | acpi_ut_release_owner_id(& | ||
446 | (acpi_gbl_root_table_list. | ||
447 | tables[table_index].owner_id)); | ||
448 | status = AE_OK; | ||
473 | } | 449 | } |
474 | 450 | ||
475 | /* Valid table, determine type of memory allocation */ | 451 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
476 | 452 | return_ACPI_STATUS(status); | |
477 | switch (table_desc->allocation) { | ||
478 | case ACPI_MEM_NOT_ALLOCATED: | ||
479 | break; | ||
480 | |||
481 | case ACPI_MEM_ALLOCATED: | ||
482 | |||
483 | ACPI_FREE(table_desc->pointer); | ||
484 | break; | ||
485 | |||
486 | case ACPI_MEM_MAPPED: | ||
487 | |||
488 | acpi_os_unmap_memory(table_desc->pointer, table_desc->length); | ||
489 | break; | ||
490 | |||
491 | default: | ||
492 | break; | ||
493 | } | ||
494 | } | 453 | } |
495 | 454 | ||
496 | /******************************************************************************* | 455 | /******************************************************************************* |
497 | * | 456 | * |
498 | * FUNCTION: acpi_tb_uninstall_table | 457 | * FUNCTION: acpi_tb_get_owner_id |
499 | * | 458 | * |
500 | * PARAMETERS: table_info - A table info struct | 459 | * PARAMETERS: table_index - Table index |
460 | * owner_id - Where the table owner_id is returned | ||
501 | * | 461 | * |
502 | * RETURN: Pointer to the next table in the list (of same type) | 462 | * RETURN: Status |
503 | * | 463 | * |
504 | * DESCRIPTION: Free the memory associated with an internal ACPI table that | 464 | * DESCRIPTION: returns owner_id for the ACPI table |
505 | * is either installed or has never been installed. | ||
506 | * Table mutex should be locked. | ||
507 | * | 465 | * |
508 | ******************************************************************************/ | 466 | ******************************************************************************/ |
509 | 467 | ||
510 | struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc | 468 | acpi_status |
511 | *table_desc) | 469 | acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id) |
512 | { | 470 | { |
513 | struct acpi_table_desc *next_desc; | 471 | acpi_status status = AE_BAD_PARAMETER; |
514 | 472 | ||
515 | ACPI_FUNCTION_TRACE_PTR(tb_uninstall_table, table_desc); | 473 | ACPI_FUNCTION_TRACE(tb_get_owner_id); |
516 | 474 | ||
517 | if (!table_desc) { | 475 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
518 | return_PTR(NULL); | 476 | if (table_index < acpi_gbl_root_table_list.count) { |
477 | *owner_id = | ||
478 | acpi_gbl_root_table_list.tables[table_index].owner_id; | ||
479 | status = AE_OK; | ||
519 | } | 480 | } |
520 | 481 | ||
521 | /* Unlink the descriptor from the doubly linked list */ | 482 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
483 | return_ACPI_STATUS(status); | ||
484 | } | ||
522 | 485 | ||
523 | if (table_desc->prev) { | 486 | /******************************************************************************* |
524 | table_desc->prev->next = table_desc->next; | 487 | * |
525 | } else { | 488 | * FUNCTION: acpi_tb_is_table_loaded |
526 | /* Is first on list, update list head */ | 489 | * |
490 | * PARAMETERS: table_index - Table index | ||
491 | * | ||
492 | * RETURN: Table Loaded Flag | ||
493 | * | ||
494 | ******************************************************************************/ | ||
527 | 495 | ||
528 | acpi_gbl_table_lists[table_desc->type].next = table_desc->next; | 496 | u8 acpi_tb_is_table_loaded(acpi_native_uint table_index) |
529 | } | 497 | { |
498 | u8 is_loaded = FALSE; | ||
530 | 499 | ||
531 | if (table_desc->next) { | 500 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
532 | table_desc->next->prev = table_desc->prev; | 501 | if (table_index < acpi_gbl_root_table_list.count) { |
502 | is_loaded = (u8) | ||
503 | (acpi_gbl_root_table_list.tables[table_index]. | ||
504 | flags & ACPI_TABLE_IS_LOADED); | ||
533 | } | 505 | } |
534 | 506 | ||
535 | /* Free the memory allocated for the table itself */ | 507 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
536 | 508 | return (is_loaded); | |
537 | acpi_tb_delete_single_table(table_desc); | 509 | } |
538 | |||
539 | /* Free the owner ID associated with this table */ | ||
540 | |||
541 | acpi_ut_release_owner_id(&table_desc->owner_id); | ||
542 | 510 | ||
543 | /* Free the table descriptor */ | 511 | /******************************************************************************* |
512 | * | ||
513 | * FUNCTION: acpi_tb_set_table_loaded_flag | ||
514 | * | ||
515 | * PARAMETERS: table_index - Table index | ||
516 | * is_loaded - TRUE if table is loaded, FALSE otherwise | ||
517 | * | ||
518 | * RETURN: None | ||
519 | * | ||
520 | * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE. | ||
521 | * | ||
522 | ******************************************************************************/ | ||
544 | 523 | ||
545 | next_desc = table_desc->next; | 524 | void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded) |
546 | ACPI_FREE(table_desc); | 525 | { |
547 | 526 | ||
548 | /* Return pointer to the next descriptor */ | 527 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
528 | if (table_index < acpi_gbl_root_table_list.count) { | ||
529 | if (is_loaded) { | ||
530 | acpi_gbl_root_table_list.tables[table_index].flags |= | ||
531 | ACPI_TABLE_IS_LOADED; | ||
532 | } else { | ||
533 | acpi_gbl_root_table_list.tables[table_index].flags &= | ||
534 | ~ACPI_TABLE_IS_LOADED; | ||
535 | } | ||
536 | } | ||
549 | 537 | ||
550 | return_PTR(next_desc); | 538 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
551 | } | 539 | } |