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