diff options
Diffstat (limited to 'drivers/acpi/acpica/nsalloc.c')
-rw-r--r-- | drivers/acpi/acpica/nsalloc.c | 94 |
1 files changed, 41 insertions, 53 deletions
diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c index 982269c1fa48..1e5ff803d9ad 100644 --- a/drivers/acpi/acpica/nsalloc.c +++ b/drivers/acpi/acpica/nsalloc.c | |||
@@ -159,7 +159,7 @@ void acpi_ns_remove_node(struct acpi_namespace_node *node) | |||
159 | 159 | ||
160 | ACPI_FUNCTION_TRACE_PTR(ns_remove_node, node); | 160 | ACPI_FUNCTION_TRACE_PTR(ns_remove_node, node); |
161 | 161 | ||
162 | parent_node = acpi_ns_get_parent_node(node); | 162 | parent_node = node->parent; |
163 | 163 | ||
164 | prev_node = NULL; | 164 | prev_node = NULL; |
165 | next_node = parent_node->child; | 165 | next_node = parent_node->child; |
@@ -168,29 +168,20 @@ void acpi_ns_remove_node(struct acpi_namespace_node *node) | |||
168 | 168 | ||
169 | while (next_node != node) { | 169 | while (next_node != node) { |
170 | prev_node = next_node; | 170 | prev_node = next_node; |
171 | next_node = prev_node->peer; | 171 | next_node = next_node->peer; |
172 | } | 172 | } |
173 | 173 | ||
174 | if (prev_node) { | 174 | if (prev_node) { |
175 | 175 | ||
176 | /* Node is not first child, unlink it */ | 176 | /* Node is not first child, unlink it */ |
177 | 177 | ||
178 | prev_node->peer = next_node->peer; | 178 | prev_node->peer = node->peer; |
179 | if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { | ||
180 | prev_node->flags |= ANOBJ_END_OF_PEER_LIST; | ||
181 | } | ||
182 | } else { | 179 | } else { |
183 | /* Node is first child (has no previous peer) */ | 180 | /* |
184 | 181 | * Node is first child (has no previous peer). | |
185 | if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { | 182 | * Link peer list to parent |
186 | 183 | */ | |
187 | /* No peers at all */ | 184 | parent_node->child = node->peer; |
188 | |||
189 | parent_node->child = NULL; | ||
190 | } else { /* Link peer list to parent */ | ||
191 | |||
192 | parent_node->child = next_node->peer; | ||
193 | } | ||
194 | } | 185 | } |
195 | 186 | ||
196 | /* Delete the node and any attached objects */ | 187 | /* Delete the node and any attached objects */ |
@@ -228,33 +219,42 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp | |||
228 | 219 | ||
229 | ACPI_FUNCTION_TRACE(ns_install_node); | 220 | ACPI_FUNCTION_TRACE(ns_install_node); |
230 | 221 | ||
231 | /* | ||
232 | * Get the owner ID from the Walk state. The owner ID is used to track | ||
233 | * table deletion and deletion of objects created by methods. | ||
234 | */ | ||
235 | if (walk_state) { | 222 | if (walk_state) { |
223 | /* | ||
224 | * Get the owner ID from the Walk state. The owner ID is used to | ||
225 | * track table deletion and deletion of objects created by methods. | ||
226 | */ | ||
236 | owner_id = walk_state->owner_id; | 227 | owner_id = walk_state->owner_id; |
228 | |||
229 | if ((walk_state->method_desc) && | ||
230 | (parent_node != walk_state->method_node)) { | ||
231 | /* | ||
232 | * A method is creating a new node that is not a child of the | ||
233 | * method (it is non-local). Mark the executing method as having | ||
234 | * modified the namespace. This is used for cleanup when the | ||
235 | * method exits. | ||
236 | */ | ||
237 | walk_state->method_desc->method.flags |= | ||
238 | AOPOBJ_MODIFIED_NAMESPACE; | ||
239 | } | ||
237 | } | 240 | } |
238 | 241 | ||
239 | /* Link the new entry into the parent and existing children */ | 242 | /* Link the new entry into the parent and existing children */ |
240 | 243 | ||
244 | node->peer = NULL; | ||
245 | node->parent = parent_node; | ||
241 | child_node = parent_node->child; | 246 | child_node = parent_node->child; |
247 | |||
242 | if (!child_node) { | 248 | if (!child_node) { |
243 | parent_node->child = node; | 249 | parent_node->child = node; |
244 | node->flags |= ANOBJ_END_OF_PEER_LIST; | ||
245 | node->peer = parent_node; | ||
246 | } else { | 250 | } else { |
247 | while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) { | 251 | /* Add node to the end of the peer list */ |
252 | |||
253 | while (child_node->peer) { | ||
248 | child_node = child_node->peer; | 254 | child_node = child_node->peer; |
249 | } | 255 | } |
250 | 256 | ||
251 | child_node->peer = node; | 257 | child_node->peer = node; |
252 | |||
253 | /* Clear end-of-list flag */ | ||
254 | |||
255 | child_node->flags &= ~ANOBJ_END_OF_PEER_LIST; | ||
256 | node->flags |= ANOBJ_END_OF_PEER_LIST; | ||
257 | node->peer = parent_node; | ||
258 | } | 258 | } |
259 | 259 | ||
260 | /* Init the new entry */ | 260 | /* Init the new entry */ |
@@ -288,9 +288,8 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp | |||
288 | 288 | ||
289 | void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) | 289 | void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) |
290 | { | 290 | { |
291 | struct acpi_namespace_node *child_node; | ||
292 | struct acpi_namespace_node *next_node; | 291 | struct acpi_namespace_node *next_node; |
293 | u8 flags; | 292 | struct acpi_namespace_node *node_to_delete; |
294 | 293 | ||
295 | ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node); | 294 | ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node); |
296 | 295 | ||
@@ -298,37 +297,26 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) | |||
298 | return_VOID; | 297 | return_VOID; |
299 | } | 298 | } |
300 | 299 | ||
301 | /* If no children, all done! */ | ||
302 | |||
303 | child_node = parent_node->child; | ||
304 | if (!child_node) { | ||
305 | return_VOID; | ||
306 | } | ||
307 | |||
308 | /* Deallocate all children at this level */ | 300 | /* Deallocate all children at this level */ |
309 | 301 | ||
310 | do { | 302 | next_node = parent_node->child; |
311 | 303 | while (next_node) { | |
312 | /* Get the things we need */ | ||
313 | |||
314 | next_node = child_node->peer; | ||
315 | flags = child_node->flags; | ||
316 | 304 | ||
317 | /* Grandchildren should have all been deleted already */ | 305 | /* Grandchildren should have all been deleted already */ |
318 | 306 | ||
319 | if (child_node->child) { | 307 | if (next_node->child) { |
320 | ACPI_ERROR((AE_INFO, "Found a grandchild! P=%p C=%p", | 308 | ACPI_ERROR((AE_INFO, "Found a grandchild! P=%p C=%p", |
321 | parent_node, child_node)); | 309 | parent_node, next_node)); |
322 | } | 310 | } |
323 | 311 | ||
324 | /* | 312 | /* |
325 | * Delete this child node and move on to the next child in the list. | 313 | * Delete this child node and move on to the next child in the list. |
326 | * No need to unlink the node since we are deleting the entire branch. | 314 | * No need to unlink the node since we are deleting the entire branch. |
327 | */ | 315 | */ |
328 | acpi_ns_delete_node(child_node); | 316 | node_to_delete = next_node; |
329 | child_node = next_node; | 317 | next_node = next_node->peer; |
330 | 318 | acpi_ns_delete_node(node_to_delete); | |
331 | } while (!(flags & ANOBJ_END_OF_PEER_LIST)); | 319 | }; |
332 | 320 | ||
333 | /* Clear the parent's child pointer */ | 321 | /* Clear the parent's child pointer */ |
334 | 322 | ||
@@ -405,7 +393,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) | |||
405 | 393 | ||
406 | /* Move up the tree to the grandparent */ | 394 | /* Move up the tree to the grandparent */ |
407 | 395 | ||
408 | parent_node = acpi_ns_get_parent_node(parent_node); | 396 | parent_node = parent_node->parent; |
409 | } | 397 | } |
410 | } | 398 | } |
411 | 399 | ||
@@ -510,7 +498,7 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id) | |||
510 | 498 | ||
511 | /* Move up the tree to the grandparent */ | 499 | /* Move up the tree to the grandparent */ |
512 | 500 | ||
513 | parent_node = acpi_ns_get_parent_node(parent_node); | 501 | parent_node = parent_node->parent; |
514 | } | 502 | } |
515 | } | 503 | } |
516 | 504 | ||