aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS8
-rw-r--r--drivers/acpi/property.c117
-rw-r--r--include/linux/acpi.h22
3 files changed, 95 insertions, 52 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index c8926c1acd22..46c526eb1bab 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -316,6 +316,14 @@ W: https://01.org/linux-acpi
316S: Supported 316S: Supported
317F: drivers/acpi/fan.c 317F: drivers/acpi/fan.c
318 318
319ACPI FOR ARM64 (ACPI/arm64)
320M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
321M: Hanjun Guo <hanjun.guo@linaro.org>
322M: Sudeep Holla <sudeep.holla@arm.com>
323L: linux-acpi@vger.kernel.org
324S: Maintained
325F: drivers/acpi/arm64
326
319ACPI THERMAL DRIVER 327ACPI THERMAL DRIVER
320M: Zhang Rui <rui.zhang@intel.com> 328M: Zhang Rui <rui.zhang@intel.com>
321L: linux-acpi@vger.kernel.org 329L: linux-acpi@vger.kernel.org
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index f2fd3fee588a..03f5ec11ab31 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -468,10 +468,11 @@ static int acpi_data_get_property_array(struct acpi_device_data *data,
468} 468}
469 469
470/** 470/**
471 * acpi_data_get_property_reference - returns handle to the referenced object 471 * __acpi_node_get_property_reference - returns handle to the referenced object
472 * @data: ACPI device data object containing the property 472 * @fwnode: Firmware node to get the property from
473 * @propname: Name of the property 473 * @propname: Name of the property
474 * @index: Index of the reference to return 474 * @index: Index of the reference to return
475 * @num_args: Maximum number of arguments after each reference
475 * @args: Location to store the returned reference with optional arguments 476 * @args: Location to store the returned reference with optional arguments
476 * 477 *
477 * Find property with @name, verifify that it is a package containing at least 478 * Find property with @name, verifify that it is a package containing at least
@@ -482,17 +483,40 @@ static int acpi_data_get_property_array(struct acpi_device_data *data,
482 * If there's more than one reference in the property value package, @index is 483 * If there's more than one reference in the property value package, @index is
483 * used to select the one to return. 484 * used to select the one to return.
484 * 485 *
486 * It is possible to leave holes in the property value set like in the
487 * example below:
488 *
489 * Package () {
490 * "cs-gpios",
491 * Package () {
492 * ^GPIO, 19, 0, 0,
493 * ^GPIO, 20, 0, 0,
494 * 0,
495 * ^GPIO, 21, 0, 0,
496 * }
497 * }
498 *
499 * Calling this function with index %2 return %-ENOENT and with index %3
500 * returns the last entry. If the property does not contain any more values
501 * %-ENODATA is returned. The NULL entry must be single integer and
502 * preferably contain value %0.
503 *
485 * Return: %0 on success, negative error code on failure. 504 * Return: %0 on success, negative error code on failure.
486 */ 505 */
487static int acpi_data_get_property_reference(struct acpi_device_data *data, 506int __acpi_node_get_property_reference(struct fwnode_handle *fwnode,
488 const char *propname, size_t index, 507 const char *propname, size_t index, size_t num_args,
489 struct acpi_reference_args *args) 508 struct acpi_reference_args *args)
490{ 509{
491 const union acpi_object *element, *end; 510 const union acpi_object *element, *end;
492 const union acpi_object *obj; 511 const union acpi_object *obj;
512 struct acpi_device_data *data;
493 struct acpi_device *device; 513 struct acpi_device *device;
494 int ret, idx = 0; 514 int ret, idx = 0;
495 515
516 data = acpi_device_data_of_node(fwnode);
517 if (!data)
518 return -EINVAL;
519
496 ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj); 520 ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj);
497 if (ret) 521 if (ret)
498 return ret; 522 return ret;
@@ -532,59 +556,54 @@ static int acpi_data_get_property_reference(struct acpi_device_data *data,
532 while (element < end) { 556 while (element < end) {
533 u32 nargs, i; 557 u32 nargs, i;
534 558
535 if (element->type != ACPI_TYPE_LOCAL_REFERENCE) 559 if (element->type == ACPI_TYPE_LOCAL_REFERENCE) {
536 return -EPROTO; 560 ret = acpi_bus_get_device(element->reference.handle,
537 561 &device);
538 ret = acpi_bus_get_device(element->reference.handle, &device); 562 if (ret)
539 if (ret) 563 return -ENODEV;
540 return -ENODEV; 564
541 565 nargs = 0;
542 element++; 566 element++;
543 nargs = 0; 567
544 568 /* assume following integer elements are all args */
545 /* assume following integer elements are all args */ 569 for (i = 0; element + i < end && i < num_args; i++) {
546 for (i = 0; element + i < end; i++) { 570 int type = element[i].type;
547 int type = element[i].type; 571
572 if (type == ACPI_TYPE_INTEGER)
573 nargs++;
574 else if (type == ACPI_TYPE_LOCAL_REFERENCE)
575 break;
576 else
577 return -EPROTO;
578 }
548 579
549 if (type == ACPI_TYPE_INTEGER) 580 if (nargs > MAX_ACPI_REFERENCE_ARGS)
550 nargs++;
551 else if (type == ACPI_TYPE_LOCAL_REFERENCE)
552 break;
553 else
554 return -EPROTO; 581 return -EPROTO;
555 }
556 582
557 if (idx++ == index) { 583 if (idx == index) {
558 args->adev = device; 584 args->adev = device;
559 args->nargs = nargs; 585 args->nargs = nargs;
560 for (i = 0; i < nargs; i++) 586 for (i = 0; i < nargs; i++)
561 args->args[i] = element[i].integer.value; 587 args->args[i] = element[i].integer.value;
562 588
563 return 0; 589 return 0;
590 }
591
592 element += nargs;
593 } else if (element->type == ACPI_TYPE_INTEGER) {
594 if (idx == index)
595 return -ENOENT;
596 element++;
597 } else {
598 return -EPROTO;
564 } 599 }
565 600
566 element += nargs; 601 idx++;
567 } 602 }
568 603
569 return -EPROTO; 604 return -ENODATA;
570}
571
572/**
573 * acpi_node_get_property_reference - get a handle to the referenced object.
574 * @fwnode: Firmware node to get the property from.
575 * @propname: Name of the property.
576 * @index: Index of the reference to return.
577 * @args: Location to store the returned reference with optional arguments.
578 */
579int acpi_node_get_property_reference(struct fwnode_handle *fwnode,
580 const char *name, size_t index,
581 struct acpi_reference_args *args)
582{
583 struct acpi_device_data *data = acpi_device_data_of_node(fwnode);
584
585 return data ? acpi_data_get_property_reference(data, name, index, args) : -EINVAL;
586} 605}
587EXPORT_SYMBOL_GPL(acpi_node_get_property_reference); 606EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference);
588 607
589static int acpi_data_prop_read_single(struct acpi_device_data *data, 608static int acpi_data_prop_read_single(struct acpi_device_data *data,
590 const char *propname, 609 const char *propname,
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 65932c08afd2..2d42fb7d56b7 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -934,9 +934,17 @@ struct acpi_reference_args {
934#ifdef CONFIG_ACPI 934#ifdef CONFIG_ACPI
935int acpi_dev_get_property(struct acpi_device *adev, const char *name, 935int acpi_dev_get_property(struct acpi_device *adev, const char *name,
936 acpi_object_type type, const union acpi_object **obj); 936 acpi_object_type type, const union acpi_object **obj);
937int acpi_node_get_property_reference(struct fwnode_handle *fwnode, 937int __acpi_node_get_property_reference(struct fwnode_handle *fwnode,
938 const char *name, size_t index, 938 const char *name, size_t index, size_t num_args,
939 struct acpi_reference_args *args); 939 struct acpi_reference_args *args);
940
941static inline int acpi_node_get_property_reference(struct fwnode_handle *fwnode,
942 const char *name, size_t index,
943 struct acpi_reference_args *args)
944{
945 return __acpi_node_get_property_reference(fwnode, name, index,
946 MAX_ACPI_REFERENCE_ARGS, args);
947}
940 948
941int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname, 949int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname,
942 void **valptr); 950 void **valptr);
@@ -1012,6 +1020,14 @@ static inline int acpi_dev_get_property(struct acpi_device *adev,
1012 return -ENXIO; 1020 return -ENXIO;
1013} 1021}
1014 1022
1023static inline int
1024__acpi_node_get_property_reference(struct fwnode_handle *fwnode,
1025 const char *name, size_t index, size_t num_args,
1026 struct acpi_reference_args *args)
1027{
1028 return -ENXIO;
1029}
1030
1015static inline int acpi_node_get_property_reference(struct fwnode_handle *fwnode, 1031static inline int acpi_node_get_property_reference(struct fwnode_handle *fwnode,
1016 const char *name, size_t index, 1032 const char *name, size_t index,
1017 struct acpi_reference_args *args) 1033 struct acpi_reference_args *args)