aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2012-09-17 22:23:26 -0700
committerYinghai Lu <yinghai@kernel.org>2012-09-17 22:23:26 -0700
commite2512d61610eed7deee003d20391b086769d0436 (patch)
tree470f58667e3cc36eca50b905c34f19de57671a6c
parent3cceccbfa740ef139985df7202ea8744761d0db2 (diff)
downloadlinux-yinghai-e2512d61610eed7deee003d20391b086769d0436.tar.gz
ACPI: Add acpi_run_dsm()
Will need to use that get dmar entries for hotplug Signed-off-by: Yinghai Lu <yinghai@kernel.org>
-rw-r--r--drivers/acpi/bus.c77
-rw-r--r--include/linux/acpi.h10
2 files changed, 87 insertions, 0 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index e0596954290b8..04b13c2fa0b14 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -560,6 +560,83 @@ out_kfree:
}
EXPORT_SYMBOL(acpi_run_osc);
+static void acpi_print_dsm_error(acpi_handle handle,
+ struct acpi_dsm_context *context, char *error)
+{
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER};
+
+ if (ACPI_FAILURE(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer)))
+ printk(KERN_DEBUG "%s for idx %x\n", error, context->func_idx);
+ else {
+ printk(KERN_DEBUG "%s:%s for idx %x\n",
+ (char *)buffer.pointer, error, context->func_idx);
+ kfree(buffer.pointer);
+ }
+}
+
+acpi_status acpi_run_dsm(acpi_handle handle, struct acpi_dsm_context *context)
+{
+ acpi_status status;
+ struct acpi_object_list input;
+ union acpi_object in_params[4];
+ union acpi_object *out_obj;
+ u8 uuid[16];
+ struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+
+ if (!context)
+ return AE_ERROR;
+ if (ACPI_FAILURE(acpi_str_to_uuid(context->uuid_str, uuid)))
+ return AE_ERROR;
+ context->ret.length = ACPI_ALLOCATE_BUFFER;
+ context->ret.pointer = NULL;
+
+ /* Setting up input parameters */
+ input.count = 4;
+ input.pointer = in_params;
+ in_params[0].type = ACPI_TYPE_BUFFER;
+ in_params[0].buffer.length = 16;
+ in_params[0].buffer.pointer = uuid;
+ in_params[1].type = ACPI_TYPE_INTEGER;
+ in_params[1].integer.value = context->rev;
+ in_params[2].type = ACPI_TYPE_INTEGER;
+ in_params[2].integer.value = context->func_idx;
+ in_params[3].type = ACPI_TYPE_PACKAGE;
+ in_params[3].package.count = context->func_argc;
+ in_params[3].package.elements = context->func_argv;
+
+ status = acpi_evaluate_object(handle, "_DSM", &input, &output);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ if (!output.length)
+ return AE_NULL_OBJECT;
+
+ out_obj = output.pointer;
+ if (out_obj->type != ACPI_TYPE_BUFFER) {
+ acpi_print_dsm_error(handle, context,
+ "_DSM evaluation returned wrong type");
+ status = AE_TYPE;
+ goto out_kfree;
+ }
+
+ context->ret.length = out_obj->buffer.length;
+ context->ret.pointer = kmalloc(context->ret.length, GFP_KERNEL);
+ if (!context->ret.pointer) {
+ status = AE_NO_MEMORY;
+ goto out_kfree;
+ }
+ memcpy(context->ret.pointer, out_obj->buffer.pointer,
+ context->ret.length);
+ status = AE_OK;
+
+out_kfree:
+ kfree(output.pointer);
+ if (status != AE_OK)
+ context->ret.pointer = NULL;
+ return status;
+}
+EXPORT_SYMBOL(acpi_run_dsm);
+
bool osc_sb_apei_support_acked;
static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48";
static void acpi_bus_osc_support(void)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 90be989811020..6dbc46d4808fb 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -283,6 +283,16 @@ struct acpi_osc_context {
acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
+struct acpi_dsm_context {
+ char *uuid_str; /* uuid string */
+ int rev;
+ int func_idx; /* function index */
+ int func_argc;
+ union acpi_object *func_argv;
+ struct acpi_buffer ret; /* free by caller if success */
+};
+acpi_status acpi_run_dsm(acpi_handle handle, struct acpi_dsm_context *context);
+
/* platform-wide _OSC bits */
#define OSC_SB_PAD_SUPPORT 1
#define OSC_SB_PPC_OST_SUPPORT 2