diff options
-rw-r--r-- | MAINTAINERS | 8 | ||||
-rw-r--r-- | drivers/acpi/property.c | 117 | ||||
-rw-r--r-- | include/linux/acpi.h | 22 |
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 | |||
316 | S: Supported | 316 | S: Supported |
317 | F: drivers/acpi/fan.c | 317 | F: drivers/acpi/fan.c |
318 | 318 | ||
319 | ACPI FOR ARM64 (ACPI/arm64) | ||
320 | M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | ||
321 | M: Hanjun Guo <hanjun.guo@linaro.org> | ||
322 | M: Sudeep Holla <sudeep.holla@arm.com> | ||
323 | L: linux-acpi@vger.kernel.org | ||
324 | S: Maintained | ||
325 | F: drivers/acpi/arm64 | ||
326 | |||
319 | ACPI THERMAL DRIVER | 327 | ACPI THERMAL DRIVER |
320 | M: Zhang Rui <rui.zhang@intel.com> | 328 | M: Zhang Rui <rui.zhang@intel.com> |
321 | L: linux-acpi@vger.kernel.org | 329 | L: 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 | */ |
487 | static int acpi_data_get_property_reference(struct acpi_device_data *data, | 506 | int __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 | */ | ||
579 | int 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 | } |
587 | EXPORT_SYMBOL_GPL(acpi_node_get_property_reference); | 606 | EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference); |
588 | 607 | ||
589 | static int acpi_data_prop_read_single(struct acpi_device_data *data, | 608 | static 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 |
935 | int acpi_dev_get_property(struct acpi_device *adev, const char *name, | 935 | int 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); |
937 | int acpi_node_get_property_reference(struct fwnode_handle *fwnode, | 937 | int __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 | |||
941 | static 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 | ||
941 | int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname, | 949 | int 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 | ||
1023 | static 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 | |||
1015 | static inline int acpi_node_get_property_reference(struct fwnode_handle *fwnode, | 1031 | static 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) |