diff options
author | Jiang Liu <jiang.liu@linux.intel.com> | 2013-12-19 07:38:10 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-01-05 10:07:14 -0500 |
commit | a65ac52041cccaf598995bc44340849027f1d79b (patch) | |
tree | 66feec04a0a904218e076cae1296dd3bbad862f6 | |
parent | e73be4a78b500374a1c42810dc073189036b4dd8 (diff) |
ACPI: introduce helper interfaces for _DSM method
There are several drivers making use of ACPI _DSM method to detect
and invoke device specific methods. Currently every driver has
implemented its private version to support ACPI _DSM method.
So this patch introduces three helper functions to support ACPI _DSM
method, which will be used to replace open-coded versions.
It helps to simplify code and improve code readability.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/acpi/utils.c | 97 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 26 |
2 files changed, 123 insertions, 0 deletions
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 6d408bfbbb1d..bcb2ed9e03aa 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c | |||
@@ -574,3 +574,100 @@ acpi_status acpi_evaluate_lck(acpi_handle handle, int lock) | |||
574 | 574 | ||
575 | return status; | 575 | return status; |
576 | } | 576 | } |
577 | |||
578 | /** | ||
579 | * acpi_evaluate_dsm - evaluate device's _DSM method | ||
580 | * @handle: ACPI device handle | ||
581 | * @uuid: UUID of requested functions, should be 16 bytes | ||
582 | * @rev: revision number of requested function | ||
583 | * @func: requested function number | ||
584 | * @argv4: the function specific parameter | ||
585 | * | ||
586 | * Evaluate device's _DSM method with specified UUID, revision id and | ||
587 | * function number. Caller needs to free the returned object. | ||
588 | * | ||
589 | * Though ACPI defines the fourth parameter for _DSM should be a package, | ||
590 | * some old BIOSes do expect a buffer or an integer etc. | ||
591 | */ | ||
592 | union acpi_object * | ||
593 | acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, int rev, int func, | ||
594 | union acpi_object *argv4) | ||
595 | { | ||
596 | acpi_status ret; | ||
597 | struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
598 | union acpi_object params[4]; | ||
599 | struct acpi_object_list input = { | ||
600 | .count = 4, | ||
601 | .pointer = params, | ||
602 | }; | ||
603 | |||
604 | params[0].type = ACPI_TYPE_BUFFER; | ||
605 | params[0].buffer.length = 16; | ||
606 | params[0].buffer.pointer = (char *)uuid; | ||
607 | params[1].type = ACPI_TYPE_INTEGER; | ||
608 | params[1].integer.value = rev; | ||
609 | params[2].type = ACPI_TYPE_INTEGER; | ||
610 | params[2].integer.value = func; | ||
611 | if (argv4) { | ||
612 | params[3] = *argv4; | ||
613 | } else { | ||
614 | params[3].type = ACPI_TYPE_PACKAGE; | ||
615 | params[3].package.count = 0; | ||
616 | params[3].package.elements = NULL; | ||
617 | } | ||
618 | |||
619 | ret = acpi_evaluate_object(handle, "_DSM", &input, &buf); | ||
620 | if (ACPI_SUCCESS(ret)) | ||
621 | return (union acpi_object *)buf.pointer; | ||
622 | |||
623 | if (ret != AE_NOT_FOUND) | ||
624 | acpi_handle_warn(handle, | ||
625 | "failed to evaluate _DSM (0x%x)\n", ret); | ||
626 | |||
627 | return NULL; | ||
628 | } | ||
629 | EXPORT_SYMBOL(acpi_evaluate_dsm); | ||
630 | |||
631 | /** | ||
632 | * acpi_check_dsm - check if _DSM method supports requested functions. | ||
633 | * @handle: ACPI device handle | ||
634 | * @uuid: UUID of requested functions, should be 16 bytes at least | ||
635 | * @rev: revision number of requested functions | ||
636 | * @funcs: bitmap of requested functions | ||
637 | * @exclude: excluding special value, used to support i915 and nouveau | ||
638 | * | ||
639 | * Evaluate device's _DSM method to check whether it supports requested | ||
640 | * functions. Currently only support 64 functions at maximum, should be | ||
641 | * enough for now. | ||
642 | */ | ||
643 | bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) | ||
644 | { | ||
645 | int i; | ||
646 | u64 mask = 0; | ||
647 | union acpi_object *obj; | ||
648 | |||
649 | if (funcs == 0) | ||
650 | return false; | ||
651 | |||
652 | obj = acpi_evaluate_dsm(handle, uuid, rev, 0, NULL); | ||
653 | if (!obj) | ||
654 | return false; | ||
655 | |||
656 | /* For compatibility, old BIOSes may return an integer */ | ||
657 | if (obj->type == ACPI_TYPE_INTEGER) | ||
658 | mask = obj->integer.value; | ||
659 | else if (obj->type == ACPI_TYPE_BUFFER) | ||
660 | for (i = 0; i < obj->buffer.length && i < 8; i++) | ||
661 | mask |= (((u8)obj->buffer.pointer[i]) << (i * 8)); | ||
662 | ACPI_FREE(obj); | ||
663 | |||
664 | /* | ||
665 | * Bit 0 indicates whether there's support for any functions other than | ||
666 | * function 0 for the specified UUID and revision. | ||
667 | */ | ||
668 | if ((mask & 0x1) && (mask & funcs) == funcs) | ||
669 | return true; | ||
670 | |||
671 | return false; | ||
672 | } | ||
673 | EXPORT_SYMBOL(acpi_check_dsm); | ||
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index ddabed1f51c2..dd9b5edc7630 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -66,6 +66,32 @@ bool acpi_ata_match(acpi_handle handle); | |||
66 | bool acpi_bay_match(acpi_handle handle); | 66 | bool acpi_bay_match(acpi_handle handle); |
67 | bool acpi_dock_match(acpi_handle handle); | 67 | bool acpi_dock_match(acpi_handle handle); |
68 | 68 | ||
69 | bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs); | ||
70 | union acpi_object *acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, | ||
71 | int rev, int func, union acpi_object *argv4); | ||
72 | |||
73 | static inline union acpi_object * | ||
74 | acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, int rev, int func, | ||
75 | union acpi_object *argv4, acpi_object_type type) | ||
76 | { | ||
77 | union acpi_object *obj; | ||
78 | |||
79 | obj = acpi_evaluate_dsm(handle, uuid, rev, func, argv4); | ||
80 | if (obj && obj->type != type) { | ||
81 | ACPI_FREE(obj); | ||
82 | obj = NULL; | ||
83 | } | ||
84 | |||
85 | return obj; | ||
86 | } | ||
87 | |||
88 | #define ACPI_INIT_DSM_ARGV4(cnt, eles) \ | ||
89 | { \ | ||
90 | .package.type = ACPI_TYPE_PACKAGE, \ | ||
91 | .package.count = (cnt), \ | ||
92 | .package.elements = (eles) \ | ||
93 | } | ||
94 | |||
69 | #ifdef CONFIG_ACPI | 95 | #ifdef CONFIG_ACPI |
70 | 96 | ||
71 | #include <linux/proc_fs.h> | 97 | #include <linux/proc_fs.h> |