diff options
author | Lin Ming <ming.m.lin@intel.com> | 2009-10-12 22:29:30 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-11-24 20:30:04 -0500 |
commit | 74d3ec77a5e0633b0c7a8490941432c2e4789037 (patch) | |
tree | e416b44a4533b77f85e30c65fe695a32d698e4d2 | |
parent | 0240d7b4f20f7d156a74dfdd0647a0231b7e8ef4 (diff) |
ACPICA: Remove possibility of executing _REG methods twice
If a custom address space handler is installed by the host
before the "initialize operation regions" phase of the ACPICA
initialization, any _REG methods for that address space could
be executed twice. This change fixes the problem.
ACPICA BZ 427.
http://www.acpica.org/bugzilla/show_bug.cgi?id=427
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>
-rw-r--r-- | drivers/acpi/acpica/evregion.c | 64 |
1 files changed, 59 insertions, 5 deletions
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 98c7f9c62653..c9fa040725d4 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c | |||
@@ -51,6 +51,10 @@ | |||
51 | ACPI_MODULE_NAME("evregion") | 51 | ACPI_MODULE_NAME("evregion") |
52 | 52 | ||
53 | /* Local prototypes */ | 53 | /* Local prototypes */ |
54 | static u8 | ||
55 | acpi_ev_has_default_handler(struct acpi_namespace_node *node, | ||
56 | acpi_adr_space_type space_id); | ||
57 | |||
54 | static acpi_status | 58 | static acpi_status |
55 | acpi_ev_reg_run(acpi_handle obj_handle, | 59 | acpi_ev_reg_run(acpi_handle obj_handle, |
56 | u32 level, void *context, void **return_value); | 60 | u32 level, void *context, void **return_value); |
@@ -142,6 +146,50 @@ acpi_status acpi_ev_install_region_handlers(void) | |||
142 | 146 | ||
143 | /******************************************************************************* | 147 | /******************************************************************************* |
144 | * | 148 | * |
149 | * FUNCTION: acpi_ev_has_default_handler | ||
150 | * | ||
151 | * PARAMETERS: Node - Namespace node for the device | ||
152 | * space_id - The address space ID | ||
153 | * | ||
154 | * RETURN: TRUE if default handler is installed, FALSE otherwise | ||
155 | * | ||
156 | * DESCRIPTION: Check if the default handler is installed for the requested | ||
157 | * space ID. | ||
158 | * | ||
159 | ******************************************************************************/ | ||
160 | |||
161 | static u8 | ||
162 | acpi_ev_has_default_handler(struct acpi_namespace_node *node, | ||
163 | acpi_adr_space_type space_id) | ||
164 | { | ||
165 | union acpi_operand_object *obj_desc; | ||
166 | union acpi_operand_object *handler_obj; | ||
167 | |||
168 | /* Must have an existing internal object */ | ||
169 | |||
170 | obj_desc = acpi_ns_get_attached_object(node); | ||
171 | if (obj_desc) { | ||
172 | handler_obj = obj_desc->device.handler; | ||
173 | |||
174 | /* Walk the linked list of handlers for this object */ | ||
175 | |||
176 | while (handler_obj) { | ||
177 | if (handler_obj->address_space.space_id == space_id) { | ||
178 | if (handler_obj->address_space.handler_flags & | ||
179 | ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { | ||
180 | return (TRUE); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | handler_obj = handler_obj->address_space.next; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | return (FALSE); | ||
189 | } | ||
190 | |||
191 | /******************************************************************************* | ||
192 | * | ||
145 | * FUNCTION: acpi_ev_initialize_op_regions | 193 | * FUNCTION: acpi_ev_initialize_op_regions |
146 | * | 194 | * |
147 | * PARAMETERS: None | 195 | * PARAMETERS: None |
@@ -169,12 +217,18 @@ acpi_status acpi_ev_initialize_op_regions(void) | |||
169 | 217 | ||
170 | for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { | 218 | for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { |
171 | /* | 219 | /* |
172 | * TBD: Make sure handler is the DEFAULT handler, otherwise | 220 | * Make sure the installed handler is the DEFAULT handler. If not the |
173 | * _REG will have already been run. | 221 | * default, the _REG methods will have already been run (when the |
222 | * handler was installed) | ||
174 | */ | 223 | */ |
175 | status = acpi_ev_execute_reg_methods(acpi_gbl_root_node, | 224 | if (acpi_ev_has_default_handler(acpi_gbl_root_node, |
176 | acpi_gbl_default_address_spaces | 225 | acpi_gbl_default_address_spaces |
177 | [i]); | 226 | [i])) { |
227 | status = | ||
228 | acpi_ev_execute_reg_methods(acpi_gbl_root_node, | ||
229 | acpi_gbl_default_address_spaces | ||
230 | [i]); | ||
231 | } | ||
178 | } | 232 | } |
179 | 233 | ||
180 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 234 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |