]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/acpi/tables/tbinstal.c
ACPICA: Allow same ACPI table to be loaded/unloaded more than once
[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 - 2008, Intel Corp.
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 = AE_OK;
65
66         ACPI_FUNCTION_TRACE(tb_verify_table);
67
68         /* Map the table if necessary */
69
70         if (!table_desc->pointer) {
71                 if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
72                     ACPI_TABLE_ORIGIN_MAPPED) {
73                         table_desc->pointer =
74                             acpi_os_map_memory(table_desc->address,
75                                                table_desc->length);
76                 }
77                 if (!table_desc->pointer) {
78                         return_ACPI_STATUS(AE_NO_MEMORY);
79                 }
80         }
81
82         /* FACS is the odd table, has no standard ACPI header and no checksum */
83
84         if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) {
85
86                 /* Always calculate checksum, ignore bad checksum if requested */
87
88                 status =
89                     acpi_tb_verify_checksum(table_desc->pointer,
90                                             table_desc->length);
91         }
92
93         return_ACPI_STATUS(status);
94 }
95
96 /*******************************************************************************
97  *
98  * FUNCTION:    acpi_tb_add_table
99  *
100  * PARAMETERS:  table_desc          - Table descriptor
101  *              table_index         - Where the table index is returned
102  *
103  * RETURN:      Status
104  *
105  * DESCRIPTION: This function is called to add the ACPI table
106  *
107  ******************************************************************************/
108
109 acpi_status
110 acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
111 {
112         u32 i;
113         u32 length;
114         acpi_status status = AE_OK;
115
116         ACPI_FUNCTION_TRACE(tb_add_table);
117
118         if (!table_desc->pointer) {
119                 status = acpi_tb_verify_table(table_desc);
120                 if (ACPI_FAILURE(status) || !table_desc->pointer) {
121                         return_ACPI_STATUS(status);
122                 }
123         }
124
125         /*
126          * Originally, we checked the table signature for "SSDT" or "PSDT" here.
127          * Next, we added support for OEMx tables, signature "OEM".
128          * Valid tables were encountered with a null signature, so we've just
129          * given up on validating the signature, since it seems to be a waste
130          * of code. The original code was removed (05/2008).
131          */
132
133         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
134
135         /* Check if table is already registered */
136
137         for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
138                 if (!acpi_gbl_root_table_list.tables[i].pointer) {
139                         status =
140                             acpi_tb_verify_table(&acpi_gbl_root_table_list.
141                                                  tables[i]);
142                         if (ACPI_FAILURE(status)
143                             || !acpi_gbl_root_table_list.tables[i].pointer) {
144                                 continue;
145                         }
146                 }
147
148                 /* Check for a table match on the entire table length */
149
150                 length = ACPI_MIN(table_desc->length,
151                                   acpi_gbl_root_table_list.tables[i].length);
152                 if (ACPI_MEMCMP(table_desc->pointer,
153                                 acpi_gbl_root_table_list.tables[i].pointer,
154                                 length)) {
155                         continue;
156                 }
157
158                 /*
159                  * Note: the current mechanism does not unregister a table if it is
160                  * dynamically unloaded. The related namespace entries are deleted,
161                  * but the table remains in the root table list.
162                  *
163                  * The assumption here is that the number of different tables that
164                  * will be loaded is actually small, and there is minimal overhead
165                  * in just keeping the table in case it is needed again.
166                  *
167                  * If this assumption changes in the future (perhaps on large
168                  * machines with many table load/unload operations), tables will
169                  * need to be unregistered when they are unloaded, and slots in the
170                  * root table list should be reused when empty.
171                  */
172
173                 /*
174                  * Table is already registered.
175                  * We can delete the table that was passed as a parameter.
176                  */
177                 acpi_tb_delete_table(table_desc);
178                 *table_index = i;
179
180                 if (acpi_gbl_root_table_list.tables[i].
181                     flags & ACPI_TABLE_IS_LOADED) {
182
183                         /* Table is still loaded, this is an error */
184
185                         status = AE_ALREADY_EXISTS;
186                         goto release;
187                 } else {
188                         /* Table was unloaded, allow it to be reloaded */
189
190                         table_desc->pointer =
191                             acpi_gbl_root_table_list.tables[i].pointer;
192                         table_desc->address =
193                             acpi_gbl_root_table_list.tables[i].address;
194                         status = AE_OK;
195                         goto print_header;
196                 }
197         }
198
199         /* Add the table to the global root table list */
200
201         status = acpi_tb_store_table(table_desc->address, table_desc->pointer,
202                                      table_desc->length, table_desc->flags,
203                                      table_index);
204         if (ACPI_FAILURE(status)) {
205                 goto release;
206         }
207
208       print_header:
209         acpi_tb_print_table_header(table_desc->address, table_desc->pointer);
210
211       release:
212         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
213         return_ACPI_STATUS(status);
214 }
215
216 /*******************************************************************************
217  *
218  * FUNCTION:    acpi_tb_resize_root_table_list
219  *
220  * PARAMETERS:  None
221  *
222  * RETURN:      Status
223  *
224  * DESCRIPTION: Expand the size of global table array
225  *
226  ******************************************************************************/
227
228 acpi_status acpi_tb_resize_root_table_list(void)
229 {
230         struct acpi_table_desc *tables;
231
232         ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
233
234         /* allow_resize flag is a parameter to acpi_initialize_tables */
235
236         if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
237                 ACPI_ERROR((AE_INFO,
238                             "Resize of Root Table Array is not allowed"));
239                 return_ACPI_STATUS(AE_SUPPORT);
240         }
241
242         /* Increase the Table Array size */
243
244         tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list.
245                                        size + ACPI_ROOT_TABLE_SIZE_INCREMENT)
246                                       * sizeof(struct acpi_table_desc));
247         if (!tables) {
248                 ACPI_ERROR((AE_INFO,
249                             "Could not allocate new root table array"));
250                 return_ACPI_STATUS(AE_NO_MEMORY);
251         }
252
253         /* Copy and free the previous table array */
254
255         if (acpi_gbl_root_table_list.tables) {
256                 ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
257                             (acpi_size) acpi_gbl_root_table_list.size *
258                             sizeof(struct acpi_table_desc));
259
260                 if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
261                         ACPI_FREE(acpi_gbl_root_table_list.tables);
262                 }
263         }
264
265         acpi_gbl_root_table_list.tables = tables;
266         acpi_gbl_root_table_list.size += ACPI_ROOT_TABLE_SIZE_INCREMENT;
267         acpi_gbl_root_table_list.flags |= (u8) ACPI_ROOT_ORIGIN_ALLOCATED;
268
269         return_ACPI_STATUS(AE_OK);
270 }
271
272 /*******************************************************************************
273  *
274  * FUNCTION:    acpi_tb_store_table
275  *
276  * PARAMETERS:  Address             - Table address
277  *              Table               - Table header
278  *              Length              - Table length
279  *              Flags               - flags
280  *
281  * RETURN:      Status and table index.
282  *
283  * DESCRIPTION: Add an ACPI table to the global table list
284  *
285  ******************************************************************************/
286
287 acpi_status
288 acpi_tb_store_table(acpi_physical_address address,
289                     struct acpi_table_header *table,
290                     u32 length, u8 flags, u32 *table_index)
291 {
292         acpi_status status = AE_OK;
293
294         /* Ensure that there is room for the table in the Root Table List */
295
296         if (acpi_gbl_root_table_list.count >= acpi_gbl_root_table_list.size) {
297                 status = acpi_tb_resize_root_table_list();
298                 if (ACPI_FAILURE(status)) {
299                         return (status);
300                 }
301         }
302
303         /* Initialize added table */
304
305         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
306             address = address;
307         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
308             pointer = table;
309         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].length =
310             length;
311         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
312             owner_id = 0;
313         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].flags =
314             flags;
315
316         ACPI_MOVE_32_TO_32(&
317                            (acpi_gbl_root_table_list.
318                             tables[acpi_gbl_root_table_list.count].signature),
319                            table->signature);
320
321         *table_index = acpi_gbl_root_table_list.count;
322         acpi_gbl_root_table_list.count++;
323         return (status);
324 }
325
326 /*******************************************************************************
327  *
328  * FUNCTION:    acpi_tb_delete_table
329  *
330  * PARAMETERS:  table_index         - Table index
331  *
332  * RETURN:      None
333  *
334  * DESCRIPTION: Delete one internal ACPI table
335  *
336  ******************************************************************************/
337
338 void acpi_tb_delete_table(struct acpi_table_desc *table_desc)
339 {
340         /* Table must be mapped or allocated */
341         if (!table_desc->pointer) {
342                 return;
343         }
344         switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
345         case ACPI_TABLE_ORIGIN_MAPPED:
346                 acpi_os_unmap_memory(table_desc->pointer, table_desc->length);
347                 break;
348         case ACPI_TABLE_ORIGIN_ALLOCATED:
349                 ACPI_FREE(table_desc->pointer);
350                 break;
351         default:;
352         }
353
354         table_desc->pointer = NULL;
355 }
356
357 /*******************************************************************************
358  *
359  * FUNCTION:    acpi_tb_terminate
360  *
361  * PARAMETERS:  None
362  *
363  * RETURN:      None
364  *
365  * DESCRIPTION: Delete all internal ACPI tables
366  *
367  ******************************************************************************/
368
369 void acpi_tb_terminate(void)
370 {
371         u32 i;
372
373         ACPI_FUNCTION_TRACE(tb_terminate);
374
375         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
376
377         /* Delete the individual tables */
378
379         for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
380                 acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]);
381         }
382
383         /*
384          * Delete the root table array if allocated locally. Array cannot be
385          * mapped, so we don't need to check for that flag.
386          */
387         if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
388                 ACPI_FREE(acpi_gbl_root_table_list.tables);
389         }
390
391         acpi_gbl_root_table_list.tables = NULL;
392         acpi_gbl_root_table_list.flags = 0;
393         acpi_gbl_root_table_list.count = 0;
394
395         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
396         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
397 }
398
399 /*******************************************************************************
400  *
401  * FUNCTION:    acpi_tb_delete_namespace_by_owner
402  *
403  * PARAMETERS:  table_index         - Table index
404  *
405  * RETURN:      None
406  *
407  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
408  *
409  ******************************************************************************/
410
411 void acpi_tb_delete_namespace_by_owner(u32 table_index)
412 {
413         acpi_owner_id owner_id;
414
415         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
416         if (table_index < acpi_gbl_root_table_list.count) {
417                 owner_id =
418                     acpi_gbl_root_table_list.tables[table_index].owner_id;
419         } else {
420                 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
421                 return;
422         }
423
424         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
425         acpi_ns_delete_namespace_by_owner(owner_id);
426 }
427
428 /*******************************************************************************
429  *
430  * FUNCTION:    acpi_tb_allocate_owner_id
431  *
432  * PARAMETERS:  table_index         - Table index
433  *
434  * RETURN:      Status
435  *
436  * DESCRIPTION: Allocates owner_id in table_desc
437  *
438  ******************************************************************************/
439
440 acpi_status acpi_tb_allocate_owner_id(u32 table_index)
441 {
442         acpi_status status = AE_BAD_PARAMETER;
443
444         ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
445
446         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
447         if (table_index < acpi_gbl_root_table_list.count) {
448                 status = acpi_ut_allocate_owner_id
449                     (&(acpi_gbl_root_table_list.tables[table_index].owner_id));
450         }
451
452         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
453         return_ACPI_STATUS(status);
454 }
455
456 /*******************************************************************************
457  *
458  * FUNCTION:    acpi_tb_release_owner_id
459  *
460  * PARAMETERS:  table_index         - Table index
461  *
462  * RETURN:      Status
463  *
464  * DESCRIPTION: Releases owner_id in table_desc
465  *
466  ******************************************************************************/
467
468 acpi_status acpi_tb_release_owner_id(u32 table_index)
469 {
470         acpi_status status = AE_BAD_PARAMETER;
471
472         ACPI_FUNCTION_TRACE(tb_release_owner_id);
473
474         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
475         if (table_index < acpi_gbl_root_table_list.count) {
476                 acpi_ut_release_owner_id(&
477                                          (acpi_gbl_root_table_list.
478                                           tables[table_index].owner_id));
479                 status = AE_OK;
480         }
481
482         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
483         return_ACPI_STATUS(status);
484 }
485
486 /*******************************************************************************
487  *
488  * FUNCTION:    acpi_tb_get_owner_id
489  *
490  * PARAMETERS:  table_index         - Table index
491  *              owner_id            - Where the table owner_id is returned
492  *
493  * RETURN:      Status
494  *
495  * DESCRIPTION: returns owner_id for the ACPI table
496  *
497  ******************************************************************************/
498
499 acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id)
500 {
501         acpi_status status = AE_BAD_PARAMETER;
502
503         ACPI_FUNCTION_TRACE(tb_get_owner_id);
504
505         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
506         if (table_index < acpi_gbl_root_table_list.count) {
507                 *owner_id =
508                     acpi_gbl_root_table_list.tables[table_index].owner_id;
509                 status = AE_OK;
510         }
511
512         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
513         return_ACPI_STATUS(status);
514 }
515
516 /*******************************************************************************
517  *
518  * FUNCTION:    acpi_tb_is_table_loaded
519  *
520  * PARAMETERS:  table_index         - Table index
521  *
522  * RETURN:      Table Loaded Flag
523  *
524  ******************************************************************************/
525
526 u8 acpi_tb_is_table_loaded(u32 table_index)
527 {
528         u8 is_loaded = FALSE;
529
530         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
531         if (table_index < acpi_gbl_root_table_list.count) {
532                 is_loaded = (u8)
533                     (acpi_gbl_root_table_list.tables[table_index].
534                      flags & ACPI_TABLE_IS_LOADED);
535         }
536
537         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
538         return (is_loaded);
539 }
540
541 /*******************************************************************************
542  *
543  * FUNCTION:    acpi_tb_set_table_loaded_flag
544  *
545  * PARAMETERS:  table_index         - Table index
546  *              is_loaded           - TRUE if table is loaded, FALSE otherwise
547  *
548  * RETURN:      None
549  *
550  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
551  *
552  ******************************************************************************/
553
554 void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
555 {
556
557         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
558         if (table_index < acpi_gbl_root_table_list.count) {
559                 if (is_loaded) {
560                         acpi_gbl_root_table_list.tables[table_index].flags |=
561                             ACPI_TABLE_IS_LOADED;
562                 } else {
563                         acpi_gbl_root_table_list.tables[table_index].flags &=
564                             ~ACPI_TABLE_IS_LOADED;
565                 }
566         }
567
568         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
569 }