diff mbox

PCI/ACPI: move _OSC code to pci_root.c

Message ID 4987DCAC.3010009@jp.fujitsu.com (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Kenji Kaneshige Feb. 3, 2009, 5:57 a.m. UTC
Move PCI _OSC management code from drivers/pci/pci-acpi.c to
drivers/acpi/pci_root.c. The benefits are

- We no longer need struct osc_data and its management code (contents
  are moved to struct acpi_pci_root). This simplify the code, and we
  no longer care about kmalloc() failure.

- We can make pci_acpi_osc_support() be a static function, which is
  called only from drivers/acpi/pci_root.c.

Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>

---
 drivers/acpi/pci_root.c  |  178 ++++++++++++++++++++++++++++++++++++++
 drivers/pci/pci-acpi.c   |  215 -----------------------------------------------
 include/linux/pci-acpi.h |    1 
 3 files changed, 176 insertions(+), 218 deletions(-)


--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Andrew Patterson Feb. 3, 2009, 11:20 p.m. UTC | #1
On Tue, 2009-02-03 at 14:57 +0900, Kenji Kaneshige wrote:
> Move PCI _OSC management code from drivers/pci/pci-acpi.c to
> drivers/acpi/pci_root.c. The benefits are
> 
> - We no longer need struct osc_data and its management code (contents
>   are moved to struct acpi_pci_root). This simplify the code, and we
>   no longer care about kmalloc() failure.
> 
> - We can make pci_acpi_osc_support() be a static function, which is
>   called only from drivers/acpi/pci_root.c.
> 
> Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
> 
> ---
>  drivers/acpi/pci_root.c  |  178 ++++++++++++++++++++++++++++++++++++++
>  drivers/pci/pci-acpi.c   |  215 -----------------------------------------------
>  include/linux/pci-acpi.h |    1 
>  3 files changed, 176 insertions(+), 218 deletions(-)
> 
> Index: 20090130/drivers/acpi/pci_root.c
> ===================================================================
> --- 20090130.orig/drivers/acpi/pci_root.c
> +++ 20090130/drivers/acpi/pci_root.c
> @@ -66,11 +66,18 @@ struct acpi_pci_root {
>  	struct acpi_device * device;
>  	struct acpi_pci_id id;
>  	struct pci_bus *bus;
> +
> +	u32 osc_support_set;	/* _OSC state of support bits */
> +	u32 osc_control_set;	/* _OSC state of control bits */
> +	u32 osc_control_qry;	/* the latest _OSC query result */
> +
> +	u32 osc_queried:1;	/* has _OSC control been queried? */
>  };
>  
>  static LIST_HEAD(acpi_pci_roots);
>  
>  static struct acpi_pci_driver *sub_driver;
> +static DEFINE_MUTEX(osc_lock);
>  
>  int acpi_pci_register_driver(struct acpi_pci_driver *driver)
>  {
> @@ -185,6 +192,173 @@ static void acpi_pci_bridge_scan(struct 
>  		}
>  }
>  
> +static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40,
> +			  0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
> +
> +static acpi_status acpi_pci_run_osc(acpi_handle handle,
> +				    const u32 *capbuf, u32 *retval)
> +{
> +	acpi_status status;
> +	struct acpi_object_list input;
> +	union acpi_object in_params[4];
> +	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
> +	union acpi_object *out_obj;
> +	u32 errors;
> +
> +	/* 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	= OSC_UUID;
> +	in_params[1].type 		= ACPI_TYPE_INTEGER;
> +	in_params[1].integer.value 	= 1;
> +	in_params[2].type 		= ACPI_TYPE_INTEGER;
> +	in_params[2].integer.value	= 3;
> +	in_params[3].type		= ACPI_TYPE_BUFFER;
> +	in_params[3].buffer.length 	= 12;
> +	in_params[3].buffer.pointer 	= (u8 *)capbuf;
> +
> +	status = acpi_evaluate_object(handle, "_OSC", &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) {
> +		printk(KERN_DEBUG "Evaluate _OSC returns 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 fails\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 (capbuf[OSC_QUERY_TYPE] & OSC_QUERY_ENABLE)
> +				goto out_success;
> +			printk(KERN_DEBUG "_OSC FW not grant req. control\n");

Can this be worded better? Perhaps "Firmware would not grant requested
_OSC control"? I know this is not your code, but maybe we can fix this
now.

> +			status = AE_SUPPORT;
> +			goto out_kfree;
> +		}
> +		status = AE_ERROR;
> +		goto out_kfree;
> +	}
> +out_success:
> +	*retval = *((u32 *)(out_obj->buffer.pointer + 8));
> +	status = AE_OK;
> +
> +out_kfree:
> +	kfree(output.pointer);
> +	return status;
> +}
> +
> +static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 flags)
> +{
> +	acpi_status status;
> +	u32 support_set, result, capbuf[3];
> +
> +	/* do _OSC query for all possible controls */
> +	support_set = root->osc_support_set | (flags & OSC_SUPPORT_MASKS);
> +	capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
> +	capbuf[OSC_SUPPORT_TYPE] = support_set;
> +	capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
> +
> +	status = acpi_pci_run_osc(root->device->handle, capbuf, &result);
> +	if (ACPI_SUCCESS(status)) {
> +		root->osc_support_set = support_set;
> +		root->osc_control_qry = result;
> +		root->osc_queried = 1;
> +	}
> +	return status;
> +}
> +
> +static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags)
> +{
> +	acpi_status status;
> +	acpi_handle tmp;
> +
> +	status = acpi_get_handle(root->device->handle, "_OSC", &tmp);
> +	if (ACPI_FAILURE(status))
> +		return status;
> +	mutex_lock(&osc_lock);
> +	status = acpi_pci_query_osc(root, flags);
> +	mutex_unlock(&osc_lock);
> +	return status;
> +}
> +
> +static struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle)
> +{
> +	struct acpi_pci_root *root;
> +	list_for_each_entry(root, &acpi_pci_roots, node) {
> +		if (root->device->handle == handle)
> +			return root;
> +	}
> +	return NULL;
> +}
> +
> +/**
> + * pci_osc_control_set - commit requested control to Firmware

Should this function be renamed to acpi_pci_osc_control_set?

> + * @handle: acpi_handle for the target ACPI object
> + * @flags: driver's requested control bits
> + *
> + * Attempt to take control from Firmware on requested control bits.
> + **/
> +acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
> +{

> +	acpi_status status;
> +	u32 control_req, result, capbuf[3];
> +	acpi_handle tmp;
> +	struct acpi_pci_root *root;
> +
> +	status = acpi_get_handle(handle, "_OSC", &tmp);
> +	if (ACPI_FAILURE(status))
> +		return status;
> +
> +	control_req = (flag

> s & OSC_CONTROL_MASKS);
> +	if (!control_req)
> +		return AE_TYPE;
> +
> +	root = acpi_pci_find_root(handle);
> +	if (!root)
> +		return AE_NOT_EXIST;
> +
> +	mutex_lock(&osc_lock);
> +	/* No need to evaluate _OSC if the control was already granted. */
> +	if ((root->osc_control_set & control_req) == control_req)
> +		goto out;
> +
> +	/* Need to query controls first before requesting them */
> +	if (!root->osc_queried) {
> +		status = acpi_pci_query_osc(root, root->osc_support_set);
> +		if (ACPI_FAILURE(status))
> +			goto out;
> +	}
> +	if ((root->osc_control_qry & control_req) != control_req) {
> +		printk(KERN

> _DEBUG "_OSC FW not grant req. control\n");

See above.

> +		status = AE_SUPPORT;
> +		goto out;
> +	}
> +
> +	capbuf[OSC_QUERY_TYPE] = 0;
> +	capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set;
> +	capbuf[OSC_CONTROL_TYPE] = root->osc_control_set | control_req;
> +	status = acpi_pci_run_osc(handle, capbuf, &result);
> +	if (ACPI_SUCCESS(status))
> +		root->osc_control_set = result;
> +out:
> +	mutex_unlock(&osc_lock);
> +	return status;
> +}
> +EXPORT_SYMBOL(pci_osc_control_set);
> +
>  static int __devinit acpi_pci_root_add(struct acpi_device *device)
>  {
>  	int result = 0;
> @@ -217,7 +391,7 @@ static int __devinit acpi_pci_root_add(s
>  	 * PCI domains, so we indicate this in _OSC support capabilities.
>  	 */
>  	flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
> -	pci_acpi_osc_support(device->handle, flags);
> +	acpi_pci_osc_support(root, flags);
>  
>  	/* 
>  	 * Segment
> @@ -353,7 +527,7 @@ static int __devinit acpi_pci_root_add(s
>  	if (pci_msi_enabled())
>  		flags |= OS

> C_MSI_SUPPORT;
>  	if (flags != base_flags)
> -		pci_acpi_osc_support(device->handle, flags);
> +		acpi_pci_osc_support(root, flags);
>  
>        end:
>  	if (result) {
> Index: 20090130/drivers/pci/pci-acpi.c
> ===================================================================
> --- 20090130.orig/drivers/pci/pci-acpi.c
> +++ 20090130/drivers/pci/pci-acpi.c
> @@ -18,221 +18,6 @@
>  #include <linux/pci-acpi.h>
>  #include "pci.h"
>  
> -struct acpi_osc_data {
> -	acpi_handle handle;
> -	u32 support_set;
> -	u32 control_set;
> -	u32 control_query;
> -	int is_queried;
> -	struct list_head sibiling;
> -};
> -static LIST_HEAD(acpi_osc_data_list);
> -
> -struct acpi_osc_args {
> -	u32 capbuf[3];
> -};
> -
> -static DEFINE_MUTEX(pci_acpi_lock);
> -
> -static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle)
> -{
> -	struct acpi_osc_data *data;
> -
> -	list_for_each_entry(data, &acpi_osc_data_list, sibiling) {
> -		if (data->handle == handle)
> -			return data;
> -	}
> -	data = kzalloc(sizeof(*data), GFP_KERNEL);
> -	if (!data)
> -		return NULL;
> -	INIT_LIST_HEAD(&data->sibiling);
> -	data->handle = handle;
> -	list_add_tail(&data->sibiling, &acpi_osc_data_list);
> -	return data;
> -}
> -
> -static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40,
> -			  0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
> -
> -static acpi_status acpi_run_osc(acpi_handle handle,
> -				struct acpi_osc_args *osc_args, u32 *retval)
> -{
> -	acpi_status status;
> -	struct acpi_object_list input;
> -	union acpi_object in_params[4];
> -	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
> -	union acpi_object *out_obj;
> -	u32 errors, flags = osc_args->capbuf[OSC_QUERY_TYPE];
> -
> -	/* 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	= OSC_UUID;
> -	in_params[1].type 		= ACPI_TYPE_INTEGER;
> -	in_params[1].integer.value 	= 1;
> -	in_params[2].type 		= ACPI_TYPE_INTEGER;
> -	in_params[2].integer.value	= 3;
> -	in_params[3].type		= ACPI_TYPE_BUFFER;
> -	in_params[3].buffer.length 	= 12;
> -	in_params[3].buffer.pointer 	= (u8 *)osc_args->capbuf;
> -
> -	status = acpi_evaluate_object(handle, "_OSC", &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) {
> -		printk(KERN_DEBUG "Evaluate _OSC returns 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 fails\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 (flags & OSC_QUERY_ENABLE)
> -				goto out_success;
> -			printk(KERN_DEBUG "_OSC FW not grant req. control\n");
> -			status = AE_SUPPORT;
> -			goto out_kfree;
> -		}
> -		status = AE_ERROR;
> -		goto out_kfree;
> -	}
> -out_success:
> -	*retval = *((u32 *)(out_obj->buffer.pointer + 8));
> -	status = AE_OK;
> -
> -out_kfree:
> -	kfree(output.pointer);
> -	return status;
> -}
> -
> -static acpi_status __acpi_

> query_osc(u32 flags, struct acpi_osc_data *osc_data)
> -{
> -	acpi_status status;
> -	u32 support_set, result;
> -	struct acpi_osc_args osc_args;
> -
> -	/* do _OSC query for all possible controls */
> -	support_set = osc_data->support_set | (flags & OSC_SUPPORT_MASKS);
> -	osc_args.capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
> -	osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set;
> -	osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
> -
> -	status = acpi_run_osc(osc_data->handle, &osc_args, &result);
> -	if (ACPI_SUCCESS(status)) {
> -		osc_data->support_set = support_set;
> -		osc_data->control_query = result;
> -		osc_data->is_queried = 1;
> -	}
> -
> -	return status;
> -}
> -
> -/*
> - * pci_acpi_osc_support: Invoke _OSC indicating support for the given feature
> - * @flags: Bitmask of flags to support
> - *
> - * See the ACPI spec for the definition of the flags
> - */
> -int pci_acpi_osc_support(acpi_handle handle, u32 flags)
> -{
> -	acpi_status status;
> -	acpi_handle tmp;
> -	struct acpi_osc_data *osc_data;
> -	int rc = 0;
> -
> -	status = acpi_get_handle(handle, "_OSC", &tmp);
> -	if (ACPI_FAILURE(status))
> -		return -ENOTTY;
> -
> -	mutex_lock(&pci_acpi_lock);
> -	osc_data = acpi_get_osc_data(handle);
> -	if (!osc_data) {
> -		printk(KERN_ERR "acpi osc data array is full\n");
> -		rc = -ENOMEM;
> -		goto out;
> -	}
> -
> -	__acpi_query_osc(flags, osc_data);
> -out:
> -	mutex_unlock(&pci_acpi_lock);
> -	return rc;
> -}
> -
> -/**
> - * pci_osc_control_set - commit requested control to Firmware
> - * @handle: acpi_handle for the target ACPI object
> - * @flags: driver's requested control bits
> - *
> - * Attempt to take control from Firmware on requested control bits.
> - **/
> -acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
> -{
> -	acpi_status status;
> -	u32 control_req, control_set, result;
> -	acpi_handle tmp;
> -	struct acpi_osc_data *osc_data;
> -	struct acpi_osc_args osc_args;
> -
> -	status = acpi_get_handle(handle, "_OSC", &tmp);
> -	if (ACPI_FAILURE(status))
> -		return status;
> -
> -	mutex_lock(&pci_acpi_lock);
> -	osc_data = acpi_get_osc_data(handle);
> -	if (!osc_data) {
> -		printk(KERN_ERR "acpi osc data array is full\n");
> -		status = AE_ERROR;
> -		goto out;
> -	}
> -
> -	control_req = (flags & OSC_CONTROL_MASKS);
> -	if (!control_req) {
> -		status = AE_TYPE;
> -		goto out;
> -	}
> -
> -	/* No need to evaluate _OSC if the control was already granted. */
> -	if ((osc_data->control_set & control_req) == control_req)
> -		goto out;
> -
> -	if (!osc_data->is_queried) {
> -		status = __acpi_query_osc(osc_data->support_set, osc_data);
> -		if (ACPI_FAILURE(status))
> -			goto out;
> -	}
> -
> -	if ((osc_data->control_query & control_req) != control_req) {
> -		status = AE_SUPPORT;
> -		goto out;
> -	}
> -
> -	control_set = osc_data->control_set | control_req;
> -	osc_args.capbuf[OSC_QUERY_TYPE] = 0;
> -	osc_args.capbuf[OSC_SUPPORT_TYPE] = osc_data->support_set;
> -	osc_args.capbuf[OSC_CONTROL_TYPE] = control_set;
> -	status = acpi_run_osc(handle, &osc_args, &result);
> -	if (ACPI_SUCCESS(status))
> -		osc_data->control_set = result;
> -out:
> -	mutex_unlock(&pci_acpi_lock);
> -	return status;
> -}
> -EXPORT_SYMBOL(pci_osc_control_set);
> -
>  /*
>   * _SxD returns the D-state with the highest power
>   * (lowest D-state number) supported in the S-state "x".
> Index: 20090130/include/linux/pci-acpi.h
> ===================================================================
> --- 20090130.orig/include/linux/pci-acpi.h
> +++ 20090130/include/linux/pci-acpi.h
> @@ -50,7 +50,6 @@
>  
>  #ifdef CONFIG_ACPI
>  extern acpi_status pci_osc_control_set(acpi_handle handle, u32 flags);
> -int pci_acpi_osc_support(acpi_handle handle, u32 flags);
>  static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
>  {
>  	/* Find root host bridge */
Alexander Chiang Feb. 4, 2009, 12:33 a.m. UTC | #2
* Andrew Patterson <andrew.patterson@hp.com>:
> On Tue, 2009-02-03 at 14:57 +0900, Kenji Kaneshige wrote:
> > +	/* 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 fails\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 (capbuf[OSC_QUERY_TYPE] & OSC_QUERY_ENABLE)
> > +				goto out_success;
> > +			printk(KERN_DEBUG "_OSC FW not grant req. control\n");
> 
> Can this be worded better? Perhaps "Firmware would not grant requested
> _OSC control"? I know this is not your code, but maybe we can fix this
> now.

Trying not to bike shed, but if you're going to change the
wording, I'd prefer to see "Firmware did not..." vs "Firmware
would not..."

Thanks.

/ac

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kenji Kaneshige Feb. 4, 2009, 6:20 a.m. UTC | #3
Hi,

Thank you for comments.

Andrew Patterson wrote:
> On Tue, 2009-02-03 at 14:57 +0900, Kenji Kaneshige wrote:
(snip.)
>> +		if (errors & OSC_CAPABILITIES_MASK_ERROR) {
>> +			if (capbuf[OSC_QUERY_TYPE] & OSC_QUERY_ENABLE)
>> +				goto out_success;
>> +			printk(KERN_DEBUG "_OSC FW not grant req. control\n");
> 
> Can this be worded better? Perhaps "Firmware would not grant requested
> _OSC control"? I know this is not your code, but maybe we can fix this
> now.
> 

Ok, I'll fix it.

>> +
>> +/**
>> + * pci_osc_control_set - commit requested control to Firmware
> 
> Should this function be renamed to acpi_pci_osc_control_set?
> 

I didn't do it because pci_osc_control_set() is exported
(EXPORT_SYMBOL(pci_osc_control_set)). And for the same reason,
I didn't move _OSC related code from include/linux/pci-acpi.h
to include/linux/acpi.h (or somewhere).
But I guess there is no user outside kernel source. So I will
rename the function as you pointed out.

>> +	if ((root->osc_control_qry & control_req) != control_req) {
>> +		printk(KERN
> 
>> _DEBUG "_OSC FW not grant req. control\n");
> 
> See above.
> 

I'll fix it.

Thanks,
Kenji Kaneshige


--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

Index: 20090130/drivers/acpi/pci_root.c
===================================================================
--- 20090130.orig/drivers/acpi/pci_root.c
+++ 20090130/drivers/acpi/pci_root.c
@@ -66,11 +66,18 @@  struct acpi_pci_root {
 	struct acpi_device * device;
 	struct acpi_pci_id id;
 	struct pci_bus *bus;
+
+	u32 osc_support_set;	/* _OSC state of support bits */
+	u32 osc_control_set;	/* _OSC state of control bits */
+	u32 osc_control_qry;	/* the latest _OSC query result */
+
+	u32 osc_queried:1;	/* has _OSC control been queried? */
 };
 
 static LIST_HEAD(acpi_pci_roots);
 
 static struct acpi_pci_driver *sub_driver;
+static DEFINE_MUTEX(osc_lock);
 
 int acpi_pci_register_driver(struct acpi_pci_driver *driver)
 {
@@ -185,6 +192,173 @@  static void acpi_pci_bridge_scan(struct 
 		}
 }
 
+static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40,
+			  0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
+
+static acpi_status acpi_pci_run_osc(acpi_handle handle,
+				    const u32 *capbuf, u32 *retval)
+{
+	acpi_status status;
+	struct acpi_object_list input;
+	union acpi_object in_params[4];
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object *out_obj;
+	u32 errors;
+
+	/* 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	= OSC_UUID;
+	in_params[1].type 		= ACPI_TYPE_INTEGER;
+	in_params[1].integer.value 	= 1;
+	in_params[2].type 		= ACPI_TYPE_INTEGER;
+	in_params[2].integer.value	= 3;
+	in_params[3].type		= ACPI_TYPE_BUFFER;
+	in_params[3].buffer.length 	= 12;
+	in_params[3].buffer.pointer 	= (u8 *)capbuf;
+
+	status = acpi_evaluate_object(handle, "_OSC", &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) {
+		printk(KERN_DEBUG "Evaluate _OSC returns 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 fails\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 (capbuf[OSC_QUERY_TYPE] & OSC_QUERY_ENABLE)
+				goto out_success;
+			printk(KERN_DEBUG "_OSC FW not grant req. control\n");
+			status = AE_SUPPORT;
+			goto out_kfree;
+		}
+		status = AE_ERROR;
+		goto out_kfree;
+	}
+out_success:
+	*retval = *((u32 *)(out_obj->buffer.pointer + 8));
+	status = AE_OK;
+
+out_kfree:
+	kfree(output.pointer);
+	return status;
+}
+
+static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 flags)
+{
+	acpi_status status;
+	u32 support_set, result, capbuf[3];
+
+	/* do _OSC query for all possible controls */
+	support_set = root->osc_support_set | (flags & OSC_SUPPORT_MASKS);
+	capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
+	capbuf[OSC_SUPPORT_TYPE] = support_set;
+	capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
+
+	status = acpi_pci_run_osc(root->device->handle, capbuf, &result);
+	if (ACPI_SUCCESS(status)) {
+		root->osc_support_set = support_set;
+		root->osc_control_qry = result;
+		root->osc_queried = 1;
+	}
+	return status;
+}
+
+static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags)
+{
+	acpi_status status;
+	acpi_handle tmp;
+
+	status = acpi_get_handle(root->device->handle, "_OSC", &tmp);
+	if (ACPI_FAILURE(status))
+		return status;
+	mutex_lock(&osc_lock);
+	status = acpi_pci_query_osc(root, flags);
+	mutex_unlock(&osc_lock);
+	return status;
+}
+
+static struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle)
+{
+	struct acpi_pci_root *root;
+	list_for_each_entry(root, &acpi_pci_roots, node) {
+		if (root->device->handle == handle)
+			return root;
+	}
+	return NULL;
+}
+
+/**
+ * pci_osc_control_set - commit requested control to Firmware
+ * @handle: acpi_handle for the target ACPI object
+ * @flags: driver's requested control bits
+ *
+ * Attempt to take control from Firmware on requested control bits.
+ **/
+acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
+{
+	acpi_status status;
+	u32 control_req, result, capbuf[3];
+	acpi_handle tmp;
+	struct acpi_pci_root *root;
+
+	status = acpi_get_handle(handle, "_OSC", &tmp);
+	if (ACPI_FAILURE(status))
+		return status;
+
+	control_req = (flags & OSC_CONTROL_MASKS);
+	if (!control_req)
+		return AE_TYPE;
+
+	root = acpi_pci_find_root(handle);
+	if (!root)
+		return AE_NOT_EXIST;
+
+	mutex_lock(&osc_lock);
+	/* No need to evaluate _OSC if the control was already granted. */
+	if ((root->osc_control_set & control_req) == control_req)
+		goto out;
+
+	/* Need to query controls first before requesting them */
+	if (!root->osc_queried) {
+		status = acpi_pci_query_osc(root, root->osc_support_set);
+		if (ACPI_FAILURE(status))
+			goto out;
+	}
+	if ((root->osc_control_qry & control_req) != control_req) {
+		printk(KERN_DEBUG "_OSC FW not grant req. control\n");
+		status = AE_SUPPORT;
+		goto out;
+	}
+
+	capbuf[OSC_QUERY_TYPE] = 0;
+	capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set;
+	capbuf[OSC_CONTROL_TYPE] = root->osc_control_set | control_req;
+	status = acpi_pci_run_osc(handle, capbuf, &result);
+	if (ACPI_SUCCESS(status))
+		root->osc_control_set = result;
+out:
+	mutex_unlock(&osc_lock);
+	return status;
+}
+EXPORT_SYMBOL(pci_osc_control_set);
+
 static int __devinit acpi_pci_root_add(struct acpi_device *device)
 {
 	int result = 0;
@@ -217,7 +391,7 @@  static int __devinit acpi_pci_root_add(s
 	 * PCI domains, so we indicate this in _OSC support capabilities.
 	 */
 	flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
-	pci_acpi_osc_support(device->handle, flags);
+	acpi_pci_osc_support(root, flags);
 
 	/* 
 	 * Segment
@@ -353,7 +527,7 @@  static int __devinit acpi_pci_root_add(s
 	if (pci_msi_enabled())
 		flags |= OSC_MSI_SUPPORT;
 	if (flags != base_flags)
-		pci_acpi_osc_support(device->handle, flags);
+		acpi_pci_osc_support(root, flags);
 
       end:
 	if (result) {
Index: 20090130/drivers/pci/pci-acpi.c
===================================================================
--- 20090130.orig/drivers/pci/pci-acpi.c
+++ 20090130/drivers/pci/pci-acpi.c
@@ -18,221 +18,6 @@ 
 #include <linux/pci-acpi.h>
 #include "pci.h"
 
-struct acpi_osc_data {
-	acpi_handle handle;
-	u32 support_set;
-	u32 control_set;
-	u32 control_query;
-	int is_queried;
-	struct list_head sibiling;
-};
-static LIST_HEAD(acpi_osc_data_list);
-
-struct acpi_osc_args {
-	u32 capbuf[3];
-};
-
-static DEFINE_MUTEX(pci_acpi_lock);
-
-static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle)
-{
-	struct acpi_osc_data *data;
-
-	list_for_each_entry(data, &acpi_osc_data_list, sibiling) {
-		if (data->handle == handle)
-			return data;
-	}
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data)
-		return NULL;
-	INIT_LIST_HEAD(&data->sibiling);
-	data->handle = handle;
-	list_add_tail(&data->sibiling, &acpi_osc_data_list);
-	return data;
-}
-
-static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40,
-			  0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
-
-static acpi_status acpi_run_osc(acpi_handle handle,
-				struct acpi_osc_args *osc_args, u32 *retval)
-{
-	acpi_status status;
-	struct acpi_object_list input;
-	union acpi_object in_params[4];
-	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
-	union acpi_object *out_obj;
-	u32 errors, flags = osc_args->capbuf[OSC_QUERY_TYPE];
-
-	/* 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	= OSC_UUID;
-	in_params[1].type 		= ACPI_TYPE_INTEGER;
-	in_params[1].integer.value 	= 1;
-	in_params[2].type 		= ACPI_TYPE_INTEGER;
-	in_params[2].integer.value	= 3;
-	in_params[3].type		= ACPI_TYPE_BUFFER;
-	in_params[3].buffer.length 	= 12;
-	in_params[3].buffer.pointer 	= (u8 *)osc_args->capbuf;
-
-	status = acpi_evaluate_object(handle, "_OSC", &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) {
-		printk(KERN_DEBUG "Evaluate _OSC returns 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 fails\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 (flags & OSC_QUERY_ENABLE)
-				goto out_success;
-			printk(KERN_DEBUG "_OSC FW not grant req. control\n");
-			status = AE_SUPPORT;
-			goto out_kfree;
-		}
-		status = AE_ERROR;
-		goto out_kfree;
-	}
-out_success:
-	*retval = *((u32 *)(out_obj->buffer.pointer + 8));
-	status = AE_OK;
-
-out_kfree:
-	kfree(output.pointer);
-	return status;
-}
-
-static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data)
-{
-	acpi_status status;
-	u32 support_set, result;
-	struct acpi_osc_args osc_args;
-
-	/* do _OSC query for all possible controls */
-	support_set = osc_data->support_set | (flags & OSC_SUPPORT_MASKS);
-	osc_args.capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
-	osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set;
-	osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
-
-	status = acpi_run_osc(osc_data->handle, &osc_args, &result);
-	if (ACPI_SUCCESS(status)) {
-		osc_data->support_set = support_set;
-		osc_data->control_query = result;
-		osc_data->is_queried = 1;
-	}
-
-	return status;
-}
-
-/*
- * pci_acpi_osc_support: Invoke _OSC indicating support for the given feature
- * @flags: Bitmask of flags to support
- *
- * See the ACPI spec for the definition of the flags
- */
-int pci_acpi_osc_support(acpi_handle handle, u32 flags)
-{
-	acpi_status status;
-	acpi_handle tmp;
-	struct acpi_osc_data *osc_data;
-	int rc = 0;
-
-	status = acpi_get_handle(handle, "_OSC", &tmp);
-	if (ACPI_FAILURE(status))
-		return -ENOTTY;
-
-	mutex_lock(&pci_acpi_lock);
-	osc_data = acpi_get_osc_data(handle);
-	if (!osc_data) {
-		printk(KERN_ERR "acpi osc data array is full\n");
-		rc = -ENOMEM;
-		goto out;
-	}
-
-	__acpi_query_osc(flags, osc_data);
-out:
-	mutex_unlock(&pci_acpi_lock);
-	return rc;
-}
-
-/**
- * pci_osc_control_set - commit requested control to Firmware
- * @handle: acpi_handle for the target ACPI object
- * @flags: driver's requested control bits
- *
- * Attempt to take control from Firmware on requested control bits.
- **/
-acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
-{
-	acpi_status status;
-	u32 control_req, control_set, result;
-	acpi_handle tmp;
-	struct acpi_osc_data *osc_data;
-	struct acpi_osc_args osc_args;
-
-	status = acpi_get_handle(handle, "_OSC", &tmp);
-	if (ACPI_FAILURE(status))
-		return status;
-
-	mutex_lock(&pci_acpi_lock);
-	osc_data = acpi_get_osc_data(handle);
-	if (!osc_data) {
-		printk(KERN_ERR "acpi osc data array is full\n");
-		status = AE_ERROR;
-		goto out;
-	}
-
-	control_req = (flags & OSC_CONTROL_MASKS);
-	if (!control_req) {
-		status = AE_TYPE;
-		goto out;
-	}
-
-	/* No need to evaluate _OSC if the control was already granted. */
-	if ((osc_data->control_set & control_req) == control_req)
-		goto out;
-
-	if (!osc_data->is_queried) {
-		status = __acpi_query_osc(osc_data->support_set, osc_data);
-		if (ACPI_FAILURE(status))
-			goto out;
-	}
-
-	if ((osc_data->control_query & control_req) != control_req) {
-		status = AE_SUPPORT;
-		goto out;
-	}
-
-	control_set = osc_data->control_set | control_req;
-	osc_args.capbuf[OSC_QUERY_TYPE] = 0;
-	osc_args.capbuf[OSC_SUPPORT_TYPE] = osc_data->support_set;
-	osc_args.capbuf[OSC_CONTROL_TYPE] = control_set;
-	status = acpi_run_osc(handle, &osc_args, &result);
-	if (ACPI_SUCCESS(status))
-		osc_data->control_set = result;
-out:
-	mutex_unlock(&pci_acpi_lock);
-	return status;
-}
-EXPORT_SYMBOL(pci_osc_control_set);
-
 /*
  * _SxD returns the D-state with the highest power
  * (lowest D-state number) supported in the S-state "x".
Index: 20090130/include/linux/pci-acpi.h
===================================================================
--- 20090130.orig/include/linux/pci-acpi.h
+++ 20090130/include/linux/pci-acpi.h
@@ -50,7 +50,6 @@ 
 
 #ifdef CONFIG_ACPI
 extern acpi_status pci_osc_control_set(acpi_handle handle, u32 flags);
-int pci_acpi_osc_support(acpi_handle handle, u32 flags);
 static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
 {
 	/* Find root host bridge */