Skip to content

Commit 9880702

Browse files
committed
ACPI: property: Support using strings in reference properties
In order to allow referencing data nodes directly, which is not possible currently, add support for representing references in device properties as strings (relative or absolute name paths). For example, after this change, the "mipi-img-flash-leds" property in the ASL snippet below will be treated as a proper reference to the LED0 object under LEDD. Package () { "mipi-img-flash-leds", "\\_SB.PCI0.I2C2.LEDD.LED0", } Device (LEDD) { Name (_DSD, Package () // _DSD: Device-Specific Data { ToUUID ("dbb8e3e6-5886-4ba6-8795-1319f52a966b"), /* Hierarchical Data Extension */, Package () { Package () { "mipi-img-flash-led-0", "LED0", } }, }) Name (LED0, Package () // _DSD: Device-Specific Data { ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301") /* Device Properties */, Package () { Package () { "mipi-img-max-current", 1000000, } } }) } Also remove the mechanism allowing data nodes to be referenced indirectly, with the help of an object reference pointing to the "ancestor" device and a path relative to it (this mechanism is not expected to be in use in any production platform firmware in the field). Note that this change allows also using strings for referencing device objects, in addition to object references that have been supported already. While at it, add pr_fmt() macro to prefix printouts and update copyright. Co-developed-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
1 parent 98b1cc8 commit 9880702

File tree

1 file changed

+82
-20
lines changed

1 file changed

+82
-20
lines changed

drivers/acpi/property.c

Lines changed: 82 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22
/*
33
* ACPI device specific properties support.
44
*
5-
* Copyright (C) 2014, Intel Corporation
5+
* Copyright (C) 2014 - 2023, Intel Corporation
66
* All rights reserved.
77
*
88
* Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
99
* Darren Hart <dvhart@linux.intel.com>
1010
* Rafael J. Wysocki <rafael.j.wysocki@intel.com>
11+
* Sakari Ailus <sakari.ailus@linux.intel.com>
1112
*/
1213

14+
#define pr_fmt(fmt) "ACPI: " fmt
15+
1316
#include <linux/acpi.h>
1417
#include <linux/device.h>
1518
#include <linux/export.h>
@@ -800,28 +803,16 @@ static int acpi_get_ref_args(struct fwnode_reference_args *args,
800803
{
801804
u32 nargs = 0, i;
802805

803-
/*
804-
* Find the referred data extension node under the
805-
* referred device node.
806-
*/
807-
for (; *element < end && (*element)->type == ACPI_TYPE_STRING;
808-
(*element)++) {
809-
const char *child_name = (*element)->string.pointer;
810-
811-
ref_fwnode = acpi_fwnode_get_named_child_node(ref_fwnode, child_name);
812-
if (!ref_fwnode)
813-
return -EINVAL;
814-
}
815-
816806
/*
817807
* Assume the following integer elements are all args. Stop counting on
818-
* the first reference or end of the package arguments. In case of
819-
* neither reference, nor integer, return an error, we can't parse it.
808+
* the first reference (possibly represented as a string) or end of the
809+
* package arguments. In case of neither reference, nor integer, return
810+
* an error, we can't parse it.
820811
*/
821812
for (i = 0; (*element) + i < end && i < num_args; i++) {
822813
acpi_object_type type = (*element)[i].type;
823814

824-
if (type == ACPI_TYPE_LOCAL_REFERENCE)
815+
if (type == ACPI_TYPE_LOCAL_REFERENCE || type == ACPI_TYPE_STRING)
825816
break;
826817

827818
if (type == ACPI_TYPE_INTEGER)
@@ -845,6 +836,44 @@ static int acpi_get_ref_args(struct fwnode_reference_args *args,
845836
return 0;
846837
}
847838

839+
static struct fwnode_handle *acpi_parse_string_ref(const struct fwnode_handle *fwnode,
840+
const char *refstring)
841+
{
842+
acpi_handle scope, handle;
843+
struct acpi_data_node *dn;
844+
struct acpi_device *device;
845+
acpi_status status;
846+
847+
if (is_acpi_device_node(fwnode)) {
848+
scope = to_acpi_device_node(fwnode)->handle;
849+
} else if (is_acpi_data_node(fwnode)) {
850+
scope = to_acpi_data_node(fwnode)->handle;
851+
} else {
852+
pr_debug("Bad node type for node %pfw\n", fwnode);
853+
return NULL;
854+
}
855+
856+
status = acpi_get_handle(scope, refstring, &handle);
857+
if (ACPI_FAILURE(status)) {
858+
acpi_handle_debug(scope, "Unable to get an ACPI handle for %s\n",
859+
refstring);
860+
return NULL;
861+
}
862+
863+
device = acpi_fetch_acpi_dev(handle);
864+
if (device)
865+
return acpi_fwnode_handle(device);
866+
867+
status = acpi_get_data_full(handle, acpi_nondev_subnode_tag,
868+
(void **)&dn, NULL);
869+
if (ACPI_FAILURE(status) || !dn) {
870+
acpi_handle_debug(handle, "Subnode not found\n");
871+
return NULL;
872+
}
873+
874+
return &dn->fwnode;
875+
}
876+
848877
/**
849878
* __acpi_node_get_property_reference - returns handle to the referenced object
850879
* @fwnode: Firmware node to get the property from
@@ -887,6 +916,7 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
887916
const union acpi_object *element, *end;
888917
const union acpi_object *obj;
889918
const struct acpi_device_data *data;
919+
struct fwnode_handle *ref_fwnode;
890920
struct acpi_device *device;
891921
int ret, idx = 0;
892922

@@ -910,16 +940,30 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
910940

911941
args->fwnode = acpi_fwnode_handle(device);
912942
args->nargs = 0;
943+
944+
return 0;
945+
case ACPI_TYPE_STRING:
946+
if (index)
947+
return -ENOENT;
948+
949+
ref_fwnode = acpi_parse_string_ref(fwnode, obj->string.pointer);
950+
if (!ref_fwnode)
951+
return -EINVAL;
952+
953+
args->fwnode = ref_fwnode;
954+
args->nargs = 0;
955+
913956
return 0;
914957
case ACPI_TYPE_PACKAGE:
915958
/*
916959
* If it is not a single reference, then it is a package of
917-
* references followed by number of ints as follows:
960+
* references, followed by number of ints as follows:
918961
*
919962
* Package () { REF, INT, REF, INT, INT }
920963
*
921-
* The index argument is then used to determine which reference
922-
* the caller wants (along with the arguments).
964+
* Here, REF may be either a local reference or a string. The
965+
* index argument is then used to determine which reference the
966+
* caller wants (along with the arguments).
923967
*/
924968
break;
925969
default:
@@ -950,6 +994,24 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
950994
if (idx == index)
951995
return 0;
952996

997+
break;
998+
case ACPI_TYPE_STRING:
999+
ref_fwnode = acpi_parse_string_ref(fwnode,
1000+
element->string.pointer);
1001+
if (!ref_fwnode)
1002+
return -EINVAL;
1003+
1004+
element++;
1005+
1006+
ret = acpi_get_ref_args(idx == index ? args : NULL,
1007+
ref_fwnode, &element, end,
1008+
num_args);
1009+
if (ret < 0)
1010+
return ret;
1011+
1012+
if (idx == index)
1013+
return 0;
1014+
9531015
break;
9541016
case ACPI_TYPE_INTEGER:
9551017
if (idx == index)

0 commit comments

Comments
 (0)