aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@linux.intel.com>2013-12-19 07:38:10 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-01-05 10:07:14 -0500
commita65ac52041cccaf598995bc44340849027f1d79b (patch)
tree66feec04a0a904218e076cae1296dd3bbad862f6
parente73be4a78b500374a1c42810dc073189036b4dd8 (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.c97
-rw-r--r--include/acpi/acpi_bus.h26
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 */
592union acpi_object *
593acpi_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}
629EXPORT_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 */
643bool 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}
673EXPORT_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);
66bool acpi_bay_match(acpi_handle handle); 66bool acpi_bay_match(acpi_handle handle);
67bool acpi_dock_match(acpi_handle handle); 67bool acpi_dock_match(acpi_handle handle);
68 68
69bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs);
70union acpi_object *acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid,
71 int rev, int func, union acpi_object *argv4);
72
73static inline union acpi_object *
74acpi_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>