cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

property.c (38561B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * ACPI device specific properties support.
      4 *
      5 * Copyright (C) 2014, Intel Corporation
      6 * All rights reserved.
      7 *
      8 * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
      9 *          Darren Hart <dvhart@linux.intel.com>
     10 *          Rafael J. Wysocki <rafael.j.wysocki@intel.com>
     11 */
     12
     13#include <linux/acpi.h>
     14#include <linux/device.h>
     15#include <linux/export.h>
     16
     17#include "internal.h"
     18
     19static int acpi_data_get_property_array(const struct acpi_device_data *data,
     20					const char *name,
     21					acpi_object_type type,
     22					const union acpi_object **obj);
     23
     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 */
     32static const guid_t prp_guids[] = {
     33	/* ACPI _DSD device properties GUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
     34	GUID_INIT(0xdaffd814, 0x6eba, 0x4d8c,
     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
     53/* ACPI _DSD data subnodes GUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */
     54static const guid_t ads_guid =
     55	GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6,
     56		  0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b);
     57
     58static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
     59					   const union acpi_object *desc,
     60					   struct acpi_device_data *data,
     61					   struct fwnode_handle *parent);
     62static bool acpi_extract_properties(const union acpi_object *desc,
     63				    struct acpi_device_data *data);
     64
     65static bool acpi_nondev_subnode_extract(const union acpi_object *desc,
     66					acpi_handle handle,
     67					const union acpi_object *link,
     68					struct list_head *list,
     69					struct fwnode_handle *parent)
     70{
     71	struct acpi_data_node *dn;
     72	bool result;
     73
     74	dn = kzalloc(sizeof(*dn), GFP_KERNEL);
     75	if (!dn)
     76		return false;
     77
     78	dn->name = link->package.elements[0].string.pointer;
     79	fwnode_init(&dn->fwnode, &acpi_data_fwnode_ops);
     80	dn->parent = parent;
     81	INIT_LIST_HEAD(&dn->data.properties);
     82	INIT_LIST_HEAD(&dn->data.subnodes);
     83
     84	result = acpi_extract_properties(desc, &dn->data);
     85
     86	if (handle) {
     87		acpi_handle scope;
     88		acpi_status status;
     89
     90		/*
     91		 * The scope for the subnode object lookup is the one of the
     92		 * namespace node (device) containing the object that has
     93		 * returned the package.  That is, it's the scope of that
     94		 * object's parent.
     95		 */
     96		status = acpi_get_parent(handle, &scope);
     97		if (ACPI_SUCCESS(status)
     98		    && acpi_enumerate_nondev_subnodes(scope, desc, &dn->data,
     99						      &dn->fwnode))
    100			result = true;
    101	} else if (acpi_enumerate_nondev_subnodes(NULL, desc, &dn->data,
    102						  &dn->fwnode)) {
    103		result = true;
    104	}
    105
    106	if (result) {
    107		dn->handle = handle;
    108		dn->data.pointer = desc;
    109		list_add_tail(&dn->sibling, list);
    110		return true;
    111	}
    112
    113	kfree(dn);
    114	acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n");
    115	return false;
    116}
    117
    118static bool acpi_nondev_subnode_data_ok(acpi_handle handle,
    119					const union acpi_object *link,
    120					struct list_head *list,
    121					struct fwnode_handle *parent)
    122{
    123	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
    124	acpi_status status;
    125
    126	status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf,
    127					    ACPI_TYPE_PACKAGE);
    128	if (ACPI_FAILURE(status))
    129		return false;
    130
    131	if (acpi_nondev_subnode_extract(buf.pointer, handle, link, list,
    132					parent))
    133		return true;
    134
    135	ACPI_FREE(buf.pointer);
    136	return false;
    137}
    138
    139static bool acpi_nondev_subnode_ok(acpi_handle scope,
    140				   const union acpi_object *link,
    141				   struct list_head *list,
    142				   struct fwnode_handle *parent)
    143{
    144	acpi_handle handle;
    145	acpi_status status;
    146
    147	if (!scope)
    148		return false;
    149
    150	status = acpi_get_handle(scope, link->package.elements[1].string.pointer,
    151				 &handle);
    152	if (ACPI_FAILURE(status))
    153		return false;
    154
    155	return acpi_nondev_subnode_data_ok(handle, link, list, parent);
    156}
    157
    158static int acpi_add_nondev_subnodes(acpi_handle scope,
    159				    const union acpi_object *links,
    160				    struct list_head *list,
    161				    struct fwnode_handle *parent)
    162{
    163	bool ret = false;
    164	int i;
    165
    166	for (i = 0; i < links->package.count; i++) {
    167		const union acpi_object *link, *desc;
    168		acpi_handle handle;
    169		bool result;
    170
    171		link = &links->package.elements[i];
    172		/* Only two elements allowed. */
    173		if (link->package.count != 2)
    174			continue;
    175
    176		/* The first one must be a string. */
    177		if (link->package.elements[0].type != ACPI_TYPE_STRING)
    178			continue;
    179
    180		/* The second one may be a string, a reference or a package. */
    181		switch (link->package.elements[1].type) {
    182		case ACPI_TYPE_STRING:
    183			result = acpi_nondev_subnode_ok(scope, link, list,
    184							 parent);
    185			break;
    186		case ACPI_TYPE_LOCAL_REFERENCE:
    187			handle = link->package.elements[1].reference.handle;
    188			result = acpi_nondev_subnode_data_ok(handle, link, list,
    189							     parent);
    190			break;
    191		case ACPI_TYPE_PACKAGE:
    192			desc = &link->package.elements[1];
    193			result = acpi_nondev_subnode_extract(desc, NULL, link,
    194							     list, parent);
    195			break;
    196		default:
    197			result = false;
    198			break;
    199		}
    200		ret = ret || result;
    201	}
    202
    203	return ret;
    204}
    205
    206static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
    207					   const union acpi_object *desc,
    208					   struct acpi_device_data *data,
    209					   struct fwnode_handle *parent)
    210{
    211	int i;
    212
    213	/* Look for the ACPI data subnodes GUID. */
    214	for (i = 0; i < desc->package.count; i += 2) {
    215		const union acpi_object *guid, *links;
    216
    217		guid = &desc->package.elements[i];
    218		links = &desc->package.elements[i + 1];
    219
    220		/*
    221		 * The first element must be a GUID and the second one must be
    222		 * a package.
    223		 */
    224		if (guid->type != ACPI_TYPE_BUFFER ||
    225		    guid->buffer.length != 16 ||
    226		    links->type != ACPI_TYPE_PACKAGE)
    227			break;
    228
    229		if (!guid_equal((guid_t *)guid->buffer.pointer, &ads_guid))
    230			continue;
    231
    232		return acpi_add_nondev_subnodes(scope, links, &data->subnodes,
    233						parent);
    234	}
    235
    236	return false;
    237}
    238
    239static bool acpi_property_value_ok(const union acpi_object *value)
    240{
    241	int j;
    242
    243	/*
    244	 * The value must be an integer, a string, a reference, or a package
    245	 * whose every element must be an integer, a string, or a reference.
    246	 */
    247	switch (value->type) {
    248	case ACPI_TYPE_INTEGER:
    249	case ACPI_TYPE_STRING:
    250	case ACPI_TYPE_LOCAL_REFERENCE:
    251		return true;
    252
    253	case ACPI_TYPE_PACKAGE:
    254		for (j = 0; j < value->package.count; j++)
    255			switch (value->package.elements[j].type) {
    256			case ACPI_TYPE_INTEGER:
    257			case ACPI_TYPE_STRING:
    258			case ACPI_TYPE_LOCAL_REFERENCE:
    259				continue;
    260
    261			default:
    262				return false;
    263			}
    264
    265		return true;
    266	}
    267	return false;
    268}
    269
    270static bool acpi_properties_format_valid(const union acpi_object *properties)
    271{
    272	int i;
    273
    274	for (i = 0; i < properties->package.count; i++) {
    275		const union acpi_object *property;
    276
    277		property = &properties->package.elements[i];
    278		/*
    279		 * Only two elements allowed, the first one must be a string and
    280		 * the second one has to satisfy certain conditions.
    281		 */
    282		if (property->package.count != 2
    283		    || property->package.elements[0].type != ACPI_TYPE_STRING
    284		    || !acpi_property_value_ok(&property->package.elements[1]))
    285			return false;
    286	}
    287	return true;
    288}
    289
    290static void acpi_init_of_compatible(struct acpi_device *adev)
    291{
    292	const union acpi_object *of_compatible;
    293	int ret;
    294
    295	ret = acpi_data_get_property_array(&adev->data, "compatible",
    296					   ACPI_TYPE_STRING, &of_compatible);
    297	if (ret) {
    298		ret = acpi_dev_get_property(adev, "compatible",
    299					    ACPI_TYPE_STRING, &of_compatible);
    300		if (ret) {
    301			if (adev->parent
    302			    && adev->parent->flags.of_compatible_ok)
    303				goto out;
    304
    305			return;
    306		}
    307	}
    308	adev->data.of_compatible = of_compatible;
    309
    310 out:
    311	adev->flags.of_compatible_ok = 1;
    312}
    313
    314static 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
    326struct acpi_device_properties *
    327acpi_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
    343static bool acpi_extract_properties(const union acpi_object *desc,
    344				    struct acpi_device_data *data)
    345{
    346	int i;
    347
    348	if (desc->package.count % 2)
    349		return false;
    350
    351	/* Look for the device properties GUID. */
    352	for (i = 0; i < desc->package.count; i += 2) {
    353		const union acpi_object *guid, *properties;
    354
    355		guid = &desc->package.elements[i];
    356		properties = &desc->package.elements[i + 1];
    357
    358		/*
    359		 * The first element must be a GUID and the second one must be
    360		 * a package.
    361		 */
    362		if (guid->type != ACPI_TYPE_BUFFER ||
    363		    guid->buffer.length != 16 ||
    364		    properties->type != ACPI_TYPE_PACKAGE)
    365			break;
    366
    367		if (!acpi_is_property_guid((guid_t *)guid->buffer.pointer))
    368			continue;
    369
    370		/*
    371		 * We found the matching GUID. Now validate the format of the
    372		 * package immediately following it.
    373		 */
    374		if (!acpi_properties_format_valid(properties))
    375			continue;
    376
    377		acpi_data_add_props(data, (const guid_t *)guid->buffer.pointer,
    378				    properties);
    379	}
    380
    381	return !list_empty(&data->properties);
    382}
    383
    384void acpi_init_properties(struct acpi_device *adev)
    385{
    386	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
    387	struct acpi_hardware_id *hwid;
    388	acpi_status status;
    389	bool acpi_of = false;
    390
    391	INIT_LIST_HEAD(&adev->data.properties);
    392	INIT_LIST_HEAD(&adev->data.subnodes);
    393
    394	if (!adev->handle)
    395		return;
    396
    397	/*
    398	 * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
    399	 * Device Tree compatible properties for this device.
    400	 */
    401	list_for_each_entry(hwid, &adev->pnp.ids, list) {
    402		if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
    403			acpi_of = true;
    404			break;
    405		}
    406	}
    407
    408	status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
    409					    ACPI_TYPE_PACKAGE);
    410	if (ACPI_FAILURE(status))
    411		goto out;
    412
    413	if (acpi_extract_properties(buf.pointer, &adev->data)) {
    414		adev->data.pointer = buf.pointer;
    415		if (acpi_of)
    416			acpi_init_of_compatible(adev);
    417	}
    418	if (acpi_enumerate_nondev_subnodes(adev->handle, buf.pointer,
    419					&adev->data, acpi_fwnode_handle(adev)))
    420		adev->data.pointer = buf.pointer;
    421
    422	if (!adev->data.pointer) {
    423		acpi_handle_debug(adev->handle, "Invalid _DSD data, skipping\n");
    424		ACPI_FREE(buf.pointer);
    425	}
    426
    427 out:
    428	if (acpi_of && !adev->flags.of_compatible_ok)
    429		acpi_handle_info(adev->handle,
    430			 ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
    431
    432	if (!adev->data.pointer)
    433		acpi_extract_apple_properties(adev);
    434}
    435
    436static 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
    446static void acpi_destroy_nondev_subnodes(struct list_head *list)
    447{
    448	struct acpi_data_node *dn, *next;
    449
    450	if (list_empty(list))
    451		return;
    452
    453	list_for_each_entry_safe_reverse(dn, next, list, sibling) {
    454		acpi_destroy_nondev_subnodes(&dn->data.subnodes);
    455		wait_for_completion(&dn->kobj_done);
    456		list_del(&dn->sibling);
    457		ACPI_FREE((void *)dn->data.pointer);
    458		acpi_free_device_properties(&dn->data.properties);
    459		kfree(dn);
    460	}
    461}
    462
    463void acpi_free_properties(struct acpi_device *adev)
    464{
    465	acpi_destroy_nondev_subnodes(&adev->data.subnodes);
    466	ACPI_FREE((void *)adev->data.pointer);
    467	adev->data.of_compatible = NULL;
    468	adev->data.pointer = NULL;
    469	acpi_free_device_properties(&adev->data.properties);
    470}
    471
    472/**
    473 * acpi_data_get_property - return an ACPI property with given name
    474 * @data: ACPI device deta object to get the property from
    475 * @name: Name of the property
    476 * @type: Expected property type
    477 * @obj: Location to store the property value (if not %NULL)
    478 *
    479 * Look up a property with @name and store a pointer to the resulting ACPI
    480 * object at the location pointed to by @obj if found.
    481 *
    482 * Callers must not attempt to free the returned objects.  These objects will be
    483 * freed by the ACPI core automatically during the removal of @data.
    484 *
    485 * Return: %0 if property with @name has been found (success),
    486 *         %-EINVAL if the arguments are invalid,
    487 *         %-EINVAL if the property doesn't exist,
    488 *         %-EPROTO if the property value type doesn't match @type.
    489 */
    490static int acpi_data_get_property(const struct acpi_device_data *data,
    491				  const char *name, acpi_object_type type,
    492				  const union acpi_object **obj)
    493{
    494	const struct acpi_device_properties *props;
    495
    496	if (!data || !name)
    497		return -EINVAL;
    498
    499	if (!data->pointer || list_empty(&data->properties))
    500		return -EINVAL;
    501
    502	list_for_each_entry(props, &data->properties, list) {
    503		const union acpi_object *properties;
    504		unsigned int i;
    505
    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;
    510
    511			property = &properties->package.elements[i];
    512
    513			propname = &property->package.elements[0];
    514			propvalue = &property->package.elements[1];
    515
    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			}
    525		}
    526	}
    527	return -EINVAL;
    528}
    529
    530/**
    531 * acpi_dev_get_property - return an ACPI property with given name.
    532 * @adev: ACPI device to get the property from.
    533 * @name: Name of the property.
    534 * @type: Expected property type.
    535 * @obj: Location to store the property value (if not %NULL).
    536 */
    537int acpi_dev_get_property(const struct acpi_device *adev, const char *name,
    538			  acpi_object_type type, const union acpi_object **obj)
    539{
    540	return adev ? acpi_data_get_property(&adev->data, name, type, obj) : -EINVAL;
    541}
    542EXPORT_SYMBOL_GPL(acpi_dev_get_property);
    543
    544static const struct acpi_device_data *
    545acpi_device_data_of_node(const struct fwnode_handle *fwnode)
    546{
    547	if (is_acpi_device_node(fwnode)) {
    548		const struct acpi_device *adev = to_acpi_device_node(fwnode);
    549		return &adev->data;
    550	}
    551	if (is_acpi_data_node(fwnode)) {
    552		const struct acpi_data_node *dn = to_acpi_data_node(fwnode);
    553		return &dn->data;
    554	}
    555	return NULL;
    556}
    557
    558/**
    559 * acpi_node_prop_get - return an ACPI property with given name.
    560 * @fwnode: Firmware node to get the property from.
    561 * @propname: Name of the property.
    562 * @valptr: Location to store a pointer to the property value (if not %NULL).
    563 */
    564int acpi_node_prop_get(const struct fwnode_handle *fwnode,
    565		       const char *propname, void **valptr)
    566{
    567	return acpi_data_get_property(acpi_device_data_of_node(fwnode),
    568				      propname, ACPI_TYPE_ANY,
    569				      (const union acpi_object **)valptr);
    570}
    571
    572/**
    573 * acpi_data_get_property_array - return an ACPI array property with given name
    574 * @data: ACPI data object to get the property from
    575 * @name: Name of the property
    576 * @type: Expected type of array elements
    577 * @obj: Location to store a pointer to the property value (if not NULL)
    578 *
    579 * Look up an array property with @name and store a pointer to the resulting
    580 * ACPI object at the location pointed to by @obj if found.
    581 *
    582 * Callers must not attempt to free the returned objects.  Those objects will be
    583 * freed by the ACPI core automatically during the removal of @data.
    584 *
    585 * Return: %0 if array property (package) with @name has been found (success),
    586 *         %-EINVAL if the arguments are invalid,
    587 *         %-EINVAL if the property doesn't exist,
    588 *         %-EPROTO if the property is not a package or the type of its elements
    589 *           doesn't match @type.
    590 */
    591static int acpi_data_get_property_array(const struct acpi_device_data *data,
    592					const char *name,
    593					acpi_object_type type,
    594					const union acpi_object **obj)
    595{
    596	const union acpi_object *prop;
    597	int ret, i;
    598
    599	ret = acpi_data_get_property(data, name, ACPI_TYPE_PACKAGE, &prop);
    600	if (ret)
    601		return ret;
    602
    603	if (type != ACPI_TYPE_ANY) {
    604		/* Check that all elements are of correct type. */
    605		for (i = 0; i < prop->package.count; i++)
    606			if (prop->package.elements[i].type != type)
    607				return -EPROTO;
    608	}
    609	if (obj)
    610		*obj = prop;
    611
    612	return 0;
    613}
    614
    615static struct fwnode_handle *
    616acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
    617				 const char *childname)
    618{
    619	struct fwnode_handle *child;
    620
    621	fwnode_for_each_child_node(fwnode, child) {
    622		if (is_acpi_data_node(child)) {
    623			if (acpi_data_node_match(child, childname))
    624				return child;
    625			continue;
    626		}
    627
    628		if (!strncmp(acpi_device_bid(to_acpi_device_node(child)),
    629			     childname, ACPI_NAMESEG_SIZE))
    630			return child;
    631	}
    632
    633	return NULL;
    634}
    635
    636/**
    637 * __acpi_node_get_property_reference - returns handle to the referenced object
    638 * @fwnode: Firmware node to get the property from
    639 * @propname: Name of the property
    640 * @index: Index of the reference to return
    641 * @num_args: Maximum number of arguments after each reference
    642 * @args: Location to store the returned reference with optional arguments
    643 *
    644 * Find property with @name, verifify that it is a package containing at least
    645 * one object reference and if so, store the ACPI device object pointer to the
    646 * target object in @args->adev.  If the reference includes arguments, store
    647 * them in the @args->args[] array.
    648 *
    649 * If there's more than one reference in the property value package, @index is
    650 * used to select the one to return.
    651 *
    652 * It is possible to leave holes in the property value set like in the
    653 * example below:
    654 *
    655 * Package () {
    656 *     "cs-gpios",
    657 *     Package () {
    658 *        ^GPIO, 19, 0, 0,
    659 *        ^GPIO, 20, 0, 0,
    660 *        0,
    661 *        ^GPIO, 21, 0, 0,
    662 *     }
    663 * }
    664 *
    665 * Calling this function with index %2 or index %3 return %-ENOENT. If the
    666 * property does not contain any more values %-ENOENT is returned. The NULL
    667 * entry must be single integer and preferably contain value %0.
    668 *
    669 * Return: %0 on success, negative error code on failure.
    670 */
    671int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
    672	const char *propname, size_t index, size_t num_args,
    673	struct fwnode_reference_args *args)
    674{
    675	const union acpi_object *element, *end;
    676	const union acpi_object *obj;
    677	const struct acpi_device_data *data;
    678	struct acpi_device *device;
    679	int ret, idx = 0;
    680
    681	data = acpi_device_data_of_node(fwnode);
    682	if (!data)
    683		return -ENOENT;
    684
    685	ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj);
    686	if (ret)
    687		return ret == -EINVAL ? -ENOENT : -EINVAL;
    688
    689	/*
    690	 * The simplest case is when the value is a single reference.  Just
    691	 * return that reference then.
    692	 */
    693	if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
    694		if (index)
    695			return -ENOENT;
    696
    697		device = acpi_fetch_acpi_dev(obj->reference.handle);
    698		if (!device)
    699			return -EINVAL;
    700
    701		args->fwnode = acpi_fwnode_handle(device);
    702		args->nargs = 0;
    703		return 0;
    704	}
    705
    706	/*
    707	 * If it is not a single reference, then it is a package of
    708	 * references followed by number of ints as follows:
    709	 *
    710	 *  Package () { REF, INT, REF, INT, INT }
    711	 *
    712	 * The index argument is then used to determine which reference
    713	 * the caller wants (along with the arguments).
    714	 */
    715	if (obj->type != ACPI_TYPE_PACKAGE)
    716		return -EINVAL;
    717	if (index >= obj->package.count)
    718		return -ENOENT;
    719
    720	element = obj->package.elements;
    721	end = element + obj->package.count;
    722
    723	while (element < end) {
    724		u32 nargs, i;
    725
    726		if (element->type == ACPI_TYPE_LOCAL_REFERENCE) {
    727			struct fwnode_handle *ref_fwnode;
    728
    729			device = acpi_fetch_acpi_dev(element->reference.handle);
    730			if (!device)
    731				return -EINVAL;
    732
    733			nargs = 0;
    734			element++;
    735
    736			/*
    737			 * Find the referred data extension node under the
    738			 * referred device node.
    739			 */
    740			for (ref_fwnode = acpi_fwnode_handle(device);
    741			     element < end && element->type == ACPI_TYPE_STRING;
    742			     element++) {
    743				ref_fwnode = acpi_fwnode_get_named_child_node(
    744					ref_fwnode, element->string.pointer);
    745				if (!ref_fwnode)
    746					return -EINVAL;
    747			}
    748
    749			/*
    750			 * Assume the following integer elements are all args.
    751			 * Stop counting on the first reference or end of the
    752			 * package arguments. In case of neither reference,
    753			 * nor integer, return an error, we can't parse it.
    754			 */
    755			for (i = 0; element + i < end && i < num_args; i++) {
    756				int type = element[i].type;
    757
    758				if (type == ACPI_TYPE_LOCAL_REFERENCE)
    759					break;
    760				if (type == ACPI_TYPE_INTEGER)
    761					nargs++;
    762				else
    763					return -EINVAL;
    764			}
    765
    766			if (nargs > NR_FWNODE_REFERENCE_ARGS)
    767				return -EINVAL;
    768
    769			if (idx == index) {
    770				args->fwnode = ref_fwnode;
    771				args->nargs = nargs;
    772				for (i = 0; i < nargs; i++)
    773					args->args[i] = element[i].integer.value;
    774
    775				return 0;
    776			}
    777
    778			element += nargs;
    779		} else if (element->type == ACPI_TYPE_INTEGER) {
    780			if (idx == index)
    781				return -ENOENT;
    782			element++;
    783		} else {
    784			return -EINVAL;
    785		}
    786
    787		idx++;
    788	}
    789
    790	return -ENOENT;
    791}
    792EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference);
    793
    794static int acpi_data_prop_read_single(const struct acpi_device_data *data,
    795				      const char *propname,
    796				      enum dev_prop_type proptype, void *val)
    797{
    798	const union acpi_object *obj;
    799	int ret;
    800
    801	if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
    802		ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
    803		if (ret)
    804			return ret;
    805
    806		switch (proptype) {
    807		case DEV_PROP_U8:
    808			if (obj->integer.value > U8_MAX)
    809				return -EOVERFLOW;
    810
    811			if (val)
    812				*(u8 *)val = obj->integer.value;
    813
    814			break;
    815		case DEV_PROP_U16:
    816			if (obj->integer.value > U16_MAX)
    817				return -EOVERFLOW;
    818
    819			if (val)
    820				*(u16 *)val = obj->integer.value;
    821
    822			break;
    823		case DEV_PROP_U32:
    824			if (obj->integer.value > U32_MAX)
    825				return -EOVERFLOW;
    826
    827			if (val)
    828				*(u32 *)val = obj->integer.value;
    829
    830			break;
    831		default:
    832			if (val)
    833				*(u64 *)val = obj->integer.value;
    834
    835			break;
    836		}
    837
    838		if (!val)
    839			return 1;
    840	} else if (proptype == DEV_PROP_STRING) {
    841		ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
    842		if (ret)
    843			return ret;
    844
    845		if (val)
    846			*(char **)val = obj->string.pointer;
    847
    848		return 1;
    849	} else {
    850		ret = -EINVAL;
    851	}
    852	return ret;
    853}
    854
    855static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
    856				       size_t nval)
    857{
    858	int i;
    859
    860	for (i = 0; i < nval; i++) {
    861		if (items[i].type != ACPI_TYPE_INTEGER)
    862			return -EPROTO;
    863		if (items[i].integer.value > U8_MAX)
    864			return -EOVERFLOW;
    865
    866		val[i] = items[i].integer.value;
    867	}
    868	return 0;
    869}
    870
    871static int acpi_copy_property_array_u16(const union acpi_object *items,
    872					u16 *val, size_t nval)
    873{
    874	int i;
    875
    876	for (i = 0; i < nval; i++) {
    877		if (items[i].type != ACPI_TYPE_INTEGER)
    878			return -EPROTO;
    879		if (items[i].integer.value > U16_MAX)
    880			return -EOVERFLOW;
    881
    882		val[i] = items[i].integer.value;
    883	}
    884	return 0;
    885}
    886
    887static int acpi_copy_property_array_u32(const union acpi_object *items,
    888					u32 *val, size_t nval)
    889{
    890	int i;
    891
    892	for (i = 0; i < nval; i++) {
    893		if (items[i].type != ACPI_TYPE_INTEGER)
    894			return -EPROTO;
    895		if (items[i].integer.value > U32_MAX)
    896			return -EOVERFLOW;
    897
    898		val[i] = items[i].integer.value;
    899	}
    900	return 0;
    901}
    902
    903static int acpi_copy_property_array_u64(const union acpi_object *items,
    904					u64 *val, size_t nval)
    905{
    906	int i;
    907
    908	for (i = 0; i < nval; i++) {
    909		if (items[i].type != ACPI_TYPE_INTEGER)
    910			return -EPROTO;
    911
    912		val[i] = items[i].integer.value;
    913	}
    914	return 0;
    915}
    916
    917static int acpi_copy_property_array_string(const union acpi_object *items,
    918					   char **val, size_t nval)
    919{
    920	int i;
    921
    922	for (i = 0; i < nval; i++) {
    923		if (items[i].type != ACPI_TYPE_STRING)
    924			return -EPROTO;
    925
    926		val[i] = items[i].string.pointer;
    927	}
    928	return nval;
    929}
    930
    931static int acpi_data_prop_read(const struct acpi_device_data *data,
    932			       const char *propname,
    933			       enum dev_prop_type proptype,
    934			       void *val, size_t nval)
    935{
    936	const union acpi_object *obj;
    937	const union acpi_object *items;
    938	int ret;
    939
    940	if (nval == 1 || !val) {
    941		ret = acpi_data_prop_read_single(data, propname, proptype, val);
    942		/*
    943		 * The overflow error means that the property is there and it is
    944		 * single-value, but its type does not match, so return.
    945		 */
    946		if (ret >= 0 || ret == -EOVERFLOW)
    947			return ret;
    948
    949		/*
    950		 * Reading this property as a single-value one failed, but its
    951		 * value may still be represented as one-element array, so
    952		 * continue.
    953		 */
    954	}
    955
    956	ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);
    957	if (ret)
    958		return ret;
    959
    960	if (!val)
    961		return obj->package.count;
    962
    963	if (proptype != DEV_PROP_STRING && nval > obj->package.count)
    964		return -EOVERFLOW;
    965	if (nval == 0)
    966		return -EINVAL;
    967
    968	items = obj->package.elements;
    969
    970	switch (proptype) {
    971	case DEV_PROP_U8:
    972		ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
    973		break;
    974	case DEV_PROP_U16:
    975		ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
    976		break;
    977	case DEV_PROP_U32:
    978		ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
    979		break;
    980	case DEV_PROP_U64:
    981		ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
    982		break;
    983	case DEV_PROP_STRING:
    984		ret = acpi_copy_property_array_string(
    985			items, (char **)val,
    986			min_t(u32, nval, obj->package.count));
    987		break;
    988	default:
    989		ret = -EINVAL;
    990		break;
    991	}
    992	return ret;
    993}
    994
    995/**
    996 * acpi_node_prop_read - retrieve the value of an ACPI property with given name.
    997 * @fwnode: Firmware node to get the property from.
    998 * @propname: Name of the property.
    999 * @proptype: Expected property type.
   1000 * @val: Location to store the property value (if not %NULL).
   1001 * @nval: Size of the array pointed to by @val.
   1002 *
   1003 * If @val is %NULL, return the number of array elements comprising the value
   1004 * of the property.  Otherwise, read at most @nval values to the array at the
   1005 * location pointed to by @val.
   1006 */
   1007static int acpi_node_prop_read(const struct fwnode_handle *fwnode,
   1008			       const char *propname, enum dev_prop_type proptype,
   1009			       void *val, size_t nval)
   1010{
   1011	return acpi_data_prop_read(acpi_device_data_of_node(fwnode),
   1012				   propname, proptype, val, nval);
   1013}
   1014
   1015/**
   1016 * acpi_get_next_subnode - Return the next child node handle for a fwnode
   1017 * @fwnode: Firmware node to find the next child node for.
   1018 * @child: Handle to one of the device's child nodes or a null handle.
   1019 */
   1020struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
   1021					    struct fwnode_handle *child)
   1022{
   1023	const struct acpi_device *adev = to_acpi_device_node(fwnode);
   1024	const struct list_head *head;
   1025	struct list_head *next;
   1026
   1027	if ((!child || is_acpi_device_node(child)) && adev) {
   1028		struct acpi_device *child_adev;
   1029
   1030		head = &adev->children;
   1031		if (list_empty(head))
   1032			goto nondev;
   1033
   1034		if (child) {
   1035			adev = to_acpi_device_node(child);
   1036			next = adev->node.next;
   1037			if (next == head) {
   1038				child = NULL;
   1039				goto nondev;
   1040			}
   1041			child_adev = list_entry(next, struct acpi_device, node);
   1042		} else {
   1043			child_adev = list_first_entry(head, struct acpi_device,
   1044						      node);
   1045		}
   1046		return acpi_fwnode_handle(child_adev);
   1047	}
   1048
   1049 nondev:
   1050	if (!child || is_acpi_data_node(child)) {
   1051		const struct acpi_data_node *data = to_acpi_data_node(fwnode);
   1052		struct acpi_data_node *dn;
   1053
   1054		/*
   1055		 * We can have a combination of device and data nodes, e.g. with
   1056		 * hierarchical _DSD properties. Make sure the adev pointer is
   1057		 * restored before going through data nodes, otherwise we will
   1058		 * be looking for data_nodes below the last device found instead
   1059		 * of the common fwnode shared by device_nodes and data_nodes.
   1060		 */
   1061		adev = to_acpi_device_node(fwnode);
   1062		if (adev)
   1063			head = &adev->data.subnodes;
   1064		else if (data)
   1065			head = &data->data.subnodes;
   1066		else
   1067			return NULL;
   1068
   1069		if (list_empty(head))
   1070			return NULL;
   1071
   1072		if (child) {
   1073			dn = to_acpi_data_node(child);
   1074			next = dn->sibling.next;
   1075			if (next == head)
   1076				return NULL;
   1077
   1078			dn = list_entry(next, struct acpi_data_node, sibling);
   1079		} else {
   1080			dn = list_first_entry(head, struct acpi_data_node, sibling);
   1081		}
   1082		return &dn->fwnode;
   1083	}
   1084	return NULL;
   1085}
   1086
   1087/**
   1088 * acpi_node_get_parent - Return parent fwnode of this fwnode
   1089 * @fwnode: Firmware node whose parent to get
   1090 *
   1091 * Returns parent node of an ACPI device or data firmware node or %NULL if
   1092 * not available.
   1093 */
   1094static struct fwnode_handle *
   1095acpi_node_get_parent(const struct fwnode_handle *fwnode)
   1096{
   1097	if (is_acpi_data_node(fwnode)) {
   1098		/* All data nodes have parent pointer so just return that */
   1099		return to_acpi_data_node(fwnode)->parent;
   1100	}
   1101	if (is_acpi_device_node(fwnode)) {
   1102		struct device *dev = to_acpi_device_node(fwnode)->dev.parent;
   1103
   1104		if (dev)
   1105			return acpi_fwnode_handle(to_acpi_device(dev));
   1106	}
   1107
   1108	return NULL;
   1109}
   1110
   1111/*
   1112 * Return true if the node is an ACPI graph node. Called on either ports
   1113 * or endpoints.
   1114 */
   1115static bool is_acpi_graph_node(struct fwnode_handle *fwnode,
   1116			       const char *str)
   1117{
   1118	unsigned int len = strlen(str);
   1119	const char *name;
   1120
   1121	if (!len || !is_acpi_data_node(fwnode))
   1122		return false;
   1123
   1124	name = to_acpi_data_node(fwnode)->name;
   1125
   1126	return (fwnode_property_present(fwnode, "reg") &&
   1127		!strncmp(name, str, len) && name[len] == '@') ||
   1128		fwnode_property_present(fwnode, str);
   1129}
   1130
   1131/**
   1132 * acpi_graph_get_next_endpoint - Get next endpoint ACPI firmware node
   1133 * @fwnode: Pointer to the parent firmware node
   1134 * @prev: Previous endpoint node or %NULL to get the first
   1135 *
   1136 * Looks up next endpoint ACPI firmware node below a given @fwnode. Returns
   1137 * %NULL if there is no next endpoint or in case of error. In case of success
   1138 * the next endpoint is returned.
   1139 */
   1140static struct fwnode_handle *acpi_graph_get_next_endpoint(
   1141	const struct fwnode_handle *fwnode, struct fwnode_handle *prev)
   1142{
   1143	struct fwnode_handle *port = NULL;
   1144	struct fwnode_handle *endpoint;
   1145
   1146	if (!prev) {
   1147		do {
   1148			port = fwnode_get_next_child_node(fwnode, port);
   1149			/*
   1150			 * The names of the port nodes begin with "port@"
   1151			 * followed by the number of the port node and they also
   1152			 * have a "reg" property that also has the number of the
   1153			 * port node. For compatibility reasons a node is also
   1154			 * recognised as a port node from the "port" property.
   1155			 */
   1156			if (is_acpi_graph_node(port, "port"))
   1157				break;
   1158		} while (port);
   1159	} else {
   1160		port = fwnode_get_parent(prev);
   1161	}
   1162
   1163	if (!port)
   1164		return NULL;
   1165
   1166	endpoint = fwnode_get_next_child_node(port, prev);
   1167	while (!endpoint) {
   1168		port = fwnode_get_next_child_node(fwnode, port);
   1169		if (!port)
   1170			break;
   1171		if (is_acpi_graph_node(port, "port"))
   1172			endpoint = fwnode_get_next_child_node(port, NULL);
   1173	}
   1174
   1175	/*
   1176	 * The names of the endpoint nodes begin with "endpoint@" followed by
   1177	 * the number of the endpoint node and they also have a "reg" property
   1178	 * that also has the number of the endpoint node. For compatibility
   1179	 * reasons a node is also recognised as an endpoint node from the
   1180	 * "endpoint" property.
   1181	 */
   1182	if (!is_acpi_graph_node(endpoint, "endpoint"))
   1183		return NULL;
   1184
   1185	return endpoint;
   1186}
   1187
   1188/**
   1189 * acpi_graph_get_child_prop_value - Return a child with a given property value
   1190 * @fwnode: device fwnode
   1191 * @prop_name: The name of the property to look for
   1192 * @val: the desired property value
   1193 *
   1194 * Return the port node corresponding to a given port number. Returns
   1195 * the child node on success, NULL otherwise.
   1196 */
   1197static struct fwnode_handle *acpi_graph_get_child_prop_value(
   1198	const struct fwnode_handle *fwnode, const char *prop_name,
   1199	unsigned int val)
   1200{
   1201	struct fwnode_handle *child;
   1202
   1203	fwnode_for_each_child_node(fwnode, child) {
   1204		u32 nr;
   1205
   1206		if (fwnode_property_read_u32(child, prop_name, &nr))
   1207			continue;
   1208
   1209		if (val == nr)
   1210			return child;
   1211	}
   1212
   1213	return NULL;
   1214}
   1215
   1216
   1217/**
   1218 * acpi_graph_get_remote_endpoint - Parses and returns remote end of an endpoint
   1219 * @__fwnode: Endpoint firmware node pointing to a remote device
   1220 *
   1221 * Returns the remote endpoint corresponding to @__fwnode. NULL on error.
   1222 */
   1223static struct fwnode_handle *
   1224acpi_graph_get_remote_endpoint(const struct fwnode_handle *__fwnode)
   1225{
   1226	struct fwnode_handle *fwnode;
   1227	unsigned int port_nr, endpoint_nr;
   1228	struct fwnode_reference_args args;
   1229	int ret;
   1230
   1231	memset(&args, 0, sizeof(args));
   1232	ret = acpi_node_get_property_reference(__fwnode, "remote-endpoint", 0,
   1233					       &args);
   1234	if (ret)
   1235		return NULL;
   1236
   1237	/* Direct endpoint reference? */
   1238	if (!is_acpi_device_node(args.fwnode))
   1239		return args.nargs ? NULL : args.fwnode;
   1240
   1241	/*
   1242	 * Always require two arguments with the reference: port and
   1243	 * endpoint indices.
   1244	 */
   1245	if (args.nargs != 2)
   1246		return NULL;
   1247
   1248	fwnode = args.fwnode;
   1249	port_nr = args.args[0];
   1250	endpoint_nr = args.args[1];
   1251
   1252	fwnode = acpi_graph_get_child_prop_value(fwnode, "port", port_nr);
   1253
   1254	return acpi_graph_get_child_prop_value(fwnode, "endpoint", endpoint_nr);
   1255}
   1256
   1257static bool acpi_fwnode_device_is_available(const struct fwnode_handle *fwnode)
   1258{
   1259	if (!is_acpi_device_node(fwnode))
   1260		return false;
   1261
   1262	return acpi_device_is_present(to_acpi_device_node(fwnode));
   1263}
   1264
   1265static const void *
   1266acpi_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
   1267				  const struct device *dev)
   1268{
   1269	return acpi_device_get_match_data(dev);
   1270}
   1271
   1272static bool acpi_fwnode_device_dma_supported(const struct fwnode_handle *fwnode)
   1273{
   1274	return acpi_dma_supported(to_acpi_device_node(fwnode));
   1275}
   1276
   1277static enum dev_dma_attr
   1278acpi_fwnode_device_get_dma_attr(const struct fwnode_handle *fwnode)
   1279{
   1280	return acpi_get_dma_attr(to_acpi_device_node(fwnode));
   1281}
   1282
   1283static bool acpi_fwnode_property_present(const struct fwnode_handle *fwnode,
   1284					 const char *propname)
   1285{
   1286	return !acpi_node_prop_get(fwnode, propname, NULL);
   1287}
   1288
   1289static int
   1290acpi_fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
   1291				    const char *propname,
   1292				    unsigned int elem_size, void *val,
   1293				    size_t nval)
   1294{
   1295	enum dev_prop_type type;
   1296
   1297	switch (elem_size) {
   1298	case sizeof(u8):
   1299		type = DEV_PROP_U8;
   1300		break;
   1301	case sizeof(u16):
   1302		type = DEV_PROP_U16;
   1303		break;
   1304	case sizeof(u32):
   1305		type = DEV_PROP_U32;
   1306		break;
   1307	case sizeof(u64):
   1308		type = DEV_PROP_U64;
   1309		break;
   1310	default:
   1311		return -ENXIO;
   1312	}
   1313
   1314	return acpi_node_prop_read(fwnode, propname, type, val, nval);
   1315}
   1316
   1317static int
   1318acpi_fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
   1319				       const char *propname, const char **val,
   1320				       size_t nval)
   1321{
   1322	return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
   1323				   val, nval);
   1324}
   1325
   1326static int
   1327acpi_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
   1328			       const char *prop, const char *nargs_prop,
   1329			       unsigned int args_count, unsigned int index,
   1330			       struct fwnode_reference_args *args)
   1331{
   1332	return __acpi_node_get_property_reference(fwnode, prop, index,
   1333						  args_count, args);
   1334}
   1335
   1336static 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
   1361static const char *
   1362acpi_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
   1382static struct fwnode_handle *
   1383acpi_fwnode_get_parent(struct fwnode_handle *fwnode)
   1384{
   1385	return acpi_node_get_parent(fwnode);
   1386}
   1387
   1388static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
   1389					    struct fwnode_endpoint *endpoint)
   1390{
   1391	struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
   1392
   1393	endpoint->local_fwnode = fwnode;
   1394
   1395	if (fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port))
   1396		fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
   1397	if (fwnode_property_read_u32(fwnode, "reg", &endpoint->id))
   1398		fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
   1399
   1400	return 0;
   1401}
   1402
   1403static int acpi_fwnode_irq_get(const struct fwnode_handle *fwnode,
   1404			       unsigned int index)
   1405{
   1406	struct resource res;
   1407	int ret;
   1408
   1409	ret = acpi_irq_get(ACPI_HANDLE_FWNODE(fwnode), index, &res);
   1410	if (ret)
   1411		return ret;
   1412
   1413	return res.start;
   1414}
   1415
   1416#define DECLARE_ACPI_FWNODE_OPS(ops) \
   1417	const struct fwnode_operations ops = {				\
   1418		.device_is_available = acpi_fwnode_device_is_available, \
   1419		.device_get_match_data = acpi_fwnode_device_get_match_data, \
   1420		.device_dma_supported =				\
   1421			acpi_fwnode_device_dma_supported,		\
   1422		.device_get_dma_attr = acpi_fwnode_device_get_dma_attr,	\
   1423		.property_present = acpi_fwnode_property_present,	\
   1424		.property_read_int_array =				\
   1425			acpi_fwnode_property_read_int_array,		\
   1426		.property_read_string_array =				\
   1427			acpi_fwnode_property_read_string_array,		\
   1428		.get_parent = acpi_node_get_parent,			\
   1429		.get_next_child_node = acpi_get_next_subnode,		\
   1430		.get_named_child_node = acpi_fwnode_get_named_child_node, \
   1431		.get_name = acpi_fwnode_get_name,			\
   1432		.get_name_prefix = acpi_fwnode_get_name_prefix,		\
   1433		.get_reference_args = acpi_fwnode_get_reference_args,	\
   1434		.graph_get_next_endpoint =				\
   1435			acpi_graph_get_next_endpoint,			\
   1436		.graph_get_remote_endpoint =				\
   1437			acpi_graph_get_remote_endpoint,			\
   1438		.graph_get_port_parent = acpi_fwnode_get_parent,	\
   1439		.graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint, \
   1440		.irq_get = acpi_fwnode_irq_get,				\
   1441	};								\
   1442	EXPORT_SYMBOL_GPL(ops)
   1443
   1444DECLARE_ACPI_FWNODE_OPS(acpi_device_fwnode_ops);
   1445DECLARE_ACPI_FWNODE_OPS(acpi_data_fwnode_ops);
   1446const struct fwnode_operations acpi_static_fwnode_ops;
   1447
   1448bool is_acpi_device_node(const struct fwnode_handle *fwnode)
   1449{
   1450	return !IS_ERR_OR_NULL(fwnode) &&
   1451		fwnode->ops == &acpi_device_fwnode_ops;
   1452}
   1453EXPORT_SYMBOL(is_acpi_device_node);
   1454
   1455bool is_acpi_data_node(const struct fwnode_handle *fwnode)
   1456{
   1457	return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &acpi_data_fwnode_ops;
   1458}
   1459EXPORT_SYMBOL(is_acpi_data_node);