diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-01-12 23:45:52 +0100 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-01-12 23:45:52 +0100 |
commit | fbb9c10d40f88011ac72f855c97e3bdd981026a9 (patch) | |
tree | 255b3c21fd859004310bfad0a829ea4392d4851b /drivers/acpi/utils.c | |
parent | 3e7cc142c1e040fd4629ad34a54b1c5b46dc3dd3 (diff) | |
parent | 7ede9f8a1805b26b3141730c9deaea8bc95a64bc (diff) |
Merge branch 'acpi-dsm'
* acpi-dsm:
ACPI / extlog: replace open-coded _DSM code with helper functions
ACPI / nouveau: replace open-coded _DSM code with helper functions
nouveau / ACPI: fix memory leak in ACPI _DSM related code
ACPI / i915: replace open-coded _DSM code with helper functions
ACPI / i2c-hid: replace open-coded _DSM code with helper functions
ACPI / TPM: detect PPI features by checking availability of _DSM functions
ACPI / TPM: replace open-coded _DSM code with helper functions
ACPI / TPM: match node name instead of full path when searching for TPM device
PCI / pci-label: treat PCI label with index 0 as valid label
ACPI / PCI: replace open-coded _DSM code with helper functions
PCI / pci-label: release allocated ACPI object on error recovery path
ACPI: introduce helper interfaces for _DSM method
Diffstat (limited to 'drivers/acpi/utils.c')
-rw-r--r-- | drivers/acpi/utils.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 1336b9151479..0347a37eb438 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -572,3 +572,100 @@ acpi_status acpi_evaluate_lck(acpi_handle handle, int lock) return status; } + +/** + * acpi_evaluate_dsm - evaluate device's _DSM method + * @handle: ACPI device handle + * @uuid: UUID of requested functions, should be 16 bytes + * @rev: revision number of requested function + * @func: requested function number + * @argv4: the function specific parameter + * + * Evaluate device's _DSM method with specified UUID, revision id and + * function number. Caller needs to free the returned object. + * + * Though ACPI defines the fourth parameter for _DSM should be a package, + * some old BIOSes do expect a buffer or an integer etc. + */ +union acpi_object * +acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, int rev, int func, + union acpi_object *argv4) +{ + acpi_status ret; + struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object params[4]; + struct acpi_object_list input = { + .count = 4, + .pointer = params, + }; + + params[0].type = ACPI_TYPE_BUFFER; + params[0].buffer.length = 16; + params[0].buffer.pointer = (char *)uuid; + params[1].type = ACPI_TYPE_INTEGER; + params[1].integer.value = rev; + params[2].type = ACPI_TYPE_INTEGER; + params[2].integer.value = func; + if (argv4) { + params[3] = *argv4; + } else { + params[3].type = ACPI_TYPE_PACKAGE; + params[3].package.count = 0; + params[3].package.elements = NULL; + } + + ret = acpi_evaluate_object(handle, "_DSM", &input, &buf); + if (ACPI_SUCCESS(ret)) + return (union acpi_object *)buf.pointer; + + if (ret != AE_NOT_FOUND) + acpi_handle_warn(handle, + "failed to evaluate _DSM (0x%x)\n", ret); + + return NULL; +} +EXPORT_SYMBOL(acpi_evaluate_dsm); + +/** + * acpi_check_dsm - check if _DSM method supports requested functions. + * @handle: ACPI device handle + * @uuid: UUID of requested functions, should be 16 bytes at least + * @rev: revision number of requested functions + * @funcs: bitmap of requested functions + * @exclude: excluding special value, used to support i915 and nouveau + * + * Evaluate device's _DSM method to check whether it supports requested + * functions. Currently only support 64 functions at maximum, should be + * enough for now. + */ +bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) +{ + int i; + u64 mask = 0; + union acpi_object *obj; + + if (funcs == 0) + return false; + + obj = acpi_evaluate_dsm(handle, uuid, rev, 0, NULL); + if (!obj) + return false; + + /* For compatibility, old BIOSes may return an integer */ + if (obj->type == ACPI_TYPE_INTEGER) + mask = obj->integer.value; + else if (obj->type == ACPI_TYPE_BUFFER) + for (i = 0; i < obj->buffer.length && i < 8; i++) + mask |= (((u8)obj->buffer.pointer[i]) << (i * 8)); + ACPI_FREE(obj); + + /* + * Bit 0 indicates whether there's support for any functions other than + * function 0 for the specified UUID and revision. + */ + if ((mask & 0x1) && (mask & funcs) == funcs) + return true; + + return false; +} +EXPORT_SYMBOL(acpi_check_dsm); |