Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/*
  2 * ACPI device specific properties support.
  3 *
  4 * Copyright (C) 2014, Intel Corporation
  5 * All rights reserved.
  6 *
  7 * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
  8 *          Darren Hart <dvhart@linux.intel.com>
  9 *          Rafael J. Wysocki <rafael.j.wysocki@intel.com>
 10 *
 11 * This program is free software; you can redistribute it and/or modify
 12 * it under the terms of the GNU General Public License version 2 as
 13 * published by the Free Software Foundation.
 14 */
 15
 16#include <linux/acpi.h>
 17#include <linux/device.h>
 18#include <linux/export.h>
 19
 20#include "internal.h"
 21
 22static int acpi_data_get_property_array(struct acpi_device_data *data,
 23					const char *name,
 24					acpi_object_type type,
 25					const union acpi_object **obj);
 26
 27/* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
 28static const u8 prp_uuid[16] = {
 29	0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
 30	0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01
 31};
 32/* ACPI _DSD data subnodes UUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */
 33static const u8 ads_uuid[16] = {
 34	0xe6, 0xe3, 0xb8, 0xdb, 0x86, 0x58, 0xa6, 0x4b,
 35	0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b
 36};
 37
 38static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
 39					   const union acpi_object *desc,
 40					   struct acpi_device_data *data);
 41static bool acpi_extract_properties(const union acpi_object *desc,
 42				    struct acpi_device_data *data);
 43
 44static bool acpi_nondev_subnode_extract(const union acpi_object *desc,
 45					acpi_handle handle,
 46					const union acpi_object *link,
 47					struct list_head *list)
 48{
 49	struct acpi_data_node *dn;
 50	bool result;
 51
 52	dn = kzalloc(sizeof(*dn), GFP_KERNEL);
 53	if (!dn)
 54		return false;
 55
 56	dn->name = link->package.elements[0].string.pointer;
 57	dn->fwnode.type = FWNODE_ACPI_DATA;
 58	INIT_LIST_HEAD(&dn->data.subnodes);
 59
 60	result = acpi_extract_properties(desc, &dn->data);
 61
 62	if (handle) {
 63		acpi_handle scope;
 64		acpi_status status;
 65
 66		/*
 67		 * The scope for the subnode object lookup is the one of the
 68		 * namespace node (device) containing the object that has
 69		 * returned the package.  That is, it's the scope of that
 70		 * object's parent.
 71		 */
 72		status = acpi_get_parent(handle, &scope);
 73		if (ACPI_SUCCESS(status)
 74		    && acpi_enumerate_nondev_subnodes(scope, desc, &dn->data))
 75			result = true;
 76	} else if (acpi_enumerate_nondev_subnodes(NULL, desc, &dn->data)) {
 77		result = true;
 78	}
 79
 80	if (result) {
 81		dn->handle = handle;
 82		dn->data.pointer = desc;
 83		list_add_tail(&dn->sibling, list);
 84		return true;
 85	}
 86
 87	kfree(dn);
 88	acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n");
 89	return false;
 90}
 91
 92static bool acpi_nondev_subnode_data_ok(acpi_handle handle,
 93					const union acpi_object *link,
 94					struct list_head *list)
 95{
 96	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
 97	acpi_status status;
 98
 99	status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf,
100					    ACPI_TYPE_PACKAGE);
101	if (ACPI_FAILURE(status))
102		return false;
103
104	if (acpi_nondev_subnode_extract(buf.pointer, handle, link, list))
105		return true;
106
107	ACPI_FREE(buf.pointer);
108	return false;
109}
110
111static bool acpi_nondev_subnode_ok(acpi_handle scope,
112				   const union acpi_object *link,
113				   struct list_head *list)
114{
115	acpi_handle handle;
116	acpi_status status;
117
118	if (!scope)
119		return false;
120
121	status = acpi_get_handle(scope, link->package.elements[1].string.pointer,
122				 &handle);
123	if (ACPI_FAILURE(status))
124		return false;
125
126	return acpi_nondev_subnode_data_ok(handle, link, list);
127}
128
129static int acpi_add_nondev_subnodes(acpi_handle scope,
130				    const union acpi_object *links,
131				    struct list_head *list)
132{
133	bool ret = false;
134	int i;
135
136	for (i = 0; i < links->package.count; i++) {
137		const union acpi_object *link, *desc;
138		acpi_handle handle;
139		bool result;
140
141		link = &links->package.elements[i];
142		/* Only two elements allowed. */
143		if (link->package.count != 2)
144			continue;
145
146		/* The first one must be a string. */
147		if (link->package.elements[0].type != ACPI_TYPE_STRING)
148			continue;
149
150		/* The second one may be a string, a reference or a package. */
151		switch (link->package.elements[1].type) {
152		case ACPI_TYPE_STRING:
153			result = acpi_nondev_subnode_ok(scope, link, list);
154			break;
155		case ACPI_TYPE_LOCAL_REFERENCE:
156			handle = link->package.elements[1].reference.handle;
157			result = acpi_nondev_subnode_data_ok(handle, link, list);
158			break;
159		case ACPI_TYPE_PACKAGE:
160			desc = &link->package.elements[1];
161			result = acpi_nondev_subnode_extract(desc, NULL, link, list);
162			break;
163		default:
164			result = false;
165			break;
166		}
167		ret = ret || result;
168	}
169
170	return ret;
171}
172
173static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
174					   const union acpi_object *desc,
175					   struct acpi_device_data *data)
176{
177	int i;
178
179	/* Look for the ACPI data subnodes UUID. */
180	for (i = 0; i < desc->package.count; i += 2) {
181		const union acpi_object *uuid, *links;
182
183		uuid = &desc->package.elements[i];
184		links = &desc->package.elements[i + 1];
185
186		/*
187		 * The first element must be a UUID and the second one must be
188		 * a package.
189		 */
190		if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
191		    || links->type != ACPI_TYPE_PACKAGE)
192			break;
193
194		if (memcmp(uuid->buffer.pointer, ads_uuid, sizeof(ads_uuid)))
195			continue;
196
197		return acpi_add_nondev_subnodes(scope, links, &data->subnodes);
198	}
199
200	return false;
201}
202
203static bool acpi_property_value_ok(const union acpi_object *value)
204{
205	int j;
206
207	/*
208	 * The value must be an integer, a string, a reference, or a package
209	 * whose every element must be an integer, a string, or a reference.
210	 */
211	switch (value->type) {
212	case ACPI_TYPE_INTEGER:
213	case ACPI_TYPE_STRING:
214	case ACPI_TYPE_LOCAL_REFERENCE:
215		return true;
216
217	case ACPI_TYPE_PACKAGE:
218		for (j = 0; j < value->package.count; j++)
219			switch (value->package.elements[j].type) {
220			case ACPI_TYPE_INTEGER:
221			case ACPI_TYPE_STRING:
222			case ACPI_TYPE_LOCAL_REFERENCE:
223				continue;
224
225			default:
226				return false;
227			}
228
229		return true;
230	}
231	return false;
232}
233
234static bool acpi_properties_format_valid(const union acpi_object *properties)
235{
236	int i;
237
238	for (i = 0; i < properties->package.count; i++) {
239		const union acpi_object *property;
240
241		property = &properties->package.elements[i];
242		/*
243		 * Only two elements allowed, the first one must be a string and
244		 * the second one has to satisfy certain conditions.
245		 */
246		if (property->package.count != 2
247		    || property->package.elements[0].type != ACPI_TYPE_STRING
248		    || !acpi_property_value_ok(&property->package.elements[1]))
249			return false;
250	}
251	return true;
252}
253
254static void acpi_init_of_compatible(struct acpi_device *adev)
255{
256	const union acpi_object *of_compatible;
257	int ret;
258
259	ret = acpi_data_get_property_array(&adev->data, "compatible",
260					   ACPI_TYPE_STRING, &of_compatible);
261	if (ret) {
262		ret = acpi_dev_get_property(adev, "compatible",
263					    ACPI_TYPE_STRING, &of_compatible);
264		if (ret) {
265			if (adev->parent
266			    && adev->parent->flags.of_compatible_ok)
267				goto out;
268
269			return;
270		}
271	}
272	adev->data.of_compatible = of_compatible;
273
274 out:
275	adev->flags.of_compatible_ok = 1;
276}
277
278static bool acpi_extract_properties(const union acpi_object *desc,
279				    struct acpi_device_data *data)
280{
281	int i;
282
283	if (desc->package.count % 2)
284		return false;
285
286	/* Look for the device properties UUID. */
287	for (i = 0; i < desc->package.count; i += 2) {
288		const union acpi_object *uuid, *properties;
289
290		uuid = &desc->package.elements[i];
291		properties = &desc->package.elements[i + 1];
292
293		/*
294		 * The first element must be a UUID and the second one must be
295		 * a package.
296		 */
297		if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
298		    || properties->type != ACPI_TYPE_PACKAGE)
299			break;
300
301		if (memcmp(uuid->buffer.pointer, prp_uuid, sizeof(prp_uuid)))
302			continue;
303
304		/*
305		 * We found the matching UUID. Now validate the format of the
306		 * package immediately following it.
307		 */
308		if (!acpi_properties_format_valid(properties))
309			break;
310
311		data->properties = properties;
312		return true;
313	}
314
315	return false;
316}
317
318void acpi_init_properties(struct acpi_device *adev)
319{
320	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
321	struct acpi_hardware_id *hwid;
322	acpi_status status;
323	bool acpi_of = false;
324
325	INIT_LIST_HEAD(&adev->data.subnodes);
326
327	/*
328	 * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
329	 * Device Tree compatible properties for this device.
330	 */
331	list_for_each_entry(hwid, &adev->pnp.ids, list) {
332		if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
333			acpi_of = true;
334			break;
335		}
336	}
337
338	status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
339					    ACPI_TYPE_PACKAGE);
340	if (ACPI_FAILURE(status))
341		goto out;
342
343	if (acpi_extract_properties(buf.pointer, &adev->data)) {
344		adev->data.pointer = buf.pointer;
345		if (acpi_of)
346			acpi_init_of_compatible(adev);
347	}
348	if (acpi_enumerate_nondev_subnodes(adev->handle, buf.pointer, &adev->data))
349		adev->data.pointer = buf.pointer;
350
351	if (!adev->data.pointer) {
352		acpi_handle_debug(adev->handle, "Invalid _DSD data, skipping\n");
353		ACPI_FREE(buf.pointer);
354	}
355
356 out:
357	if (acpi_of && !adev->flags.of_compatible_ok)
358		acpi_handle_info(adev->handle,
359			 ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
360}
361
362static void acpi_destroy_nondev_subnodes(struct list_head *list)
363{
364	struct acpi_data_node *dn, *next;
365
366	if (list_empty(list))
367		return;
368
369	list_for_each_entry_safe_reverse(dn, next, list, sibling) {
370		acpi_destroy_nondev_subnodes(&dn->data.subnodes);
371		wait_for_completion(&dn->kobj_done);
372		list_del(&dn->sibling);
373		ACPI_FREE((void *)dn->data.pointer);
374		kfree(dn);
375	}
376}
377
378void acpi_free_properties(struct acpi_device *adev)
379{
380	acpi_destroy_nondev_subnodes(&adev->data.subnodes);
381	ACPI_FREE((void *)adev->data.pointer);
382	adev->data.of_compatible = NULL;
383	adev->data.pointer = NULL;
384	adev->data.properties = NULL;
385}
386
387/**
388 * acpi_data_get_property - return an ACPI property with given name
389 * @data: ACPI device deta object to get the property from
390 * @name: Name of the property
391 * @type: Expected property type
392 * @obj: Location to store the property value (if not %NULL)
393 *
394 * Look up a property with @name and store a pointer to the resulting ACPI
395 * object at the location pointed to by @obj if found.
396 *
397 * Callers must not attempt to free the returned objects.  These objects will be
398 * freed by the ACPI core automatically during the removal of @data.
399 *
400 * Return: %0 if property with @name has been found (success),
401 *         %-EINVAL if the arguments are invalid,
402 *         %-EINVAL if the property doesn't exist,
403 *         %-EPROTO if the property value type doesn't match @type.
404 */
405static int acpi_data_get_property(struct acpi_device_data *data,
406				  const char *name, acpi_object_type type,
407				  const union acpi_object **obj)
408{
409	const union acpi_object *properties;
410	int i;
411
412	if (!data || !name)
413		return -EINVAL;
414
415	if (!data->pointer || !data->properties)
416		return -EINVAL;
417
418	properties = data->properties;
419	for (i = 0; i < properties->package.count; i++) {
420		const union acpi_object *propname, *propvalue;
421		const union acpi_object *property;
422
423		property = &properties->package.elements[i];
424
425		propname = &property->package.elements[0];
426		propvalue = &property->package.elements[1];
427
428		if (!strcmp(name, propname->string.pointer)) {
429			if (type != ACPI_TYPE_ANY && propvalue->type != type)
430				return -EPROTO;
431			if (obj)
432				*obj = propvalue;
433
434			return 0;
435		}
436	}
437	return -EINVAL;
438}
439
440/**
441 * acpi_dev_get_property - return an ACPI property with given name.
442 * @adev: ACPI device to get the property from.
443 * @name: Name of the property.
444 * @type: Expected property type.
445 * @obj: Location to store the property value (if not %NULL).
446 */
447int acpi_dev_get_property(struct acpi_device *adev, const char *name,
448			  acpi_object_type type, const union acpi_object **obj)
449{
450	return adev ? acpi_data_get_property(&adev->data, name, type, obj) : -EINVAL;
451}
452EXPORT_SYMBOL_GPL(acpi_dev_get_property);
453
454static struct acpi_device_data *acpi_device_data_of_node(struct fwnode_handle *fwnode)
455{
456	if (fwnode->type == FWNODE_ACPI) {
457		struct acpi_device *adev = to_acpi_device_node(fwnode);
458		return &adev->data;
459	} else if (fwnode->type == FWNODE_ACPI_DATA) {
460		struct acpi_data_node *dn = to_acpi_data_node(fwnode);
461		return &dn->data;
462	}
463	return NULL;
464}
465
466/**
467 * acpi_node_prop_get - return an ACPI property with given name.
468 * @fwnode: Firmware node to get the property from.
469 * @propname: Name of the property.
470 * @valptr: Location to store a pointer to the property value (if not %NULL).
471 */
472int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname,
473		       void **valptr)
474{
475	return acpi_data_get_property(acpi_device_data_of_node(fwnode),
476				      propname, ACPI_TYPE_ANY,
477				      (const union acpi_object **)valptr);
478}
479
480/**
481 * acpi_data_get_property_array - return an ACPI array property with given name
482 * @adev: ACPI data object to get the property from
483 * @name: Name of the property
484 * @type: Expected type of array elements
485 * @obj: Location to store a pointer to the property value (if not NULL)
486 *
487 * Look up an array property with @name and store a pointer to the resulting
488 * ACPI object at the location pointed to by @obj if found.
489 *
490 * Callers must not attempt to free the returned objects.  Those objects will be
491 * freed by the ACPI core automatically during the removal of @data.
492 *
493 * Return: %0 if array property (package) with @name has been found (success),
494 *         %-EINVAL if the arguments are invalid,
495 *         %-EINVAL if the property doesn't exist,
496 *         %-EPROTO if the property is not a package or the type of its elements
497 *           doesn't match @type.
498 */
499static int acpi_data_get_property_array(struct acpi_device_data *data,
500					const char *name,
501					acpi_object_type type,
502					const union acpi_object **obj)
503{
504	const union acpi_object *prop;
505	int ret, i;
506
507	ret = acpi_data_get_property(data, name, ACPI_TYPE_PACKAGE, &prop);
508	if (ret)
509		return ret;
510
511	if (type != ACPI_TYPE_ANY) {
512		/* Check that all elements are of correct type. */
513		for (i = 0; i < prop->package.count; i++)
514			if (prop->package.elements[i].type != type)
515				return -EPROTO;
516	}
517	if (obj)
518		*obj = prop;
519
520	return 0;
521}
522
523/**
524 * __acpi_node_get_property_reference - returns handle to the referenced object
525 * @fwnode: Firmware node to get the property from
526 * @propname: Name of the property
527 * @index: Index of the reference to return
528 * @num_args: Maximum number of arguments after each reference
529 * @args: Location to store the returned reference with optional arguments
530 *
531 * Find property with @name, verifify that it is a package containing at least
532 * one object reference and if so, store the ACPI device object pointer to the
533 * target object in @args->adev.  If the reference includes arguments, store
534 * them in the @args->args[] array.
535 *
536 * If there's more than one reference in the property value package, @index is
537 * used to select the one to return.
538 *
539 * It is possible to leave holes in the property value set like in the
540 * example below:
541 *
542 * Package () {
543 *     "cs-gpios",
544 *     Package () {
545 *        ^GPIO, 19, 0, 0,
546 *        ^GPIO, 20, 0, 0,
547 *        0,
548 *        ^GPIO, 21, 0, 0,
549 *     }
550 * }
551 *
552 * Calling this function with index %2 return %-ENOENT and with index %3
553 * returns the last entry. If the property does not contain any more values
554 * %-ENODATA is returned. The NULL entry must be single integer and
555 * preferably contain value %0.
556 *
557 * Return: %0 on success, negative error code on failure.
558 */
559int __acpi_node_get_property_reference(struct fwnode_handle *fwnode,
560	const char *propname, size_t index, size_t num_args,
561	struct acpi_reference_args *args)
562{
563	const union acpi_object *element, *end;
564	const union acpi_object *obj;
565	struct acpi_device_data *data;
566	struct acpi_device *device;
567	int ret, idx = 0;
568
569	data = acpi_device_data_of_node(fwnode);
570	if (!data)
571		return -EINVAL;
572
573	ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj);
574	if (ret)
575		return ret;
576
577	/*
578	 * The simplest case is when the value is a single reference.  Just
579	 * return that reference then.
580	 */
581	if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
582		if (index)
583			return -EINVAL;
584
585		ret = acpi_bus_get_device(obj->reference.handle, &device);
586		if (ret)
587			return ret;
588
589		args->adev = device;
590		args->nargs = 0;
591		return 0;
592	}
593
594	/*
595	 * If it is not a single reference, then it is a package of
596	 * references followed by number of ints as follows:
597	 *
598	 *  Package () { REF, INT, REF, INT, INT }
599	 *
600	 * The index argument is then used to determine which reference
601	 * the caller wants (along with the arguments).
602	 */
603	if (obj->type != ACPI_TYPE_PACKAGE || index >= obj->package.count)
604		return -EPROTO;
605
606	element = obj->package.elements;
607	end = element + obj->package.count;
608
609	while (element < end) {
610		u32 nargs, i;
611
612		if (element->type == ACPI_TYPE_LOCAL_REFERENCE) {
613			ret = acpi_bus_get_device(element->reference.handle,
614						  &device);
615			if (ret)
616				return -ENODEV;
617
618			nargs = 0;
619			element++;
620
621			/* assume following integer elements are all args */
622			for (i = 0; element + i < end && i < num_args; i++) {
623				int type = element[i].type;
624
625				if (type == ACPI_TYPE_INTEGER)
626					nargs++;
627				else if (type == ACPI_TYPE_LOCAL_REFERENCE)
628					break;
629				else
630					return -EPROTO;
631			}
632
633			if (nargs > MAX_ACPI_REFERENCE_ARGS)
634				return -EPROTO;
635
636			if (idx == index) {
637				args->adev = device;
638				args->nargs = nargs;
639				for (i = 0; i < nargs; i++)
640					args->args[i] = element[i].integer.value;
641
642				return 0;
643			}
644
645			element += nargs;
646		} else if (element->type == ACPI_TYPE_INTEGER) {
647			if (idx == index)
648				return -ENOENT;
649			element++;
650		} else {
651			return -EPROTO;
652		}
653
654		idx++;
655	}
656
657	return -ENODATA;
658}
659EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference);
660
661static int acpi_data_prop_read_single(struct acpi_device_data *data,
662				      const char *propname,
663				      enum dev_prop_type proptype, void *val)
664{
665	const union acpi_object *obj;
666	int ret;
667
668	if (!val)
669		return -EINVAL;
670
671	if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
672		ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
673		if (ret)
674			return ret;
675
676		switch (proptype) {
677		case DEV_PROP_U8:
678			if (obj->integer.value > U8_MAX)
679				return -EOVERFLOW;
680			*(u8 *)val = obj->integer.value;
681			break;
682		case DEV_PROP_U16:
683			if (obj->integer.value > U16_MAX)
684				return -EOVERFLOW;
685			*(u16 *)val = obj->integer.value;
686			break;
687		case DEV_PROP_U32:
688			if (obj->integer.value > U32_MAX)
689				return -EOVERFLOW;
690			*(u32 *)val = obj->integer.value;
691			break;
692		default:
693			*(u64 *)val = obj->integer.value;
694			break;
695		}
696	} else if (proptype == DEV_PROP_STRING) {
697		ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
698		if (ret)
699			return ret;
700
701		*(char **)val = obj->string.pointer;
702	} else {
703		ret = -EINVAL;
704	}
705	return ret;
706}
707
708int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
709			      enum dev_prop_type proptype, void *val)
710{
711	return adev ? acpi_data_prop_read_single(&adev->data, propname, proptype, val) : -EINVAL;
712}
713
714static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
715				       size_t nval)
716{
717	int i;
718
719	for (i = 0; i < nval; i++) {
720		if (items[i].type != ACPI_TYPE_INTEGER)
721			return -EPROTO;
722		if (items[i].integer.value > U8_MAX)
723			return -EOVERFLOW;
724
725		val[i] = items[i].integer.value;
726	}
727	return 0;
728}
729
730static int acpi_copy_property_array_u16(const union acpi_object *items,
731					u16 *val, size_t nval)
732{
733	int i;
734
735	for (i = 0; i < nval; i++) {
736		if (items[i].type != ACPI_TYPE_INTEGER)
737			return -EPROTO;
738		if (items[i].integer.value > U16_MAX)
739			return -EOVERFLOW;
740
741		val[i] = items[i].integer.value;
742	}
743	return 0;
744}
745
746static int acpi_copy_property_array_u32(const union acpi_object *items,
747					u32 *val, size_t nval)
748{
749	int i;
750
751	for (i = 0; i < nval; i++) {
752		if (items[i].type != ACPI_TYPE_INTEGER)
753			return -EPROTO;
754		if (items[i].integer.value > U32_MAX)
755			return -EOVERFLOW;
756
757		val[i] = items[i].integer.value;
758	}
759	return 0;
760}
761
762static int acpi_copy_property_array_u64(const union acpi_object *items,
763					u64 *val, size_t nval)
764{
765	int i;
766
767	for (i = 0; i < nval; i++) {
768		if (items[i].type != ACPI_TYPE_INTEGER)
769			return -EPROTO;
770
771		val[i] = items[i].integer.value;
772	}
773	return 0;
774}
775
776static int acpi_copy_property_array_string(const union acpi_object *items,
777					   char **val, size_t nval)
778{
779	int i;
780
781	for (i = 0; i < nval; i++) {
782		if (items[i].type != ACPI_TYPE_STRING)
783			return -EPROTO;
784
785		val[i] = items[i].string.pointer;
786	}
787	return 0;
788}
789
790static int acpi_data_prop_read(struct acpi_device_data *data,
791			       const char *propname,
792			       enum dev_prop_type proptype,
793			       void *val, size_t nval)
794{
795	const union acpi_object *obj;
796	const union acpi_object *items;
797	int ret;
798
799	if (val && nval == 1) {
800		ret = acpi_data_prop_read_single(data, propname, proptype, val);
801		if (!ret)
802			return ret;
803	}
804
805	ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);
806	if (ret)
807		return ret;
808
809	if (!val)
810		return obj->package.count;
811
812	if (nval > obj->package.count)
813		return -EOVERFLOW;
814	else if (nval <= 0)
815		return -EINVAL;
816
817	items = obj->package.elements;
818
819	switch (proptype) {
820	case DEV_PROP_U8:
821		ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
822		break;
823	case DEV_PROP_U16:
824		ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
825		break;
826	case DEV_PROP_U32:
827		ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
828		break;
829	case DEV_PROP_U64:
830		ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
831		break;
832	case DEV_PROP_STRING:
833		ret = acpi_copy_property_array_string(items, (char **)val, nval);
834		break;
835	default:
836		ret = -EINVAL;
837		break;
838	}
839	return ret;
840}
841
842int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
843		       enum dev_prop_type proptype, void *val, size_t nval)
844{
845	return adev ? acpi_data_prop_read(&adev->data, propname, proptype, val, nval) : -EINVAL;
846}
847
848/**
849 * acpi_node_prop_read - retrieve the value of an ACPI property with given name.
850 * @fwnode: Firmware node to get the property from.
851 * @propname: Name of the property.
852 * @proptype: Expected property type.
853 * @val: Location to store the property value (if not %NULL).
854 * @nval: Size of the array pointed to by @val.
855 *
856 * If @val is %NULL, return the number of array elements comprising the value
857 * of the property.  Otherwise, read at most @nval values to the array at the
858 * location pointed to by @val.
859 */
860int acpi_node_prop_read(struct fwnode_handle *fwnode,  const char *propname,
861		        enum dev_prop_type proptype, void *val, size_t nval)
862{
863	return acpi_data_prop_read(acpi_device_data_of_node(fwnode),
864				   propname, proptype, val, nval);
865}
866
867/**
868 * acpi_get_next_subnode - Return the next child node handle for a device.
869 * @dev: Device to find the next child node for.
870 * @child: Handle to one of the device's child nodes or a null handle.
871 */
872struct fwnode_handle *acpi_get_next_subnode(struct device *dev,
873					    struct fwnode_handle *child)
874{
875	struct acpi_device *adev = ACPI_COMPANION(dev);
876	struct list_head *head, *next;
877
878	if (!adev)
879		return NULL;
880
881	if (!child || child->type == FWNODE_ACPI) {
882		head = &adev->children;
883		if (list_empty(head))
884			goto nondev;
885
886		if (child) {
887			adev = to_acpi_device_node(child);
888			next = adev->node.next;
889			if (next == head) {
890				child = NULL;
891				adev = ACPI_COMPANION(dev);
892				goto nondev;
893			}
894			adev = list_entry(next, struct acpi_device, node);
895		} else {
896			adev = list_first_entry(head, struct acpi_device, node);
897		}
898		return acpi_fwnode_handle(adev);
899	}
900
901 nondev:
902	if (!child || child->type == FWNODE_ACPI_DATA) {
903		struct acpi_data_node *dn;
904
905		head = &adev->data.subnodes;
906		if (list_empty(head))
907			return NULL;
908
909		if (child) {
910			dn = to_acpi_data_node(child);
911			next = dn->sibling.next;
912			if (next == head)
913				return NULL;
914
915			dn = list_entry(next, struct acpi_data_node, sibling);
916		} else {
917			dn = list_first_entry(head, struct acpi_data_node, sibling);
918		}
919		return &dn->fwnode;
920	}
921	return NULL;
922}