diff options
Diffstat (limited to 'drivers/acpi/namespace/nsalloc.c')
-rw-r--r-- | drivers/acpi/namespace/nsalloc.c | 118 |
1 files changed, 23 insertions, 95 deletions
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c index 9b871f38b61b..dc3f0739a46b 100644 --- a/drivers/acpi/namespace/nsalloc.c +++ b/drivers/acpi/namespace/nsalloc.c | |||
@@ -47,9 +47,6 @@ | |||
47 | #define _COMPONENT ACPI_NAMESPACE | 47 | #define _COMPONENT ACPI_NAMESPACE |
48 | ACPI_MODULE_NAME("nsalloc") | 48 | ACPI_MODULE_NAME("nsalloc") |
49 | 49 | ||
50 | /* Local prototypes */ | ||
51 | static void acpi_ns_remove_reference(struct acpi_namespace_node *node); | ||
52 | |||
53 | /******************************************************************************* | 50 | /******************************************************************************* |
54 | * | 51 | * |
55 | * FUNCTION: acpi_ns_create_node | 52 | * FUNCTION: acpi_ns_create_node |
@@ -61,14 +58,13 @@ static void acpi_ns_remove_reference(struct acpi_namespace_node *node); | |||
61 | * DESCRIPTION: Create a namespace node | 58 | * DESCRIPTION: Create a namespace node |
62 | * | 59 | * |
63 | ******************************************************************************/ | 60 | ******************************************************************************/ |
64 | |||
65 | struct acpi_namespace_node *acpi_ns_create_node(u32 name) | 61 | struct acpi_namespace_node *acpi_ns_create_node(u32 name) |
66 | { | 62 | { |
67 | struct acpi_namespace_node *node; | 63 | struct acpi_namespace_node *node; |
68 | 64 | ||
69 | ACPI_FUNCTION_TRACE("ns_create_node"); | 65 | ACPI_FUNCTION_TRACE(ns_create_node); |
70 | 66 | ||
71 | node = ACPI_MEM_CALLOCATE(sizeof(struct acpi_namespace_node)); | 67 | node = acpi_os_acquire_object(acpi_gbl_namespace_cache); |
72 | if (!node) { | 68 | if (!node) { |
73 | return_PTR(NULL); | 69 | return_PTR(NULL); |
74 | } | 70 | } |
@@ -76,9 +72,7 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name) | |||
76 | ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_allocated++); | 72 | ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_allocated++); |
77 | 73 | ||
78 | node->name.integer = name; | 74 | node->name.integer = name; |
79 | node->reference_count = 1; | ||
80 | ACPI_SET_DESCRIPTOR_TYPE(node, ACPI_DESC_TYPE_NAMED); | 75 | ACPI_SET_DESCRIPTOR_TYPE(node, ACPI_DESC_TYPE_NAMED); |
81 | |||
82 | return_PTR(node); | 76 | return_PTR(node); |
83 | } | 77 | } |
84 | 78 | ||
@@ -100,7 +94,7 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) | |||
100 | struct acpi_namespace_node *prev_node; | 94 | struct acpi_namespace_node *prev_node; |
101 | struct acpi_namespace_node *next_node; | 95 | struct acpi_namespace_node *next_node; |
102 | 96 | ||
103 | ACPI_FUNCTION_TRACE_PTR("ns_delete_node", node); | 97 | ACPI_FUNCTION_TRACE_PTR(ns_delete_node, node); |
104 | 98 | ||
105 | parent_node = acpi_ns_get_parent_node(node); | 99 | parent_node = acpi_ns_get_parent_node(node); |
106 | 100 | ||
@@ -115,6 +109,7 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) | |||
115 | } | 109 | } |
116 | 110 | ||
117 | if (prev_node) { | 111 | if (prev_node) { |
112 | |||
118 | /* Node is not first child, unlink it */ | 113 | /* Node is not first child, unlink it */ |
119 | 114 | ||
120 | prev_node->peer = next_node->peer; | 115 | prev_node->peer = next_node->peer; |
@@ -125,6 +120,7 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) | |||
125 | /* Node is first child (has no previous peer) */ | 120 | /* Node is first child (has no previous peer) */ |
126 | 121 | ||
127 | if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { | 122 | if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { |
123 | |||
128 | /* No peers at all */ | 124 | /* No peers at all */ |
129 | 125 | ||
130 | parent_node->child = NULL; | 126 | parent_node->child = NULL; |
@@ -137,10 +133,10 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) | |||
137 | ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); | 133 | ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); |
138 | 134 | ||
139 | /* | 135 | /* |
140 | * Detach an object if there is one then delete the node | 136 | * Detach an object if there is one, then delete the node |
141 | */ | 137 | */ |
142 | acpi_ns_detach_object(node); | 138 | acpi_ns_detach_object(node); |
143 | ACPI_MEM_FREE(node); | 139 | (void)acpi_os_release_object(acpi_gbl_namespace_cache, node); |
144 | return_VOID; | 140 | return_VOID; |
145 | } | 141 | } |
146 | 142 | ||
@@ -171,7 +167,7 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp | |||
171 | acpi_owner_id owner_id = 0; | 167 | acpi_owner_id owner_id = 0; |
172 | struct acpi_namespace_node *child_node; | 168 | struct acpi_namespace_node *child_node; |
173 | 169 | ||
174 | ACPI_FUNCTION_TRACE("ns_install_node"); | 170 | ACPI_FUNCTION_TRACE(ns_install_node); |
175 | 171 | ||
176 | /* | 172 | /* |
177 | * Get the owner ID from the Walk state | 173 | * Get the owner ID from the Walk state |
@@ -216,14 +212,6 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp | |||
216 | acpi_ut_get_type_name(parent_node->type), | 212 | acpi_ut_get_type_name(parent_node->type), |
217 | parent_node)); | 213 | parent_node)); |
218 | 214 | ||
219 | /* | ||
220 | * Increment the reference count(s) of all parents up to | ||
221 | * the root! | ||
222 | */ | ||
223 | while ((node = acpi_ns_get_parent_node(node)) != NULL) { | ||
224 | node->reference_count++; | ||
225 | } | ||
226 | |||
227 | return_VOID; | 215 | return_VOID; |
228 | } | 216 | } |
229 | 217 | ||
@@ -244,10 +232,9 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) | |||
244 | { | 232 | { |
245 | struct acpi_namespace_node *child_node; | 233 | struct acpi_namespace_node *child_node; |
246 | struct acpi_namespace_node *next_node; | 234 | struct acpi_namespace_node *next_node; |
247 | struct acpi_namespace_node *node; | ||
248 | u8 flags; | 235 | u8 flags; |
249 | 236 | ||
250 | ACPI_FUNCTION_TRACE_PTR("ns_delete_children", parent_node); | 237 | ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node); |
251 | 238 | ||
252 | if (!parent_node) { | 239 | if (!parent_node) { |
253 | return_VOID; | 240 | return_VOID; |
@@ -264,6 +251,7 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) | |||
264 | * Deallocate all children at this level | 251 | * Deallocate all children at this level |
265 | */ | 252 | */ |
266 | do { | 253 | do { |
254 | |||
267 | /* Get the things we need */ | 255 | /* Get the things we need */ |
268 | 256 | ||
269 | next_node = child_node->peer; | 257 | next_node = child_node->peer; |
@@ -289,26 +277,10 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) | |||
289 | */ | 277 | */ |
290 | acpi_ns_detach_object(child_node); | 278 | acpi_ns_detach_object(child_node); |
291 | 279 | ||
292 | /* | ||
293 | * Decrement the reference count(s) of all parents up to | ||
294 | * the root! (counts were incremented when the node was created) | ||
295 | */ | ||
296 | node = child_node; | ||
297 | while ((node = acpi_ns_get_parent_node(node)) != NULL) { | ||
298 | node->reference_count--; | ||
299 | } | ||
300 | |||
301 | /* There should be only one reference remaining on this node */ | ||
302 | |||
303 | if (child_node->reference_count != 1) { | ||
304 | ACPI_WARNING((AE_INFO, | ||
305 | "Existing references (%d) on node being deleted (%p)", | ||
306 | child_node->reference_count, child_node)); | ||
307 | } | ||
308 | |||
309 | /* Now we can delete the node */ | 280 | /* Now we can delete the node */ |
310 | 281 | ||
311 | ACPI_MEM_FREE(child_node); | 282 | (void)acpi_os_release_object(acpi_gbl_namespace_cache, |
283 | child_node); | ||
312 | 284 | ||
313 | /* And move on to the next child in the list */ | 285 | /* And move on to the next child in the list */ |
314 | 286 | ||
@@ -341,7 +313,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) | |||
341 | struct acpi_namespace_node *child_node = NULL; | 313 | struct acpi_namespace_node *child_node = NULL; |
342 | u32 level = 1; | 314 | u32 level = 1; |
343 | 315 | ||
344 | ACPI_FUNCTION_TRACE("ns_delete_namespace_subtree"); | 316 | ACPI_FUNCTION_TRACE(ns_delete_namespace_subtree); |
345 | 317 | ||
346 | if (!parent_node) { | 318 | if (!parent_node) { |
347 | return_VOID; | 319 | return_VOID; |
@@ -352,11 +324,14 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) | |||
352 | * to where we started. | 324 | * to where we started. |
353 | */ | 325 | */ |
354 | while (level > 0) { | 326 | while (level > 0) { |
327 | |||
355 | /* Get the next node in this scope (NULL if none) */ | 328 | /* Get the next node in this scope (NULL if none) */ |
356 | 329 | ||
357 | child_node = acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node, | 330 | child_node = |
358 | child_node); | 331 | acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node, |
332 | child_node); | ||
359 | if (child_node) { | 333 | if (child_node) { |
334 | |||
360 | /* Found a child node - detach any attached object */ | 335 | /* Found a child node - detach any attached object */ |
361 | 336 | ||
362 | acpi_ns_detach_object(child_node); | 337 | acpi_ns_detach_object(child_node); |
@@ -401,55 +376,6 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node) | |||
401 | 376 | ||
402 | /******************************************************************************* | 377 | /******************************************************************************* |
403 | * | 378 | * |
404 | * FUNCTION: acpi_ns_remove_reference | ||
405 | * | ||
406 | * PARAMETERS: Node - Named node whose reference count is to be | ||
407 | * decremented | ||
408 | * | ||
409 | * RETURN: None. | ||
410 | * | ||
411 | * DESCRIPTION: Remove a Node reference. Decrements the reference count | ||
412 | * of all parent Nodes up to the root. Any node along | ||
413 | * the way that reaches zero references is freed. | ||
414 | * | ||
415 | ******************************************************************************/ | ||
416 | |||
417 | static void acpi_ns_remove_reference(struct acpi_namespace_node *node) | ||
418 | { | ||
419 | struct acpi_namespace_node *parent_node; | ||
420 | struct acpi_namespace_node *this_node; | ||
421 | |||
422 | ACPI_FUNCTION_ENTRY(); | ||
423 | |||
424 | /* | ||
425 | * Decrement the reference count(s) of this node and all | ||
426 | * nodes up to the root, Delete anything with zero remaining references. | ||
427 | */ | ||
428 | this_node = node; | ||
429 | while (this_node) { | ||
430 | /* Prepare to move up to parent */ | ||
431 | |||
432 | parent_node = acpi_ns_get_parent_node(this_node); | ||
433 | |||
434 | /* Decrement the reference count on this node */ | ||
435 | |||
436 | this_node->reference_count--; | ||
437 | |||
438 | /* Delete the node if no more references */ | ||
439 | |||
440 | if (!this_node->reference_count) { | ||
441 | /* Delete all children and delete the node */ | ||
442 | |||
443 | acpi_ns_delete_children(this_node); | ||
444 | acpi_ns_delete_node(this_node); | ||
445 | } | ||
446 | |||
447 | this_node = parent_node; | ||
448 | } | ||
449 | } | ||
450 | |||
451 | /******************************************************************************* | ||
452 | * | ||
453 | * FUNCTION: acpi_ns_delete_namespace_by_owner | 379 | * FUNCTION: acpi_ns_delete_namespace_by_owner |
454 | * | 380 | * |
455 | * PARAMETERS: owner_id - All nodes with this owner will be deleted | 381 | * PARAMETERS: owner_id - All nodes with this owner will be deleted |
@@ -469,15 +395,15 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id) | |||
469 | u32 level; | 395 | u32 level; |
470 | struct acpi_namespace_node *parent_node; | 396 | struct acpi_namespace_node *parent_node; |
471 | 397 | ||
472 | ACPI_FUNCTION_TRACE_U32("ns_delete_namespace_by_owner", owner_id); | 398 | ACPI_FUNCTION_TRACE_U32(ns_delete_namespace_by_owner, owner_id); |
473 | 399 | ||
474 | if (owner_id == 0) { | 400 | if (owner_id == 0) { |
475 | return_VOID; | 401 | return_VOID; |
476 | } | 402 | } |
477 | 403 | ||
404 | deletion_node = NULL; | ||
478 | parent_node = acpi_gbl_root_node; | 405 | parent_node = acpi_gbl_root_node; |
479 | child_node = NULL; | 406 | child_node = NULL; |
480 | deletion_node = NULL; | ||
481 | level = 1; | 407 | level = 1; |
482 | 408 | ||
483 | /* | 409 | /* |
@@ -494,12 +420,14 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id) | |||
494 | child_node); | 420 | child_node); |
495 | 421 | ||
496 | if (deletion_node) { | 422 | if (deletion_node) { |
497 | acpi_ns_remove_reference(deletion_node); | 423 | acpi_ns_delete_children(deletion_node); |
424 | acpi_ns_delete_node(deletion_node); | ||
498 | deletion_node = NULL; | 425 | deletion_node = NULL; |
499 | } | 426 | } |
500 | 427 | ||
501 | if (child_node) { | 428 | if (child_node) { |
502 | if (child_node->owner_id == owner_id) { | 429 | if (child_node->owner_id == owner_id) { |
430 | |||
503 | /* Found a matching child node - detach any attached object */ | 431 | /* Found a matching child node - detach any attached object */ |
504 | 432 | ||
505 | acpi_ns_detach_object(child_node); | 433 | acpi_ns_detach_object(child_node); |