]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/acpi/tables/tbinstal.c
ACPICA: misc fixes for new Table Manager:
[linux-2.6-omap-h63xx.git] / drivers / acpi / tables / tbinstal.c
1 /******************************************************************************
2  *
3  * Module Name: tbinstal - ACPI table installation and removal
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2006, R. Byron Moore
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44 #include <acpi/acpi.h>
45 #include <acpi/acnamesp.h>
46 #include <acpi/actables.h>
47
48 #define _COMPONENT          ACPI_TABLES
49 ACPI_MODULE_NAME("tbinstal")
50
51 /******************************************************************************
52  *
53  * FUNCTION:    acpi_tb_verify_table
54  *
55  * PARAMETERS:  table_desc          - table
56  *
57  * RETURN:      Status
58  *
59  * DESCRIPTION: this function is called to verify and map table
60  *
61  *****************************************************************************/
62 acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
63 {
64         acpi_status status;
65
66         ACPI_FUNCTION_TRACE(tb_verify_table);
67
68         /* Map the table if necessary */
69
70         if (!table_desc->pointer) {
71                 table_desc->pointer =
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);
76                 }
77         }
78
79         /* FACS is the odd table, has no standard ACPI header and no checksum */
80
81         if (ACPI_COMPARE_NAME(&(table_desc->signature), ACPI_SIG_FACS)) {
82                 return_ACPI_STATUS(AE_OK);
83         }
84
85         /* Always calculate checksum, ignore bad checksum if requested */
86
87         status =
88             acpi_tb_verify_checksum(table_desc->pointer, table_desc->length);
89         return_ACPI_STATUS(status);
90 }
91
92 /*******************************************************************************
93  *
94  * FUNCTION:    acpi_tb_add_table
95  *
96  * PARAMETERS:  Table               - Pointer to the table header
97  *              table_index         - Where the table index is returned
98  *
99  * RETURN:      Status
100  *
101  * DESCRIPTION: This function is called to add the ACPI table
102  *
103  ******************************************************************************/
104
105 acpi_status
106 acpi_tb_add_table(struct acpi_table_header *table,
107                   acpi_native_uint * table_index)
108 {
109         acpi_native_uint i;
110         acpi_native_uint length;
111         acpi_status status = AE_OK;
112
113         ACPI_FUNCTION_TRACE(tb_add_table);
114
115         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
116
117         /* Check if table is already registered */
118
119         for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
120                 if (!acpi_gbl_root_table_list.tables[i].pointer) {
121                         status =
122                             acpi_tb_verify_table(&acpi_gbl_root_table_list.
123                                                  tables[i]);
124                         if (ACPI_FAILURE(status)
125                             || !acpi_gbl_root_table_list.tables[i].pointer) {
126                                 continue;
127                         }
128                 }
129
130                 length = ACPI_MIN(table->length,
131                                   acpi_gbl_root_table_list.tables[i].pointer->
132                                   length);
133                 if (ACPI_MEMCMP
134                     (table, acpi_gbl_root_table_list.tables[i].pointer,
135                      length)) {
136                         continue;
137                 }
138
139                 /* Table is already registered */
140
141                 ACPI_FREE(table);
142                 *table_index = i;
143                 goto release;
144         }
145
146         /*
147          * Add the table to the global table list
148          */
149         status = acpi_tb_store_table(ACPI_TO_INTEGER(table),
150                                      table, table->length,
151                                      ACPI_TABLE_ORIGIN_ALLOCATED, table_index);
152         if (ACPI_FAILURE(status)) {
153                 goto release;
154         }
155
156         acpi_tb_print_table_header(0, table);
157
158       release:
159         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
160         return_ACPI_STATUS(status);
161 }
162
163 /*******************************************************************************
164  *
165  * FUNCTION:    acpi_tb_resize_root_table_list
166  *
167  * PARAMETERS:  None
168  *
169  * RETURN:      Status
170  *
171  * DESCRIPTION: Expand the size of global table array
172  *
173  ******************************************************************************/
174
175 acpi_status acpi_tb_resize_root_table_list(void)
176 {
177         struct acpi_table_desc *tables;
178
179         ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
180
181         /* allow_resize flag is a parameter to acpi_initialize_tables */
182
183         if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
184                 ACPI_ERROR((AE_INFO,
185                             "Resize of Root Table Array is not allowed"));
186                 return_ACPI_STATUS(AE_SUPPORT);
187         }
188
189         /* Increase the Table Array size */
190
191         tables = ACPI_ALLOCATE_ZEROED((acpi_gbl_root_table_list.size +
192                                        ACPI_ROOT_TABLE_SIZE_INCREMENT)
193                                       * sizeof(struct acpi_table_desc));
194         if (!tables) {
195                 ACPI_ERROR((AE_INFO,
196                             "Could not allocate new root table array"));
197                 return_ACPI_STATUS(AE_NO_MEMORY);
198         }
199
200         /* Copy and free the previous table array */
201
202         if (acpi_gbl_root_table_list.tables) {
203                 ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
204                             acpi_gbl_root_table_list.size *
205                             sizeof(struct acpi_table_desc));
206
207                 if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
208                         ACPI_FREE(acpi_gbl_root_table_list.tables);
209                 }
210         }
211
212         acpi_gbl_root_table_list.tables = tables;
213         acpi_gbl_root_table_list.size += ACPI_ROOT_TABLE_SIZE_INCREMENT;
214         acpi_gbl_root_table_list.flags |= (u8) ACPI_ROOT_ORIGIN_ALLOCATED;
215
216         return_ACPI_STATUS(AE_OK);
217 }
218
219 /*******************************************************************************
220  *
221  * FUNCTION:    acpi_tb_store_table
222  *
223  * PARAMETERS:  Address             - Table address
224  *              Table               - Table header
225  *              Length              - Table length
226  *              Flags               - flags
227  *
228  * RETURN:      Status and table index.
229  *
230  * DESCRIPTION: Add an ACPI table to the global table list
231  *
232  ******************************************************************************/
233
234 acpi_status
235 acpi_tb_store_table(acpi_physical_address address,
236                     struct acpi_table_header *table,
237                     u32 length, u8 flags, acpi_native_uint * table_index)
238 {
239         acpi_status status = AE_OK;
240
241         /* Ensure that there is room for the table in the Root Table List */
242
243         if (acpi_gbl_root_table_list.count >= acpi_gbl_root_table_list.size) {
244                 status = acpi_tb_resize_root_table_list();
245                 if (ACPI_FAILURE(status)) {
246                         return (status);
247                 }
248         }
249
250         /* Initialize added table */
251
252         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
253             address = address;
254         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
255             pointer = table;
256         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].length =
257             length;
258         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
259             owner_id = 0;
260         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].flags =
261             flags;
262
263         ACPI_MOVE_32_TO_32(&
264                            (acpi_gbl_root_table_list.
265                             tables[acpi_gbl_root_table_list.count].signature),
266                            table->signature);
267
268         *table_index = acpi_gbl_root_table_list.count;
269         acpi_gbl_root_table_list.count++;
270         return (status);
271 }
272
273 /*******************************************************************************
274  *
275  * FUNCTION:    acpi_tb_delete_table
276  *
277  * PARAMETERS:  table_index         - Table index
278  *
279  * RETURN:      None
280  *
281  * DESCRIPTION: Delete one internal ACPI table
282  *
283  ******************************************************************************/
284
285 void acpi_tb_delete_table(acpi_native_uint table_index)
286 {
287         struct acpi_table_desc *table_desc;
288
289         /* table_index assumed valid */
290
291         table_desc = &acpi_gbl_root_table_list.tables[table_index];
292
293         /* Table must be mapped or allocated */
294
295         if (!table_desc->pointer) {
296                 return;
297         }
298
299         if (table_desc->flags & ACPI_TABLE_ORIGIN_MAPPED) {
300                 acpi_tb_unmap(table_desc->pointer, table_desc->length,
301                               table_desc->flags & ACPI_TABLE_ORIGIN_MASK);
302         } else if (table_desc->flags & ACPI_TABLE_ORIGIN_ALLOCATED) {
303                 ACPI_FREE(table_desc->pointer);
304         }
305
306         table_desc->pointer = NULL;
307 }
308
309 /*******************************************************************************
310  *
311  * FUNCTION:    acpi_tb_terminate
312  *
313  * PARAMETERS:  None
314  *
315  * RETURN:      None
316  *
317  * DESCRIPTION: Delete all internal ACPI tables
318  *
319  ******************************************************************************/
320
321 void acpi_tb_terminate(void)
322 {
323         acpi_native_uint i;
324
325         ACPI_FUNCTION_TRACE(tb_terminate);
326
327         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
328
329         /* Delete the individual tables */
330
331         for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
332                 acpi_tb_delete_table(i);
333         }
334
335         /*
336          * Delete the root table array if allocated locally. Array cannot be
337          * mapped, so we don't need to check for that flag.
338          */
339         if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
340                 ACPI_FREE(acpi_gbl_root_table_list.tables);
341         }
342
343         acpi_gbl_root_table_list.tables = NULL;
344         acpi_gbl_root_table_list.flags = 0;
345         acpi_gbl_root_table_list.count = 0;
346
347         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
348         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
349 }
350
351 /*******************************************************************************
352  *
353  * FUNCTION:    acpi_tb_delete_namespace_by_owner
354  *
355  * PARAMETERS:  table_index         - Table index
356  *
357  * RETURN:      None
358  *
359  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
360  *
361  ******************************************************************************/
362
363 void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index)
364 {
365         acpi_owner_id owner_id;
366
367         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
368         if (table_index < acpi_gbl_root_table_list.count) {
369                 owner_id =
370                     acpi_gbl_root_table_list.tables[table_index].owner_id;
371         } else {
372                 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
373                 return;
374         }
375
376         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
377         acpi_ns_delete_namespace_by_owner(owner_id);
378 }
379
380 /*******************************************************************************
381  *
382  * FUNCTION:    acpi_tb_allocate_owner_id
383  *
384  * PARAMETERS:  table_index         - Table index
385  *
386  * RETURN:      Status
387  *
388  * DESCRIPTION: Allocates owner_id in table_desc
389  *
390  ******************************************************************************/
391
392 acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index)
393 {
394         acpi_status status = AE_BAD_PARAMETER;
395
396         ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
397
398         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
399         if (table_index < acpi_gbl_root_table_list.count) {
400                 status = acpi_ut_allocate_owner_id
401                     (&(acpi_gbl_root_table_list.tables[table_index].owner_id));
402         }
403
404         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
405         return_ACPI_STATUS(status);
406 }
407
408 /*******************************************************************************
409  *
410  * FUNCTION:    acpi_tb_release_owner_id
411  *
412  * PARAMETERS:  table_index         - Table index
413  *
414  * RETURN:      Status
415  *
416  * DESCRIPTION: Releases owner_id in table_desc
417  *
418  ******************************************************************************/
419
420 acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index)
421 {
422         acpi_status status = AE_BAD_PARAMETER;
423
424         ACPI_FUNCTION_TRACE(tb_release_owner_id);
425
426         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
427         if (table_index < acpi_gbl_root_table_list.count) {
428                 acpi_ut_release_owner_id(&
429                                          (acpi_gbl_root_table_list.
430                                           tables[table_index].owner_id));
431                 status = AE_OK;
432         }
433
434         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
435         return_ACPI_STATUS(status);
436 }
437
438 /*******************************************************************************
439  *
440  * FUNCTION:    acpi_tb_get_owner_id
441  *
442  * PARAMETERS:  table_index         - Table index
443  *              owner_id            - Where the table owner_id is returned
444  *
445  * RETURN:      Status
446  *
447  * DESCRIPTION: returns owner_id for the ACPI table
448  *
449  ******************************************************************************/
450
451 acpi_status
452 acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id)
453 {
454         acpi_status status = AE_BAD_PARAMETER;
455
456         ACPI_FUNCTION_TRACE(tb_get_owner_id);
457
458         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
459         if (table_index < acpi_gbl_root_table_list.count) {
460                 *owner_id =
461                     acpi_gbl_root_table_list.tables[table_index].owner_id;
462                 status = AE_OK;
463         }
464
465         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
466         return_ACPI_STATUS(status);
467 }
468
469 /*******************************************************************************
470  *
471  * FUNCTION:    acpi_tb_is_table_loaded
472  *
473  * PARAMETERS:  table_index         - Table index
474  *
475  * RETURN:      Table Loaded Flag
476  *
477  ******************************************************************************/
478
479 u8 acpi_tb_is_table_loaded(acpi_native_uint table_index)
480 {
481         u8 is_loaded = FALSE;
482
483         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
484         if (table_index < acpi_gbl_root_table_list.count) {
485                 is_loaded = (u8)
486                     (acpi_gbl_root_table_list.tables[table_index].
487                      flags & ACPI_TABLE_IS_LOADED);
488         }
489
490         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
491         return (is_loaded);
492 }
493
494 /*******************************************************************************
495  *
496  * FUNCTION:    acpi_tb_set_table_loaded_flag
497  *
498  * PARAMETERS:  table_index         - Table index
499  *              is_loaded           - TRUE if table is loaded, FALSE otherwise
500  *
501  * RETURN:      None
502  *
503  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
504  *
505  ******************************************************************************/
506
507 void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded)
508 {
509
510         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
511         if (table_index < acpi_gbl_root_table_list.count) {
512                 if (is_loaded) {
513                         acpi_gbl_root_table_list.tables[table_index].flags |=
514                             ACPI_TABLE_IS_LOADED;
515                 } else {
516                         acpi_gbl_root_table_list.tables[table_index].flags &=
517                             ~ACPI_TABLE_IS_LOADED;
518                 }
519         }
520
521         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
522 }