diff options
-rw-r--r-- | drivers/acpi/bus.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 65f7e335f122..0c1ad3105da1 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -397,6 +397,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) | |||
397 | union acpi_object *out_obj; | 397 | union acpi_object *out_obj; |
398 | u8 uuid[16]; | 398 | u8 uuid[16]; |
399 | u32 errors; | 399 | u32 errors; |
400 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
400 | 401 | ||
401 | if (!context) | 402 | if (!context) |
402 | return AE_ERROR; | 403 | return AE_ERROR; |
@@ -419,16 +420,16 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) | |||
419 | in_params[3].buffer.length = context->cap.length; | 420 | in_params[3].buffer.length = context->cap.length; |
420 | in_params[3].buffer.pointer = context->cap.pointer; | 421 | in_params[3].buffer.pointer = context->cap.pointer; |
421 | 422 | ||
422 | status = acpi_evaluate_object(handle, "_OSC", &input, &context->ret); | 423 | status = acpi_evaluate_object(handle, "_OSC", &input, &output); |
423 | if (ACPI_FAILURE(status)) | 424 | if (ACPI_FAILURE(status)) |
424 | return status; | 425 | return status; |
425 | 426 | ||
426 | /* return buffer should have the same length as cap buffer */ | 427 | if (!output.length) |
427 | if (context->ret.length != context->cap.length) | ||
428 | return AE_NULL_OBJECT; | 428 | return AE_NULL_OBJECT; |
429 | 429 | ||
430 | out_obj = context->ret.pointer; | 430 | out_obj = output.pointer; |
431 | if (out_obj->type != ACPI_TYPE_BUFFER) { | 431 | if (out_obj->type != ACPI_TYPE_BUFFER |
432 | || out_obj->buffer.length != context->cap.length) { | ||
432 | acpi_print_osc_error(handle, context, | 433 | acpi_print_osc_error(handle, context, |
433 | "_OSC evaluation returned wrong type"); | 434 | "_OSC evaluation returned wrong type"); |
434 | status = AE_TYPE; | 435 | status = AE_TYPE; |
@@ -457,11 +458,20 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) | |||
457 | goto out_kfree; | 458 | goto out_kfree; |
458 | } | 459 | } |
459 | out_success: | 460 | out_success: |
460 | return AE_OK; | 461 | context->ret.length = out_obj->buffer.length; |
462 | context->ret.pointer = kmalloc(context->ret.length, GFP_KERNEL); | ||
463 | if (!context->ret.pointer) { | ||
464 | status = AE_NO_MEMORY; | ||
465 | goto out_kfree; | ||
466 | } | ||
467 | memcpy(context->ret.pointer, out_obj->buffer.pointer, | ||
468 | context->ret.length); | ||
469 | status = AE_OK; | ||
461 | 470 | ||
462 | out_kfree: | 471 | out_kfree: |
463 | kfree(context->ret.pointer); | 472 | kfree(output.pointer); |
464 | context->ret.pointer = NULL; | 473 | if (status != AE_OK) |
474 | context->ret.pointer = NULL; | ||
465 | return status; | 475 | return status; |
466 | } | 476 | } |
467 | EXPORT_SYMBOL(acpi_run_osc); | 477 | EXPORT_SYMBOL(acpi_run_osc); |