From owner-svn-src-all@FreeBSD.ORG Tue Oct 19 19:53:07 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 056D51065670; Tue, 19 Oct 2010 19:53:07 +0000 (UTC) (envelope-from jkim@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E6F7A8FC0C; Tue, 19 Oct 2010 19:53:06 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o9JJr6DQ025167; Tue, 19 Oct 2010 19:53:06 GMT (envelope-from jkim@svn.freebsd.org) Received: (from jkim@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o9JJr6Fr025163; Tue, 19 Oct 2010 19:53:06 GMT (envelope-from jkim@svn.freebsd.org) Message-Id: <201010191953.o9JJr6Fr025163@svn.freebsd.org> From: Jung-uk Kim Date: Tue, 19 Oct 2010 19:53:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r214072 - head/sys/dev/acpica X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 Oct 2010 19:53:07 -0000 Author: jkim Date: Tue Oct 19 19:53:06 2010 New Revision: 214072 URL: http://svn.freebsd.org/changeset/base/214072 Log: Remove PCI_SET_POWERSTATE method from acpi.c and eradicate all PCI-specific knowledges from the file. All PCI devices enumerated in ACPI tree must use correct one from acpi_pci.c any way. Reduce duplicate codes as we did for pci.c in r213905. Do not return ESRCH from PCIB_POWER_FOR_SLEEP method. When the method is not found, just return zero without modifying the given default value as it is completely optional. As a side effect, the return state must not be NULL. Note there is actually no functional change by removing ESRCH because acpi_pcib_power_for_sleep() always returns zero. Adjust debugging messages and add new ones under bootverbose to help debugging device power state related issues. Reviewed by: jhb, imp (earlier versions) Modified: head/sys/dev/acpica/acpi.c head/sys/dev/acpica/acpi_if.m head/sys/dev/acpica/acpi_pci.c Modified: head/sys/dev/acpica/acpi.c ============================================================================== --- head/sys/dev/acpica/acpi.c Tue Oct 19 19:44:05 2010 (r214071) +++ head/sys/dev/acpica/acpi.c Tue Oct 19 19:53:06 2010 (r214072) @@ -66,10 +66,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include "pci_if.h" -#include -#include - #include MALLOC_DEFINE(M_ACPIDEV, "acpidev", "ACPI devices"); @@ -133,8 +129,7 @@ static ACPI_STATUS acpi_device_scan_cb(A void *context, void **retval); static ACPI_STATUS acpi_device_scan_children(device_t bus, device_t dev, int max_depth, acpi_scan_cb_t user_fn, void *arg); -static int acpi_set_powerstate_method(device_t bus, device_t child, - int state); +static int acpi_set_powerstate(device_t child, int state); static int acpi_isa_pnp_probe(device_t bus, device_t child, struct isa_pnp_id *ids); static void acpi_probe_children(device_t bus); @@ -205,9 +200,6 @@ static device_method_t acpi_methods[] = DEVMETHOD(acpi_pwr_for_sleep, acpi_device_pwr_for_sleep), DEVMETHOD(acpi_scan_children, acpi_device_scan_children), - /* PCI emulation */ - DEVMETHOD(pci_set_powerstate, acpi_set_powerstate_method), - /* ISA emulation */ DEVMETHOD(isa_pnp_probe, acpi_isa_pnp_probe), @@ -668,45 +660,46 @@ acpi_attach(device_t dev) return_VALUE (error); } +static void +acpi_set_power_children(device_t dev, int state) +{ + device_t child, parent; + device_t *devlist; + struct pci_devinfo *dinfo; + int dstate, i, numdevs; + + if (!acpi_do_powerstate) + return; + + if (device_get_children(dev, &devlist, &numdevs) != 0) + return; + + /* + * Retrieve and set D-state for the sleep state if _SxD is present. + * Skip children who aren't attached since they are handled separately. + */ + parent = device_get_parent(dev); + for (i = 0; i < numdevs; i++) { + child = devlist[i]; + dinfo = device_get_ivars(child); + dstate = state; + if (device_is_attached(child) && + acpi_device_pwr_for_sleep(parent, dev, &dstate) == 0) + acpi_set_powerstate(child, dstate); + } + free(devlist, M_TEMP); +} + static int acpi_suspend(device_t dev) { - device_t child, *devlist; - int error, i, numdevs, pstate; + int error; GIANT_REQUIRED; - /* First give child devices a chance to suspend. */ error = bus_generic_suspend(dev); - if (error) - return (error); - - /* - * Now, set them into the appropriate power state, usually D3. If the - * device has an _SxD method for the next sleep state, use that power - * state instead. - */ - error = device_get_children(dev, &devlist, &numdevs); - if (error) - return (error); - for (i = 0; i < numdevs; i++) { - /* If the device is not attached, we've powered it down elsewhere. */ - child = devlist[i]; - if (!device_is_attached(child)) - continue; - - /* - * Default to D3 for all sleep states. The _SxD method is optional - * so set the powerstate even if it's absent. - */ - pstate = PCI_POWERSTATE_D3; - error = acpi_device_pwr_for_sleep(device_get_parent(child), - child, &pstate); - if ((error == 0 || error == ESRCH) && acpi_do_powerstate) - pci_set_powerstate(child, pstate); - } - free(devlist, M_TEMP); - error = 0; + if (error == 0) + acpi_set_power_children(dev, ACPI_STATE_D3); return (error); } @@ -714,28 +707,10 @@ acpi_suspend(device_t dev) static int acpi_resume(device_t dev) { - ACPI_HANDLE handle; - int i, numdevs, error; - device_t child, *devlist; GIANT_REQUIRED; - /* - * Put all devices in D0 before resuming them. Call _S0D on each one - * since some systems expect this. - */ - error = device_get_children(dev, &devlist, &numdevs); - if (error) - return (error); - for (i = 0; i < numdevs; i++) { - child = devlist[i]; - handle = acpi_get_handle(child); - if (handle) - AcpiEvaluateObject(handle, "_S0D", NULL, NULL); - if (device_is_attached(child) && acpi_do_powerstate) - pci_set_powerstate(child, PCI_POWERSTATE_D0); - } - free(devlist, M_TEMP); + acpi_set_power_children(dev, ACPI_STATE_D0); return (bus_generic_resume(dev)); } @@ -811,7 +786,7 @@ static void acpi_probe_nomatch(device_t bus, device_t child) { #ifdef ACPI_ENABLE_POWERDOWN_NODRIVER - pci_set_powerstate(child, PCI_POWERSTATE_D3); + acpi_set_powerstate(child, ACPI_STATE_D3); #endif } @@ -833,9 +808,9 @@ acpi_driver_added(device_t dev, driver_t child = devlist[i]; if (device_get_state(child) == DS_NOTPRESENT) { #ifdef ACPI_ENABLE_POWERDOWN_NODRIVER - pci_set_powerstate(child, PCI_POWERSTATE_D0); + acpi_set_powerstate(child, ACPI_STATE_D0); if (device_probe_and_attach(child) != 0) - pci_set_powerstate(child, PCI_POWERSTATE_D3); + acpi_set_powerstate(child, ACPI_STATE_D3); #else device_probe_and_attach(child); #endif @@ -1401,9 +1376,7 @@ acpi_device_pwr_for_sleep(device_t bus, ACPI_HANDLE handle; ACPI_STATUS status; char sxd[8]; - int error; - sc = device_get_softc(bus); handle = acpi_get_handle(dev); /* @@ -1412,7 +1385,7 @@ acpi_device_pwr_for_sleep(device_t bus, * set to D3 and it appears that such legacy devices may * need special handling in their drivers. */ - if (handle == NULL || + if (dstate == NULL || handle == NULL || acpi_MatchHid(handle, "PNP0500") || acpi_MatchHid(handle, "PNP0501") || acpi_MatchHid(handle, "PNP0502") || @@ -1421,28 +1394,19 @@ acpi_device_pwr_for_sleep(device_t bus, return (ENXIO); /* - * Override next state with the value from _SxD, if present. If no - * dstate argument was provided, don't fetch the return value. + * Override next state with the value from _SxD, if present. + * Note illegal _S0D is evaluated because some systems expect this. */ + sc = device_get_softc(bus); snprintf(sxd, sizeof(sxd), "_S%dD", sc->acpi_sstate); - if (dstate) - status = acpi_GetInteger(handle, sxd, dstate); - else - status = AcpiEvaluateObject(handle, sxd, NULL, NULL); - - switch (status) { - case AE_OK: - error = 0; - break; - case AE_NOT_FOUND: - error = ESRCH; - break; - default: - error = ENXIO; - break; + status = acpi_GetInteger(handle, sxd, dstate); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + device_printf(dev, "failed to get %s on %s: %s\n", sxd, + acpi_name(handle), AcpiFormatException(status)); + return (ENXIO); } - return (error); + return (0); } /* Callback arg for our implementation of walking the namespace. */ @@ -1524,13 +1488,14 @@ acpi_device_scan_children(device_t bus, * device power states since it's close enough to ACPI. */ static int -acpi_set_powerstate_method(device_t bus, device_t child, int state) +acpi_set_powerstate(device_t child, int state) { ACPI_HANDLE h; ACPI_STATUS status; - int error; - error = 0; + if (!acpi_do_powerstate) + return (0); + h = acpi_get_handle(child); if (state < ACPI_STATE_D0 || state > ACPI_D_STATES_MAX) return (EINVAL); @@ -1539,12 +1504,16 @@ acpi_set_powerstate_method(device_t bus, /* Ignore errors if the power methods aren't present. */ status = acpi_pwr_switch_consumer(h, state); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND - && status != AE_BAD_PARAMETER) - device_printf(bus, "failed to set ACPI power state D%d on %s: %s\n", - state, acpi_name(h), AcpiFormatException(status)); + if (ACPI_SUCCESS(status)) { + if (bootverbose) + device_printf(child, "set ACPI power state D%d on %s\n", + state, acpi_name(h)); + } else if (status != AE_NOT_FOUND) + device_printf(child, + "failed to set ACPI power state D%d on %s: %s\n", state, + acpi_name(h), AcpiFormatException(status)); - return (error); + return (0); } static int Modified: head/sys/dev/acpica/acpi_if.m ============================================================================== --- head/sys/dev/acpica/acpi_if.m Tue Oct 19 19:44:05 2010 (r214071) +++ head/sys/dev/acpica/acpi_if.m Tue Oct 19 19:53:06 2010 (r214072) @@ -123,8 +123,7 @@ METHOD ACPI_STATUS evaluate_object { # # int *dstate: if successful, contains the highest valid sleep state # -# Returns: 0 on success, ESRCH if device has no special state, or -# some other error value. +# Returns: 0 on success or some other error value. # METHOD int pwr_for_sleep { device_t bus; Modified: head/sys/dev/acpica/acpi_pci.c ============================================================================== --- head/sys/dev/acpica/acpi_pci.c Tue Oct 19 19:44:05 2010 (r214071) +++ head/sys/dev/acpica/acpi_pci.c Tue Oct 19 19:53:06 2010 (r214072) @@ -186,9 +186,13 @@ acpi_pci_set_powerstate_method(device_t } h = acpi_get_handle(child); status = acpi_pwr_switch_consumer(h, state); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) + if (ACPI_SUCCESS(status)) { + if (bootverbose) + device_printf(dev, "set ACPI power state D%d on %s\n", + state, acpi_name(h)); + } else if (status != AE_NOT_FOUND) device_printf(dev, - "Failed to set ACPI power state D%d on %s: %s\n", + "failed to set ACPI power state D%d on %s: %s\n", state, acpi_name(h), AcpiFormatException(status)); if (old_state > state && pci_do_power_resume) error = pci_set_powerstate_method(dev, child, state);