int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, enum dev_prop_type proptype, void *val) { const union acpi_object *obj; int ret; if (!val) return -EINVAL; if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) { ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_INTEGER, &obj); if (ret) return ret; switch (proptype) { case DEV_PROP_U8: if (obj->integer.value > U8_MAX) return -EOVERFLOW; *(u8 *)val = obj->integer.value; break; case DEV_PROP_U16: if (obj->integer.value > U16_MAX) return -EOVERFLOW; *(u16 *)val = obj->integer.value; break; case DEV_PROP_U32: if (obj->integer.value > U32_MAX) return -EOVERFLOW; *(u32 *)val = obj->integer.value; break; default: *(u64 *)val = obj->integer.value; break; } } else if (proptype == DEV_PROP_STRING) { ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_STRING, &obj); if (ret) return ret; *(char **)val = obj->string.pointer; } else { ret = -EINVAL; } return ret; }
static acpi_status acpi_register_phy(acpi_handle handle, u32 lvl, void *context, void **ret) { struct mii_bus *mdio = context; struct acpi_device *adev; struct phy_device *phy_dev; const union acpi_object *obj; u32 phy_addr; if (acpi_bus_get_device(handle, &adev)) return AE_OK; if (acpi_dev_get_property(adev, "phy-channel", ACPI_TYPE_INTEGER, &obj)) return AE_OK; phy_addr = obj->integer.value; phy_dev = xgene_enet_phy_register(mdio, phy_addr); adev->driver_data = phy_dev; return AE_OK; }
/** * acpi_dev_get_property_array - return an ACPI array property with given name * @adev: ACPI device to get property * @name: Name of the property * @type: Expected type of array elements * @obj: Location to store a pointer to the property value (if not NULL) * * Look up an array property with @name and store a pointer to the resulting * ACPI object at the location pointed to by @obj if found. * * Callers must not attempt to free the returned objects. Those objects will be * freed by the ACPI core automatically during the removal of @adev. * * Return: %0 if array property (package) with @name has been found (success), * %-EINVAL if the arguments are invalid, * %-ENODATA if the property doesn't exist, * %-EPROTO if the property is not a package or the type of its elements * doesn't match @type. */ int acpi_dev_get_property_array(struct acpi_device *adev, const char *name, acpi_object_type type, const union acpi_object **obj) { const union acpi_object *prop; int ret, i; ret = acpi_dev_get_property(adev, name, ACPI_TYPE_PACKAGE, &prop); if (ret) return ret; if (type != ACPI_TYPE_ANY) { /* Check that all elements are of correct type. */ for (i = 0; i < prop->package.count; i++) if (prop->package.elements[i].type != type) return -EPROTO; } if (obj) *obj = prop; return 0; }
int acpi_dev_prop_get(struct acpi_device *adev, const char *propname, void **valptr) { return acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY, (const union acpi_object **)valptr); }
/** * acpi_dev_get_property_reference - returns handle to the referenced object * @adev: ACPI device to get property * @name: Name of the property * @size_prop: Name of the "size" property in referenced object * @index: Index of the reference to return * @args: Location to store the returned reference with optional arguments * * Find property with @name, verifify that it is a package containing at least * one object reference and if so, store the ACPI device object pointer to the * target object in @args->adev. * * If the reference includes arguments (@size_prop is not %NULL) follow the * reference and check whether or not there is an integer property @size_prop * under the target object and if so, whether or not its value matches the * number of arguments that follow the reference. If there's more than one * reference in the property value package, @index is used to select the one to * return. * * Return: %0 on success, negative error code on failure. */ int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name, const char *size_prop, size_t index, struct acpi_reference_args *args) { const union acpi_object *element, *end; const union acpi_object *obj; struct acpi_device *device; int ret, idx = 0; ret = acpi_dev_get_property(adev, name, ACPI_TYPE_ANY, &obj); if (ret) return ret; /* * The simplest case is when the value is a single reference. Just * return that reference then. */ if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) { if (size_prop || index) return -EINVAL; ret = acpi_bus_get_device(obj->reference.handle, &device); if (ret) return ret; args->adev = device; args->nargs = 0; return 0; } /* * If it is not a single reference, then it is a package of * references followed by number of ints as follows: * * Package () { REF, INT, REF, INT, INT } * * The index argument is then used to determine which reference * the caller wants (along with the arguments). */ if (obj->type != ACPI_TYPE_PACKAGE || index >= obj->package.count) return -EPROTO; element = obj->package.elements; end = element + obj->package.count; while (element < end) { u32 nargs, i; if (element->type != ACPI_TYPE_LOCAL_REFERENCE) return -EPROTO; ret = acpi_bus_get_device(element->reference.handle, &device); if (ret) return -ENODEV; element++; nargs = 0; if (size_prop) { const union acpi_object *prop; /* * Find out how many arguments the refenced object * expects by reading its size_prop property. */ ret = acpi_dev_get_property(device, size_prop, ACPI_TYPE_INTEGER, &prop); if (ret) return ret; nargs = prop->integer.value; if (nargs > MAX_ACPI_REFERENCE_ARGS || element + nargs > end) return -EPROTO; /* * Skip to the start of the arguments and verify * that they all are in fact integers. */ for (i = 0; i < nargs; i++) if (element[i].type != ACPI_TYPE_INTEGER) return -EPROTO; } else { /* assume following integer elements are all args */ for (i = 0; element + i < end; i++) { int type = element[i].type; if (type == ACPI_TYPE_INTEGER) nargs++; else if (type == ACPI_TYPE_LOCAL_REFERENCE) break; else return -EPROTO; } } if (idx++ == index) { args->adev = device; args->nargs = nargs; for (i = 0; i < nargs; i++) args->args[i] = element[i].integer.value; return 0; } element += nargs; } return -EPROTO; }