Date: Wed, 24 Sep 2003 11:05:36 -0700 (PDT) From: John Baldwin <jhb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 38520 for review Message-ID: <200309241805.h8OI5alR099408@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=38520 Change 38520 by jhb@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,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200309241805.h8OI5alR099408>