svn commit: r214072 - head/sys/dev/acpica
Jung-uk Kim
jkim at FreeBSD.org
Tue Oct 19 19:53:07 UTC 2010
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 <dev/acpica/acpivar.h>
#include <dev/acpica/acpiio.h>
-#include "pci_if.h"
-#include <dev/pci/pcivar.h>
-#include <dev/pci/pci_private.h>
-
#include <vm/vm_param.h>
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);
More information about the svn-src-all
mailing list