diff options
author | Lin Ming <ming.m.lin@intel.com> | 2009-11-12 21:06:08 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-11-24 21:31:10 -0500 |
commit | 2263576cfc6e8f6ab038126c3254404b9fcb1c33 (patch) | |
tree | 1c1bd06cc5d89978a23a19d549764d3dc8c7c6c4 /drivers/acpi/acpica | |
parent | 7d5d05d0704127c9acd24090c14731c111bd0af1 (diff) |
ACPICA: Add post-order callback to acpi_walk_namespace
The existing interface only has a pre-order callback. This change
adds an additional parameter for a post-order callback which will
be more useful for bus scans. ACPICA BZ 779.
Also update the external calls to acpi_walk_namespace.
http://www.acpica.org/bugzilla/show_bug.cgi?id=779
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/acpi/acpica')
-rw-r--r-- | drivers/acpi/acpica/acnamesp.h | 3 | ||||
-rw-r--r-- | drivers/acpi/acpica/dsinit.c | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/evgpeblk.c | 8 | ||||
-rw-r--r-- | drivers/acpi/acpica/evregion.c | 6 | ||||
-rw-r--r-- | drivers/acpi/acpica/nsdump.c | 4 | ||||
-rw-r--r-- | drivers/acpi/acpica/nsdumpdv.c | 3 | ||||
-rw-r--r-- | drivers/acpi/acpica/nsinit.c | 8 | ||||
-rw-r--r-- | drivers/acpi/acpica/nswalk.c | 200 | ||||
-rw-r--r-- | drivers/acpi/acpica/nsxfeval.c | 32 |
9 files changed, 155 insertions, 111 deletions
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 09a2764c734b..168e60893a2a 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h | |||
@@ -104,7 +104,8 @@ acpi_ns_walk_namespace(acpi_object_type type, | |||
104 | acpi_handle start_object, | 104 | acpi_handle start_object, |
105 | u32 max_depth, | 105 | u32 max_depth, |
106 | u32 flags, | 106 | u32 flags, |
107 | acpi_walk_callback user_function, | 107 | acpi_walk_callback pre_order_visit, |
108 | acpi_walk_callback post_order_visit, | ||
108 | void *context, void **return_value); | 109 | void *context, void **return_value); |
109 | 110 | ||
110 | struct acpi_namespace_node *acpi_ns_get_next_node(struct acpi_namespace_node | 111 | struct acpi_namespace_node *acpi_ns_get_next_node(struct acpi_namespace_node |
diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c index 3aae13f30c5e..f23fa0be6fc2 100644 --- a/drivers/acpi/acpica/dsinit.c +++ b/drivers/acpi/acpica/dsinit.c | |||
@@ -192,7 +192,7 @@ acpi_ds_initialize_objects(u32 table_index, | |||
192 | status = | 192 | status = |
193 | acpi_ns_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, | 193 | acpi_ns_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, |
194 | ACPI_NS_WALK_UNLOCK, acpi_ds_init_one_object, | 194 | ACPI_NS_WALK_UNLOCK, acpi_ds_init_one_object, |
195 | &info, NULL); | 195 | NULL, &info, NULL); |
196 | if (ACPI_FAILURE(status)) { | 196 | if (ACPI_FAILURE(status)) { |
197 | ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); | 197 | ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); |
198 | } | 198 | } |
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index a60aaa7635f3..247920900187 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c | |||
@@ -945,8 +945,8 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, | |||
945 | 945 | ||
946 | status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device, | 946 | status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device, |
947 | ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, | 947 | ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, |
948 | acpi_ev_save_method_info, gpe_block, | 948 | acpi_ev_save_method_info, NULL, |
949 | NULL); | 949 | gpe_block, NULL); |
950 | 950 | ||
951 | /* Return the new block */ | 951 | /* Return the new block */ |
952 | 952 | ||
@@ -1022,8 +1022,8 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, | |||
1022 | status = | 1022 | status = |
1023 | acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | 1023 | acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
1024 | ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, | 1024 | ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, |
1025 | acpi_ev_match_prw_and_gpe, &gpe_info, | 1025 | acpi_ev_match_prw_and_gpe, NULL, |
1026 | NULL); | 1026 | &gpe_info, NULL); |
1027 | } | 1027 | } |
1028 | 1028 | ||
1029 | /* | 1029 | /* |
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index c9fa040725d4..582b0af01e99 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c | |||
@@ -1025,8 +1025,8 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, | |||
1025 | */ | 1025 | */ |
1026 | status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, | 1026 | status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, |
1027 | ACPI_NS_WALK_UNLOCK, | 1027 | ACPI_NS_WALK_UNLOCK, |
1028 | acpi_ev_install_handler, handler_obj, | 1028 | acpi_ev_install_handler, NULL, |
1029 | NULL); | 1029 | handler_obj, NULL); |
1030 | 1030 | ||
1031 | unlock_and_exit: | 1031 | unlock_and_exit: |
1032 | return_ACPI_STATUS(status); | 1032 | return_ACPI_STATUS(status); |
@@ -1062,7 +1062,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, | |||
1062 | */ | 1062 | */ |
1063 | status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, | 1063 | status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, |
1064 | ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, | 1064 | ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, |
1065 | &space_id, NULL); | 1065 | NULL, &space_id, NULL); |
1066 | 1066 | ||
1067 | return_ACPI_STATUS(status); | 1067 | return_ACPI_STATUS(status); |
1068 | } | 1068 | } |
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 2bad613db73a..2deb986861ca 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c | |||
@@ -634,8 +634,8 @@ acpi_ns_dump_objects(acpi_object_type type, | |||
634 | (void)acpi_ns_walk_namespace(type, start_handle, max_depth, | 634 | (void)acpi_ns_walk_namespace(type, start_handle, max_depth, |
635 | ACPI_NS_WALK_NO_UNLOCK | | 635 | ACPI_NS_WALK_NO_UNLOCK | |
636 | ACPI_NS_WALK_TEMP_NODES, | 636 | ACPI_NS_WALK_TEMP_NODES, |
637 | acpi_ns_dump_one_object, (void *)&info, | 637 | acpi_ns_dump_one_object, NULL, |
638 | NULL); | 638 | (void *)&info, NULL); |
639 | } | 639 | } |
640 | #endif /* ACPI_FUTURE_USAGE */ | 640 | #endif /* ACPI_FUTURE_USAGE */ |
641 | 641 | ||
diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c index 0fe87f1aef16..36be7f0e97ec 100644 --- a/drivers/acpi/acpica/nsdumpdv.c +++ b/drivers/acpi/acpica/nsdumpdv.c | |||
@@ -131,7 +131,8 @@ void acpi_ns_dump_root_devices(void) | |||
131 | 131 | ||
132 | status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, sys_bus_handle, | 132 | status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, sys_bus_handle, |
133 | ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, | 133 | ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, |
134 | acpi_ns_dump_one_device, NULL, NULL); | 134 | acpi_ns_dump_one_device, NULL, NULL, |
135 | NULL); | ||
135 | } | 136 | } |
136 | 137 | ||
137 | #endif | 138 | #endif |
diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 1d5b360eb25b..4f8abac231d2 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c | |||
@@ -96,7 +96,7 @@ acpi_status acpi_ns_initialize_objects(void) | |||
96 | /* Walk entire namespace from the supplied root */ | 96 | /* Walk entire namespace from the supplied root */ |
97 | 97 | ||
98 | status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, | 98 | status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, |
99 | ACPI_UINT32_MAX, acpi_ns_init_one_object, | 99 | ACPI_UINT32_MAX, acpi_ns_init_one_object, NULL, |
100 | &info, NULL); | 100 | &info, NULL); |
101 | if (ACPI_FAILURE(status)) { | 101 | if (ACPI_FAILURE(status)) { |
102 | ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); | 102 | ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); |
@@ -156,7 +156,8 @@ acpi_status acpi_ns_initialize_devices(void) | |||
156 | 156 | ||
157 | status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, | 157 | status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, |
158 | ACPI_UINT32_MAX, FALSE, | 158 | ACPI_UINT32_MAX, FALSE, |
159 | acpi_ns_find_ini_methods, &info, NULL); | 159 | acpi_ns_find_ini_methods, NULL, &info, |
160 | NULL); | ||
160 | if (ACPI_FAILURE(status)) { | 161 | if (ACPI_FAILURE(status)) { |
161 | goto error_exit; | 162 | goto error_exit; |
162 | } | 163 | } |
@@ -189,7 +190,8 @@ acpi_status acpi_ns_initialize_devices(void) | |||
189 | 190 | ||
190 | status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, | 191 | status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, |
191 | ACPI_UINT32_MAX, FALSE, | 192 | ACPI_UINT32_MAX, FALSE, |
192 | acpi_ns_init_one_device, &info, NULL); | 193 | acpi_ns_init_one_device, NULL, &info, |
194 | NULL); | ||
193 | 195 | ||
194 | ACPI_FREE(info.evaluate_info); | 196 | ACPI_FREE(info.evaluate_info); |
195 | if (ACPI_FAILURE(status)) { | 197 | if (ACPI_FAILURE(status)) { |
diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c index 35539df5c75d..d7e6b52b4482 100644 --- a/drivers/acpi/acpica/nswalk.c +++ b/drivers/acpi/acpica/nswalk.c | |||
@@ -165,24 +165,27 @@ struct acpi_namespace_node *acpi_ns_get_next_node_typed(acpi_object_type type, | |||
165 | * max_depth - Depth to which search is to reach | 165 | * max_depth - Depth to which search is to reach |
166 | * Flags - Whether to unlock the NS before invoking | 166 | * Flags - Whether to unlock the NS before invoking |
167 | * the callback routine | 167 | * the callback routine |
168 | * user_function - Called when an object of "Type" is found | 168 | * pre_order_visit - Called during tree pre-order visit |
169 | * Context - Passed to user function | 169 | * when an object of "Type" is found |
170 | * return_value - from the user_function if terminated early. | 170 | * post_order_visit - Called during tree post-order visit |
171 | * Otherwise, returns NULL. | 171 | * when an object of "Type" is found |
172 | * Context - Passed to user function(s) above | ||
173 | * return_value - from the user_function if terminated | ||
174 | * early. Otherwise, returns NULL. | ||
172 | * RETURNS: Status | 175 | * RETURNS: Status |
173 | * | 176 | * |
174 | * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, | 177 | * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, |
175 | * starting (and ending) at the node specified by start_handle. | 178 | * starting (and ending) at the node specified by start_handle. |
176 | * The user_function is called whenever a node that matches | 179 | * The callback function is called whenever a node that matches |
177 | * the type parameter is found. If the user function returns | 180 | * the type parameter is found. If the callback function returns |
178 | * a non-zero value, the search is terminated immediately and | 181 | * a non-zero value, the search is terminated immediately and |
179 | * this value is returned to the caller. | 182 | * this value is returned to the caller. |
180 | * | 183 | * |
181 | * The point of this procedure is to provide a generic namespace | 184 | * The point of this procedure is to provide a generic namespace |
182 | * walk routine that can be called from multiple places to | 185 | * walk routine that can be called from multiple places to |
183 | * provide multiple services; the User Function can be tailored | 186 | * provide multiple services; the callback function(s) can be |
184 | * to each task, whether it is a print function, a compare | 187 | * tailored to each task, whether it is a print function, |
185 | * function, etc. | 188 | * a compare function, etc. |
186 | * | 189 | * |
187 | ******************************************************************************/ | 190 | ******************************************************************************/ |
188 | 191 | ||
@@ -191,7 +194,8 @@ acpi_ns_walk_namespace(acpi_object_type type, | |||
191 | acpi_handle start_node, | 194 | acpi_handle start_node, |
192 | u32 max_depth, | 195 | u32 max_depth, |
193 | u32 flags, | 196 | u32 flags, |
194 | acpi_walk_callback user_function, | 197 | acpi_walk_callback pre_order_visit, |
198 | acpi_walk_callback post_order_visit, | ||
195 | void *context, void **return_value) | 199 | void *context, void **return_value) |
196 | { | 200 | { |
197 | acpi_status status; | 201 | acpi_status status; |
@@ -200,6 +204,7 @@ acpi_ns_walk_namespace(acpi_object_type type, | |||
200 | struct acpi_namespace_node *parent_node; | 204 | struct acpi_namespace_node *parent_node; |
201 | acpi_object_type child_type; | 205 | acpi_object_type child_type; |
202 | u32 level; | 206 | u32 level; |
207 | u8 node_previously_visited = FALSE; | ||
203 | 208 | ||
204 | ACPI_FUNCTION_TRACE(ns_walk_namespace); | 209 | ACPI_FUNCTION_TRACE(ns_walk_namespace); |
205 | 210 | ||
@@ -212,7 +217,7 @@ acpi_ns_walk_namespace(acpi_object_type type, | |||
212 | /* Null child means "get first node" */ | 217 | /* Null child means "get first node" */ |
213 | 218 | ||
214 | parent_node = start_node; | 219 | parent_node = start_node; |
215 | child_node = NULL; | 220 | child_node = acpi_ns_get_next_node(parent_node, NULL); |
216 | child_type = ACPI_TYPE_ANY; | 221 | child_type = ACPI_TYPE_ANY; |
217 | level = 1; | 222 | level = 1; |
218 | 223 | ||
@@ -221,102 +226,129 @@ acpi_ns_walk_namespace(acpi_object_type type, | |||
221 | * started. When Level is zero, the loop is done because we have | 226 | * started. When Level is zero, the loop is done because we have |
222 | * bubbled up to (and passed) the original parent handle (start_entry) | 227 | * bubbled up to (and passed) the original parent handle (start_entry) |
223 | */ | 228 | */ |
224 | while (level > 0) { | 229 | while (level > 0 && child_node) { |
230 | status = AE_OK; | ||
225 | 231 | ||
226 | /* Get the next node in this scope. Null if not found */ | 232 | /* Found next child, get the type if we are not searching for ANY */ |
227 | 233 | ||
228 | status = AE_OK; | 234 | if (type != ACPI_TYPE_ANY) { |
229 | child_node = acpi_ns_get_next_node(parent_node, child_node); | 235 | child_type = child_node->type; |
230 | if (child_node) { | 236 | } |
231 | 237 | ||
232 | /* Found next child, get the type if we are not searching for ANY */ | 238 | /* |
239 | * Ignore all temporary namespace nodes (created during control | ||
240 | * method execution) unless told otherwise. These temporary nodes | ||
241 | * can cause a race condition because they can be deleted during | ||
242 | * the execution of the user function (if the namespace is | ||
243 | * unlocked before invocation of the user function.) Only the | ||
244 | * debugger namespace dump will examine the temporary nodes. | ||
245 | */ | ||
246 | if ((child_node->flags & ANOBJ_TEMPORARY) && | ||
247 | !(flags & ACPI_NS_WALK_TEMP_NODES)) { | ||
248 | status = AE_CTRL_DEPTH; | ||
249 | } | ||
233 | 250 | ||
234 | if (type != ACPI_TYPE_ANY) { | 251 | /* Type must match requested type */ |
235 | child_type = child_node->type; | ||
236 | } | ||
237 | 252 | ||
253 | else if (child_type == type) { | ||
238 | /* | 254 | /* |
239 | * Ignore all temporary namespace nodes (created during control | 255 | * Found a matching node, invoke the user callback function. |
240 | * method execution) unless told otherwise. These temporary nodes | 256 | * Unlock the namespace if flag is set. |
241 | * can cause a race condition because they can be deleted during | ||
242 | * the execution of the user function (if the namespace is | ||
243 | * unlocked before invocation of the user function.) Only the | ||
244 | * debugger namespace dump will examine the temporary nodes. | ||
245 | */ | 257 | */ |
246 | if ((child_node->flags & ANOBJ_TEMPORARY) && | 258 | if (flags & ACPI_NS_WALK_UNLOCK) { |
247 | !(flags & ACPI_NS_WALK_TEMP_NODES)) { | 259 | mutex_status = |
248 | status = AE_CTRL_DEPTH; | 260 | acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
261 | if (ACPI_FAILURE(mutex_status)) { | ||
262 | return_ACPI_STATUS(mutex_status); | ||
263 | } | ||
249 | } | 264 | } |
250 | 265 | ||
251 | /* Type must match requested type */ | 266 | /* |
252 | 267 | * Invoke the user function, either pre-order or post-order | |
253 | else if (child_type == type) { | 268 | * or both. |
254 | /* | 269 | */ |
255 | * Found a matching node, invoke the user callback function. | 270 | if (!node_previously_visited) { |
256 | * Unlock the namespace if flag is set. | 271 | if (pre_order_visit) { |
257 | */ | 272 | status = |
258 | if (flags & ACPI_NS_WALK_UNLOCK) { | 273 | pre_order_visit(child_node, level, |
259 | mutex_status = | 274 | context, |
260 | acpi_ut_release_mutex | 275 | return_value); |
261 | (ACPI_MTX_NAMESPACE); | ||
262 | if (ACPI_FAILURE(mutex_status)) { | ||
263 | return_ACPI_STATUS | ||
264 | (mutex_status); | ||
265 | } | ||
266 | } | 276 | } |
277 | } else { | ||
278 | if (post_order_visit) { | ||
279 | status = | ||
280 | post_order_visit(child_node, level, | ||
281 | context, | ||
282 | return_value); | ||
283 | } | ||
284 | } | ||
267 | 285 | ||
268 | status = | 286 | if (flags & ACPI_NS_WALK_UNLOCK) { |
269 | user_function(child_node, level, context, | 287 | mutex_status = |
270 | return_value); | 288 | acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); |
271 | 289 | if (ACPI_FAILURE(mutex_status)) { | |
272 | if (flags & ACPI_NS_WALK_UNLOCK) { | 290 | return_ACPI_STATUS(mutex_status); |
273 | mutex_status = | ||
274 | acpi_ut_acquire_mutex | ||
275 | (ACPI_MTX_NAMESPACE); | ||
276 | if (ACPI_FAILURE(mutex_status)) { | ||
277 | return_ACPI_STATUS | ||
278 | (mutex_status); | ||
279 | } | ||
280 | } | 291 | } |
292 | } | ||
281 | 293 | ||
282 | switch (status) { | 294 | switch (status) { |
283 | case AE_OK: | 295 | case AE_OK: |
284 | case AE_CTRL_DEPTH: | 296 | case AE_CTRL_DEPTH: |
285 | 297 | ||
286 | /* Just keep going */ | 298 | /* Just keep going */ |
287 | break; | 299 | break; |
288 | 300 | ||
289 | case AE_CTRL_TERMINATE: | 301 | case AE_CTRL_TERMINATE: |
290 | 302 | ||
291 | /* Exit now, with OK status */ | 303 | /* Exit now, with OK status */ |
292 | 304 | ||
293 | return_ACPI_STATUS(AE_OK); | 305 | return_ACPI_STATUS(AE_OK); |
294 | 306 | ||
295 | default: | 307 | default: |
296 | 308 | ||
297 | /* All others are valid exceptions */ | 309 | /* All others are valid exceptions */ |
298 | 310 | ||
299 | return_ACPI_STATUS(status); | 311 | return_ACPI_STATUS(status); |
300 | } | 312 | } |
313 | } | ||
314 | |||
315 | /* | ||
316 | * Depth first search: Attempt to go down another level in the | ||
317 | * namespace if we are allowed to. Don't go any further if we have | ||
318 | * reached the caller specified maximum depth or if the user | ||
319 | * function has specified that the maximum depth has been reached. | ||
320 | */ | ||
321 | if (!node_previously_visited && | ||
322 | (level < max_depth) && (status != AE_CTRL_DEPTH)) { | ||
323 | if (child_node->child) { | ||
324 | |||
325 | /* There is at least one child of this node, visit it */ | ||
326 | |||
327 | level++; | ||
328 | parent_node = child_node; | ||
329 | child_node = | ||
330 | acpi_ns_get_next_node(parent_node, NULL); | ||
331 | continue; | ||
301 | } | 332 | } |
333 | } | ||
302 | 334 | ||
303 | /* | 335 | /* No more children, re-visit this node */ |
304 | * Depth first search: Attempt to go down another level in the | ||
305 | * namespace if we are allowed to. Don't go any further if we have | ||
306 | * reached the caller specified maximum depth or if the user | ||
307 | * function has specified that the maximum depth has been reached. | ||
308 | */ | ||
309 | if ((level < max_depth) && (status != AE_CTRL_DEPTH)) { | ||
310 | if (child_node->child) { | ||
311 | 336 | ||
312 | /* There is at least one child of this node, visit it */ | 337 | if (!node_previously_visited) { |
338 | node_previously_visited = TRUE; | ||
339 | continue; | ||
340 | } | ||
313 | 341 | ||
314 | level++; | 342 | /* No more children, visit peers */ |
315 | parent_node = child_node; | 343 | |
316 | child_node = NULL; | 344 | child_node = acpi_ns_get_next_node(parent_node, child_node); |
317 | } | 345 | if (child_node) { |
318 | } | 346 | node_previously_visited = FALSE; |
319 | } else { | 347 | } |
348 | |||
349 | /* No peers, re-visit parent */ | ||
350 | |||
351 | else { | ||
320 | /* | 352 | /* |
321 | * No more children of this node (acpi_ns_get_next_node failed), go | 353 | * No more children of this node (acpi_ns_get_next_node failed), go |
322 | * back upwards in the namespace tree to the node's parent. | 354 | * back upwards in the namespace tree to the node's parent. |
@@ -324,6 +356,8 @@ acpi_ns_walk_namespace(acpi_object_type type, | |||
324 | level--; | 356 | level--; |
325 | child_node = parent_node; | 357 | child_node = parent_node; |
326 | parent_node = acpi_ns_get_parent_node(parent_node); | 358 | parent_node = acpi_ns_get_parent_node(parent_node); |
359 | |||
360 | node_previously_visited = TRUE; | ||
327 | } | 361 | } |
328 | } | 362 | } |
329 | 363 | ||
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index 4929dbdbc8f0..f2bd1da77001 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c | |||
@@ -433,8 +433,11 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) | |||
433 | * PARAMETERS: Type - acpi_object_type to search for | 433 | * PARAMETERS: Type - acpi_object_type to search for |
434 | * start_object - Handle in namespace where search begins | 434 | * start_object - Handle in namespace where search begins |
435 | * max_depth - Depth to which search is to reach | 435 | * max_depth - Depth to which search is to reach |
436 | * user_function - Called when an object of "Type" is found | 436 | * pre_order_visit - Called during tree pre-order visit |
437 | * Context - Passed to user function | 437 | * when an object of "Type" is found |
438 | * post_order_visit - Called during tree post-order visit | ||
439 | * when an object of "Type" is found | ||
440 | * Context - Passed to user function(s) above | ||
438 | * return_value - Location where return value of | 441 | * return_value - Location where return value of |
439 | * user_function is put if terminated early | 442 | * user_function is put if terminated early |
440 | * | 443 | * |
@@ -443,16 +446,16 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) | |||
443 | * | 446 | * |
444 | * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, | 447 | * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, |
445 | * starting (and ending) at the object specified by start_handle. | 448 | * starting (and ending) at the object specified by start_handle. |
446 | * The user_function is called whenever an object that matches | 449 | * The callback function is called whenever an object that matches |
447 | * the type parameter is found. If the user function returns | 450 | * the type parameter is found. If the callback function returns |
448 | * a non-zero value, the search is terminated immediately and this | 451 | * a non-zero value, the search is terminated immediately and this |
449 | * value is returned to the caller. | 452 | * value is returned to the caller. |
450 | * | 453 | * |
451 | * The point of this procedure is to provide a generic namespace | 454 | * The point of this procedure is to provide a generic namespace |
452 | * walk routine that can be called from multiple places to | 455 | * walk routine that can be called from multiple places to |
453 | * provide multiple services; the User Function can be tailored | 456 | * provide multiple services; the callback function(s) can be |
454 | * to each task, whether it is a print function, a compare | 457 | * tailored to each task, whether it is a print function, |
455 | * function, etc. | 458 | * a compare function, etc. |
456 | * | 459 | * |
457 | ******************************************************************************/ | 460 | ******************************************************************************/ |
458 | 461 | ||
@@ -460,7 +463,8 @@ acpi_status | |||
460 | acpi_walk_namespace(acpi_object_type type, | 463 | acpi_walk_namespace(acpi_object_type type, |
461 | acpi_handle start_object, | 464 | acpi_handle start_object, |
462 | u32 max_depth, | 465 | u32 max_depth, |
463 | acpi_walk_callback user_function, | 466 | acpi_walk_callback pre_order_visit, |
467 | acpi_walk_callback post_order_visit, | ||
464 | void *context, void **return_value) | 468 | void *context, void **return_value) |
465 | { | 469 | { |
466 | acpi_status status; | 470 | acpi_status status; |
@@ -469,7 +473,8 @@ acpi_walk_namespace(acpi_object_type type, | |||
469 | 473 | ||
470 | /* Parameter validation */ | 474 | /* Parameter validation */ |
471 | 475 | ||
472 | if ((type > ACPI_TYPE_LOCAL_MAX) || (!max_depth) || (!user_function)) { | 476 | if ((type > ACPI_TYPE_LOCAL_MAX) || |
477 | (!max_depth) || (!pre_order_visit && !post_order_visit)) { | ||
473 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 478 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
474 | } | 479 | } |
475 | 480 | ||
@@ -501,8 +506,9 @@ acpi_walk_namespace(acpi_object_type type, | |||
501 | } | 506 | } |
502 | 507 | ||
503 | status = acpi_ns_walk_namespace(type, start_object, max_depth, | 508 | status = acpi_ns_walk_namespace(type, start_object, max_depth, |
504 | ACPI_NS_WALK_UNLOCK, user_function, | 509 | ACPI_NS_WALK_UNLOCK, pre_order_visit, |
505 | context, return_value); | 510 | post_order_visit, context, |
511 | return_value); | ||
506 | 512 | ||
507 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 513 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
508 | 514 | ||
@@ -681,8 +687,8 @@ acpi_get_devices(const char *HID, | |||
681 | 687 | ||
682 | status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | 688 | status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
683 | ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, | 689 | ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, |
684 | acpi_ns_get_device_callback, &info, | 690 | acpi_ns_get_device_callback, NULL, |
685 | return_value); | 691 | &info, return_value); |
686 | 692 | ||
687 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 693 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
688 | return_ACPI_STATUS(status); | 694 | return_ACPI_STATUS(status); |