Currently when capabilities have been masked by firmware during a negotiation with OSC_QUERY_ENABLE set they're silently ignored by the caller. If the caller calls `acpi_run_osc` again without query set and the same capabilities, then they instead get a failure possibly leading to downstream problems. So instead when query is set return AE_SUPPORT which callers can then use for determining that capabilities were masked. Signed-off-by: Mario Limonciello <mario.limonciello@xxxxxxx> --- Changes from v2->v3: * Add kernel doc for the acpi_run_osc function * Correct a logic error drivers/acpi/bus.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 07f604832fd6..81647591ec27 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -184,6 +184,18 @@ static void acpi_print_osc_error(acpi_handle handle, pr_debug("\n"); } +/** + * acpi_run_osc - Evaluate the _OSC method for a given ACPI handle + * @handle: ACPI handle containing _OSC to evaluate + * @context: A structure specifying UUID, revision, and buffer for data + * + * Used for negotiating with firmware the capabilities that will be used + * by the OSPM. Although the return type is acpi_status, the ACPI_SUCCESS + * macro can not be used to determine whether to free the buffer of + * returned data. + * + * The buffer must be freed when this function returns AE_OK or AE_SUCCESS. + */ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) { acpi_status status; @@ -243,16 +255,19 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) acpi_print_osc_error(handle, context, "_OSC invalid revision"); if (errors & OSC_CAPABILITIES_MASK_ERROR) { + acpi_print_osc_error(handle, context, "_OSC capabilities masked"); if (((u32 *)context->cap.pointer)[OSC_QUERY_DWORD] - & OSC_QUERY_ENABLE) - goto out_success; - status = AE_SUPPORT; - goto out_kfree; + & OSC_QUERY_ENABLE) { + status = AE_SUPPORT; + goto out_masked; + } } status = AE_ERROR; goto out_kfree; } -out_success: + + status = AE_OK; +out_masked: context->ret.length = out_obj->buffer.length; context->ret.pointer = kmemdup(out_obj->buffer.pointer, context->ret.length, GFP_KERNEL); @@ -260,7 +275,6 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) status = AE_NO_MEMORY; goto out_kfree; } - status = AE_OK; out_kfree: kfree(output.pointer); -- 2.34.1