1
2
3
4
5
6
7
8#include <acpi/acpi.h>
9#include "accommon.h"
10#include "acnamesp.h"
11
12#define _COMPONENT ACPI_NAMESPACE
13ACPI_MODULE_NAME("nsalloc")
14
15
16
17
18
19
20
21
22
23
24
25
26struct acpi_namespace_node *acpi_ns_create_node(u32 name)
27{
28 struct acpi_namespace_node *node;
29#ifdef ACPI_DBG_TRACK_ALLOCATIONS
30 u32 temp;
31#endif
32
33 ACPI_FUNCTION_TRACE(ns_create_node);
34
35 node = acpi_os_acquire_object(acpi_gbl_namespace_cache);
36 if (!node) {
37 return_PTR(NULL);
38 }
39
40 ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_allocated++);
41
42#ifdef ACPI_DBG_TRACK_ALLOCATIONS
43 temp = acpi_gbl_ns_node_list->total_allocated -
44 acpi_gbl_ns_node_list->total_freed;
45 if (temp > acpi_gbl_ns_node_list->max_occupied) {
46 acpi_gbl_ns_node_list->max_occupied = temp;
47 }
48#endif
49
50 node->name.integer = name;
51 ACPI_SET_DESCRIPTOR_TYPE(node, ACPI_DESC_TYPE_NAMED);
52 return_PTR(node);
53}
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70void acpi_ns_delete_node(struct acpi_namespace_node *node)
71{
72 union acpi_operand_object *obj_desc;
73 union acpi_operand_object *next_desc;
74
75 ACPI_FUNCTION_NAME(ns_delete_node);
76
77
78
79 acpi_ns_detach_object(node);
80
81
82
83
84
85
86
87 obj_desc = node->object;
88 while (obj_desc && (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) {
89
90
91
92 if (obj_desc->data.handler) {
93 obj_desc->data.handler(node, obj_desc->data.pointer);
94 }
95
96 next_desc = obj_desc->common.next_object;
97 acpi_ut_remove_reference(obj_desc);
98 obj_desc = next_desc;
99 }
100
101
102
103 if (node == acpi_gbl_root_node) {
104 return;
105 }
106
107
108
109 (void)acpi_os_release_object(acpi_gbl_namespace_cache, node);
110
111 ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++);
112 ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n",
113 node, acpi_gbl_current_node_count));
114}
115
116
117
118
119
120
121
122
123
124
125
126
127
128void acpi_ns_remove_node(struct acpi_namespace_node *node)
129{
130 struct acpi_namespace_node *parent_node;
131 struct acpi_namespace_node *prev_node;
132 struct acpi_namespace_node *next_node;
133
134 ACPI_FUNCTION_TRACE_PTR(ns_remove_node, node);
135
136 parent_node = node->parent;
137
138 prev_node = NULL;
139 next_node = parent_node->child;
140
141
142
143 while (next_node != node) {
144 prev_node = next_node;
145 next_node = next_node->peer;
146 }
147
148 if (prev_node) {
149
150
151
152 prev_node->peer = node->peer;
153 } else {
154
155
156
157
158 parent_node->child = node->peer;
159 }
160
161
162
163 acpi_ns_delete_node(node);
164 return_VOID;
165}
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namespace_node *parent_node,
188 struct acpi_namespace_node *node,
189 acpi_object_type type)
190{
191 acpi_owner_id owner_id = 0;
192 struct acpi_namespace_node *child_node;
193
194 ACPI_FUNCTION_TRACE(ns_install_node);
195
196 if (walk_state) {
197
198
199
200
201 owner_id = walk_state->owner_id;
202
203 if ((walk_state->method_desc) &&
204 (parent_node != walk_state->method_node)) {
205
206
207
208
209
210
211 walk_state->method_desc->method.info_flags |=
212 ACPI_METHOD_MODIFIED_NAMESPACE;
213 }
214 }
215
216
217
218 node->peer = NULL;
219 node->parent = parent_node;
220 child_node = parent_node->child;
221
222 if (!child_node) {
223 parent_node->child = node;
224 } else {
225
226
227 while (child_node->peer) {
228 child_node = child_node->peer;
229 }
230
231 child_node->peer = node;
232 }
233
234
235
236 node->owner_id = owner_id;
237 node->type = (u8) type;
238
239 ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
240 "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
241 acpi_ut_get_node_name(node),
242 acpi_ut_get_type_name(node->type), node, owner_id,
243 acpi_ut_get_node_name(parent_node),
244 acpi_ut_get_type_name(parent_node->type),
245 parent_node));
246
247 return_VOID;
248}
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
264{
265 struct acpi_namespace_node *next_node;
266 struct acpi_namespace_node *node_to_delete;
267
268 ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node);
269
270 if (!parent_node) {
271 return_VOID;
272 }
273
274
275
276 next_node = parent_node->child;
277 while (next_node) {
278
279
280
281 if (next_node->child) {
282 ACPI_ERROR((AE_INFO, "Found a grandchild! P=%p C=%p",
283 parent_node, next_node));
284 }
285
286
287
288
289
290 node_to_delete = next_node;
291 next_node = next_node->peer;
292 acpi_ns_delete_node(node_to_delete);
293 };
294
295
296
297 parent_node->child = NULL;
298 return_VOID;
299}
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node)
315{
316 struct acpi_namespace_node *child_node = NULL;
317 u32 level = 1;
318 acpi_status status;
319
320 ACPI_FUNCTION_TRACE(ns_delete_namespace_subtree);
321
322 if (!parent_node) {
323 return_VOID;
324 }
325
326
327
328 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
329 if (ACPI_FAILURE(status)) {
330 return_VOID;
331 }
332
333
334
335
336
337 while (level > 0) {
338
339
340
341 child_node = acpi_ns_get_next_node(parent_node, child_node);
342 if (child_node) {
343
344
345
346 acpi_ns_detach_object(child_node);
347
348
349
350 if (child_node->child) {
351
352
353
354
355 level++;
356 parent_node = child_node;
357 child_node = NULL;
358 }
359 } else {
360
361
362
363
364 level--;
365
366
367
368
369
370 acpi_ns_delete_children(parent_node);
371
372
373
374 child_node = parent_node;
375
376
377
378 parent_node = parent_node->parent;
379 }
380 }
381
382 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
383 return_VOID;
384}
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id)
403{
404 struct acpi_namespace_node *child_node;
405 struct acpi_namespace_node *deletion_node;
406 struct acpi_namespace_node *parent_node;
407 u32 level;
408 acpi_status status;
409
410 ACPI_FUNCTION_TRACE_U32(ns_delete_namespace_by_owner, owner_id);
411
412 if (owner_id == 0) {
413 return_VOID;
414 }
415
416
417
418 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
419 if (ACPI_FAILURE(status)) {
420 return_VOID;
421 }
422
423 deletion_node = NULL;
424 parent_node = acpi_gbl_root_node;
425 child_node = NULL;
426 level = 1;
427
428
429
430
431
432 while (level > 0) {
433
434
435
436
437 child_node = acpi_ns_get_next_node(parent_node, child_node);
438
439 if (deletion_node) {
440 acpi_ns_delete_children(deletion_node);
441 acpi_ns_remove_node(deletion_node);
442 deletion_node = NULL;
443 }
444
445 if (child_node) {
446 if (child_node->owner_id == owner_id) {
447
448
449
450 acpi_ns_detach_object(child_node);
451 }
452
453
454
455 if (child_node->child) {
456
457
458
459
460 level++;
461 parent_node = child_node;
462 child_node = NULL;
463 } else if (child_node->owner_id == owner_id) {
464 deletion_node = child_node;
465 }
466 } else {
467
468
469
470
471 level--;
472 if (level != 0) {
473 if (parent_node->owner_id == owner_id) {
474 deletion_node = parent_node;
475 }
476 }
477
478
479
480 child_node = parent_node;
481
482
483
484 parent_node = parent_node->parent;
485 }
486 }
487
488 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
489 return_VOID;
490}
491