From patchwork Tue Oct 27 06:36:37 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shaohua Li X-Patchwork-Id: 56034 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n9R6aexM017482 for ; Tue, 27 Oct 2009 06:36:40 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756191AbZJ0Gge (ORCPT ); Tue, 27 Oct 2009 02:36:34 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756199AbZJ0Gge (ORCPT ); Tue, 27 Oct 2009 02:36:34 -0400 Received: from mga01.intel.com ([192.55.52.88]:38043 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756191AbZJ0Gge (ORCPT ); Tue, 27 Oct 2009 02:36:34 -0400 Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 26 Oct 2009 23:29:54 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.44,631,1249282800"; d="scan'208";a="507852611" Received: from sli10-conroe.sh.intel.com (HELO sli10-desk.sh.intel.com) ([10.239.13.1]) by fmsmga002.fm.intel.com with ESMTP; 26 Oct 2009 23:28:06 -0700 Received: from david by sli10-desk.sh.intel.com with local (Exim 4.69) (envelope-from ) id 1N2ffZ-0007Hm-RJ; Tue, 27 Oct 2009 14:36:37 +0800 Date: Tue, 27 Oct 2009 14:36:37 +0800 From: Shaohua Li To: linux-acpi@vger.kernel.org Cc: lenb@kernel.org Subject: [PATCH 1/3] Add a generic API for _OSC Message-ID: <20091027063637.GA22237@sli10-desk.sh.intel.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.18 (2008-05-17) Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Index: linux/drivers/acpi/bus.c =================================================================== --- linux.orig/drivers/acpi/bus.c 2009-10-27 13:50:24.000000000 +0800 +++ linux/drivers/acpi/bus.c 2009-10-27 14:02:30.000000000 +0800 @@ -344,6 +344,78 @@ bool acpi_bus_can_wakeup(acpi_handle han EXPORT_SYMBOL(acpi_bus_can_wakeup); +acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) +{ + acpi_status status; + struct acpi_object_list input; + union acpi_object in_params[4]; + union acpi_object *out_obj; + u32 errors; + + if (!context) + 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 = context->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->cap.length/sizeof(u32); + in_params[3].type = ACPI_TYPE_BUFFER; + in_params[3].buffer.length = context->cap.length; + in_params[3].buffer.pointer = context->cap.pointer; + + status = acpi_evaluate_object(handle, "_OSC", &input, &context->ret); + if (ACPI_FAILURE(status)) + return status; + + /* return buffer should have the same length as cap buffer */ + if (context->ret.length != context->cap.length) + return AE_NULL_OBJECT; + + out_obj = context->ret.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER) { + printk(KERN_DEBUG "_OSC evaluation returned wrong type\n"); + status = AE_TYPE; + goto out_kfree; + } + /* Need to ignore the bit0 in result code */ + errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); + if (errors) { + if (errors & OSC_REQUEST_ERROR) + printk(KERN_DEBUG "_OSC request failed\n"); + if (errors & OSC_INVALID_UUID_ERROR) + printk(KERN_DEBUG "_OSC invalid UUID\n"); + if (errors & OSC_INVALID_REVISION_ERROR) + printk(KERN_DEBUG "_OSC invalid revision\n"); + if (errors & OSC_CAPABILITIES_MASK_ERROR) { + if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE] + & OSC_QUERY_ENABLE) + goto out_success; + printk(KERN_DEBUG + "Firmware did not grant requested _OSC control\n"); + status = AE_SUPPORT; + goto out_kfree; + } + status = AE_ERROR; + goto out_kfree; + } +out_success: + return AE_OK; + +out_kfree: + kfree(context->ret.pointer); + context->ret.pointer = NULL; + return status; +} +EXPORT_SYMBOL(acpi_run_osc); + /* -------------------------------------------------------------------------- Event Management -------------------------------------------------------------------------- */ Index: linux/include/linux/acpi.h =================================================================== --- linux.orig/include/linux/acpi.h 2009-10-27 13:50:24.000000000 +0800 +++ linux/include/linux/acpi.h 2009-10-27 13:50:35.000000000 +0800 @@ -253,6 +253,13 @@ void __init acpi_old_suspend_ordering(vo void __init acpi_s4_no_nvs(void); #endif /* CONFIG_PM_SLEEP */ +struct acpi_osc_context { + u8 *uuid; + int rev; + struct acpi_buffer cap; /* arg2/arg3 */ + struct acpi_buffer ret; /* free by caller if success */ +}; + #define OSC_QUERY_TYPE 0 #define OSC_SUPPORT_TYPE 1 #define OSC_CONTROL_TYPE 2 @@ -265,6 +272,8 @@ void __init acpi_s4_no_nvs(void); #define OSC_INVALID_REVISION_ERROR 8 #define OSC_CAPABILITIES_MASK_ERROR 16 +acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); + /* _OSC DW1 Definition (OS Support Fields) */ #define OSC_EXT_PCI_CONFIG_SUPPORT 1 #define OSC_ACTIVE_STATE_PWR_SUPPORT 2