aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLin Ming <ming.m.lin@intel.com>2010-08-05 21:35:51 -0400
committerLen Brown <len.brown@intel.com>2010-10-01 01:47:43 -0400
commitb0ed7a915abac309fcb5a51bccd3782e3daa7417 (patch)
tree0bffdd098549d61180e6959217c84a05dadb99fa /drivers
parent09387b43153953006471dbb06ece6bf779d10937 (diff)
ACPICA/ACPI: Add new host interfaces for _OSI support
Adds install/remove interfaces so that the host can dynamically alter the global _OSI table. Also adds support for _OSI handlers. Additional support: new debugger command (osi), and test support in the acpiexec utility. Adds new file, utilities/utosi.c. ACPICA bugzilla 836. The Linux OSL _OSI code is also changed. acpi_osi_setup can't call acpi_install/remove_interface because ACPICA is not initialized yet at this early time. So we just save the osi string in acpi_osi_setup and will handle it later in a new function acpi_osi_setup_late. http://www.acpica.org/bugzilla/show_bug.cgi?id=836 Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Bob Moore <robert.moore@intel.com Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/acpica/Makefile3
-rw-r--r--drivers/acpi/acpica/acdebug.h2
-rw-r--r--drivers/acpi/acpica/acglobal.h6
-rw-r--r--drivers/acpi/acpica/aclocal.h5
-rw-r--r--drivers/acpi/acpica/acutils.h17
-rw-r--r--drivers/acpi/acpica/uteval.c147
-rw-r--r--drivers/acpi/acpica/utglobal.c2
-rw-r--r--drivers/acpi/acpica/utinit.c4
-rw-r--r--drivers/acpi/acpica/utmutex.c8
-rw-r--r--drivers/acpi/acpica/utosi.c379
-rw-r--r--drivers/acpi/acpica/utxface.c125
-rw-r--r--drivers/acpi/osl.c88
12 files changed, 593 insertions, 193 deletions
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index d93cc06f4bf8..262903e98196 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -44,4 +44,5 @@ acpi-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
44 44
45acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ 45acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
46 utcopy.o utdelete.o utglobal.o utmath.o utobject.o \ 46 utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
47 utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o 47 utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o \
48 utosi.o
diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h
index 48faf3eba9fb..72e9d5eb083c 100644
--- a/drivers/acpi/acpica/acdebug.h
+++ b/drivers/acpi/acpica/acdebug.h
@@ -105,6 +105,8 @@ void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg);
105acpi_status 105acpi_status
106acpi_db_display_objects(char *obj_type_arg, char *display_count_arg); 106acpi_db_display_objects(char *obj_type_arg, char *display_count_arg);
107 107
108void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg);
109
108acpi_status acpi_db_find_name_in_namespace(char *name_arg); 110acpi_status acpi_db_find_name_in_namespace(char *name_arg);
109 111
110void acpi_db_set_scope(char *name); 112void acpi_db_set_scope(char *name);
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 1d192142c691..fe50f57d4e42 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -187,6 +187,10 @@ ACPI_EXTERN u8 acpi_gbl_integer_bit_width;
187ACPI_EXTERN u8 acpi_gbl_integer_byte_width; 187ACPI_EXTERN u8 acpi_gbl_integer_byte_width;
188ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; 188ACPI_EXTERN u8 acpi_gbl_integer_nybble_width;
189 189
190/* Mutex for _OSI support */
191
192ACPI_EXTERN acpi_mutex acpi_gbl_osi_mutex;
193
190/* Reader/Writer lock is used for namespace walk and dynamic table unload */ 194/* Reader/Writer lock is used for namespace walk and dynamic table unload */
191 195
192ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock; 196ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock;
@@ -255,6 +259,7 @@ ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler;
255ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler; 259ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler;
256ACPI_EXTERN void *acpi_gbl_table_handler_context; 260ACPI_EXTERN void *acpi_gbl_table_handler_context;
257ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; 261ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk;
262ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler;
258 263
259/* Owner ID support */ 264/* Owner ID support */
260 265
@@ -275,6 +280,7 @@ ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present;
275ACPI_EXTERN u8 acpi_gbl_events_initialized; 280ACPI_EXTERN u8 acpi_gbl_events_initialized;
276ACPI_EXTERN u8 acpi_gbl_system_awake_and_running; 281ACPI_EXTERN u8 acpi_gbl_system_awake_and_running;
277ACPI_EXTERN u8 acpi_gbl_osi_data; 282ACPI_EXTERN u8 acpi_gbl_osi_data;
283ACPI_EXTERN struct acpi_interface_info *acpi_gbl_supported_interfaces;
278 284
279#ifndef DEFINE_ACPI_GLOBALS 285#ifndef DEFINE_ACPI_GLOBALS
280 286
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index df85b53a674f..53f7512b060f 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -914,9 +914,14 @@ struct acpi_bit_register_info {
914 914
915struct acpi_interface_info { 915struct acpi_interface_info {
916 char *name; 916 char *name;
917 struct acpi_interface_info *next;
918 u8 flags;
917 u8 value; 919 u8 value;
918}; 920};
919 921
922#define ACPI_OSI_INVALID 0x01
923#define ACPI_OSI_DYNAMIC 0x02
924
920struct acpi_port_info { 925struct acpi_port_info {
921 char *name; 926 char *name;
922 u16 start; 927 u16 start;
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index 35df755251ce..78e01211c7a1 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -312,8 +312,6 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list);
312/* 312/*
313 * uteval - object evaluation 313 * uteval - object evaluation
314 */ 314 */
315acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state);
316
317acpi_status 315acpi_status
318acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, 316acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
319 char *path, 317 char *path,
@@ -395,6 +393,21 @@ acpi_status
395acpi_ut_get_object_size(union acpi_operand_object *obj, acpi_size * obj_length); 393acpi_ut_get_object_size(union acpi_operand_object *obj, acpi_size * obj_length);
396 394
397/* 395/*
396 * utosi - Support for the _OSI predefined control method
397 */
398acpi_status acpi_ut_initialize_interfaces(void);
399
400void acpi_ut_interface_terminate(void);
401
402acpi_status acpi_ut_install_interface(acpi_string interface_name);
403
404acpi_status acpi_ut_remove_interface(acpi_string interface_name);
405
406struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name);
407
408acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state);
409
410/*
398 * utstate - Generic state creation/cache routines 411 * utstate - Generic state creation/cache routines
399 */ 412 */
400void 413void
diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c
index 6dfdeb653490..22f59ef604e0 100644
--- a/drivers/acpi/acpica/uteval.c
+++ b/drivers/acpi/acpica/uteval.c
@@ -48,153 +48,6 @@
48#define _COMPONENT ACPI_UTILITIES 48#define _COMPONENT ACPI_UTILITIES
49ACPI_MODULE_NAME("uteval") 49ACPI_MODULE_NAME("uteval")
50 50
51/*
52 * Strings supported by the _OSI predefined (internal) method.
53 *
54 * March 2009: Removed "Linux" as this host no longer wants to respond true
55 * for this string. Basically, the only safe OS strings are windows-related
56 * and in many or most cases represent the only test path within the
57 * BIOS-provided ASL code.
58 *
59 * The second element of each entry is used to track the newest version of
60 * Windows that the BIOS has requested.
61 */
62static struct acpi_interface_info acpi_interfaces_supported[] = {
63 /* Operating System Vendor Strings */
64
65 {"Windows 2000", ACPI_OSI_WIN_2000}, /* Windows 2000 */
66 {"Windows 2001", ACPI_OSI_WIN_XP}, /* Windows XP */
67 {"Windows 2001 SP1", ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */
68 {"Windows 2001.1", ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */
69 {"Windows 2001 SP2", ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */
70 {"Windows 2001.1 SP1", ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */
71 {"Windows 2006", ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */
72 {"Windows 2006.1", ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */
73 {"Windows 2006 SP1", ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */
74 {"Windows 2009", ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */
75
76 /* Feature Group Strings */
77
78 {"Extended Address Space Descriptor", 0}
79
80 /*
81 * All "optional" feature group strings (features that are implemented
82 * by the host) should be implemented in the host version of
83 * acpi_os_validate_interface and should not be added here.
84 */
85};
86
87/*******************************************************************************
88 *
89 * FUNCTION: acpi_ut_osi_implementation
90 *
91 * PARAMETERS: walk_state - Current walk state
92 *
93 * RETURN: Status
94 *
95 * DESCRIPTION: Implementation of the _OSI predefined control method
96 *
97 ******************************************************************************/
98
99acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
100{
101 acpi_status status;
102 union acpi_operand_object *string_desc;
103 union acpi_operand_object *return_desc;
104 u32 return_value;
105 u32 i;
106
107 ACPI_FUNCTION_TRACE(ut_osi_implementation);
108
109 /* Validate the string input argument */
110
111 string_desc = walk_state->arguments[0].object;
112 if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
113 return_ACPI_STATUS(AE_TYPE);
114 }
115
116 /* Create a return object */
117
118 return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
119 if (!return_desc) {
120 return_ACPI_STATUS(AE_NO_MEMORY);
121 }
122
123 /* Default return value is 0, NOT SUPPORTED */
124
125 return_value = 0;
126
127 /* Compare input string to static table of supported interfaces */
128
129 for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
130 if (!ACPI_STRCMP(string_desc->string.pointer,
131 acpi_interfaces_supported[i].name)) {
132 /*
133 * The interface is supported.
134 * Update the osi_data if necessary. We keep track of the latest
135 * version of Windows that has been requested by the BIOS.
136 */
137 if (acpi_interfaces_supported[i].value >
138 acpi_gbl_osi_data) {
139 acpi_gbl_osi_data =
140 acpi_interfaces_supported[i].value;
141 }
142
143 return_value = ACPI_UINT32_MAX;
144 goto exit;
145 }
146 }
147
148 /*
149 * Did not match the string in the static table, call the host OSL to
150 * check for a match with one of the optional strings (such as
151 * "Module Device", "3.0 Thermal Model", etc.)
152 */
153 status = acpi_os_validate_interface(string_desc->string.pointer);
154 if (ACPI_SUCCESS(status)) {
155
156 /* The interface is supported */
157
158 return_value = ACPI_UINT32_MAX;
159 }
160
161exit:
162 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO,
163 "ACPI: BIOS _OSI(%s) is %ssupported\n",
164 string_desc->string.pointer, return_value == 0 ? "not " : ""));
165
166 /* Complete the return value */
167
168 return_desc->integer.value = return_value;
169 walk_state->return_desc = return_desc;
170 return_ACPI_STATUS (AE_OK);
171}
172
173/*******************************************************************************
174 *
175 * FUNCTION: acpi_osi_invalidate
176 *
177 * PARAMETERS: interface_string
178 *
179 * RETURN: Status
180 *
181 * DESCRIPTION: invalidate string in pre-defiend _OSI string list
182 *
183 ******************************************************************************/
184
185acpi_status acpi_osi_invalidate(char *interface)
186{
187 int i;
188
189 for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
190 if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i].name)) {
191 *acpi_interfaces_supported[i].name = '\0';
192 return AE_OK;
193 }
194 }
195 return AE_NOT_FOUND;
196}
197
198/******************************************************************************* 51/*******************************************************************************
199 * 52 *
200 * FUNCTION: acpi_ut_evaluate_object 53 * FUNCTION: acpi_ut_evaluate_object
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c
index 0558747579ef..45f63340ca5f 100644
--- a/drivers/acpi/acpica/utglobal.c
+++ b/drivers/acpi/acpica/utglobal.c
@@ -774,6 +774,7 @@ acpi_status acpi_ut_init_globals(void)
774 acpi_gbl_exception_handler = NULL; 774 acpi_gbl_exception_handler = NULL;
775 acpi_gbl_init_handler = NULL; 775 acpi_gbl_init_handler = NULL;
776 acpi_gbl_table_handler = NULL; 776 acpi_gbl_table_handler = NULL;
777 acpi_gbl_interface_handler = NULL;
777 778
778 /* Global Lock support */ 779 /* Global Lock support */
779 780
@@ -800,6 +801,7 @@ acpi_status acpi_ut_init_globals(void)
800 acpi_gbl_debugger_configuration = DEBUGGER_THREADING; 801 acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
801 acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; 802 acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
802 acpi_gbl_osi_data = 0; 803 acpi_gbl_osi_data = 0;
804 acpi_gbl_osi_mutex = NULL;
803 805
804 /* Hardware oriented */ 806 /* Hardware oriented */
805 807
diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c
index a39c93dac719..c1b1c803ea9b 100644
--- a/drivers/acpi/acpica/utinit.c
+++ b/drivers/acpi/acpica/utinit.c
@@ -117,6 +117,10 @@ void acpi_ut_subsystem_shutdown(void)
117 /* Close the acpi_event Handling */ 117 /* Close the acpi_event Handling */
118 118
119 acpi_ev_terminate(); 119 acpi_ev_terminate();
120
121 /* Delete any dynamic _OSI interfaces */
122
123 acpi_ut_interface_terminate();
120#endif 124#endif
121 125
122 /* Close the Namespace */ 126 /* Close the Namespace */
diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c
index f5cca3a1300c..b07b425e2113 100644
--- a/drivers/acpi/acpica/utmutex.c
+++ b/drivers/acpi/acpica/utmutex.c
@@ -86,6 +86,12 @@ acpi_status acpi_ut_mutex_initialize(void)
86 spin_lock_init(acpi_gbl_gpe_lock); 86 spin_lock_init(acpi_gbl_gpe_lock);
87 spin_lock_init(acpi_gbl_hardware_lock); 87 spin_lock_init(acpi_gbl_hardware_lock);
88 88
89 /* Mutex for _OSI support */
90 status = acpi_os_create_mutex(&acpi_gbl_osi_mutex);
91 if (ACPI_FAILURE(status)) {
92 return_ACPI_STATUS(status);
93 }
94
89 /* Create the reader/writer lock for namespace access */ 95 /* Create the reader/writer lock for namespace access */
90 96
91 status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock); 97 status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock);
@@ -117,6 +123,8 @@ void acpi_ut_mutex_terminate(void)
117 acpi_ut_delete_mutex(i); 123 acpi_ut_delete_mutex(i);
118 } 124 }
119 125
126 acpi_os_delete_mutex(acpi_gbl_osi_mutex);
127
120 /* Delete the spinlocks */ 128 /* Delete the spinlocks */
121 129
122 acpi_os_delete_lock(acpi_gbl_gpe_lock); 130 acpi_os_delete_lock(acpi_gbl_gpe_lock);
diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c
new file mode 100644
index 000000000000..0a37950c96aa
--- /dev/null
+++ b/drivers/acpi/acpica/utosi.c
@@ -0,0 +1,379 @@
1/******************************************************************************
2 *
3 * Module Name: utosi - Support for the _OSI predefined control method
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2010, 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 "accommon.h"
46
47#define _COMPONENT ACPI_UTILITIES
48ACPI_MODULE_NAME("utosi")
49
50/*
51 * Strings supported by the _OSI predefined control method (which is
52 * implemented internally within this module.)
53 *
54 * March 2009: Removed "Linux" as this host no longer wants to respond true
55 * for this string. Basically, the only safe OS strings are windows-related
56 * and in many or most cases represent the only test path within the
57 * BIOS-provided ASL code.
58 *
59 * The last element of each entry is used to track the newest version of
60 * Windows that the BIOS has requested.
61 */
62static struct acpi_interface_info acpi_default_supported_interfaces[] = {
63 /* Operating System Vendor Strings */
64
65 {"Windows 2000", NULL, 0, ACPI_OSI_WIN_2000}, /* Windows 2000 */
66 {"Windows 2001", NULL, 0, ACPI_OSI_WIN_XP}, /* Windows XP */
67 {"Windows 2001 SP1", NULL, 0, ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */
68 {"Windows 2001.1", NULL, 0, ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */
69 {"Windows 2001 SP2", NULL, 0, ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */
70 {"Windows 2001.1 SP1", NULL, 0, ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */
71 {"Windows 2006", NULL, 0, ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */
72 {"Windows 2006.1", NULL, 0, ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */
73 {"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */
74 {"Windows 2009", NULL, 0, ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */
75
76 /* Feature Group Strings */
77
78 {"Extended Address Space Descriptor", NULL, 0, 0}
79
80 /*
81 * All "optional" feature group strings (features that are implemented
82 * by the host) should be dynamically added by the host via
83 * acpi_install_interface and should not be manually added here.
84 *
85 * Examples of optional feature group strings:
86 *
87 * "Module Device"
88 * "Processor Device"
89 * "3.0 Thermal Model"
90 * "3.0 _SCP Extensions"
91 * "Processor Aggregator Device"
92 */
93};
94
95/*******************************************************************************
96 *
97 * FUNCTION: acpi_ut_initialize_interfaces
98 *
99 * PARAMETERS: None
100 *
101 * RETURN: Status
102 *
103 * DESCRIPTION: Initialize the global _OSI supported interfaces list
104 *
105 ******************************************************************************/
106
107acpi_status acpi_ut_initialize_interfaces(void)
108{
109 u32 i;
110
111 (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
112 acpi_gbl_supported_interfaces = acpi_default_supported_interfaces;
113
114 /* Link the static list of supported interfaces */
115
116 for (i = 0;
117 i < (ACPI_ARRAY_LENGTH(acpi_default_supported_interfaces) - 1);
118 i++) {
119 acpi_default_supported_interfaces[i].next =
120 &acpi_default_supported_interfaces[(acpi_size) i + 1];
121 }
122
123 acpi_os_release_mutex(acpi_gbl_osi_mutex);
124 return (AE_OK);
125}
126
127/*******************************************************************************
128 *
129 * FUNCTION: acpi_ut_interface_terminate
130 *
131 * PARAMETERS: None
132 *
133 * RETURN: None
134 *
135 * DESCRIPTION: Delete all interfaces in the global list. Sets
136 * acpi_gbl_supported_interfaces to NULL.
137 *
138 ******************************************************************************/
139
140void acpi_ut_interface_terminate(void)
141{
142 struct acpi_interface_info *next_interface;
143
144 (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
145 next_interface = acpi_gbl_supported_interfaces;
146
147 while (next_interface) {
148 acpi_gbl_supported_interfaces = next_interface->next;
149
150 /* Only interfaces added at runtime can be freed */
151
152 if (next_interface->flags & ACPI_OSI_DYNAMIC) {
153 ACPI_FREE(next_interface->name);
154 ACPI_FREE(next_interface);
155 }
156
157 next_interface = acpi_gbl_supported_interfaces;
158 }
159
160 acpi_os_release_mutex(acpi_gbl_osi_mutex);
161}
162
163/*******************************************************************************
164 *
165 * FUNCTION: acpi_ut_install_interface
166 *
167 * PARAMETERS: interface_name - The interface to install
168 *
169 * RETURN: Status
170 *
171 * DESCRIPTION: Install the interface into the global interface list.
172 * Caller MUST hold acpi_gbl_osi_mutex
173 *
174 ******************************************************************************/
175
176acpi_status acpi_ut_install_interface(acpi_string interface_name)
177{
178 struct acpi_interface_info *interface_info;
179
180 /* Allocate info block and space for the name string */
181
182 interface_info =
183 ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_interface_info));
184 if (!interface_info) {
185 return (AE_NO_MEMORY);
186 }
187
188 interface_info->name =
189 ACPI_ALLOCATE_ZEROED(ACPI_STRLEN(interface_name) + 1);
190 if (!interface_info->name) {
191 ACPI_FREE(interface_info);
192 return (AE_NO_MEMORY);
193 }
194
195 /* Initialize new info and insert at the head of the global list */
196
197 ACPI_STRCPY(interface_info->name, interface_name);
198 interface_info->flags = ACPI_OSI_DYNAMIC;
199 interface_info->next = acpi_gbl_supported_interfaces;
200
201 acpi_gbl_supported_interfaces = interface_info;
202 return (AE_OK);
203}
204
205/*******************************************************************************
206 *
207 * FUNCTION: acpi_ut_remove_interface
208 *
209 * PARAMETERS: interface_name - The interface to remove
210 *
211 * RETURN: Status
212 *
213 * DESCRIPTION: Remove the interface from the global interface list.
214 * Caller MUST hold acpi_gbl_osi_mutex
215 *
216 ******************************************************************************/
217
218acpi_status acpi_ut_remove_interface(acpi_string interface_name)
219{
220 struct acpi_interface_info *previous_interface;
221 struct acpi_interface_info *next_interface;
222
223 previous_interface = next_interface = acpi_gbl_supported_interfaces;
224 while (next_interface) {
225 if (!ACPI_STRCMP(interface_name, next_interface->name)) {
226
227 /* Found: name is in either the static list or was added at runtime */
228
229 if (next_interface->flags & ACPI_OSI_DYNAMIC) {
230
231 /* Interface was added dynamically, remove and free it */
232
233 if (previous_interface == next_interface) {
234 acpi_gbl_supported_interfaces =
235 next_interface->next;
236 } else {
237 previous_interface->next =
238 next_interface->next;
239 }
240
241 ACPI_FREE(next_interface->name);
242 ACPI_FREE(next_interface);
243 } else {
244 /*
245 * Interface is in static list. If marked invalid, then it
246 * does not actually exist. Else, mark it invalid.
247 */
248 if (next_interface->flags & ACPI_OSI_INVALID) {
249 return (AE_NOT_EXIST);
250 }
251
252 next_interface->flags |= ACPI_OSI_INVALID;
253 }
254
255 return (AE_OK);
256 }
257
258 previous_interface = next_interface;
259 next_interface = next_interface->next;
260 }
261
262 /* Interface was not found */
263
264 return (AE_NOT_EXIST);
265}
266
267/*******************************************************************************
268 *
269 * FUNCTION: acpi_ut_get_interface
270 *
271 * PARAMETERS: interface_name - The interface to find
272 *
273 * RETURN: struct acpi_interface_info if found. NULL if not found.
274 *
275 * DESCRIPTION: Search for the specified interface name in the global list.
276 * Caller MUST hold acpi_gbl_osi_mutex
277 *
278 ******************************************************************************/
279
280struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name)
281{
282 struct acpi_interface_info *next_interface;
283
284 next_interface = acpi_gbl_supported_interfaces;
285 while (next_interface) {
286 if (!ACPI_STRCMP(interface_name, next_interface->name)) {
287 return (next_interface);
288 }
289
290 next_interface = next_interface->next;
291 }
292
293 return (NULL);
294}
295
296/*******************************************************************************
297 *
298 * FUNCTION: acpi_ut_osi_implementation
299 *
300 * PARAMETERS: walk_state - Current walk state
301 *
302 * RETURN: Status
303 *
304 * DESCRIPTION: Implementation of the _OSI predefined control method. When
305 * an invocation of _OSI is encountered in the system AML,
306 * control is transferred to this function.
307 *
308 ******************************************************************************/
309
310acpi_status acpi_ut_osi_implementation(struct acpi_walk_state * walk_state)
311{
312 union acpi_operand_object *string_desc;
313 union acpi_operand_object *return_desc;
314 struct acpi_interface_info *interface_info;
315 acpi_interface_handler interface_handler;
316 u32 return_value;
317
318 ACPI_FUNCTION_TRACE(ut_osi_implementation);
319
320 /* Validate the string input argument (from the AML caller) */
321
322 string_desc = walk_state->arguments[0].object;
323 if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
324 return_ACPI_STATUS(AE_TYPE);
325 }
326
327 /* Create a return object */
328
329 return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
330 if (!return_desc) {
331 return_ACPI_STATUS(AE_NO_MEMORY);
332 }
333
334 /* Default return value is 0, NOT SUPPORTED */
335
336 return_value = 0;
337 (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
338
339 /* Lookup the interface in the global _OSI list */
340
341 interface_info = acpi_ut_get_interface(string_desc->string.pointer);
342 if (interface_info && !(interface_info->flags & ACPI_OSI_INVALID)) {
343 /*
344 * The interface is supported.
345 * Update the osi_data if necessary. We keep track of the latest
346 * version of Windows that has been requested by the BIOS.
347 */
348 if (interface_info->value > acpi_gbl_osi_data) {
349 acpi_gbl_osi_data = interface_info->value;
350 }
351
352 return_value = ACPI_UINT32_MAX;
353 }
354
355 acpi_os_release_mutex(acpi_gbl_osi_mutex);
356
357 /*
358 * Invoke an optional _OSI interface handler. The host OS may wish
359 * to do some interface-specific handling. For example, warn about
360 * certain interfaces or override the true/false support value.
361 */
362 interface_handler = acpi_gbl_interface_handler;
363 if (interface_handler) {
364 return_value =
365 interface_handler(string_desc->string.pointer,
366 return_value);
367 }
368
369 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
370 "ACPI: BIOS _OSI(\"%s\") is %ssupported\n",
371 string_desc->string.pointer,
372 return_value == 0 ? "not " : ""));
373
374 /* Complete the return object */
375
376 return_desc->integer.value = return_value;
377 walk_state->return_desc = return_desc;
378 return_ACPI_STATUS(AE_OK);
379}
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c
index 7f8cefcb2b32..c2da90f5fbe9 100644
--- a/drivers/acpi/acpica/utxface.c
+++ b/drivers/acpi/acpica/utxface.c
@@ -110,6 +110,15 @@ acpi_status __init acpi_initialize_subsystem(void)
110 return_ACPI_STATUS(status); 110 return_ACPI_STATUS(status);
111 } 111 }
112 112
113 /* Initialize the global OSI interfaces list with the static names */
114
115 status = acpi_ut_initialize_interfaces();
116 if (ACPI_FAILURE(status)) {
117 ACPI_EXCEPTION((AE_INFO, status,
118 "During OSI interfaces initialization"));
119 return_ACPI_STATUS(status);
120 }
121
113 /* If configured, initialize the AML debugger */ 122 /* If configured, initialize the AML debugger */
114 123
115 ACPI_DEBUGGER_EXEC(status = acpi_db_initialize()); 124 ACPI_DEBUGGER_EXEC(status = acpi_db_initialize());
@@ -506,6 +515,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function)
506 515
507ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler) 516ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler)
508#endif /* ACPI_FUTURE_USAGE */ 517#endif /* ACPI_FUTURE_USAGE */
518
509/***************************************************************************** 519/*****************************************************************************
510 * 520 *
511 * FUNCTION: acpi_purge_cached_objects 521 * FUNCTION: acpi_purge_cached_objects
@@ -529,4 +539,117 @@ acpi_status acpi_purge_cached_objects(void)
529} 539}
530 540
531ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects) 541ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects)
532#endif 542
543/*****************************************************************************
544 *
545 * FUNCTION: acpi_install_interface
546 *
547 * PARAMETERS: interface_name - The interface to install
548 *
549 * RETURN: Status
550 *
551 * DESCRIPTION: Install an _OSI interface to the global list
552 *
553 ****************************************************************************/
554acpi_status acpi_install_interface(acpi_string interface_name)
555{
556 acpi_status status;
557 struct acpi_interface_info *interface_info;
558
559 /* Parameter validation */
560
561 if (!interface_name || (ACPI_STRLEN(interface_name) == 0)) {
562 return (AE_BAD_PARAMETER);
563 }
564
565 (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
566
567 /* Check if the interface name is already in the global list */
568
569 interface_info = acpi_ut_get_interface(interface_name);
570 if (interface_info) {
571 /*
572 * The interface already exists in the list. This is OK if the
573 * interface has been marked invalid -- just clear the bit.
574 */
575 if (interface_info->flags & ACPI_OSI_INVALID) {
576 interface_info->flags &= ~ACPI_OSI_INVALID;
577 status = AE_OK;
578 } else {
579 status = AE_ALREADY_EXISTS;
580 }
581 } else {
582 /* New interface name, install into the global list */
583
584 status = acpi_ut_install_interface(interface_name);
585 }
586
587 acpi_os_release_mutex(acpi_gbl_osi_mutex);
588 return (status);
589}
590
591ACPI_EXPORT_SYMBOL(acpi_install_interface)
592
593/*****************************************************************************
594 *
595 * FUNCTION: acpi_remove_interface
596 *
597 * PARAMETERS: interface_name - The interface to remove
598 *
599 * RETURN: Status
600 *
601 * DESCRIPTION: Remove an _OSI interface from the global list
602 *
603 ****************************************************************************/
604acpi_status acpi_remove_interface(acpi_string interface_name)
605{
606 acpi_status status;
607
608 /* Parameter validation */
609
610 if (!interface_name || (ACPI_STRLEN(interface_name) == 0)) {
611 return (AE_BAD_PARAMETER);
612 }
613
614 (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
615
616 status = acpi_ut_remove_interface(interface_name);
617
618 acpi_os_release_mutex(acpi_gbl_osi_mutex);
619 return (status);
620}
621
622ACPI_EXPORT_SYMBOL(acpi_remove_interface)
623
624/*****************************************************************************
625 *
626 * FUNCTION: acpi_install_interface_handler
627 *
628 * PARAMETERS: Handler - The _OSI interface handler to install
629 * NULL means "remove existing handler"
630 *
631 * RETURN: Status
632 *
633 * DESCRIPTION: Install a handler for the predefined _OSI ACPI method.
634 * invoked during execution of the internal implementation of
635 * _OSI. A NULL handler simply removes any existing handler.
636 *
637 ****************************************************************************/
638acpi_status acpi_install_interface_handler(acpi_interface_handler handler)
639{
640 acpi_status status = AE_OK;
641
642 (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
643
644 if (handler && acpi_gbl_interface_handler) {
645 status = AE_ALREADY_EXISTS;
646 } else {
647 acpi_gbl_interface_handler = handler;
648 }
649
650 acpi_os_release_mutex(acpi_gbl_osi_mutex);
651 return (status);
652}
653
654ACPI_EXPORT_SYMBOL(acpi_install_interface_handler)
655#endif /* !ACPI_ASL_COMPILER */
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index a351291496ff..6652c4929391 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -96,7 +96,9 @@ static LIST_HEAD(resource_list_head);
96static DEFINE_SPINLOCK(acpi_res_lock); 96static DEFINE_SPINLOCK(acpi_res_lock);
97 97
98#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ 98#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
99static char osi_additional_string[OSI_STRING_LENGTH_MAX]; 99static char osi_setup_string[OSI_STRING_LENGTH_MAX];
100
101static void __init acpi_osi_setup_late(void);
100 102
101/* 103/*
102 * The story of _OSI(Linux) 104 * The story of _OSI(Linux)
@@ -138,6 +140,20 @@ static struct osi_linux {
138 unsigned int known:1; 140 unsigned int known:1;
139} osi_linux = { 0, 0, 0, 0}; 141} osi_linux = { 0, 0, 0, 0};
140 142
143static u32 acpi_osi_handler(acpi_string interface, u32 supported)
144{
145 if (!strcmp("Linux", interface)) {
146
147 printk(KERN_NOTICE PREFIX
148 "BIOS _OSI(Linux) query %s%s\n",
149 osi_linux.enable ? "honored" : "ignored",
150 osi_linux.cmdline ? " via cmdline" :
151 osi_linux.dmi ? " via DMI" : "");
152 }
153
154 return supported;
155}
156
141static void __init acpi_request_region (struct acpi_generic_address *addr, 157static void __init acpi_request_region (struct acpi_generic_address *addr,
142 unsigned int length, char *desc) 158 unsigned int length, char *desc)
143{ 159{
@@ -198,6 +214,8 @@ acpi_status acpi_os_initialize1(void)
198 BUG_ON(!kacpid_wq); 214 BUG_ON(!kacpid_wq);
199 BUG_ON(!kacpi_notify_wq); 215 BUG_ON(!kacpi_notify_wq);
200 BUG_ON(!kacpi_hotplug_wq); 216 BUG_ON(!kacpi_hotplug_wq);
217 acpi_install_interface_handler(acpi_osi_handler);
218 acpi_osi_setup_late();
201 return AE_OK; 219 return AE_OK;
202} 220}
203 221
@@ -979,6 +997,12 @@ static void __init set_osi_linux(unsigned int enable)
979 printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n", 997 printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n",
980 enable ? "Add": "Delet"); 998 enable ? "Add": "Delet");
981 } 999 }
1000
1001 if (osi_linux.enable)
1002 acpi_osi_setup("Linux");
1003 else
1004 acpi_osi_setup("!Linux");
1005
982 return; 1006 return;
983} 1007}
984 1008
@@ -1013,21 +1037,33 @@ void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
1013 * string starting with '!' disables that string 1037 * string starting with '!' disables that string
1014 * otherwise string is added to list, augmenting built-in strings 1038 * otherwise string is added to list, augmenting built-in strings
1015 */ 1039 */
1016int __init acpi_osi_setup(char *str) 1040static void __init acpi_osi_setup_late(void)
1017{ 1041{
1018 if (str == NULL || *str == '\0') { 1042 char *str = osi_setup_string;
1019 printk(KERN_INFO PREFIX "_OSI method disabled\n"); 1043
1020 acpi_gbl_create_osi_method = FALSE; 1044 if (*str == '\0')
1021 } else if (!strcmp("!Linux", str)) { 1045 return;
1046
1047 if (!strcmp("!Linux", str)) {
1022 acpi_cmdline_osi_linux(0); /* !enable */ 1048 acpi_cmdline_osi_linux(0); /* !enable */
1023 } else if (*str == '!') { 1049 } else if (*str == '!') {
1024 if (acpi_osi_invalidate(++str) == AE_OK) 1050 if (acpi_remove_interface(++str) == AE_OK)
1025 printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); 1051 printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
1026 } else if (!strcmp("Linux", str)) { 1052 } else if (!strcmp("Linux", str)) {
1027 acpi_cmdline_osi_linux(1); /* enable */ 1053 acpi_cmdline_osi_linux(1); /* enable */
1028 } else if (*osi_additional_string == '\0') { 1054 } else {
1029 strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX); 1055 if (acpi_install_interface(str) == AE_OK)
1030 printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); 1056 printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
1057 }
1058}
1059
1060int __init acpi_osi_setup(char *str)
1061{
1062 if (str == NULL || *str == '\0') {
1063 printk(KERN_INFO PREFIX "_OSI method disabled\n");
1064 acpi_gbl_create_osi_method = FALSE;
1065 } else {
1066 strncpy(osi_setup_string, str, OSI_STRING_LENGTH_MAX);
1031 } 1067 }
1032 1068
1033 return 1; 1069 return 1;
@@ -1284,38 +1320,6 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
1284 return (AE_OK); 1320 return (AE_OK);
1285} 1321}
1286 1322
1287/******************************************************************************
1288 *
1289 * FUNCTION: acpi_os_validate_interface
1290 *
1291 * PARAMETERS: interface - Requested interface to be validated
1292 *
1293 * RETURN: AE_OK if interface is supported, AE_SUPPORT otherwise
1294 *
1295 * DESCRIPTION: Match an interface string to the interfaces supported by the
1296 * host. Strings originate from an AML call to the _OSI method.
1297 *
1298 *****************************************************************************/
1299
1300acpi_status
1301acpi_os_validate_interface (char *interface)
1302{
1303 if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX))
1304 return AE_OK;
1305 if (!strcmp("Linux", interface)) {
1306
1307 printk(KERN_NOTICE PREFIX
1308 "BIOS _OSI(Linux) query %s%s\n",
1309 osi_linux.enable ? "honored" : "ignored",
1310 osi_linux.cmdline ? " via cmdline" :
1311 osi_linux.dmi ? " via DMI" : "");
1312
1313 if (osi_linux.enable)
1314 return AE_OK;
1315 }
1316 return AE_SUPPORT;
1317}
1318
1319static inline int acpi_res_list_add(struct acpi_res_list *res) 1323static inline int acpi_res_list_add(struct acpi_res_list *res)
1320{ 1324{
1321 struct acpi_res_list *res_list_elem; 1325 struct acpi_res_list *res_list_elem;