diff options
Diffstat (limited to 'drivers/acpi/acpica/nsalloc.c')
-rw-r--r-- | drivers/acpi/acpica/nsalloc.c | 88 |
1 files changed, 61 insertions, 27 deletions
diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c index efc971ab7d65..8a58a1b85aa0 100644 --- a/drivers/acpi/acpica/nsalloc.c +++ b/drivers/acpi/acpica/nsalloc.c | |||
@@ -96,17 +96,68 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name) | |||
96 | * | 96 | * |
97 | * RETURN: None | 97 | * RETURN: None |
98 | * | 98 | * |
99 | * DESCRIPTION: Delete a namespace node | 99 | * DESCRIPTION: Delete a namespace node. All node deletions must come through |
100 | * here. Detaches any attached objects, including any attached | ||
101 | * data. If a handler is associated with attached data, it is | ||
102 | * invoked before the node is deleted. | ||
100 | * | 103 | * |
101 | ******************************************************************************/ | 104 | ******************************************************************************/ |
102 | 105 | ||
103 | void acpi_ns_delete_node(struct acpi_namespace_node *node) | 106 | void acpi_ns_delete_node(struct acpi_namespace_node *node) |
104 | { | 107 | { |
108 | union acpi_operand_object *obj_desc; | ||
109 | |||
110 | ACPI_FUNCTION_NAME(ns_delete_node); | ||
111 | |||
112 | /* Detach an object if there is one */ | ||
113 | |||
114 | acpi_ns_detach_object(node); | ||
115 | |||
116 | /* | ||
117 | * Delete an attached data object if present (an object that was created | ||
118 | * and attached via acpi_attach_data). Note: After any normal object is | ||
119 | * detached above, the only possible remaining object is a data object. | ||
120 | */ | ||
121 | obj_desc = node->object; | ||
122 | if (obj_desc && (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) { | ||
123 | |||
124 | /* Invoke the attached data deletion handler if present */ | ||
125 | |||
126 | if (obj_desc->data.handler) { | ||
127 | obj_desc->data.handler(node, obj_desc->data.pointer); | ||
128 | } | ||
129 | |||
130 | acpi_ut_remove_reference(obj_desc); | ||
131 | } | ||
132 | |||
133 | /* Now we can delete the node */ | ||
134 | |||
135 | (void)acpi_os_release_object(acpi_gbl_namespace_cache, node); | ||
136 | |||
137 | ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); | ||
138 | ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n", | ||
139 | node, acpi_gbl_current_node_count)); | ||
140 | } | ||
141 | |||
142 | /******************************************************************************* | ||
143 | * | ||
144 | * FUNCTION: acpi_ns_remove_node | ||
145 | * | ||
146 | * PARAMETERS: Node - Node to be removed/deleted | ||
147 | * | ||
148 | * RETURN: None | ||
149 | * | ||
150 | * DESCRIPTION: Remove (unlink) and delete a namespace node | ||
151 | * | ||
152 | ******************************************************************************/ | ||
153 | |||
154 | void acpi_ns_remove_node(struct acpi_namespace_node *node) | ||
155 | { | ||
105 | struct acpi_namespace_node *parent_node; | 156 | struct acpi_namespace_node *parent_node; |
106 | struct acpi_namespace_node *prev_node; | 157 | struct acpi_namespace_node *prev_node; |
107 | struct acpi_namespace_node *next_node; | 158 | struct acpi_namespace_node *next_node; |
108 | 159 | ||
109 | ACPI_FUNCTION_TRACE_PTR(ns_delete_node, node); | 160 | ACPI_FUNCTION_TRACE_PTR(ns_remove_node, node); |
110 | 161 | ||
111 | parent_node = acpi_ns_get_parent_node(node); | 162 | parent_node = acpi_ns_get_parent_node(node); |
112 | 163 | ||
@@ -142,12 +193,9 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) | |||
142 | } | 193 | } |
143 | } | 194 | } |
144 | 195 | ||
145 | ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); | 196 | /* Delete the node and any attached objects */ |
146 | |||
147 | /* Detach an object if there is one, then delete the node */ | ||
148 | 197 | ||
149 | acpi_ns_detach_object(node); | 198 | acpi_ns_delete_node(node); |
150 | (void)acpi_os_release_object(acpi_gbl_namespace_cache, node); | ||
151 | return_VOID; | 199 | return_VOID; |
152 | } | 200 | } |
153 | 201 | ||
@@ -273,25 +321,11 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) | |||
273 | parent_node, child_node)); | 321 | parent_node, child_node)); |
274 | } | 322 | } |
275 | 323 | ||
276 | /* Now we can free this child object */ | 324 | /* |
277 | 325 | * Delete this child node and move on to the next child in the list. | |
278 | ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); | 326 | * No need to unlink the node since we are deleting the entire branch. |
279 | 327 | */ | |
280 | ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, | 328 | acpi_ns_delete_node(child_node); |
281 | "Object %p, Remaining %X\n", child_node, | ||
282 | acpi_gbl_current_node_count)); | ||
283 | |||
284 | /* Detach an object if there is one, then free the child node */ | ||
285 | |||
286 | acpi_ns_detach_object(child_node); | ||
287 | |||
288 | /* Now we can delete the node */ | ||
289 | |||
290 | (void)acpi_os_release_object(acpi_gbl_namespace_cache, | ||
291 | child_node); | ||
292 | |||
293 | /* And move on to the next child in the list */ | ||
294 | |||
295 | child_node = next_node; | 329 | child_node = next_node; |
296 | 330 | ||
297 | } while (!(flags & ANOBJ_END_OF_PEER_LIST)); | 331 | } while (!(flags & ANOBJ_END_OF_PEER_LIST)); |
@@ -433,7 +467,7 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id) | |||
433 | 467 | ||
434 | if (deletion_node) { | 468 | if (deletion_node) { |
435 | acpi_ns_delete_children(deletion_node); | 469 | acpi_ns_delete_children(deletion_node); |
436 | acpi_ns_delete_node(deletion_node); | 470 | acpi_ns_remove_node(deletion_node); |
437 | deletion_node = NULL; | 471 | deletion_node = NULL; |
438 | } | 472 | } |
439 | 473 | ||