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> |
