@@ -83,6 +83,7 @@ static bool acpi_nondev_subnode_extract(union acpi_object *desc,
8383 struct fwnode_handle * parent )
8484{
8585 struct acpi_data_node * dn ;
86+ acpi_handle scope = NULL ;
8687 bool result ;
8788
8889 if (acpi_graph_ignore_port (handle ))
@@ -98,69 +99,62 @@ static bool acpi_nondev_subnode_extract(union acpi_object *desc,
9899 INIT_LIST_HEAD (& dn -> data .properties );
99100 INIT_LIST_HEAD (& dn -> data .subnodes );
100101
101- result = acpi_extract_properties (handle , desc , & dn -> data );
102-
103- if (handle ) {
104- acpi_handle scope ;
105- acpi_status status ;
102+ /*
103+ * The scope for the completion of relative pathname segments and
104+ * subnode object lookup is the one of the namespace node (device)
105+ * containing the object that has returned the package. That is, it's
106+ * the scope of that object's parent device.
107+ */
108+ if (handle )
109+ acpi_get_parent (handle , & scope );
106110
107- /*
108- * The scope for the subnode object lookup is the one of the
109- * namespace node (device) containing the object that has
110- * returned the package. That is, it's the scope of that
111- * object's parent.
112- */
113- status = acpi_get_parent ( handle , & scope );
114- if ( ACPI_SUCCESS ( status )
115- && acpi_enumerate_nondev_subnodes ( scope , desc , & dn -> data ,
116- & dn -> fwnode ))
117- result = true;
118- } else if ( acpi_enumerate_nondev_subnodes ( NULL , desc , & dn -> data ,
119- & dn -> fwnode )) {
111+ /*
112+ * Extract properties from the _DSD-equivalent package pointed to by
113+ * desc and use scope (if not NULL) for the completion of relative
114+ * pathname segments.
115+ *
116+ * The extracted properties will be held in the new data node dn.
117+ */
118+ result = acpi_extract_properties ( scope , desc , & dn -> data );
119+ /*
120+ * Look for subnodes in the _DSD-equivalent package pointed to by desc
121+ * and create child nodes of dn if there are any.
122+ */
123+ if ( acpi_enumerate_nondev_subnodes ( scope , desc , & dn -> data , & dn -> fwnode ))
120124 result = true;
121- }
122-
123- if (result ) {
124- dn -> handle = handle ;
125- dn -> data .pointer = desc ;
126- list_add_tail (& dn -> sibling , list );
127- return true;
128- }
129-
130- kfree (dn );
131- acpi_handle_debug (handle , "Invalid properties/subnodes data, skipping\n" );
132- return false;
133- }
134125
135- static bool acpi_nondev_subnode_data_ok (acpi_handle handle ,
136- const union acpi_object * link ,
137- struct list_head * list ,
138- struct fwnode_handle * parent )
139- {
140- struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
141- acpi_status status ;
142-
143- status = acpi_evaluate_object_typed (handle , NULL , NULL , & buf ,
144- ACPI_TYPE_PACKAGE );
145- if (ACPI_FAILURE (status ))
126+ if (!result ) {
127+ kfree (dn );
128+ acpi_handle_debug (handle , "Invalid properties/subnodes data, skipping\n" );
146129 return false;
130+ }
147131
148- if (acpi_nondev_subnode_extract (buf .pointer , handle , link , list ,
149- parent ))
150- return true;
132+ /*
133+ * This will be NULL if the desc package is embedded in an outer
134+ * _DSD-equivalent package and its scope cannot be determined.
135+ */
136+ dn -> handle = handle ;
137+ dn -> data .pointer = desc ;
138+ list_add_tail (& dn -> sibling , list );
151139
152- ACPI_FREE (buf .pointer );
153- return false;
140+ return true;
154141}
155142
156143static bool acpi_nondev_subnode_ok (acpi_handle scope ,
157144 const union acpi_object * link ,
158145 struct list_head * list ,
159146 struct fwnode_handle * parent )
160147{
148+ struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
161149 acpi_handle handle ;
162150 acpi_status status ;
163151
152+ /*
153+ * If the scope is unknown, the _DSD-equivalent package being parsed
154+ * was embedded in an outer _DSD-equivalent package as a result of
155+ * direct evaluation of an object pointed to by a reference. In that
156+ * case, using a pathname as the target object pointer is invalid.
157+ */
164158 if (!scope )
165159 return false;
166160
@@ -169,7 +163,17 @@ static bool acpi_nondev_subnode_ok(acpi_handle scope,
169163 if (ACPI_FAILURE (status ))
170164 return false;
171165
172- return acpi_nondev_subnode_data_ok (handle , link , list , parent );
166+ status = acpi_evaluate_object_typed (handle , NULL , NULL , & buf ,
167+ ACPI_TYPE_PACKAGE );
168+ if (ACPI_FAILURE (status ))
169+ return false;
170+
171+ if (acpi_nondev_subnode_extract (buf .pointer , handle , link , list ,
172+ parent ))
173+ return true;
174+
175+ ACPI_FREE (buf .pointer );
176+ return false;
173177}
174178
175179static bool acpi_add_nondev_subnodes (acpi_handle scope ,
@@ -180,36 +184,66 @@ static bool acpi_add_nondev_subnodes(acpi_handle scope,
180184 bool ret = false;
181185 int i ;
182186
187+ /*
188+ * Every element in the links package is expected to represent a link
189+ * to a non-device node in a tree containing device-specific data.
190+ */
183191 for (i = 0 ; i < links -> package .count ; i ++ ) {
184192 union acpi_object * link , * desc ;
185- acpi_handle handle ;
186193 bool result ;
187194
188195 link = & links -> package .elements [i ];
189196 /* Only two elements allowed. */
190197 if (link -> package .count != 2 )
191198 continue ;
192199
193- /* The first one must be a string. */
200+ /* The first one (the key) must be a string. */
194201 if (link -> package .elements [0 ].type != ACPI_TYPE_STRING )
195202 continue ;
196203
197- /* The second one may be a string, a reference or a package. */
204+ /* The second one (the target) may be a string or a package. */
198205 switch (link -> package .elements [1 ].type ) {
199206 case ACPI_TYPE_STRING :
207+ /*
208+ * The string is expected to be a full pathname or a
209+ * pathname segment relative to the given scope. That
210+ * pathname is expected to point to an object returning
211+ * a package that contains _DSD-equivalent information.
212+ */
200213 result = acpi_nondev_subnode_ok (scope , link , list ,
201214 parent );
202215 break ;
203- case ACPI_TYPE_LOCAL_REFERENCE :
204- handle = link -> package .elements [1 ].reference .handle ;
205- result = acpi_nondev_subnode_data_ok (handle , link , list ,
206- parent );
207- break ;
208216 case ACPI_TYPE_PACKAGE :
217+ /*
218+ * This happens when a reference is used in AML to
219+ * point to the target. Since the target is expected
220+ * to be a named object, a reference to it will cause it
221+ * to be avaluated in place and its return package will
222+ * be embedded in the links package at the location of
223+ * the reference.
224+ *
225+ * The target package is expected to contain _DSD-
226+ * equivalent information, but the scope in which it
227+ * is located in the original AML is unknown. Thus
228+ * it cannot contain pathname segments represented as
229+ * strings because there is no way to build full
230+ * pathnames out of them.
231+ */
232+ acpi_handle_debug (scope , "subnode %s: Unknown scope\n" ,
233+ link -> package .elements [0 ].string .pointer );
209234 desc = & link -> package .elements [1 ];
210235 result = acpi_nondev_subnode_extract (desc , NULL , link ,
211236 list , parent );
212237 break ;
238+ case ACPI_TYPE_LOCAL_REFERENCE :
239+ /*
240+ * It is not expected to see any local references in
241+ * the links package because referencing a named object
242+ * should cause it to be evaluated in place.
243+ */
244+ acpi_handle_info (scope , "subnode %s: Unexpected reference\n" ,
245+ link -> package .elements [0 ].string .pointer );
246+ fallthrough ;
213247 default :
214248 result = false;
215249 break ;
@@ -369,6 +403,9 @@ static void acpi_untie_nondev_subnodes(struct acpi_device_data *data)
369403 struct acpi_data_node * dn ;
370404
371405 list_for_each_entry (dn , & data -> subnodes , sibling ) {
406+ if (!dn -> handle )
407+ continue ;
408+
372409 acpi_detach_data (dn -> handle , acpi_nondev_subnode_tag );
373410
374411 acpi_untie_nondev_subnodes (& dn -> data );
@@ -383,6 +420,9 @@ static bool acpi_tie_nondev_subnodes(struct acpi_device_data *data)
383420 acpi_status status ;
384421 bool ret ;
385422
423+ if (!dn -> handle )
424+ continue ;
425+
386426 status = acpi_attach_data (dn -> handle , acpi_nondev_subnode_tag , dn );
387427 if (ACPI_FAILURE (status ) && status != AE_ALREADY_EXISTS ) {
388428 acpi_handle_err (dn -> handle , "Can't tag data node\n" );
0 commit comments