mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
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>
This commit is contained in:
parent
e73be4a78b
commit
a65ac52041
@ -574,3 +574,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);
|
||||
|
@ -66,6 +66,32 @@ bool acpi_ata_match(acpi_handle handle);
|
||||
bool acpi_bay_match(acpi_handle handle);
|
||||
bool acpi_dock_match(acpi_handle handle);
|
||||
|
||||
bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs);
|
||||
union acpi_object *acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid,
|
||||
int rev, int func, union acpi_object *argv4);
|
||||
|
||||
static inline union acpi_object *
|
||||
acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, int rev, int func,
|
||||
union acpi_object *argv4, acpi_object_type type)
|
||||
{
|
||||
union acpi_object *obj;
|
||||
|
||||
obj = acpi_evaluate_dsm(handle, uuid, rev, func, argv4);
|
||||
if (obj && obj->type != type) {
|
||||
ACPI_FREE(obj);
|
||||
obj = NULL;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
#define ACPI_INIT_DSM_ARGV4(cnt, eles) \
|
||||
{ \
|
||||
.package.type = ACPI_TYPE_PACKAGE, \
|
||||
.package.count = (cnt), \
|
||||
.package.elements = (eles) \
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
|
||||
#include <linux/proc_fs.h>
|
||||
|
Loading…
Reference in New Issue
Block a user