hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/drivers/acpi/property.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * ACPI device specific properties support.
34 *
....@@ -7,10 +8,6 @@
78 * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
89 * Darren Hart <dvhart@linux.intel.com>
910 * Rafael J. Wysocki <rafael.j.wysocki@intel.com>
10
- *
11
- * This program is free software; you can redistribute it and/or modify
12
- * it under the terms of the GNU General Public License version 2 as
13
- * published by the Free Software Foundation.
1411 */
1512
1613 #include <linux/acpi.h>
....@@ -24,10 +21,35 @@
2421 acpi_object_type type,
2522 const union acpi_object **obj);
2623
27
-/* ACPI _DSD device properties GUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
28
-static const guid_t prp_guid =
24
+/*
25
+ * The GUIDs here are made equivalent to each other in order to avoid extra
26
+ * complexity in the properties handling code, with the caveat that the
27
+ * kernel will accept certain combinations of GUID and properties that are
28
+ * not defined without a warning. For instance if any of the properties
29
+ * from different GUID appear in a property list of another, it will be
30
+ * accepted by the kernel. Firmware validation tools should catch these.
31
+ */
32
+static const guid_t prp_guids[] = {
33
+ /* ACPI _DSD device properties GUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
2934 GUID_INIT(0xdaffd814, 0x6eba, 0x4d8c,
30
- 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01);
35
+ 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01),
36
+ /* Hotplug in D3 GUID: 6211e2c0-58a3-4af3-90e1-927a4e0c55a4 */
37
+ GUID_INIT(0x6211e2c0, 0x58a3, 0x4af3,
38
+ 0x90, 0xe1, 0x92, 0x7a, 0x4e, 0x0c, 0x55, 0xa4),
39
+ /* External facing port GUID: efcc06cc-73ac-4bc3-bff0-76143807c389 */
40
+ GUID_INIT(0xefcc06cc, 0x73ac, 0x4bc3,
41
+ 0xbf, 0xf0, 0x76, 0x14, 0x38, 0x07, 0xc3, 0x89),
42
+ /* Thunderbolt GUID for IMR_VALID: c44d002f-69f9-4e7d-a904-a7baabdf43f7 */
43
+ GUID_INIT(0xc44d002f, 0x69f9, 0x4e7d,
44
+ 0xa9, 0x04, 0xa7, 0xba, 0xab, 0xdf, 0x43, 0xf7),
45
+ /* Thunderbolt GUID for WAKE_SUPPORTED: 6c501103-c189-4296-ba72-9bf5a26ebe5d */
46
+ GUID_INIT(0x6c501103, 0xc189, 0x4296,
47
+ 0xba, 0x72, 0x9b, 0xf5, 0xa2, 0x6e, 0xbe, 0x5d),
48
+ /* Storage device needs D3 GUID: 5025030f-842f-4ab4-a561-99a5189762d0 */
49
+ GUID_INIT(0x5025030f, 0x842f, 0x4ab4,
50
+ 0xa5, 0x61, 0x99, 0xa5, 0x18, 0x97, 0x62, 0xd0),
51
+};
52
+
3153 /* ACPI _DSD data subnodes GUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */
3254 static const guid_t ads_guid =
3355 GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6,
....@@ -54,8 +76,9 @@
5476 return false;
5577
5678 dn->name = link->package.elements[0].string.pointer;
57
- dn->fwnode.ops = &acpi_data_fwnode_ops;
79
+ fwnode_init(&dn->fwnode, &acpi_data_fwnode_ops);
5880 dn->parent = parent;
81
+ INIT_LIST_HEAD(&dn->data.properties);
5982 INIT_LIST_HEAD(&dn->data.subnodes);
6083
6184 result = acpi_extract_properties(desc, &dn->data);
....@@ -132,10 +155,10 @@
132155 return acpi_nondev_subnode_data_ok(handle, link, list, parent);
133156 }
134157
135
-static int acpi_add_nondev_subnodes(acpi_handle scope,
136
- const union acpi_object *links,
137
- struct list_head *list,
138
- struct fwnode_handle *parent)
158
+static bool acpi_add_nondev_subnodes(acpi_handle scope,
159
+ const union acpi_object *links,
160
+ struct list_head *list,
161
+ struct fwnode_handle *parent)
139162 {
140163 bool ret = false;
141164 int i;
....@@ -288,6 +311,35 @@
288311 adev->flags.of_compatible_ok = 1;
289312 }
290313
314
+static bool acpi_is_property_guid(const guid_t *guid)
315
+{
316
+ int i;
317
+
318
+ for (i = 0; i < ARRAY_SIZE(prp_guids); i++) {
319
+ if (guid_equal(guid, &prp_guids[i]))
320
+ return true;
321
+ }
322
+
323
+ return false;
324
+}
325
+
326
+struct acpi_device_properties *
327
+acpi_data_add_props(struct acpi_device_data *data, const guid_t *guid,
328
+ const union acpi_object *properties)
329
+{
330
+ struct acpi_device_properties *props;
331
+
332
+ props = kzalloc(sizeof(*props), GFP_KERNEL);
333
+ if (props) {
334
+ INIT_LIST_HEAD(&props->list);
335
+ props->guid = guid;
336
+ props->properties = properties;
337
+ list_add_tail(&props->list, &data->properties);
338
+ }
339
+
340
+ return props;
341
+}
342
+
291343 static bool acpi_extract_properties(const union acpi_object *desc,
292344 struct acpi_device_data *data)
293345 {
....@@ -312,7 +364,7 @@
312364 properties->type != ACPI_TYPE_PACKAGE)
313365 break;
314366
315
- if (!guid_equal((guid_t *)guid->buffer.pointer, &prp_guid))
367
+ if (!acpi_is_property_guid((guid_t *)guid->buffer.pointer))
316368 continue;
317369
318370 /*
....@@ -320,13 +372,13 @@
320372 * package immediately following it.
321373 */
322374 if (!acpi_properties_format_valid(properties))
323
- break;
375
+ continue;
324376
325
- data->properties = properties;
326
- return true;
377
+ acpi_data_add_props(data, (const guid_t *)guid->buffer.pointer,
378
+ properties);
327379 }
328380
329
- return false;
381
+ return !list_empty(&data->properties);
330382 }
331383
332384 void acpi_init_properties(struct acpi_device *adev)
....@@ -336,6 +388,7 @@
336388 acpi_status status;
337389 bool acpi_of = false;
338390
391
+ INIT_LIST_HEAD(&adev->data.properties);
339392 INIT_LIST_HEAD(&adev->data.subnodes);
340393
341394 if (!adev->handle)
....@@ -380,6 +433,16 @@
380433 acpi_extract_apple_properties(adev);
381434 }
382435
436
+static void acpi_free_device_properties(struct list_head *list)
437
+{
438
+ struct acpi_device_properties *props, *tmp;
439
+
440
+ list_for_each_entry_safe(props, tmp, list, list) {
441
+ list_del(&props->list);
442
+ kfree(props);
443
+ }
444
+}
445
+
383446 static void acpi_destroy_nondev_subnodes(struct list_head *list)
384447 {
385448 struct acpi_data_node *dn, *next;
....@@ -392,6 +455,7 @@
392455 wait_for_completion(&dn->kobj_done);
393456 list_del(&dn->sibling);
394457 ACPI_FREE((void *)dn->data.pointer);
458
+ acpi_free_device_properties(&dn->data.properties);
395459 kfree(dn);
396460 }
397461 }
....@@ -402,7 +466,7 @@
402466 ACPI_FREE((void *)adev->data.pointer);
403467 adev->data.of_compatible = NULL;
404468 adev->data.pointer = NULL;
405
- adev->data.properties = NULL;
469
+ acpi_free_device_properties(&adev->data.properties);
406470 }
407471
408472 /**
....@@ -427,32 +491,37 @@
427491 const char *name, acpi_object_type type,
428492 const union acpi_object **obj)
429493 {
430
- const union acpi_object *properties;
431
- int i;
494
+ const struct acpi_device_properties *props;
432495
433496 if (!data || !name)
434497 return -EINVAL;
435498
436
- if (!data->pointer || !data->properties)
499
+ if (!data->pointer || list_empty(&data->properties))
437500 return -EINVAL;
438501
439
- properties = data->properties;
440
- for (i = 0; i < properties->package.count; i++) {
441
- const union acpi_object *propname, *propvalue;
442
- const union acpi_object *property;
502
+ list_for_each_entry(props, &data->properties, list) {
503
+ const union acpi_object *properties;
504
+ unsigned int i;
443505
444
- property = &properties->package.elements[i];
506
+ properties = props->properties;
507
+ for (i = 0; i < properties->package.count; i++) {
508
+ const union acpi_object *propname, *propvalue;
509
+ const union acpi_object *property;
445510
446
- propname = &property->package.elements[0];
447
- propvalue = &property->package.elements[1];
511
+ property = &properties->package.elements[i];
448512
449
- if (!strcmp(name, propname->string.pointer)) {
450
- if (type != ACPI_TYPE_ANY && propvalue->type != type)
451
- return -EPROTO;
452
- if (obj)
453
- *obj = propvalue;
513
+ propname = &property->package.elements[0];
514
+ propvalue = &property->package.elements[1];
454515
455
- return 0;
516
+ if (!strcmp(name, propname->string.pointer)) {
517
+ if (type != ACPI_TYPE_ANY &&
518
+ propvalue->type != type)
519
+ return -EPROTO;
520
+ if (obj)
521
+ *obj = propvalue;
522
+
523
+ return 0;
524
+ }
456525 }
457526 }
458527 return -EINVAL;
....@@ -548,13 +617,17 @@
548617 {
549618 struct fwnode_handle *child;
550619
551
- /*
552
- * Find first matching named child node of this fwnode.
553
- * For ACPI this will be a data only sub-node.
554
- */
555
- fwnode_for_each_child_node(fwnode, child)
556
- if (acpi_data_node_match(child, childname))
620
+ fwnode_for_each_child_node(fwnode, child) {
621
+ if (is_acpi_data_node(child)) {
622
+ if (acpi_data_node_match(child, childname))
623
+ return child;
624
+ continue;
625
+ }
626
+
627
+ if (!strncmp(acpi_device_bid(to_acpi_device_node(child)),
628
+ childname, ACPI_NAMESEG_SIZE))
557629 return child;
630
+ }
558631
559632 return NULL;
560633 }
....@@ -618,7 +691,7 @@
618691 */
619692 if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
620693 if (index)
621
- return -EINVAL;
694
+ return -ENOENT;
622695
623696 ret = acpi_bus_get_device(obj->reference.handle, &device);
624697 if (ret)
....@@ -1043,15 +1116,10 @@
10431116 /* All data nodes have parent pointer so just return that */
10441117 return to_acpi_data_node(fwnode)->parent;
10451118 } else if (is_acpi_device_node(fwnode)) {
1046
- acpi_handle handle, parent_handle;
1119
+ struct device *dev = to_acpi_device_node(fwnode)->dev.parent;
10471120
1048
- handle = to_acpi_device_node(fwnode)->handle;
1049
- if (ACPI_SUCCESS(acpi_get_parent(handle, &parent_handle))) {
1050
- struct acpi_device *adev;
1051
-
1052
- if (!acpi_bus_get_device(parent_handle, &adev))
1053
- return acpi_fwnode_handle(adev);
1054
- }
1121
+ if (dev)
1122
+ return acpi_fwnode_handle(to_acpi_device(dev));
10551123 }
10561124
10571125 return NULL;
....@@ -1164,7 +1232,7 @@
11641232
11651233
11661234 /**
1167
- * acpi_graph_get_remote_enpoint - Parses and returns remote end of an endpoint
1235
+ * acpi_graph_get_remote_endpoint - Parses and returns remote end of an endpoint
11681236 * @fwnode: Endpoint firmware node pointing to a remote device
11691237 * @endpoint: Firmware node of remote endpoint is filled here if not %NULL
11701238 *
....@@ -1265,6 +1333,52 @@
12651333 args_count, args);
12661334 }
12671335
1336
+static const char *acpi_fwnode_get_name(const struct fwnode_handle *fwnode)
1337
+{
1338
+ const struct acpi_device *adev;
1339
+ struct fwnode_handle *parent;
1340
+
1341
+ /* Is this the root node? */
1342
+ parent = fwnode_get_parent(fwnode);
1343
+ if (!parent)
1344
+ return "\\";
1345
+
1346
+ fwnode_handle_put(parent);
1347
+
1348
+ if (is_acpi_data_node(fwnode)) {
1349
+ const struct acpi_data_node *dn = to_acpi_data_node(fwnode);
1350
+
1351
+ return dn->name;
1352
+ }
1353
+
1354
+ adev = to_acpi_device_node(fwnode);
1355
+ if (WARN_ON(!adev))
1356
+ return NULL;
1357
+
1358
+ return acpi_device_bid(adev);
1359
+}
1360
+
1361
+static const char *
1362
+acpi_fwnode_get_name_prefix(const struct fwnode_handle *fwnode)
1363
+{
1364
+ struct fwnode_handle *parent;
1365
+
1366
+ /* Is this the root node? */
1367
+ parent = fwnode_get_parent(fwnode);
1368
+ if (!parent)
1369
+ return "";
1370
+
1371
+ /* Is this 2nd node from the root? */
1372
+ parent = fwnode_get_next_parent(parent);
1373
+ if (!parent)
1374
+ return "";
1375
+
1376
+ fwnode_handle_put(parent);
1377
+
1378
+ /* ACPI device or data node. */
1379
+ return ".";
1380
+}
1381
+
12681382 static struct fwnode_handle *
12691383 acpi_fwnode_get_parent(struct fwnode_handle *fwnode)
12701384 {
....@@ -1305,6 +1419,8 @@
13051419 .get_parent = acpi_node_get_parent, \
13061420 .get_next_child_node = acpi_get_next_subnode, \
13071421 .get_named_child_node = acpi_fwnode_get_named_child_node, \
1422
+ .get_name = acpi_fwnode_get_name, \
1423
+ .get_name_prefix = acpi_fwnode_get_name_prefix, \
13081424 .get_reference_args = acpi_fwnode_get_reference_args, \
13091425 .graph_get_next_endpoint = \
13101426 acpi_graph_get_next_endpoint, \