On Thursday, August 05, 2010, Rafael J. Wysocki wrote: > 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. The patch below is incorrect, sorry. Please disregard it. 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 > > -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html