Commit | Line | Data |
---|---|---|
95857638 | 1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
1da177e4 LT |
2 | /****************************************************************************** |
3 | * | |
b7ed9a8e | 4 | * Module Name: tbxface - ACPI table-oriented external interfaces |
1da177e4 | 5 | * |
800ba7c5 | 6 | * Copyright (C) 2000 - 2020, Intel Corp. |
1da177e4 | 7 | * |
95857638 | 8 | *****************************************************************************/ |
1da177e4 | 9 | |
839e928f LZ |
10 | #define EXPORT_ACPI_INTERFACES |
11 | ||
1da177e4 | 12 | #include <acpi/acpi.h> |
e2f7a777 | 13 | #include "accommon.h" |
e2f7a777 | 14 | #include "actables.h" |
1da177e4 | 15 | |
1da177e4 | 16 | #define _COMPONENT ACPI_TABLES |
4be44fcd | 17 | ACPI_MODULE_NAME("tbxface") |
1da177e4 | 18 | |
77389e12 BM |
19 | /******************************************************************************* |
20 | * | |
21 | * FUNCTION: acpi_allocate_root_table | |
22 | * | |
23 | * PARAMETERS: initial_table_count - Size of initial_table_array, in number of | |
24 | * struct acpi_table_desc structures | |
25 | * | |
26 | * RETURN: Status | |
27 | * | |
ba494bee | 28 | * DESCRIPTION: Allocate a root table array. Used by iASL compiler and |
77389e12 BM |
29 | * acpi_initialize_tables. |
30 | * | |
31 | ******************************************************************************/ | |
77389e12 BM |
32 | acpi_status acpi_allocate_root_table(u32 initial_table_count) |
33 | { | |
34 | ||
b9ee2043 | 35 | acpi_gbl_root_table_list.max_table_count = initial_table_count; |
77389e12 BM |
36 | acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE; |
37 | ||
38 | return (acpi_tb_resize_root_table_list()); | |
39 | } | |
40 | ||
1da177e4 LT |
41 | /******************************************************************************* |
42 | * | |
f3d2e786 | 43 | * FUNCTION: acpi_initialize_tables |
1da177e4 | 44 | * |
f3d2e786 BM |
45 | * PARAMETERS: initial_table_array - Pointer to an array of pre-allocated |
46 | * struct acpi_table_desc structures. If NULL, the | |
47 | * array is dynamically allocated. | |
48 | * initial_table_count - Size of initial_table_array, in number of | |
49 | * struct acpi_table_desc structures | |
b7ed9a8e | 50 | * allow_resize - Flag to tell Table Manager if resize of |
f3d2e786 BM |
51 | * pre-allocated array is allowed. Ignored |
52 | * if initial_table_array is NULL. | |
1da177e4 LT |
53 | * |
54 | * RETURN: Status | |
55 | * | |
f3d2e786 BM |
56 | * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT. |
57 | * | |
58 | * NOTE: Allows static allocation of the initial table array in order | |
59 | * to avoid the use of dynamic memory in confined environments | |
60 | * such as the kernel boot sequence where it may not be available. | |
61 | * | |
62 | * If the host OS memory managers are initialized, use NULL for | |
63 | * initial_table_array, and the table will be dynamically allocated. | |
1da177e4 LT |
64 | * |
65 | ******************************************************************************/ | |
f3d2e786 | 66 | |
2368b1a1 | 67 | acpi_status ACPI_INIT_FUNCTION |
f5c1e1c5 | 68 | acpi_initialize_tables(struct acpi_table_desc *initial_table_array, |
f3d2e786 | 69 | u32 initial_table_count, u8 allow_resize) |
1da177e4 | 70 | { |
c5fc42ac | 71 | acpi_physical_address rsdp_address; |
4be44fcd | 72 | acpi_status status; |
1da177e4 | 73 | |
f3d2e786 | 74 | ACPI_FUNCTION_TRACE(acpi_initialize_tables); |
1da177e4 | 75 | |
f3d2e786 | 76 | /* |
b7ed9a8e TC |
77 | * Setup the Root Table Array and allocate the table array |
78 | * if requested | |
f3d2e786 BM |
79 | */ |
80 | if (!initial_table_array) { | |
77389e12 | 81 | status = acpi_allocate_root_table(initial_table_count); |
f3d2e786 BM |
82 | if (ACPI_FAILURE(status)) { |
83 | return_ACPI_STATUS(status); | |
84 | } | |
85 | } else { | |
86 | /* Root Table Array has been statically allocated by the host */ | |
87 | ||
4fa4616e | 88 | memset(initial_table_array, 0, |
f5c1e1c5 | 89 | (acpi_size)initial_table_count * |
4fa4616e | 90 | sizeof(struct acpi_table_desc)); |
c5fc42ac | 91 | |
f3d2e786 | 92 | acpi_gbl_root_table_list.tables = initial_table_array; |
b9ee2043 | 93 | acpi_gbl_root_table_list.max_table_count = initial_table_count; |
c5fc42ac | 94 | acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN; |
f3d2e786 | 95 | if (allow_resize) { |
c5fc42ac BM |
96 | acpi_gbl_root_table_list.flags |= |
97 | ACPI_ROOT_ALLOW_RESIZE; | |
f3d2e786 | 98 | } |
1da177e4 LT |
99 | } |
100 | ||
c5fc42ac | 101 | /* Get the address of the RSDP */ |
1da177e4 | 102 | |
c5fc42ac BM |
103 | rsdp_address = acpi_os_get_root_pointer(); |
104 | if (!rsdp_address) { | |
f3d2e786 BM |
105 | return_ACPI_STATUS(AE_NOT_FOUND); |
106 | } | |
1da177e4 | 107 | |
f3d2e786 BM |
108 | /* |
109 | * Get the root table (RSDT or XSDT) and extract all entries to the local | |
110 | * Root Table Array. This array contains the information of the RSDT/XSDT | |
c163f90c | 111 | * in a common, more usable format. |
f3d2e786 | 112 | */ |
97cbb7d1 | 113 | status = acpi_tb_parse_root_table(rsdp_address); |
f3d2e786 BM |
114 | return_ACPI_STATUS(status); |
115 | } | |
1da177e4 | 116 | |
d21f600b LZ |
117 | ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_tables) |
118 | ||
f3d2e786 BM |
119 | /******************************************************************************* |
120 | * | |
121 | * FUNCTION: acpi_reallocate_root_table | |
122 | * | |
123 | * PARAMETERS: None | |
124 | * | |
125 | * RETURN: Status | |
126 | * | |
127 | * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the | |
128 | * root list from the previously provided scratch area. Should | |
129 | * be called once dynamic memory allocation is available in the | |
2bc198c1 | 130 | * kernel. |
f3d2e786 BM |
131 | * |
132 | ******************************************************************************/ | |
2368b1a1 | 133 | acpi_status ACPI_INIT_FUNCTION acpi_reallocate_root_table(void) |
f3d2e786 | 134 | { |
2bc198c1 | 135 | acpi_status status; |
19df56bd LZ |
136 | struct acpi_table_desc *table_desc; |
137 | u32 i, j; | |
f3d2e786 BM |
138 | |
139 | ACPI_FUNCTION_TRACE(acpi_reallocate_root_table); | |
140 | ||
141 | /* | |
979fba94 LZ |
142 | * If there are tables unverified, it is required to reallocate the |
143 | * root table list to clean up invalid table entries. Otherwise only | |
144 | * reallocate the root table list if the host provided a static buffer | |
145 | * for the table array in the call to acpi_initialize_tables(). | |
f3d2e786 | 146 | */ |
979fba94 LZ |
147 | if ((acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) && |
148 | acpi_gbl_enable_table_validation) { | |
f3d2e786 | 149 | return_ACPI_STATUS(AE_SUPPORT); |
1da177e4 LT |
150 | } |
151 | ||
19df56bd LZ |
152 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
153 | ||
173fcf80 LZ |
154 | /* |
155 | * Ensure OS early boot logic, which is required by some hosts. If the | |
156 | * table state is reported to be wrong, developers should fix the | |
157 | * issue by invoking acpi_put_table() for the reported table during the | |
158 | * early stage. | |
159 | */ | |
160 | for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { | |
19df56bd LZ |
161 | table_desc = &acpi_gbl_root_table_list.tables[i]; |
162 | if (table_desc->pointer) { | |
173fcf80 LZ |
163 | ACPI_ERROR((AE_INFO, |
164 | "Table [%4.4s] is not invalidated during early boot stage", | |
19df56bd | 165 | table_desc->signature.ascii)); |
173fcf80 LZ |
166 | } |
167 | } | |
168 | ||
023e2ee1 LZ |
169 | if (!acpi_gbl_enable_table_validation) { |
170 | /* | |
171 | * Now it's safe to do full table validation. We can do deferred | |
c163f90c | 172 | * table initialization here once the flag is set. |
023e2ee1 LZ |
173 | */ |
174 | acpi_gbl_enable_table_validation = TRUE; | |
19df56bd LZ |
175 | for (i = 0; i < acpi_gbl_root_table_list.current_table_count; |
176 | ++i) { | |
177 | table_desc = &acpi_gbl_root_table_list.tables[i]; | |
178 | if (!(table_desc->flags & ACPI_TABLE_IS_VERIFIED)) { | |
179 | status = | |
180 | acpi_tb_verify_temp_table(table_desc, NULL, | |
181 | &j); | |
182 | if (ACPI_FAILURE(status)) { | |
183 | acpi_tb_uninstall_table(table_desc); | |
184 | } | |
185 | } | |
186 | } | |
023e2ee1 LZ |
187 | } |
188 | ||
2bc198c1 | 189 | acpi_gbl_root_table_list.flags |= ACPI_ROOT_ALLOW_RESIZE; |
2bc198c1 | 190 | status = acpi_tb_resize_root_table_list(); |
19df56bd LZ |
191 | acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED; |
192 | ||
193 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | |
2bc198c1 | 194 | return_ACPI_STATUS(status); |
f3d2e786 | 195 | } |
fd350943 | 196 | |
d21f600b LZ |
197 | ACPI_EXPORT_SYMBOL_INIT(acpi_reallocate_root_table) |
198 | ||
ec41f193 | 199 | /******************************************************************************* |
f3d2e786 BM |
200 | * |
201 | * FUNCTION: acpi_get_table_header | |
202 | * | |
ba494bee BM |
203 | * PARAMETERS: signature - ACPI signature of needed table |
204 | * instance - Which instance (for SSDTs) | |
464fa2bd BM |
205 | * out_table_header - The pointer to the where the table header |
206 | * is returned | |
f3d2e786 | 207 | * |
464fa2bd | 208 | * RETURN: Status and a copy of the table header |
f3d2e786 | 209 | * |
464fa2bd BM |
210 | * DESCRIPTION: Finds and returns an ACPI table header. Caller provides the |
211 | * memory where a copy of the header is to be returned | |
212 | * (fixed length). | |
f3d2e786 | 213 | * |
ec41f193 | 214 | ******************************************************************************/ |
f3d2e786 BM |
215 | acpi_status |
216 | acpi_get_table_header(char *signature, | |
67a119f9 | 217 | u32 instance, struct acpi_table_header *out_table_header) |
f3d2e786 | 218 | { |
5582982d LZ |
219 | u32 i; |
220 | u32 j; | |
428f2112 | 221 | struct acpi_table_header *header; |
0c9938cc | 222 | |
c5fc42ac BM |
223 | /* Parameter validation */ |
224 | ||
225 | if (!signature || !out_table_header) { | |
226 | return (AE_BAD_PARAMETER); | |
227 | } | |
228 | ||
ec41f193 BM |
229 | /* Walk the root table list */ |
230 | ||
b9ee2043 BM |
231 | for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count; |
232 | i++) { | |
5599fb69 | 233 | if (!ACPI_COMPARE_NAMESEG |
f3d2e786 BM |
234 | (&(acpi_gbl_root_table_list.tables[i].signature), |
235 | signature)) { | |
236 | continue; | |
0c9938cc RM |
237 | } |
238 | ||
f3d2e786 BM |
239 | if (++j < instance) { |
240 | continue; | |
241 | } | |
1da177e4 | 242 | |
428f2112 | 243 | if (!acpi_gbl_root_table_list.tables[i].pointer) { |
ec41f193 BM |
244 | if ((acpi_gbl_root_table_list.tables[i].flags & |
245 | ACPI_TABLE_ORIGIN_MASK) == | |
ed6f1d44 | 246 | ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL) { |
428f2112 AS |
247 | header = |
248 | acpi_os_map_memory(acpi_gbl_root_table_list. | |
249 | tables[i].address, | |
250 | sizeof(struct | |
251 | acpi_table_header)); | |
252 | if (!header) { | |
68aafc35 | 253 | return (AE_NO_MEMORY); |
428f2112 | 254 | } |
52c1d803 | 255 | |
4fa4616e BM |
256 | memcpy(out_table_header, header, |
257 | sizeof(struct acpi_table_header)); | |
428f2112 AS |
258 | acpi_os_unmap_memory(header, |
259 | sizeof(struct | |
260 | acpi_table_header)); | |
261 | } else { | |
68aafc35 | 262 | return (AE_NOT_FOUND); |
428f2112 AS |
263 | } |
264 | } else { | |
4fa4616e BM |
265 | memcpy(out_table_header, |
266 | acpi_gbl_root_table_list.tables[i].pointer, | |
267 | sizeof(struct acpi_table_header)); | |
f3d2e786 | 268 | } |
f3d2e786 | 269 | return (AE_OK); |
1da177e4 LT |
270 | } |
271 | ||
f3d2e786 | 272 | return (AE_NOT_FOUND); |
1da177e4 LT |
273 | } |
274 | ||
f3d2e786 | 275 | ACPI_EXPORT_SYMBOL(acpi_get_table_header) |
8313524a | 276 | |
1da177e4 LT |
277 | /******************************************************************************* |
278 | * | |
174cc718 | 279 | * FUNCTION: acpi_get_table |
1da177e4 | 280 | * |
ba494bee BM |
281 | * PARAMETERS: signature - ACPI signature of needed table |
282 | * instance - Which instance (for SSDTs) | |
f3d2e786 | 283 | * out_table - Where the pointer to the table is returned |
1da177e4 | 284 | * |
b7ed9a8e | 285 | * RETURN: Status and pointer to the requested table |
1da177e4 | 286 | * |
b7ed9a8e TC |
287 | * DESCRIPTION: Finds and verifies an ACPI table. Table must be in the |
288 | * RSDT/XSDT. | |
174cc718 LZ |
289 | * Note that an early stage acpi_get_table() call must be paired |
290 | * with an early stage acpi_put_table() call. otherwise the table | |
291 | * pointer mapped by the early stage mapping implementation may be | |
292 | * erroneously unmapped by the late stage unmapping implementation | |
293 | * in an acpi_put_table() invoked during the late stage. | |
1da177e4 | 294 | * |
ec41f193 | 295 | ******************************************************************************/ |
f3d2e786 | 296 | acpi_status |
174cc718 LZ |
297 | acpi_get_table(char *signature, |
298 | u32 instance, struct acpi_table_header ** out_table) | |
1da177e4 | 299 | { |
5582982d LZ |
300 | u32 i; |
301 | u32 j; | |
174cc718 LZ |
302 | acpi_status status = AE_NOT_FOUND; |
303 | struct acpi_table_desc *table_desc; | |
1da177e4 | 304 | |
c5fc42ac BM |
305 | /* Parameter validation */ |
306 | ||
307 | if (!signature || !out_table) { | |
308 | return (AE_BAD_PARAMETER); | |
309 | } | |
310 | ||
174cc718 LZ |
311 | /* |
312 | * Note that the following line is required by some OSPMs, they only | |
313 | * check if the returned table is NULL instead of the returned status | |
314 | * to determined if this function is succeeded. | |
315 | */ | |
316 | *out_table = NULL; | |
317 | ||
318 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | |
319 | ||
ec41f193 BM |
320 | /* Walk the root table list */ |
321 | ||
b9ee2043 BM |
322 | for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count; |
323 | i++) { | |
174cc718 LZ |
324 | table_desc = &acpi_gbl_root_table_list.tables[i]; |
325 | ||
5599fb69 | 326 | if (!ACPI_COMPARE_NAMESEG(&table_desc->signature, signature)) { |
f3d2e786 BM |
327 | continue; |
328 | } | |
1da177e4 | 329 | |
f3d2e786 BM |
330 | if (++j < instance) { |
331 | continue; | |
332 | } | |
1da177e4 | 333 | |
174cc718 LZ |
334 | status = acpi_tb_get_table(table_desc, out_table); |
335 | break; | |
1da177e4 LT |
336 | } |
337 | ||
174cc718 LZ |
338 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
339 | return (status); | |
1da177e4 | 340 | } |
d21f600b | 341 | |
174cc718 | 342 | ACPI_EXPORT_SYMBOL(acpi_get_table) |
1da177e4 | 343 | |
174cc718 LZ |
344 | /******************************************************************************* |
345 | * | |
346 | * FUNCTION: acpi_put_table | |
347 | * | |
348 | * PARAMETERS: table - The pointer to the table | |
349 | * | |
350 | * RETURN: None | |
351 | * | |
352 | * DESCRIPTION: Release a table returned by acpi_get_table() and its clones. | |
353 | * Note that it is not safe if this function was invoked after an | |
354 | * uninstallation happened to the original table descriptor. | |
355 | * Currently there is no OSPMs' requirement to handle such | |
356 | * situations. | |
357 | * | |
358 | ******************************************************************************/ | |
359 | void acpi_put_table(struct acpi_table_header *table) | |
7d97277b | 360 | { |
174cc718 LZ |
361 | u32 i; |
362 | struct acpi_table_desc *table_desc; | |
363 | ||
364 | ACPI_FUNCTION_TRACE(acpi_put_table); | |
365 | ||
96d07940 LZ |
366 | if (!table) { |
367 | return_VOID; | |
368 | } | |
369 | ||
174cc718 LZ |
370 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
371 | ||
372 | /* Walk the root table list */ | |
373 | ||
374 | for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { | |
375 | table_desc = &acpi_gbl_root_table_list.tables[i]; | |
7d97277b | 376 | |
174cc718 LZ |
377 | if (table_desc->pointer != table) { |
378 | continue; | |
379 | } | |
380 | ||
381 | acpi_tb_put_table(table_desc); | |
382 | break; | |
383 | } | |
384 | ||
385 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | |
386 | return_VOID; | |
7d97277b | 387 | } |
d21f600b | 388 | |
174cc718 | 389 | ACPI_EXPORT_SYMBOL(acpi_put_table) |
8313524a | 390 | |
1da177e4 LT |
391 | /******************************************************************************* |
392 | * | |
f3d2e786 | 393 | * FUNCTION: acpi_get_table_by_index |
1da177e4 | 394 | * |
f3d2e786 | 395 | * PARAMETERS: table_index - Table index |
174cc718 | 396 | * out_table - Where the pointer to the table is returned |
1da177e4 | 397 | * |
b7ed9a8e | 398 | * RETURN: Status and pointer to the requested table |
1da177e4 | 399 | * |
b7ed9a8e TC |
400 | * DESCRIPTION: Obtain a table by an index into the global table list. Used |
401 | * internally also. | |
1da177e4 LT |
402 | * |
403 | ******************************************************************************/ | |
1da177e4 | 404 | acpi_status |
174cc718 | 405 | acpi_get_table_by_index(u32 table_index, struct acpi_table_header **out_table) |
1da177e4 | 406 | { |
4be44fcd | 407 | acpi_status status; |
1da177e4 | 408 | |
f3d2e786 | 409 | ACPI_FUNCTION_TRACE(acpi_get_table_by_index); |
1da177e4 | 410 | |
c5fc42ac BM |
411 | /* Parameter validation */ |
412 | ||
174cc718 | 413 | if (!out_table) { |
c5fc42ac BM |
414 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
415 | } | |
416 | ||
174cc718 LZ |
417 | /* |
418 | * Note that the following line is required by some OSPMs, they only | |
419 | * check if the returned table is NULL instead of the returned status | |
420 | * to determined if this function is succeeded. | |
421 | */ | |
422 | *out_table = NULL; | |
423 | ||
f3d2e786 | 424 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
1da177e4 | 425 | |
f3d2e786 | 426 | /* Validate index */ |
1da177e4 | 427 | |
b9ee2043 | 428 | if (table_index >= acpi_gbl_root_table_list.current_table_count) { |
174cc718 LZ |
429 | status = AE_BAD_PARAMETER; |
430 | goto unlock_and_exit; | |
1da177e4 LT |
431 | } |
432 | ||
174cc718 LZ |
433 | status = |
434 | acpi_tb_get_table(&acpi_gbl_root_table_list.tables[table_index], | |
435 | out_table); | |
1da177e4 | 436 | |
174cc718 | 437 | unlock_and_exit: |
f3d2e786 | 438 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
174cc718 | 439 | return_ACPI_STATUS(status); |
1da177e4 LT |
440 | } |
441 | ||
f3d2e786 | 442 | ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) |
1da177e4 | 443 | |
3e08e2d2 LM |
444 | /******************************************************************************* |
445 | * | |
446 | * FUNCTION: acpi_install_table_handler | |
447 | * | |
ba494bee BM |
448 | * PARAMETERS: handler - Table event handler |
449 | * context - Value passed to the handler on each event | |
3e08e2d2 LM |
450 | * |
451 | * RETURN: Status | |
452 | * | |
b7ed9a8e | 453 | * DESCRIPTION: Install a global table event handler. |
3e08e2d2 LM |
454 | * |
455 | ******************************************************************************/ | |
456 | acpi_status | |
b43e1065 | 457 | acpi_install_table_handler(acpi_table_handler handler, void *context) |
3e08e2d2 LM |
458 | { |
459 | acpi_status status; | |
460 | ||
461 | ACPI_FUNCTION_TRACE(acpi_install_table_handler); | |
462 | ||
463 | if (!handler) { | |
464 | return_ACPI_STATUS(AE_BAD_PARAMETER); | |
465 | } | |
466 | ||
467 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | |
468 | if (ACPI_FAILURE(status)) { | |
469 | return_ACPI_STATUS(status); | |
470 | } | |
471 | ||
472 | /* Don't allow more than one handler */ | |
473 | ||
474 | if (acpi_gbl_table_handler) { | |
475 | status = AE_ALREADY_EXISTS; | |
476 | goto cleanup; | |
477 | } | |
478 | ||
479 | /* Install the handler */ | |
480 | ||
481 | acpi_gbl_table_handler = handler; | |
482 | acpi_gbl_table_handler_context = context; | |
483 | ||
10622bf8 | 484 | cleanup: |
3e08e2d2 LM |
485 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); |
486 | return_ACPI_STATUS(status); | |
487 | } | |
488 | ||
489 | ACPI_EXPORT_SYMBOL(acpi_install_table_handler) | |
490 | ||
491 | /******************************************************************************* | |
492 | * | |
493 | * FUNCTION: acpi_remove_table_handler | |
494 | * | |
ba494bee | 495 | * PARAMETERS: handler - Table event handler that was installed |
3e08e2d2 LM |
496 | * previously. |
497 | * | |
498 | * RETURN: Status | |
499 | * | |
b7ed9a8e | 500 | * DESCRIPTION: Remove a table event handler |
3e08e2d2 LM |
501 | * |
502 | ******************************************************************************/ | |
b43e1065 | 503 | acpi_status acpi_remove_table_handler(acpi_table_handler handler) |
3e08e2d2 LM |
504 | { |
505 | acpi_status status; | |
506 | ||
507 | ACPI_FUNCTION_TRACE(acpi_remove_table_handler); | |
508 | ||
509 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | |
510 | if (ACPI_FAILURE(status)) { | |
511 | return_ACPI_STATUS(status); | |
512 | } | |
513 | ||
514 | /* Make sure that the installed handler is the same */ | |
515 | ||
516 | if (!handler || handler != acpi_gbl_table_handler) { | |
517 | status = AE_BAD_PARAMETER; | |
518 | goto cleanup; | |
519 | } | |
520 | ||
521 | /* Remove the handler */ | |
522 | ||
523 | acpi_gbl_table_handler = NULL; | |
524 | ||
10622bf8 | 525 | cleanup: |
3e08e2d2 LM |
526 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); |
527 | return_ACPI_STATUS(status); | |
528 | } | |
529 | ||
530 | ACPI_EXPORT_SYMBOL(acpi_remove_table_handler) |