Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 : : /******************************************************************************
3 : : *
4 : : * Module Name: dsinit - Object initialization namespace walk
5 : : *
6 : : * Copyright (C) 2000 - 2020, Intel Corp.
7 : : *
8 : : *****************************************************************************/
9 : :
10 : : #include <acpi/acpi.h>
11 : : #include "accommon.h"
12 : : #include "acdispat.h"
13 : : #include "acnamesp.h"
14 : : #include "actables.h"
15 : : #include "acinterp.h"
16 : :
17 : : #define _COMPONENT ACPI_DISPATCHER
18 : : ACPI_MODULE_NAME("dsinit")
19 : :
20 : : /* Local prototypes */
21 : : static acpi_status
22 : : acpi_ds_init_one_object(acpi_handle obj_handle,
23 : : u32 level, void *context, void **return_value);
24 : :
25 : : /*******************************************************************************
26 : : *
27 : : * FUNCTION: acpi_ds_init_one_object
28 : : *
29 : : * PARAMETERS: obj_handle - Node for the object
30 : : * level - Current nesting level
31 : : * context - Points to a init info struct
32 : : * return_value - Not used
33 : : *
34 : : * RETURN: Status
35 : : *
36 : : * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every object
37 : : * within the namespace.
38 : : *
39 : : * Currently, the only objects that require initialization are:
40 : : * 1) Methods
41 : : * 2) Operation Regions
42 : : *
43 : : ******************************************************************************/
44 : :
45 : : static acpi_status
46 : 6195 : acpi_ds_init_one_object(acpi_handle obj_handle,
47 : : u32 level, void *context, void **return_value)
48 : : {
49 : 6195 : struct acpi_init_walk_info *info =
50 : : (struct acpi_init_walk_info *)context;
51 : 6195 : struct acpi_namespace_node *node =
52 : : (struct acpi_namespace_node *)obj_handle;
53 : 6195 : acpi_status status;
54 : 6195 : union acpi_operand_object *obj_desc;
55 : :
56 : 6195 : ACPI_FUNCTION_ENTRY();
57 : :
58 : : /*
59 : : * We are only interested in NS nodes owned by the table that
60 : : * was just loaded
61 : : */
62 [ + + ]: 6195 : if (node->owner_id != info->owner_id) {
63 : : return (AE_OK);
64 : : }
65 : :
66 : 6006 : info->object_count++;
67 : :
68 : : /* And even then, we are only interested in a few object types */
69 : :
70 [ + + + + ]: 6006 : switch (acpi_ns_get_type(obj_handle)) {
71 : 168 : case ACPI_TYPE_REGION:
72 : :
73 : 168 : status = acpi_ds_initialize_region(obj_handle);
74 [ - + ]: 168 : if (ACPI_FAILURE(status)) {
75 : 0 : ACPI_EXCEPTION((AE_INFO, status,
76 : : "During Region initialization %p [%4.4s]",
77 : : obj_handle,
78 : : acpi_ut_get_node_name(obj_handle)));
79 : : }
80 : :
81 : 168 : info->op_region_count++;
82 : 168 : break;
83 : :
84 : 1596 : case ACPI_TYPE_METHOD:
85 : : /*
86 : : * Auto-serialization support. We will examine each method that is
87 : : * not_serialized to determine if it creates any Named objects. If
88 : : * it does, it will be marked serialized to prevent problems if
89 : : * the method is entered by two or more threads and an attempt is
90 : : * made to create the same named object twice -- which results in
91 : : * an AE_ALREADY_EXISTS exception and method abort.
92 : : */
93 : 1596 : info->method_count++;
94 : 1596 : obj_desc = acpi_ns_get_attached_object(node);
95 [ - + ]: 1596 : if (!obj_desc) {
96 : : break;
97 : : }
98 : :
99 : : /* Ignore if already serialized */
100 : :
101 [ + + ]: 1596 : if (obj_desc->method.info_flags & ACPI_METHOD_SERIALIZED) {
102 : 168 : info->serial_method_count++;
103 : 168 : break;
104 : : }
105 : :
106 [ + - ]: 1428 : if (acpi_gbl_auto_serialize_methods) {
107 : :
108 : : /* Parse/scan method and serialize it if necessary */
109 : :
110 : 1428 : acpi_ds_auto_serialize_method(node, obj_desc);
111 [ + + ]: 1428 : if (obj_desc->method.
112 : : info_flags & ACPI_METHOD_SERIALIZED) {
113 : :
114 : : /* Method was just converted to Serialized */
115 : :
116 : 84 : info->serial_method_count++;
117 : 84 : info->serialized_method_count++;
118 : 84 : break;
119 : : }
120 : : }
121 : :
122 : 1344 : info->non_serial_method_count++;
123 : 1344 : break;
124 : :
125 : 1113 : case ACPI_TYPE_DEVICE:
126 : :
127 : 1113 : info->device_count++;
128 : 1113 : break;
129 : :
130 : : default:
131 : :
132 : : break;
133 : : }
134 : :
135 : : /*
136 : : * We ignore errors from above, and always return OK, since
137 : : * we don't want to abort the walk on a single error.
138 : : */
139 : 0 : return (AE_OK);
140 : : }
141 : :
142 : : /*******************************************************************************
143 : : *
144 : : * FUNCTION: acpi_ds_initialize_objects
145 : : *
146 : : * PARAMETERS: table_desc - Descriptor for parent ACPI table
147 : : * start_node - Root of subtree to be initialized.
148 : : *
149 : : * RETURN: Status
150 : : *
151 : : * DESCRIPTION: Walk the namespace starting at "StartNode" and perform any
152 : : * necessary initialization on the objects found therein
153 : : *
154 : : ******************************************************************************/
155 : :
156 : : acpi_status
157 : 21 : acpi_ds_initialize_objects(u32 table_index,
158 : : struct acpi_namespace_node *start_node)
159 : : {
160 : 21 : acpi_status status;
161 : 21 : struct acpi_init_walk_info info;
162 : 21 : struct acpi_table_header *table;
163 : 21 : acpi_owner_id owner_id;
164 : :
165 : 21 : ACPI_FUNCTION_TRACE(ds_initialize_objects);
166 : :
167 : 21 : status = acpi_tb_get_owner_id(table_index, &owner_id);
168 [ + - ]: 21 : if (ACPI_FAILURE(status)) {
169 : : return_ACPI_STATUS(status);
170 : : }
171 : :
172 : : ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
173 : 21 : "**** Starting initialization of namespace objects ****\n"));
174 : :
175 : : /* Set all init info to zero */
176 : :
177 : 21 : memset(&info, 0, sizeof(struct acpi_init_walk_info));
178 : :
179 : 21 : info.owner_id = owner_id;
180 : 21 : info.table_index = table_index;
181 : :
182 : : /* Walk entire namespace from the supplied root */
183 : :
184 : : /*
185 : : * We don't use acpi_walk_namespace since we do not want to acquire
186 : : * the namespace reader lock.
187 : : */
188 : 21 : status =
189 : 21 : acpi_ns_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
190 : : ACPI_NS_WALK_NO_UNLOCK,
191 : : acpi_ds_init_one_object, NULL, &info, NULL);
192 [ - + ]: 21 : if (ACPI_FAILURE(status)) {
193 : 0 : ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
194 : : }
195 : :
196 : 21 : status = acpi_get_table_by_index(table_index, &table);
197 : 21 : if (ACPI_FAILURE(status)) {
198 : : return_ACPI_STATUS(status);
199 : : }
200 : :
201 : : /* DSDT is always the first AML table */
202 : :
203 : : if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_DSDT)) {
204 : : ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
205 : : "\nACPI table initialization:\n"));
206 : : }
207 : :
208 : : /* Summary of objects initialized */
209 : :
210 : : ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
211 : : "Table [%4.4s: %-8.8s] (id %.2X) - %4u Objects with %3u Devices, "
212 : : "%3u Regions, %4u Methods (%u/%u/%u Serial/Non/Cvt)\n",
213 : : table->signature, table->oem_table_id, owner_id,
214 : : info.object_count, info.device_count,
215 : : info.op_region_count, info.method_count,
216 : : info.serial_method_count,
217 : : info.non_serial_method_count,
218 : : info.serialized_method_count));
219 : :
220 : : ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "%u Methods, %u Regions\n",
221 : : info.method_count, info.op_region_count));
222 : :
223 : : return_ACPI_STATUS(AE_OK);
224 : : }
|