Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ACPI device specific properties support.
0004  *
0005  * Copyright (C) 2014, Intel Corporation
0006  * All rights reserved.
0007  *
0008  * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
0009  *          Darren Hart <dvhart@linux.intel.com>
0010  *          Rafael J. Wysocki <rafael.j.wysocki@intel.com>
0011  */
0012 
0013 #include <linux/acpi.h>
0014 #include <linux/device.h>
0015 #include <linux/export.h>
0016 
0017 #include "internal.h"
0018 
0019 static int acpi_data_get_property_array(const struct acpi_device_data *data,
0020                     const char *name,
0021                     acpi_object_type type,
0022                     const union acpi_object **obj);
0023 
0024 /*
0025  * The GUIDs here are made equivalent to each other in order to avoid extra
0026  * complexity in the properties handling code, with the caveat that the
0027  * kernel will accept certain combinations of GUID and properties that are
0028  * not defined without a warning. For instance if any of the properties
0029  * from different GUID appear in a property list of another, it will be
0030  * accepted by the kernel. Firmware validation tools should catch these.
0031  */
0032 static const guid_t prp_guids[] = {
0033     /* ACPI _DSD device properties GUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
0034     GUID_INIT(0xdaffd814, 0x6eba, 0x4d8c,
0035           0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01),
0036     /* Hotplug in D3 GUID: 6211e2c0-58a3-4af3-90e1-927a4e0c55a4 */
0037     GUID_INIT(0x6211e2c0, 0x58a3, 0x4af3,
0038           0x90, 0xe1, 0x92, 0x7a, 0x4e, 0x0c, 0x55, 0xa4),
0039     /* External facing port GUID: efcc06cc-73ac-4bc3-bff0-76143807c389 */
0040     GUID_INIT(0xefcc06cc, 0x73ac, 0x4bc3,
0041           0xbf, 0xf0, 0x76, 0x14, 0x38, 0x07, 0xc3, 0x89),
0042     /* Thunderbolt GUID for IMR_VALID: c44d002f-69f9-4e7d-a904-a7baabdf43f7 */
0043     GUID_INIT(0xc44d002f, 0x69f9, 0x4e7d,
0044           0xa9, 0x04, 0xa7, 0xba, 0xab, 0xdf, 0x43, 0xf7),
0045     /* Thunderbolt GUID for WAKE_SUPPORTED: 6c501103-c189-4296-ba72-9bf5a26ebe5d */
0046     GUID_INIT(0x6c501103, 0xc189, 0x4296,
0047           0xba, 0x72, 0x9b, 0xf5, 0xa2, 0x6e, 0xbe, 0x5d),
0048     /* Storage device needs D3 GUID: 5025030f-842f-4ab4-a561-99a5189762d0 */
0049     GUID_INIT(0x5025030f, 0x842f, 0x4ab4,
0050           0xa5, 0x61, 0x99, 0xa5, 0x18, 0x97, 0x62, 0xd0),
0051 };
0052 
0053 /* ACPI _DSD data subnodes GUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */
0054 static const guid_t ads_guid =
0055     GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6,
0056           0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b);
0057 
0058 static const guid_t buffer_prop_guid =
0059     GUID_INIT(0xedb12dd0, 0x363d, 0x4085,
0060           0xa3, 0xd2, 0x49, 0x52, 0x2c, 0xa1, 0x60, 0xc4);
0061 
0062 static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
0063                        union acpi_object *desc,
0064                        struct acpi_device_data *data,
0065                        struct fwnode_handle *parent);
0066 static bool acpi_extract_properties(acpi_handle handle,
0067                     union acpi_object *desc,
0068                     struct acpi_device_data *data);
0069 
0070 static bool acpi_nondev_subnode_extract(union acpi_object *desc,
0071                     acpi_handle handle,
0072                     const union acpi_object *link,
0073                     struct list_head *list,
0074                     struct fwnode_handle *parent)
0075 {
0076     struct acpi_data_node *dn;
0077     bool result;
0078 
0079     dn = kzalloc(sizeof(*dn), GFP_KERNEL);
0080     if (!dn)
0081         return false;
0082 
0083     dn->name = link->package.elements[0].string.pointer;
0084     fwnode_init(&dn->fwnode, &acpi_data_fwnode_ops);
0085     dn->parent = parent;
0086     INIT_LIST_HEAD(&dn->data.properties);
0087     INIT_LIST_HEAD(&dn->data.subnodes);
0088 
0089     result = acpi_extract_properties(handle, desc, &dn->data);
0090 
0091     if (handle) {
0092         acpi_handle scope;
0093         acpi_status status;
0094 
0095         /*
0096          * The scope for the subnode object lookup is the one of the
0097          * namespace node (device) containing the object that has
0098          * returned the package.  That is, it's the scope of that
0099          * object's parent.
0100          */
0101         status = acpi_get_parent(handle, &scope);
0102         if (ACPI_SUCCESS(status)
0103             && acpi_enumerate_nondev_subnodes(scope, desc, &dn->data,
0104                               &dn->fwnode))
0105             result = true;
0106     } else if (acpi_enumerate_nondev_subnodes(NULL, desc, &dn->data,
0107                           &dn->fwnode)) {
0108         result = true;
0109     }
0110 
0111     if (result) {
0112         dn->handle = handle;
0113         dn->data.pointer = desc;
0114         list_add_tail(&dn->sibling, list);
0115         return true;
0116     }
0117 
0118     kfree(dn);
0119     acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n");
0120     return false;
0121 }
0122 
0123 static bool acpi_nondev_subnode_data_ok(acpi_handle handle,
0124                     const union acpi_object *link,
0125                     struct list_head *list,
0126                     struct fwnode_handle *parent)
0127 {
0128     struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
0129     acpi_status status;
0130 
0131     status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf,
0132                         ACPI_TYPE_PACKAGE);
0133     if (ACPI_FAILURE(status))
0134         return false;
0135 
0136     if (acpi_nondev_subnode_extract(buf.pointer, handle, link, list,
0137                     parent))
0138         return true;
0139 
0140     ACPI_FREE(buf.pointer);
0141     return false;
0142 }
0143 
0144 static bool acpi_nondev_subnode_ok(acpi_handle scope,
0145                    const union acpi_object *link,
0146                    struct list_head *list,
0147                    struct fwnode_handle *parent)
0148 {
0149     acpi_handle handle;
0150     acpi_status status;
0151 
0152     if (!scope)
0153         return false;
0154 
0155     status = acpi_get_handle(scope, link->package.elements[1].string.pointer,
0156                  &handle);
0157     if (ACPI_FAILURE(status))
0158         return false;
0159 
0160     return acpi_nondev_subnode_data_ok(handle, link, list, parent);
0161 }
0162 
0163 static bool acpi_add_nondev_subnodes(acpi_handle scope,
0164                      union acpi_object *links,
0165                      struct list_head *list,
0166                      struct fwnode_handle *parent)
0167 {
0168     bool ret = false;
0169     int i;
0170 
0171     for (i = 0; i < links->package.count; i++) {
0172         union acpi_object *link, *desc;
0173         acpi_handle handle;
0174         bool result;
0175 
0176         link = &links->package.elements[i];
0177         /* Only two elements allowed. */
0178         if (link->package.count != 2)
0179             continue;
0180 
0181         /* The first one must be a string. */
0182         if (link->package.elements[0].type != ACPI_TYPE_STRING)
0183             continue;
0184 
0185         /* The second one may be a string, a reference or a package. */
0186         switch (link->package.elements[1].type) {
0187         case ACPI_TYPE_STRING:
0188             result = acpi_nondev_subnode_ok(scope, link, list,
0189                              parent);
0190             break;
0191         case ACPI_TYPE_LOCAL_REFERENCE:
0192             handle = link->package.elements[1].reference.handle;
0193             result = acpi_nondev_subnode_data_ok(handle, link, list,
0194                                  parent);
0195             break;
0196         case ACPI_TYPE_PACKAGE:
0197             desc = &link->package.elements[1];
0198             result = acpi_nondev_subnode_extract(desc, NULL, link,
0199                                  list, parent);
0200             break;
0201         default:
0202             result = false;
0203             break;
0204         }
0205         ret = ret || result;
0206     }
0207 
0208     return ret;
0209 }
0210 
0211 static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
0212                        union acpi_object *desc,
0213                        struct acpi_device_data *data,
0214                        struct fwnode_handle *parent)
0215 {
0216     int i;
0217 
0218     /* Look for the ACPI data subnodes GUID. */
0219     for (i = 0; i < desc->package.count; i += 2) {
0220         const union acpi_object *guid;
0221         union acpi_object *links;
0222 
0223         guid = &desc->package.elements[i];
0224         links = &desc->package.elements[i + 1];
0225 
0226         /*
0227          * The first element must be a GUID and the second one must be
0228          * a package.
0229          */
0230         if (guid->type != ACPI_TYPE_BUFFER ||
0231             guid->buffer.length != 16 ||
0232             links->type != ACPI_TYPE_PACKAGE)
0233             break;
0234 
0235         if (!guid_equal((guid_t *)guid->buffer.pointer, &ads_guid))
0236             continue;
0237 
0238         return acpi_add_nondev_subnodes(scope, links, &data->subnodes,
0239                         parent);
0240     }
0241 
0242     return false;
0243 }
0244 
0245 static bool acpi_property_value_ok(const union acpi_object *value)
0246 {
0247     int j;
0248 
0249     /*
0250      * The value must be an integer, a string, a reference, or a package
0251      * whose every element must be an integer, a string, or a reference.
0252      */
0253     switch (value->type) {
0254     case ACPI_TYPE_INTEGER:
0255     case ACPI_TYPE_STRING:
0256     case ACPI_TYPE_LOCAL_REFERENCE:
0257         return true;
0258 
0259     case ACPI_TYPE_PACKAGE:
0260         for (j = 0; j < value->package.count; j++)
0261             switch (value->package.elements[j].type) {
0262             case ACPI_TYPE_INTEGER:
0263             case ACPI_TYPE_STRING:
0264             case ACPI_TYPE_LOCAL_REFERENCE:
0265                 continue;
0266 
0267             default:
0268                 return false;
0269             }
0270 
0271         return true;
0272     }
0273     return false;
0274 }
0275 
0276 static bool acpi_properties_format_valid(const union acpi_object *properties)
0277 {
0278     int i;
0279 
0280     for (i = 0; i < properties->package.count; i++) {
0281         const union acpi_object *property;
0282 
0283         property = &properties->package.elements[i];
0284         /*
0285          * Only two elements allowed, the first one must be a string and
0286          * the second one has to satisfy certain conditions.
0287          */
0288         if (property->package.count != 2
0289             || property->package.elements[0].type != ACPI_TYPE_STRING
0290             || !acpi_property_value_ok(&property->package.elements[1]))
0291             return false;
0292     }
0293     return true;
0294 }
0295 
0296 static void acpi_init_of_compatible(struct acpi_device *adev)
0297 {
0298     const union acpi_object *of_compatible;
0299     int ret;
0300 
0301     ret = acpi_data_get_property_array(&adev->data, "compatible",
0302                        ACPI_TYPE_STRING, &of_compatible);
0303     if (ret) {
0304         ret = acpi_dev_get_property(adev, "compatible",
0305                         ACPI_TYPE_STRING, &of_compatible);
0306         if (ret) {
0307             if (adev->parent
0308                 && adev->parent->flags.of_compatible_ok)
0309                 goto out;
0310 
0311             return;
0312         }
0313     }
0314     adev->data.of_compatible = of_compatible;
0315 
0316  out:
0317     adev->flags.of_compatible_ok = 1;
0318 }
0319 
0320 static bool acpi_is_property_guid(const guid_t *guid)
0321 {
0322     int i;
0323 
0324     for (i = 0; i < ARRAY_SIZE(prp_guids); i++) {
0325         if (guid_equal(guid, &prp_guids[i]))
0326             return true;
0327     }
0328 
0329     return false;
0330 }
0331 
0332 struct acpi_device_properties *
0333 acpi_data_add_props(struct acpi_device_data *data, const guid_t *guid,
0334             union acpi_object *properties)
0335 {
0336     struct acpi_device_properties *props;
0337 
0338     props = kzalloc(sizeof(*props), GFP_KERNEL);
0339     if (props) {
0340         INIT_LIST_HEAD(&props->list);
0341         props->guid = guid;
0342         props->properties = properties;
0343         list_add_tail(&props->list, &data->properties);
0344     }
0345 
0346     return props;
0347 }
0348 
0349 static void acpi_nondev_subnode_tag(acpi_handle handle, void *context)
0350 {
0351 }
0352 
0353 static void acpi_untie_nondev_subnodes(struct acpi_device_data *data)
0354 {
0355     struct acpi_data_node *dn;
0356 
0357     list_for_each_entry(dn, &data->subnodes, sibling) {
0358         acpi_detach_data(dn->handle, acpi_nondev_subnode_tag);
0359 
0360         acpi_untie_nondev_subnodes(&dn->data);
0361     }
0362 }
0363 
0364 static bool acpi_tie_nondev_subnodes(struct acpi_device_data *data)
0365 {
0366     struct acpi_data_node *dn;
0367 
0368     list_for_each_entry(dn, &data->subnodes, sibling) {
0369         acpi_status status;
0370         bool ret;
0371 
0372         status = acpi_attach_data(dn->handle, acpi_nondev_subnode_tag, dn);
0373         if (ACPI_FAILURE(status) && status != AE_ALREADY_EXISTS) {
0374             acpi_handle_err(dn->handle, "Can't tag data node\n");
0375             return false;
0376         }
0377 
0378         ret = acpi_tie_nondev_subnodes(&dn->data);
0379         if (!ret)
0380             return ret;
0381     }
0382 
0383     return true;
0384 }
0385 
0386 static void acpi_data_add_buffer_props(acpi_handle handle,
0387                        struct acpi_device_data *data,
0388                        union acpi_object *properties)
0389 {
0390     struct acpi_device_properties *props;
0391     union acpi_object *package;
0392     size_t alloc_size;
0393     unsigned int i;
0394     u32 *count;
0395 
0396     if (check_mul_overflow((size_t)properties->package.count,
0397                    sizeof(*package) + sizeof(void *),
0398                    &alloc_size) ||
0399         check_add_overflow(sizeof(*props) + sizeof(*package), alloc_size,
0400                    &alloc_size)) {
0401         acpi_handle_warn(handle,
0402                  "can't allocate memory for %u buffer props",
0403                  properties->package.count);
0404         return;
0405     }
0406 
0407     props = kvzalloc(alloc_size, GFP_KERNEL);
0408     if (!props)
0409         return;
0410 
0411     props->guid = &buffer_prop_guid;
0412     props->bufs = (void *)(props + 1);
0413     props->properties = (void *)(props->bufs + properties->package.count);
0414 
0415     /* Outer package */
0416     package = props->properties;
0417     package->type = ACPI_TYPE_PACKAGE;
0418     package->package.elements = package + 1;
0419     count = &package->package.count;
0420     *count = 0;
0421 
0422     /* Inner packages */
0423     package++;
0424 
0425     for (i = 0; i < properties->package.count; i++) {
0426         struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
0427         union acpi_object *property = &properties->package.elements[i];
0428         union acpi_object *prop, *obj, *buf_obj;
0429         acpi_status status;
0430 
0431         if (property->type != ACPI_TYPE_PACKAGE ||
0432             property->package.count != 2) {
0433             acpi_handle_warn(handle,
0434                      "buffer property %u has %u entries\n",
0435                      i, property->package.count);
0436             continue;
0437         }
0438 
0439         prop = &property->package.elements[0];
0440         obj = &property->package.elements[1];
0441 
0442         if (prop->type != ACPI_TYPE_STRING ||
0443             obj->type != ACPI_TYPE_STRING) {
0444             acpi_handle_warn(handle,
0445                      "wrong object types %u and %u\n",
0446                      prop->type, obj->type);
0447             continue;
0448         }
0449 
0450         status = acpi_evaluate_object_typed(handle, obj->string.pointer,
0451                             NULL, &buf,
0452                             ACPI_TYPE_BUFFER);
0453         if (ACPI_FAILURE(status)) {
0454             acpi_handle_warn(handle,
0455                      "can't evaluate \"%*pE\" as buffer\n",
0456                      obj->string.length,
0457                      obj->string.pointer);
0458             continue;
0459         }
0460 
0461         package->type = ACPI_TYPE_PACKAGE;
0462         package->package.elements = prop;
0463         package->package.count = 2;
0464 
0465         buf_obj = buf.pointer;
0466 
0467         /* Replace the string object with a buffer object */
0468         obj->type = ACPI_TYPE_BUFFER;
0469         obj->buffer.length = buf_obj->buffer.length;
0470         obj->buffer.pointer = buf_obj->buffer.pointer;
0471 
0472         props->bufs[i] = buf.pointer;
0473         package++;
0474         (*count)++;
0475     }
0476 
0477     if (*count)
0478         list_add(&props->list, &data->properties);
0479     else
0480         kvfree(props);
0481 }
0482 
0483 static bool acpi_extract_properties(acpi_handle scope, union acpi_object *desc,
0484                     struct acpi_device_data *data)
0485 {
0486     int i;
0487 
0488     if (desc->package.count % 2)
0489         return false;
0490 
0491     /* Look for the device properties GUID. */
0492     for (i = 0; i < desc->package.count; i += 2) {
0493         const union acpi_object *guid;
0494         union acpi_object *properties;
0495 
0496         guid = &desc->package.elements[i];
0497         properties = &desc->package.elements[i + 1];
0498 
0499         /*
0500          * The first element must be a GUID and the second one must be
0501          * a package.
0502          */
0503         if (guid->type != ACPI_TYPE_BUFFER ||
0504             guid->buffer.length != 16 ||
0505             properties->type != ACPI_TYPE_PACKAGE)
0506             break;
0507 
0508         if (guid_equal((guid_t *)guid->buffer.pointer,
0509                    &buffer_prop_guid)) {
0510             acpi_data_add_buffer_props(scope, data, properties);
0511             continue;
0512         }
0513 
0514         if (!acpi_is_property_guid((guid_t *)guid->buffer.pointer))
0515             continue;
0516 
0517         /*
0518          * We found the matching GUID. Now validate the format of the
0519          * package immediately following it.
0520          */
0521         if (!acpi_properties_format_valid(properties))
0522             continue;
0523 
0524         acpi_data_add_props(data, (const guid_t *)guid->buffer.pointer,
0525                     properties);
0526     }
0527 
0528     return !list_empty(&data->properties);
0529 }
0530 
0531 void acpi_init_properties(struct acpi_device *adev)
0532 {
0533     struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
0534     struct acpi_hardware_id *hwid;
0535     acpi_status status;
0536     bool acpi_of = false;
0537 
0538     INIT_LIST_HEAD(&adev->data.properties);
0539     INIT_LIST_HEAD(&adev->data.subnodes);
0540 
0541     if (!adev->handle)
0542         return;
0543 
0544     /*
0545      * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
0546      * Device Tree compatible properties for this device.
0547      */
0548     list_for_each_entry(hwid, &adev->pnp.ids, list) {
0549         if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
0550             acpi_of = true;
0551             break;
0552         }
0553     }
0554 
0555     status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
0556                         ACPI_TYPE_PACKAGE);
0557     if (ACPI_FAILURE(status))
0558         goto out;
0559 
0560     if (acpi_extract_properties(adev->handle, buf.pointer, &adev->data)) {
0561         adev->data.pointer = buf.pointer;
0562         if (acpi_of)
0563             acpi_init_of_compatible(adev);
0564     }
0565     if (acpi_enumerate_nondev_subnodes(adev->handle, buf.pointer,
0566                     &adev->data, acpi_fwnode_handle(adev)))
0567         adev->data.pointer = buf.pointer;
0568 
0569     if (!adev->data.pointer) {
0570         acpi_handle_debug(adev->handle, "Invalid _DSD data, skipping\n");
0571         ACPI_FREE(buf.pointer);
0572     } else {
0573         if (!acpi_tie_nondev_subnodes(&adev->data))
0574             acpi_untie_nondev_subnodes(&adev->data);
0575     }
0576 
0577  out:
0578     if (acpi_of && !adev->flags.of_compatible_ok)
0579         acpi_handle_info(adev->handle,
0580              ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
0581 
0582     if (!adev->data.pointer)
0583         acpi_extract_apple_properties(adev);
0584 }
0585 
0586 static void acpi_free_device_properties(struct list_head *list)
0587 {
0588     struct acpi_device_properties *props, *tmp;
0589 
0590     list_for_each_entry_safe(props, tmp, list, list) {
0591         u32 i;
0592 
0593         list_del(&props->list);
0594         /* Buffer data properties were separately allocated */
0595         if (props->bufs)
0596             for (i = 0; i < props->properties->package.count; i++)
0597                 ACPI_FREE(props->bufs[i]);
0598         kvfree(props);
0599     }
0600 }
0601 
0602 static void acpi_destroy_nondev_subnodes(struct list_head *list)
0603 {
0604     struct acpi_data_node *dn, *next;
0605 
0606     if (list_empty(list))
0607         return;
0608 
0609     list_for_each_entry_safe_reverse(dn, next, list, sibling) {
0610         acpi_destroy_nondev_subnodes(&dn->data.subnodes);
0611         wait_for_completion(&dn->kobj_done);
0612         list_del(&dn->sibling);
0613         ACPI_FREE((void *)dn->data.pointer);
0614         acpi_free_device_properties(&dn->data.properties);
0615         kfree(dn);
0616     }
0617 }
0618 
0619 void acpi_free_properties(struct acpi_device *adev)
0620 {
0621     acpi_untie_nondev_subnodes(&adev->data);
0622     acpi_destroy_nondev_subnodes(&adev->data.subnodes);
0623     ACPI_FREE((void *)adev->data.pointer);
0624     adev->data.of_compatible = NULL;
0625     adev->data.pointer = NULL;
0626     acpi_free_device_properties(&adev->data.properties);
0627 }
0628 
0629 /**
0630  * acpi_data_get_property - return an ACPI property with given name
0631  * @data: ACPI device deta object to get the property from
0632  * @name: Name of the property
0633  * @type: Expected property type
0634  * @obj: Location to store the property value (if not %NULL)
0635  *
0636  * Look up a property with @name and store a pointer to the resulting ACPI
0637  * object at the location pointed to by @obj if found.
0638  *
0639  * Callers must not attempt to free the returned objects.  These objects will be
0640  * freed by the ACPI core automatically during the removal of @data.
0641  *
0642  * Return: %0 if property with @name has been found (success),
0643  *         %-EINVAL if the arguments are invalid,
0644  *         %-EINVAL if the property doesn't exist,
0645  *         %-EPROTO if the property value type doesn't match @type.
0646  */
0647 static int acpi_data_get_property(const struct acpi_device_data *data,
0648                   const char *name, acpi_object_type type,
0649                   const union acpi_object **obj)
0650 {
0651     const struct acpi_device_properties *props;
0652 
0653     if (!data || !name)
0654         return -EINVAL;
0655 
0656     if (!data->pointer || list_empty(&data->properties))
0657         return -EINVAL;
0658 
0659     list_for_each_entry(props, &data->properties, list) {
0660         const union acpi_object *properties;
0661         unsigned int i;
0662 
0663         properties = props->properties;
0664         for (i = 0; i < properties->package.count; i++) {
0665             const union acpi_object *propname, *propvalue;
0666             const union acpi_object *property;
0667 
0668             property = &properties->package.elements[i];
0669 
0670             propname = &property->package.elements[0];
0671             propvalue = &property->package.elements[1];
0672 
0673             if (!strcmp(name, propname->string.pointer)) {
0674                 if (type != ACPI_TYPE_ANY &&
0675                     propvalue->type != type)
0676                     return -EPROTO;
0677                 if (obj)
0678                     *obj = propvalue;
0679 
0680                 return 0;
0681             }
0682         }
0683     }
0684     return -EINVAL;
0685 }
0686 
0687 /**
0688  * acpi_dev_get_property - return an ACPI property with given name.
0689  * @adev: ACPI device to get the property from.
0690  * @name: Name of the property.
0691  * @type: Expected property type.
0692  * @obj: Location to store the property value (if not %NULL).
0693  */
0694 int acpi_dev_get_property(const struct acpi_device *adev, const char *name,
0695               acpi_object_type type, const union acpi_object **obj)
0696 {
0697     return adev ? acpi_data_get_property(&adev->data, name, type, obj) : -EINVAL;
0698 }
0699 EXPORT_SYMBOL_GPL(acpi_dev_get_property);
0700 
0701 static const struct acpi_device_data *
0702 acpi_device_data_of_node(const struct fwnode_handle *fwnode)
0703 {
0704     if (is_acpi_device_node(fwnode)) {
0705         const struct acpi_device *adev = to_acpi_device_node(fwnode);
0706         return &adev->data;
0707     }
0708     if (is_acpi_data_node(fwnode)) {
0709         const struct acpi_data_node *dn = to_acpi_data_node(fwnode);
0710         return &dn->data;
0711     }
0712     return NULL;
0713 }
0714 
0715 /**
0716  * acpi_node_prop_get - return an ACPI property with given name.
0717  * @fwnode: Firmware node to get the property from.
0718  * @propname: Name of the property.
0719  * @valptr: Location to store a pointer to the property value (if not %NULL).
0720  */
0721 int acpi_node_prop_get(const struct fwnode_handle *fwnode,
0722                const char *propname, void **valptr)
0723 {
0724     return acpi_data_get_property(acpi_device_data_of_node(fwnode),
0725                       propname, ACPI_TYPE_ANY,
0726                       (const union acpi_object **)valptr);
0727 }
0728 
0729 /**
0730  * acpi_data_get_property_array - return an ACPI array property with given name
0731  * @data: ACPI data object to get the property from
0732  * @name: Name of the property
0733  * @type: Expected type of array elements
0734  * @obj: Location to store a pointer to the property value (if not NULL)
0735  *
0736  * Look up an array property with @name and store a pointer to the resulting
0737  * ACPI object at the location pointed to by @obj if found.
0738  *
0739  * Callers must not attempt to free the returned objects.  Those objects will be
0740  * freed by the ACPI core automatically during the removal of @data.
0741  *
0742  * Return: %0 if array property (package) with @name has been found (success),
0743  *         %-EINVAL if the arguments are invalid,
0744  *         %-EINVAL if the property doesn't exist,
0745  *         %-EPROTO if the property is not a package or the type of its elements
0746  *           doesn't match @type.
0747  */
0748 static int acpi_data_get_property_array(const struct acpi_device_data *data,
0749                     const char *name,
0750                     acpi_object_type type,
0751                     const union acpi_object **obj)
0752 {
0753     const union acpi_object *prop;
0754     int ret, i;
0755 
0756     ret = acpi_data_get_property(data, name, ACPI_TYPE_PACKAGE, &prop);
0757     if (ret)
0758         return ret;
0759 
0760     if (type != ACPI_TYPE_ANY) {
0761         /* Check that all elements are of correct type. */
0762         for (i = 0; i < prop->package.count; i++)
0763             if (prop->package.elements[i].type != type)
0764                 return -EPROTO;
0765     }
0766     if (obj)
0767         *obj = prop;
0768 
0769     return 0;
0770 }
0771 
0772 static struct fwnode_handle *
0773 acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
0774                  const char *childname)
0775 {
0776     struct fwnode_handle *child;
0777 
0778     fwnode_for_each_child_node(fwnode, child) {
0779         if (is_acpi_data_node(child)) {
0780             if (acpi_data_node_match(child, childname))
0781                 return child;
0782             continue;
0783         }
0784 
0785         if (!strncmp(acpi_device_bid(to_acpi_device_node(child)),
0786                  childname, ACPI_NAMESEG_SIZE))
0787             return child;
0788     }
0789 
0790     return NULL;
0791 }
0792 
0793 static int acpi_get_ref_args(struct fwnode_reference_args *args,
0794                  struct fwnode_handle *ref_fwnode,
0795                  const union acpi_object **element,
0796                  const union acpi_object *end, size_t num_args)
0797 {
0798     u32 nargs = 0, i;
0799 
0800     /*
0801      * Find the referred data extension node under the
0802      * referred device node.
0803      */
0804     for (; *element < end && (*element)->type == ACPI_TYPE_STRING;
0805          (*element)++) {
0806         const char *child_name = (*element)->string.pointer;
0807 
0808         ref_fwnode = acpi_fwnode_get_named_child_node(ref_fwnode, child_name);
0809         if (!ref_fwnode)
0810             return -EINVAL;
0811     }
0812 
0813     /*
0814      * Assume the following integer elements are all args. Stop counting on
0815      * the first reference or end of the package arguments. In case of
0816      * neither reference, nor integer, return an error, we can't parse it.
0817      */
0818     for (i = 0; (*element) + i < end && i < num_args; i++) {
0819         acpi_object_type type = (*element)[i].type;
0820 
0821         if (type == ACPI_TYPE_LOCAL_REFERENCE)
0822             break;
0823 
0824         if (type == ACPI_TYPE_INTEGER)
0825             nargs++;
0826         else
0827             return -EINVAL;
0828     }
0829 
0830     if (nargs > NR_FWNODE_REFERENCE_ARGS)
0831         return -EINVAL;
0832 
0833     if (args) {
0834         args->fwnode = ref_fwnode;
0835         args->nargs = nargs;
0836         for (i = 0; i < nargs; i++)
0837             args->args[i] = (*element)[i].integer.value;
0838     }
0839 
0840     (*element) += nargs;
0841 
0842     return 0;
0843 }
0844 
0845 /**
0846  * __acpi_node_get_property_reference - returns handle to the referenced object
0847  * @fwnode: Firmware node to get the property from
0848  * @propname: Name of the property
0849  * @index: Index of the reference to return
0850  * @num_args: Maximum number of arguments after each reference
0851  * @args: Location to store the returned reference with optional arguments
0852  *
0853  * Find property with @name, verifify that it is a package containing at least
0854  * one object reference and if so, store the ACPI device object pointer to the
0855  * target object in @args->adev.  If the reference includes arguments, store
0856  * them in the @args->args[] array.
0857  *
0858  * If there's more than one reference in the property value package, @index is
0859  * used to select the one to return.
0860  *
0861  * It is possible to leave holes in the property value set like in the
0862  * example below:
0863  *
0864  * Package () {
0865  *     "cs-gpios",
0866  *     Package () {
0867  *        ^GPIO, 19, 0, 0,
0868  *        ^GPIO, 20, 0, 0,
0869  *        0,
0870  *        ^GPIO, 21, 0, 0,
0871  *     }
0872  * }
0873  *
0874  * Calling this function with index %2 or index %3 return %-ENOENT. If the
0875  * property does not contain any more values %-ENOENT is returned. The NULL
0876  * entry must be single integer and preferably contain value %0.
0877  *
0878  * Return: %0 on success, negative error code on failure.
0879  */
0880 int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
0881     const char *propname, size_t index, size_t num_args,
0882     struct fwnode_reference_args *args)
0883 {
0884     const union acpi_object *element, *end;
0885     const union acpi_object *obj;
0886     const struct acpi_device_data *data;
0887     struct acpi_device *device;
0888     int ret, idx = 0;
0889 
0890     data = acpi_device_data_of_node(fwnode);
0891     if (!data)
0892         return -ENOENT;
0893 
0894     ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj);
0895     if (ret)
0896         return ret == -EINVAL ? -ENOENT : -EINVAL;
0897 
0898     switch (obj->type) {
0899     case ACPI_TYPE_LOCAL_REFERENCE:
0900         /* Plain single reference without arguments. */
0901         if (index)
0902             return -ENOENT;
0903 
0904         device = acpi_fetch_acpi_dev(obj->reference.handle);
0905         if (!device)
0906             return -EINVAL;
0907 
0908         args->fwnode = acpi_fwnode_handle(device);
0909         args->nargs = 0;
0910         return 0;
0911     case ACPI_TYPE_PACKAGE:
0912         /*
0913          * If it is not a single reference, then it is a package of
0914          * references followed by number of ints as follows:
0915          *
0916          *  Package () { REF, INT, REF, INT, INT }
0917          *
0918          * The index argument is then used to determine which reference
0919          * the caller wants (along with the arguments).
0920          */
0921         break;
0922     default:
0923         return -EINVAL;
0924     }
0925 
0926     if (index >= obj->package.count)
0927         return -ENOENT;
0928 
0929     element = obj->package.elements;
0930     end = element + obj->package.count;
0931 
0932     while (element < end) {
0933         switch (element->type) {
0934         case ACPI_TYPE_LOCAL_REFERENCE:
0935             device = acpi_fetch_acpi_dev(element->reference.handle);
0936             if (!device)
0937                 return -EINVAL;
0938 
0939             element++;
0940 
0941             ret = acpi_get_ref_args(idx == index ? args : NULL,
0942                         acpi_fwnode_handle(device),
0943                         &element, end, num_args);
0944             if (ret < 0)
0945                 return ret;
0946 
0947             if (idx == index)
0948                 return 0;
0949 
0950             break;
0951         case ACPI_TYPE_INTEGER:
0952             if (idx == index)
0953                 return -ENOENT;
0954             element++;
0955             break;
0956         default:
0957             return -EINVAL;
0958         }
0959 
0960         idx++;
0961     }
0962 
0963     return -ENOENT;
0964 }
0965 EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference);
0966 
0967 static int acpi_data_prop_read_single(const struct acpi_device_data *data,
0968                       const char *propname,
0969                       enum dev_prop_type proptype, void *val)
0970 {
0971     const union acpi_object *obj;
0972     int ret;
0973 
0974     if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
0975         ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
0976         if (ret)
0977             return ret;
0978 
0979         switch (proptype) {
0980         case DEV_PROP_U8:
0981             if (obj->integer.value > U8_MAX)
0982                 return -EOVERFLOW;
0983 
0984             if (val)
0985                 *(u8 *)val = obj->integer.value;
0986 
0987             break;
0988         case DEV_PROP_U16:
0989             if (obj->integer.value > U16_MAX)
0990                 return -EOVERFLOW;
0991 
0992             if (val)
0993                 *(u16 *)val = obj->integer.value;
0994 
0995             break;
0996         case DEV_PROP_U32:
0997             if (obj->integer.value > U32_MAX)
0998                 return -EOVERFLOW;
0999 
1000             if (val)
1001                 *(u32 *)val = obj->integer.value;
1002 
1003             break;
1004         default:
1005             if (val)
1006                 *(u64 *)val = obj->integer.value;
1007 
1008             break;
1009         }
1010 
1011         if (!val)
1012             return 1;
1013     } else if (proptype == DEV_PROP_STRING) {
1014         ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
1015         if (ret)
1016             return ret;
1017 
1018         if (val)
1019             *(char **)val = obj->string.pointer;
1020 
1021         return 1;
1022     } else {
1023         ret = -EINVAL;
1024     }
1025     return ret;
1026 }
1027 
1028 #define acpi_copy_property_array_uint(items, val, nval)         \
1029     ({                              \
1030         typeof(items) __items = items;              \
1031         typeof(val) __val = val;                \
1032         typeof(nval) __nval = nval;             \
1033         size_t i;                       \
1034         int ret = 0;                        \
1035                                     \
1036         for (i = 0; i < __nval; i++) {              \
1037             if (__items->type == ACPI_TYPE_BUFFER) {    \
1038                 __val[i] = __items->buffer.pointer[i];  \
1039                 continue;               \
1040             }                       \
1041             if (__items[i].type != ACPI_TYPE_INTEGER) { \
1042                 ret = -EPROTO;              \
1043                 break;                  \
1044             }                       \
1045             if (__items[i].integer.value > _Generic(__val,  \
1046                                 u8 *: U8_MAX, \
1047                                 u16 *: U16_MAX, \
1048                                 u32 *: U32_MAX, \
1049                                 u64 *: U64_MAX)) { \
1050                 ret = -EOVERFLOW;           \
1051                 break;                  \
1052             }                       \
1053                                     \
1054             __val[i] = __items[i].integer.value;        \
1055         }                           \
1056         ret;                            \
1057     })
1058 
1059 static int acpi_copy_property_array_string(const union acpi_object *items,
1060                        char **val, size_t nval)
1061 {
1062     int i;
1063 
1064     for (i = 0; i < nval; i++) {
1065         if (items[i].type != ACPI_TYPE_STRING)
1066             return -EPROTO;
1067 
1068         val[i] = items[i].string.pointer;
1069     }
1070     return nval;
1071 }
1072 
1073 static int acpi_data_prop_read(const struct acpi_device_data *data,
1074                    const char *propname,
1075                    enum dev_prop_type proptype,
1076                    void *val, size_t nval)
1077 {
1078     const union acpi_object *obj;
1079     const union acpi_object *items;
1080     int ret;
1081 
1082     if (nval == 1 || !val) {
1083         ret = acpi_data_prop_read_single(data, propname, proptype, val);
1084         /*
1085          * The overflow error means that the property is there and it is
1086          * single-value, but its type does not match, so return.
1087          */
1088         if (ret >= 0 || ret == -EOVERFLOW)
1089             return ret;
1090 
1091         /*
1092          * Reading this property as a single-value one failed, but its
1093          * value may still be represented as one-element array, so
1094          * continue.
1095          */
1096     }
1097 
1098     ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);
1099     if (ret && proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64)
1100         ret = acpi_data_get_property(data, propname, ACPI_TYPE_BUFFER,
1101                          &obj);
1102     if (ret)
1103         return ret;
1104 
1105     if (!val) {
1106         if (obj->type == ACPI_TYPE_BUFFER)
1107             return obj->buffer.length;
1108 
1109         return obj->package.count;
1110     }
1111 
1112     switch (proptype) {
1113     case DEV_PROP_STRING:
1114         break;
1115     case DEV_PROP_U8 ... DEV_PROP_U64:
1116         if (obj->type == ACPI_TYPE_BUFFER) {
1117             if (nval > obj->buffer.length)
1118                 return -EOVERFLOW;
1119             break;
1120         }
1121         fallthrough;
1122     default:
1123         if (nval > obj->package.count)
1124             return -EOVERFLOW;
1125         break;
1126     }
1127     if (nval == 0)
1128         return -EINVAL;
1129 
1130     if (obj->type != ACPI_TYPE_BUFFER)
1131         items = obj->package.elements;
1132     else
1133         items = obj;
1134 
1135     switch (proptype) {
1136     case DEV_PROP_U8:
1137         ret = acpi_copy_property_array_uint(items, (u8 *)val, nval);
1138         break;
1139     case DEV_PROP_U16:
1140         ret = acpi_copy_property_array_uint(items, (u16 *)val, nval);
1141         break;
1142     case DEV_PROP_U32:
1143         ret = acpi_copy_property_array_uint(items, (u32 *)val, nval);
1144         break;
1145     case DEV_PROP_U64:
1146         ret = acpi_copy_property_array_uint(items, (u64 *)val, nval);
1147         break;
1148     case DEV_PROP_STRING:
1149         ret = acpi_copy_property_array_string(
1150             items, (char **)val,
1151             min_t(u32, nval, obj->package.count));
1152         break;
1153     default:
1154         ret = -EINVAL;
1155         break;
1156     }
1157     return ret;
1158 }
1159 
1160 /**
1161  * acpi_node_prop_read - retrieve the value of an ACPI property with given name.
1162  * @fwnode: Firmware node to get the property from.
1163  * @propname: Name of the property.
1164  * @proptype: Expected property type.
1165  * @val: Location to store the property value (if not %NULL).
1166  * @nval: Size of the array pointed to by @val.
1167  *
1168  * If @val is %NULL, return the number of array elements comprising the value
1169  * of the property.  Otherwise, read at most @nval values to the array at the
1170  * location pointed to by @val.
1171  */
1172 static int acpi_node_prop_read(const struct fwnode_handle *fwnode,
1173                    const char *propname, enum dev_prop_type proptype,
1174                    void *val, size_t nval)
1175 {
1176     return acpi_data_prop_read(acpi_device_data_of_node(fwnode),
1177                    propname, proptype, val, nval);
1178 }
1179 
1180 static int stop_on_next(struct acpi_device *adev, void *data)
1181 {
1182     struct acpi_device **ret_p = data;
1183 
1184     if (!*ret_p) {
1185         *ret_p = adev;
1186         return 1;
1187     }
1188 
1189     /* Skip until the "previous" object is found. */
1190     if (*ret_p == adev)
1191         *ret_p = NULL;
1192 
1193     return 0;
1194 }
1195 
1196 /**
1197  * acpi_get_next_subnode - Return the next child node handle for a fwnode
1198  * @fwnode: Firmware node to find the next child node for.
1199  * @child: Handle to one of the device's child nodes or a null handle.
1200  */
1201 struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
1202                         struct fwnode_handle *child)
1203 {
1204     struct acpi_device *adev = to_acpi_device_node(fwnode);
1205 
1206     if ((!child || is_acpi_device_node(child)) && adev) {
1207         struct acpi_device *child_adev = to_acpi_device_node(child);
1208 
1209         acpi_dev_for_each_child(adev, stop_on_next, &child_adev);
1210         if (child_adev)
1211             return acpi_fwnode_handle(child_adev);
1212 
1213         child = NULL;
1214     }
1215 
1216     if (!child || is_acpi_data_node(child)) {
1217         const struct acpi_data_node *data = to_acpi_data_node(fwnode);
1218         const struct list_head *head;
1219         struct list_head *next;
1220         struct acpi_data_node *dn;
1221 
1222         /*
1223          * We can have a combination of device and data nodes, e.g. with
1224          * hierarchical _DSD properties. Make sure the adev pointer is
1225          * restored before going through data nodes, otherwise we will
1226          * be looking for data_nodes below the last device found instead
1227          * of the common fwnode shared by device_nodes and data_nodes.
1228          */
1229         adev = to_acpi_device_node(fwnode);
1230         if (adev)
1231             head = &adev->data.subnodes;
1232         else if (data)
1233             head = &data->data.subnodes;
1234         else
1235             return NULL;
1236 
1237         if (list_empty(head))
1238             return NULL;
1239 
1240         if (child) {
1241             dn = to_acpi_data_node(child);
1242             next = dn->sibling.next;
1243             if (next == head)
1244                 return NULL;
1245 
1246             dn = list_entry(next, struct acpi_data_node, sibling);
1247         } else {
1248             dn = list_first_entry(head, struct acpi_data_node, sibling);
1249         }
1250         return &dn->fwnode;
1251     }
1252     return NULL;
1253 }
1254 
1255 /**
1256  * acpi_node_get_parent - Return parent fwnode of this fwnode
1257  * @fwnode: Firmware node whose parent to get
1258  *
1259  * Returns parent node of an ACPI device or data firmware node or %NULL if
1260  * not available.
1261  */
1262 static struct fwnode_handle *
1263 acpi_node_get_parent(const struct fwnode_handle *fwnode)
1264 {
1265     if (is_acpi_data_node(fwnode)) {
1266         /* All data nodes have parent pointer so just return that */
1267         return to_acpi_data_node(fwnode)->parent;
1268     }
1269     if (is_acpi_device_node(fwnode)) {
1270         struct device *dev = to_acpi_device_node(fwnode)->dev.parent;
1271 
1272         if (dev)
1273             return acpi_fwnode_handle(to_acpi_device(dev));
1274     }
1275 
1276     return NULL;
1277 }
1278 
1279 /*
1280  * Return true if the node is an ACPI graph node. Called on either ports
1281  * or endpoints.
1282  */
1283 static bool is_acpi_graph_node(struct fwnode_handle *fwnode,
1284                    const char *str)
1285 {
1286     unsigned int len = strlen(str);
1287     const char *name;
1288 
1289     if (!len || !is_acpi_data_node(fwnode))
1290         return false;
1291 
1292     name = to_acpi_data_node(fwnode)->name;
1293 
1294     return (fwnode_property_present(fwnode, "reg") &&
1295         !strncmp(name, str, len) && name[len] == '@') ||
1296         fwnode_property_present(fwnode, str);
1297 }
1298 
1299 /**
1300  * acpi_graph_get_next_endpoint - Get next endpoint ACPI firmware node
1301  * @fwnode: Pointer to the parent firmware node
1302  * @prev: Previous endpoint node or %NULL to get the first
1303  *
1304  * Looks up next endpoint ACPI firmware node below a given @fwnode. Returns
1305  * %NULL if there is no next endpoint or in case of error. In case of success
1306  * the next endpoint is returned.
1307  */
1308 static struct fwnode_handle *acpi_graph_get_next_endpoint(
1309     const struct fwnode_handle *fwnode, struct fwnode_handle *prev)
1310 {
1311     struct fwnode_handle *port = NULL;
1312     struct fwnode_handle *endpoint;
1313 
1314     if (!prev) {
1315         do {
1316             port = fwnode_get_next_child_node(fwnode, port);
1317             /*
1318              * The names of the port nodes begin with "port@"
1319              * followed by the number of the port node and they also
1320              * have a "reg" property that also has the number of the
1321              * port node. For compatibility reasons a node is also
1322              * recognised as a port node from the "port" property.
1323              */
1324             if (is_acpi_graph_node(port, "port"))
1325                 break;
1326         } while (port);
1327     } else {
1328         port = fwnode_get_parent(prev);
1329     }
1330 
1331     if (!port)
1332         return NULL;
1333 
1334     endpoint = fwnode_get_next_child_node(port, prev);
1335     while (!endpoint) {
1336         port = fwnode_get_next_child_node(fwnode, port);
1337         if (!port)
1338             break;
1339         if (is_acpi_graph_node(port, "port"))
1340             endpoint = fwnode_get_next_child_node(port, NULL);
1341     }
1342 
1343     /*
1344      * The names of the endpoint nodes begin with "endpoint@" followed by
1345      * the number of the endpoint node and they also have a "reg" property
1346      * that also has the number of the endpoint node. For compatibility
1347      * reasons a node is also recognised as an endpoint node from the
1348      * "endpoint" property.
1349      */
1350     if (!is_acpi_graph_node(endpoint, "endpoint"))
1351         return NULL;
1352 
1353     return endpoint;
1354 }
1355 
1356 /**
1357  * acpi_graph_get_child_prop_value - Return a child with a given property value
1358  * @fwnode: device fwnode
1359  * @prop_name: The name of the property to look for
1360  * @val: the desired property value
1361  *
1362  * Return the port node corresponding to a given port number. Returns
1363  * the child node on success, NULL otherwise.
1364  */
1365 static struct fwnode_handle *acpi_graph_get_child_prop_value(
1366     const struct fwnode_handle *fwnode, const char *prop_name,
1367     unsigned int val)
1368 {
1369     struct fwnode_handle *child;
1370 
1371     fwnode_for_each_child_node(fwnode, child) {
1372         u32 nr;
1373 
1374         if (fwnode_property_read_u32(child, prop_name, &nr))
1375             continue;
1376 
1377         if (val == nr)
1378             return child;
1379     }
1380 
1381     return NULL;
1382 }
1383 
1384 
1385 /**
1386  * acpi_graph_get_remote_endpoint - Parses and returns remote end of an endpoint
1387  * @__fwnode: Endpoint firmware node pointing to a remote device
1388  *
1389  * Returns the remote endpoint corresponding to @__fwnode. NULL on error.
1390  */
1391 static struct fwnode_handle *
1392 acpi_graph_get_remote_endpoint(const struct fwnode_handle *__fwnode)
1393 {
1394     struct fwnode_handle *fwnode;
1395     unsigned int port_nr, endpoint_nr;
1396     struct fwnode_reference_args args;
1397     int ret;
1398 
1399     memset(&args, 0, sizeof(args));
1400     ret = acpi_node_get_property_reference(__fwnode, "remote-endpoint", 0,
1401                            &args);
1402     if (ret)
1403         return NULL;
1404 
1405     /* Direct endpoint reference? */
1406     if (!is_acpi_device_node(args.fwnode))
1407         return args.nargs ? NULL : args.fwnode;
1408 
1409     /*
1410      * Always require two arguments with the reference: port and
1411      * endpoint indices.
1412      */
1413     if (args.nargs != 2)
1414         return NULL;
1415 
1416     fwnode = args.fwnode;
1417     port_nr = args.args[0];
1418     endpoint_nr = args.args[1];
1419 
1420     fwnode = acpi_graph_get_child_prop_value(fwnode, "port", port_nr);
1421 
1422     return acpi_graph_get_child_prop_value(fwnode, "endpoint", endpoint_nr);
1423 }
1424 
1425 static bool acpi_fwnode_device_is_available(const struct fwnode_handle *fwnode)
1426 {
1427     if (!is_acpi_device_node(fwnode))
1428         return false;
1429 
1430     return acpi_device_is_present(to_acpi_device_node(fwnode));
1431 }
1432 
1433 static const void *
1434 acpi_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
1435                   const struct device *dev)
1436 {
1437     return acpi_device_get_match_data(dev);
1438 }
1439 
1440 static bool acpi_fwnode_device_dma_supported(const struct fwnode_handle *fwnode)
1441 {
1442     return acpi_dma_supported(to_acpi_device_node(fwnode));
1443 }
1444 
1445 static enum dev_dma_attr
1446 acpi_fwnode_device_get_dma_attr(const struct fwnode_handle *fwnode)
1447 {
1448     return acpi_get_dma_attr(to_acpi_device_node(fwnode));
1449 }
1450 
1451 static bool acpi_fwnode_property_present(const struct fwnode_handle *fwnode,
1452                      const char *propname)
1453 {
1454     return !acpi_node_prop_get(fwnode, propname, NULL);
1455 }
1456 
1457 static int
1458 acpi_fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
1459                     const char *propname,
1460                     unsigned int elem_size, void *val,
1461                     size_t nval)
1462 {
1463     enum dev_prop_type type;
1464 
1465     switch (elem_size) {
1466     case sizeof(u8):
1467         type = DEV_PROP_U8;
1468         break;
1469     case sizeof(u16):
1470         type = DEV_PROP_U16;
1471         break;
1472     case sizeof(u32):
1473         type = DEV_PROP_U32;
1474         break;
1475     case sizeof(u64):
1476         type = DEV_PROP_U64;
1477         break;
1478     default:
1479         return -ENXIO;
1480     }
1481 
1482     return acpi_node_prop_read(fwnode, propname, type, val, nval);
1483 }
1484 
1485 static int
1486 acpi_fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
1487                        const char *propname, const char **val,
1488                        size_t nval)
1489 {
1490     return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
1491                    val, nval);
1492 }
1493 
1494 static int
1495 acpi_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
1496                    const char *prop, const char *nargs_prop,
1497                    unsigned int args_count, unsigned int index,
1498                    struct fwnode_reference_args *args)
1499 {
1500     return __acpi_node_get_property_reference(fwnode, prop, index,
1501                           args_count, args);
1502 }
1503 
1504 static const char *acpi_fwnode_get_name(const struct fwnode_handle *fwnode)
1505 {
1506     const struct acpi_device *adev;
1507     struct fwnode_handle *parent;
1508 
1509     /* Is this the root node? */
1510     parent = fwnode_get_parent(fwnode);
1511     if (!parent)
1512         return "\\";
1513 
1514     fwnode_handle_put(parent);
1515 
1516     if (is_acpi_data_node(fwnode)) {
1517         const struct acpi_data_node *dn = to_acpi_data_node(fwnode);
1518 
1519         return dn->name;
1520     }
1521 
1522     adev = to_acpi_device_node(fwnode);
1523     if (WARN_ON(!adev))
1524         return NULL;
1525 
1526     return acpi_device_bid(adev);
1527 }
1528 
1529 static const char *
1530 acpi_fwnode_get_name_prefix(const struct fwnode_handle *fwnode)
1531 {
1532     struct fwnode_handle *parent;
1533 
1534     /* Is this the root node? */
1535     parent = fwnode_get_parent(fwnode);
1536     if (!parent)
1537         return "";
1538 
1539     /* Is this 2nd node from the root? */
1540     parent = fwnode_get_next_parent(parent);
1541     if (!parent)
1542         return "";
1543 
1544     fwnode_handle_put(parent);
1545 
1546     /* ACPI device or data node. */
1547     return ".";
1548 }
1549 
1550 static struct fwnode_handle *
1551 acpi_fwnode_get_parent(struct fwnode_handle *fwnode)
1552 {
1553     return acpi_node_get_parent(fwnode);
1554 }
1555 
1556 static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
1557                         struct fwnode_endpoint *endpoint)
1558 {
1559     struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
1560 
1561     endpoint->local_fwnode = fwnode;
1562 
1563     if (fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port))
1564         fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
1565     if (fwnode_property_read_u32(fwnode, "reg", &endpoint->id))
1566         fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
1567 
1568     return 0;
1569 }
1570 
1571 static int acpi_fwnode_irq_get(const struct fwnode_handle *fwnode,
1572                    unsigned int index)
1573 {
1574     struct resource res;
1575     int ret;
1576 
1577     ret = acpi_irq_get(ACPI_HANDLE_FWNODE(fwnode), index, &res);
1578     if (ret)
1579         return ret;
1580 
1581     return res.start;
1582 }
1583 
1584 #define DECLARE_ACPI_FWNODE_OPS(ops) \
1585     const struct fwnode_operations ops = {              \
1586         .device_is_available = acpi_fwnode_device_is_available, \
1587         .device_get_match_data = acpi_fwnode_device_get_match_data, \
1588         .device_dma_supported =             \
1589             acpi_fwnode_device_dma_supported,       \
1590         .device_get_dma_attr = acpi_fwnode_device_get_dma_attr, \
1591         .property_present = acpi_fwnode_property_present,   \
1592         .property_read_int_array =              \
1593             acpi_fwnode_property_read_int_array,        \
1594         .property_read_string_array =               \
1595             acpi_fwnode_property_read_string_array,     \
1596         .get_parent = acpi_node_get_parent,         \
1597         .get_next_child_node = acpi_get_next_subnode,       \
1598         .get_named_child_node = acpi_fwnode_get_named_child_node, \
1599         .get_name = acpi_fwnode_get_name,           \
1600         .get_name_prefix = acpi_fwnode_get_name_prefix,     \
1601         .get_reference_args = acpi_fwnode_get_reference_args,   \
1602         .graph_get_next_endpoint =              \
1603             acpi_graph_get_next_endpoint,           \
1604         .graph_get_remote_endpoint =                \
1605             acpi_graph_get_remote_endpoint,         \
1606         .graph_get_port_parent = acpi_fwnode_get_parent,    \
1607         .graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint, \
1608         .irq_get = acpi_fwnode_irq_get,             \
1609     };                              \
1610     EXPORT_SYMBOL_GPL(ops)
1611 
1612 DECLARE_ACPI_FWNODE_OPS(acpi_device_fwnode_ops);
1613 DECLARE_ACPI_FWNODE_OPS(acpi_data_fwnode_ops);
1614 const struct fwnode_operations acpi_static_fwnode_ops;
1615 
1616 bool is_acpi_device_node(const struct fwnode_handle *fwnode)
1617 {
1618     return !IS_ERR_OR_NULL(fwnode) &&
1619         fwnode->ops == &acpi_device_fwnode_ops;
1620 }
1621 EXPORT_SYMBOL(is_acpi_device_node);
1622 
1623 bool is_acpi_data_node(const struct fwnode_handle *fwnode)
1624 {
1625     return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &acpi_data_fwnode_ops;
1626 }
1627 EXPORT_SYMBOL(is_acpi_data_node);