aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/nsalloc.c
diff options
context:
space:
mode:
authorAlexey Starikovskiy <astarikovskiy@suse.de>2010-05-25 23:53:07 -0400
committerLen Brown <len.brown@intel.com>2010-07-06 22:33:56 -0400
commitc45b5c097001480e66d4c523eb715ad317a4ef77 (patch)
tree5b9415840b97a724537273db99b2c66975c63347 /drivers/acpi/acpica/nsalloc.c
parent5821f75421aa7c7bafdec291223153597f649934 (diff)
ACPICA: Performance enhancement for namespace search and access
This change enhances the performance of namespace searches and walks by adding a backpointer to the parent in each namespace node. On large namespaces, this change can improve overall ACPI performance by up to 9X. Adding a pointer to each namespace node increases the overall size of the internal namespace by about 5%, since each namespace entry usually consists of both a namespace node and an ACPI operand object. Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de> Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/acpica/nsalloc.c')
-rw-r--r--drivers/acpi/acpica/nsalloc.c74
1 files changed, 25 insertions, 49 deletions
diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c
index 982269c1fa48..8d3a43a061ab 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 */
@@ -238,23 +229,20 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp
238 229
239 /* Link the new entry into the parent and existing children */ 230 /* Link the new entry into the parent and existing children */
240 231
232 node->peer = NULL;
233 node->parent = parent_node;
241 child_node = parent_node->child; 234 child_node = parent_node->child;
235
242 if (!child_node) { 236 if (!child_node) {
243 parent_node->child = node; 237 parent_node->child = node;
244 node->flags |= ANOBJ_END_OF_PEER_LIST;
245 node->peer = parent_node;
246 } else { 238 } else {
247 while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) { 239 /* Add node to the end of the peer list */
240
241 while (child_node->peer) {
248 child_node = child_node->peer; 242 child_node = child_node->peer;
249 } 243 }
250 244
251 child_node->peer = node; 245 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 } 246 }
259 247
260 /* Init the new entry */ 248 /* Init the new entry */
@@ -288,9 +276,8 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp
288 276
289void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) 277void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
290{ 278{
291 struct acpi_namespace_node *child_node;
292 struct acpi_namespace_node *next_node; 279 struct acpi_namespace_node *next_node;
293 u8 flags; 280 struct acpi_namespace_node *node_to_delete;
294 281
295 ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node); 282 ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node);
296 283
@@ -298,37 +285,26 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
298 return_VOID; 285 return_VOID;
299 } 286 }
300 287
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 */ 288 /* Deallocate all children at this level */
309 289
310 do { 290 next_node = parent_node->child;
311 291 while (next_node) {
312 /* Get the things we need */
313
314 next_node = child_node->peer;
315 flags = child_node->flags;
316 292
317 /* Grandchildren should have all been deleted already */ 293 /* Grandchildren should have all been deleted already */
318 294
319 if (child_node->child) { 295 if (next_node->child) {
320 ACPI_ERROR((AE_INFO, "Found a grandchild! P=%p C=%p", 296 ACPI_ERROR((AE_INFO, "Found a grandchild! P=%p C=%p",
321 parent_node, child_node)); 297 parent_node, next_node));
322 } 298 }
323 299
324 /* 300 /*
325 * Delete this child node and move on to the next child in the list. 301 * 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. 302 * No need to unlink the node since we are deleting the entire branch.
327 */ 303 */
328 acpi_ns_delete_node(child_node); 304 node_to_delete = next_node;
329 child_node = next_node; 305 next_node = next_node->peer;
330 306 acpi_ns_delete_node(node_to_delete);
331 } while (!(flags & ANOBJ_END_OF_PEER_LIST)); 307 };
332 308
333 /* Clear the parent's child pointer */ 309 /* Clear the parent's child pointer */
334 310
@@ -405,7 +381,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node)
405 381
406 /* Move up the tree to the grandparent */ 382 /* Move up the tree to the grandparent */
407 383
408 parent_node = acpi_ns_get_parent_node(parent_node); 384 parent_node = parent_node->parent;
409 } 385 }
410 } 386 }
411 387
@@ -510,7 +486,7 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id)
510 486
511 /* Move up the tree to the grandparent */ 487 /* Move up the tree to the grandparent */
512 488
513 parent_node = acpi_ns_get_parent_node(parent_node); 489 parent_node = parent_node->parent;
514 } 490 }
515 } 491 }
516 492