PERFORCE change 38520 for review
John Baldwin
jhb at FreeBSD.org
Wed Sep 24 11:05:38 PDT 2003
http://perforce.freebsd.org/chv.cgi?CH=38520
Change 38520 by jhb at jhb_laptop on 2003/09/24 11:05:16
Update the ACPI PCI bus driver to set the ACPI device power state
"outside" of the PCI power state.
Affected files ...
.. //depot/projects/power/sys/dev/acpica/acpi_pci.c#2 edit
Differences ...
==== //depot/projects/power/sys/dev/acpica/acpi_pci.c#2 (text+ko) ====
@@ -65,11 +65,8 @@
static int acpi_pci_attach(device_t dev);
static int acpi_pci_read_ivar(device_t dev, device_t child, int which,
uintptr_t *result);
-#if 0
static int acpi_pci_set_powerstate_method(device_t dev, device_t child,
int state);
-static int acpi_pci_get_powerstate_method(device_t dev, device_t child);
-#endif
static ACPI_STATUS acpi_pci_save_handle(ACPI_HANDLE handle, UINT32 level,
void *context, void **status);
@@ -108,9 +105,8 @@
DEVMETHOD(pci_disable_busmaster, pci_disable_busmaster_method),
DEVMETHOD(pci_enable_io, pci_enable_io_method),
DEVMETHOD(pci_disable_io, pci_disable_io_method),
- /* XXX: We should override these two. */
DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method),
- DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method),
+ DEVMETHOD(pci_set_powerstate, acpi_pci_set_powerstate_method),
DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method),
{ 0, 0 }
@@ -140,24 +136,58 @@
return(pci_read_ivar(dev, child, which, result));
}
-#if 0
/*
* PCI power manangement
*/
static int
acpi_pci_set_powerstate_method(device_t dev, device_t child, int state)
{
- /* XXX: TODO */
- return (ENXIO);
-}
+ ACPI_STATUS status;
+ int acpi_state, old_state, error;
+
+ switch (state) {
+ case PCI_POWERSTATE_D0:
+ acpi_state = ACPI_STATE_D0;
+ break;
+ case PCI_POWERSTATE_D1:
+ acpi_state = ACPI_STATE_D1;
+ break;
+ case PCI_POWERSTATE_D2:
+ acpi_state = ACPI_STATE_D2;
+ break;
+ case PCI_POWERSTATE_D3:
+ acpi_state = ACPI_STATE_D3;
+ break;
+ default:
+ return (EINVAL);
+ }
-static int
-acpi_pci_get_powerstate_method(device_t dev, device_t child)
-{
- /* XXX: TODO */
- return (ENXIO);
+ /*
+ * We set the state using PCI Power Management outside of setting
+ * the ACPI state. This means that when powering down a device, we
+ * first shut it down using PCI, and then using ACPI, which lets ACPI
+ * try to power down any Power Resources that are now no longer used.
+ * When powering up a device, we let ACPI set the state first so that
+ * it can enable any needed Power Resources before changing the PCI
+ * power state.
+ */
+ old_state = pci_get_powerstate(child);
+ if (old_state < state) {
+ error = pci_set_powerstate_method(dev, child, state);
+ if (error)
+ return (error);
+ }
+ status = acpi_SetPowerState(acpi_get_handle(child), acpi_state);
+ if (ACPI_FAILURE(status))
+ device_printf(dev,
+ "Failed to set ACPI power state D%d on %s: %s\n",
+ acpi_state, device_get_nameunit(child),
+ AcpiFormatException(status));
+ if (state > old_state)
+ return (pci_set_powerstate_method(dev, child, state));
+ else
+ return (0);
}
-#endif
static ACPI_STATUS
acpi_pci_save_handle(ACPI_HANDLE handle, UINT32 level, void *context,
More information about the p4-projects
mailing list