diff options
author | Bob Moore <robert.moore@intel.com> | 2007-02-02 11:48:18 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-02-02 21:14:21 -0500 |
commit | f3d2e7865c816258c699ff965768e46b50d536d3 (patch) | |
tree | 83d21269e506109275b77d3ed161883bba8a39cf /drivers/acpi/tables/tbinstal.c | |
parent | 2e42005bcdb4f63bed1cea7f537a5534d4bd7a57 (diff) |
ACPICA: Implement simplified Table Manager
The Table Manager component has been completely
redesigned and reimplemented. The new design is much
simpler, and reduces the overall code and data size of
the kernel-resident ACPICA by approximately 5%. Also,
it is now possible to obtain the ACPI tables very early
during kernel initialization, even before dynamic memory
management is initialized.
Signed-off-by: Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
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 | } |