Re: [PATCH 1/8] ACPI / PCI: Introduce acpi_pci_osc_control_query()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wednesday, August 04, 2010, Kenji Kaneshige wrote:
> (2010/08/04 5:58), Rafael J. Wysocki wrote:
> > On Tuesday, August 03, 2010, Rafael J. Wysocki wrote:
> >> On Tuesday, August 03, 2010, Kenji Kaneshige wrote:
> >>> (2010/08/03 6:53), Rafael J. Wysocki wrote:
> >>>> From: Rafael J. Wysocki<rjw@xxxxxxx>
> >>>
> >>> <snip.>
> >>>
> >>>> +	mutex_lock(&osc_lock);
> >>>> +	status = acpi_pci_query_osc(root, root->osc_support_set, ctrl_mask);
> >>>> +	mutex_unlock(&osc_lock);
> >>>> +
> >>>
> >>> One more comment here.
> >>>
> >>> I think we can skip acpi_pci_query_osc() if all of queried controls are
> >>> already granted to OS. Please see below
> >>>
> >>> 	mutex_lock(&osc_lock);
> >>> 	if ((root->osc_control_set&  *ctrl_mask) == *ctrl_mask) {
> >>> 		*ctrl_mask = root->osc_control_set;
> >>> 		goto out;
> >>> 	}
> >>> 	status = acpi_pci_query_osc(root, root->osc_support_set, ctrl_mask);
> >>> 	mutex_unlock(&osc_lock);
> >>> out:
> >>
> >> Well I guess you mean:
> >>
> >>   	mutex_lock(&osc_lock);
> >>   	if ((root->osc_control_set&  *ctrl_mask) != *ctrl_mask)
> >>   		status = acpi_pci_query_osc(root, root->osc_support_set, ctrl_mask);
> >>   	mutex_unlock(&osc_lock);
> >>
> >> Otherwise we would return with the mutex held. :-)
> >
> 
> Oops... sorry...
> 
> > Updated patch is appended, please tell me what you think.
> 
> Looks good to me. The below (in your updated patch) was what I wanted to mean
> 
> > +	mutex_lock(&osc_lock);
> > +	if ((*mask & root->osc_control_set) == *mask)
> > +		*mask = root->osc_control_set;
> > +	else
> > +		status = acpi_pci_query_osc(root, root->osc_support_set, mask);
> > +	mutex_unlock(&osc_lock);

OK

However, I think we can put the looping into that function so that the caller
doesn't have to loop.

The patch below implements that.

Thanks,
Rafael

---
From: Rafael J. Wysocki <rjw@xxxxxxx>
Subject: ACPI / PCI: Introduce acpi_pci_osc_control_query() (v3)

Introduce a function allowing the caller to obtain a mask of _OSC
control bits the BIOS will allow the kernel to control for a given
PCI root bridge.

Signed-off-by: Rafael J. Wysocki <rjw@xxxxxxx>
---
 drivers/acpi/pci_root.c |   71 +++++++++++++++++++++++++++++++++++++++++-------
 include/linux/acpi.h    |    1 
 2 files changed, 63 insertions(+), 9 deletions(-)

Index: linux-2.6/drivers/acpi/pci_root.c
===================================================================
--- linux-2.6.orig/drivers/acpi/pci_root.c
+++ linux-2.6/drivers/acpi/pci_root.c
@@ -225,21 +225,32 @@ static acpi_status acpi_pci_run_osc(acpi
 	return status;
 }
 
-static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 flags)
+static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root,
+					u32 support,
+					u32 *control)
 {
 	acpi_status status;
-	u32 support_set, result, capbuf[3];
+	u32 result, capbuf[3];
+
+	support &= OSC_PCI_SUPPORT_MASKS;
+	support |= root->osc_support_set;
 
-	/* do _OSC query for all possible controls */
-	support_set = root->osc_support_set | (flags & OSC_PCI_SUPPORT_MASKS);
 	capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
-	capbuf[OSC_SUPPORT_TYPE] = support_set;
-	capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS;
+	capbuf[OSC_SUPPORT_TYPE] = support;
+	if (control) {
+		*control &= OSC_PCI_CONTROL_MASKS;
+		capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set;
+	} else {
+		/* Run _OSC query for all possible controls. */
+		capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS;
+	}
 
 	status = acpi_pci_run_osc(root->device->handle, capbuf, &result);
 	if (ACPI_SUCCESS(status)) {
-		root->osc_support_set = support_set;
+		root->osc_support_set = support;
 		root->osc_control_qry = result;
+		if (control)
+			*control = result;
 		root->osc_queried = 1;
 	}
 	return status;
@@ -254,7 +265,7 @@ static acpi_status acpi_pci_osc_support(
 	if (ACPI_FAILURE(status))
 		return status;
 	mutex_lock(&osc_lock);
-	status = acpi_pci_query_osc(root, flags);
+	status = acpi_pci_query_osc(root, flags, NULL);
 	mutex_unlock(&osc_lock);
 	return status;
 }
@@ -363,6 +374,48 @@ out:
 }
 EXPORT_SYMBOL_GPL(acpi_get_pci_dev);
 
+ /**
+ * acpi_pci_osc_control_query - Get the _OSC bits the kernel can control.
+ * @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex).
+ * @mask: Mask of _OSC bits to query and the place to put the result into.
+ **/
+acpi_status acpi_pci_osc_control_query(acpi_handle handle, u32 *mask)
+{
+	struct acpi_pci_root *root;
+	acpi_handle tmp;
+	acpi_status status = AE_OK;
+	u32 ctrl = *mask;
+
+	if (!ctrl || !(ctrl & OSC_PCI_CONTROL_MASKS))
+		return AE_BAD_PARAMETER;
+
+	root = acpi_pci_find_root(handle);
+	if (!root)
+		return AE_NOT_EXIST;
+
+	status = acpi_get_handle(handle, "_OSC", &tmp);
+	if (ACPI_FAILURE(status))
+		return status;
+
+	mutex_lock(&osc_lock);
+
+	*mask |= root->osc_control_set;
+	if ((ctrl & root->osc_control_set) == ctrl)
+		goto out;
+
+	while (*mask && *mask != ctrl) {
+		ctrl = *mask;
+		status = acpi_pci_query_osc(root, root->osc_support_set, mask);
+		if (ACPI_FAILURE(status))
+			break;
+	}
+
+ out:
+	mutex_unlock(&osc_lock);
+
+	return status;
+}
+
 /**
  * acpi_pci_osc_control_set - commit requested control to Firmware
  * @handle: acpi_handle for the target ACPI object
@@ -396,7 +449,7 @@ acpi_status acpi_pci_osc_control_set(acp
 
 	/* Need to query controls first before requesting them */
 	if (!root->osc_queried) {
-		status = acpi_pci_query_osc(root, root->osc_support_set);
+		status = acpi_pci_query_osc(root, root->osc_support_set, NULL);
 		if (ACPI_FAILURE(status))
 			goto out;
 	}
Index: linux-2.6/include/linux/acpi.h
===================================================================
--- linux-2.6.orig/include/linux/acpi.h
+++ linux-2.6/include/linux/acpi.h
@@ -305,6 +305,7 @@ acpi_status acpi_run_osc(acpi_handle han
 				OSC_PCI_EXPRESS_AER_CONTROL |		\
 				OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL)
 
+extern acpi_status acpi_pci_osc_control_query(acpi_handle handle, u32 *mask);
 extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags);
 extern void acpi_early_init(void);
 
_______________________________________________
linux-pm mailing list
linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/linux-pm


[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux