summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica/acpi_powerres.c
diff options
context:
space:
mode:
authoriwasaki <iwasaki@FreeBSD.org>2001-08-21 18:22:40 +0000
committeriwasaki <iwasaki@FreeBSD.org>2001-08-21 18:22:40 +0000
commitfbda0f8d3ba2dd9cecf9c63819e8cd9f6c8c3ef3 (patch)
tree4e489c49cf33a22d4cc6f6d48193f7e528aced54 /sys/dev/acpica/acpi_powerres.c
parentdb70defc697ebad9df0f3d6ae725fa952e52941e (diff)
downloadFreeBSD-src-fbda0f8d3ba2dd9cecf9c63819e8cd9f6c8c3ef3.zip
FreeBSD-src-fbda0f8d3ba2dd9cecf9c63819e8cd9f6c8c3ef3.tar.gz
Fix error checking about device state transition from D0 to D3.
Turn off the resources listed in _PR0 to go to D3 if we don't have _PR3/_PS3. Reviewed by: msmith
Diffstat (limited to 'sys/dev/acpica/acpi_powerres.c')
-rw-r--r--sys/dev/acpica/acpi_powerres.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/sys/dev/acpica/acpi_powerres.c b/sys/dev/acpica/acpi_powerres.c
index b3d98d3..390c0bd 100644
--- a/sys/dev/acpica/acpi_powerres.c
+++ b/sys/dev/acpica/acpi_powerres.c
@@ -299,7 +299,7 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
{
struct acpi_powerconsumer *pc;
struct acpi_powerreference *pr;
- ACPI_HANDLE method_handle, reslist_handle;
+ ACPI_HANDLE method_handle, reslist_handle, pr0_handle;
ACPI_BUFFER reslist_buffer;
ACPI_OBJECT *reslist_object;
ACPI_STATUS status;
@@ -355,6 +355,7 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
* support D0 and D3. It's never an error to try to go to
* D0.
*/
+ reslist_object = NULL;
if (AcpiGetHandle(consumer, method_name, &method_handle) != AE_OK)
method_handle = NULL;
if (AcpiGetHandle(consumer, reslist_name, &reslist_handle) != AE_OK)
@@ -364,9 +365,24 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
pc->ac_state = ACPI_STATE_D0;
return_ACPI_STATUS(AE_OK);
}
- DEBUG_PRINT(TRACE_OBJECTS, ("attempt to set unsupported state D%d\n",
- state));
- return_ACPI_STATUS(AE_BAD_PARAMETER);
+ if (state != ACPI_STATE_D3) {
+ goto bad;
+ }
+
+ /* turn off the resources listed in _PR0 to go to D3. */
+ if (AcpiGetHandle(consumer, "_PR0", &pr0_handle) != AE_OK) {
+ goto bad;
+ }
+ status = acpi_EvaluateIntoBuffer(pr0_handle, NULL, NULL, &reslist_buffer);
+ if (status != AE_OK) {
+ goto bad;
+ }
+ reslist_object = (ACPI_OBJECT *)reslist_buffer.Pointer;
+ if ((reslist_object->Type != ACPI_TYPE_PACKAGE) ||
+ (reslist_object->Package.Count == 0)) {
+ goto bad;
+ }
+ AcpiOsFree(reslist_object);
}
/*
@@ -434,6 +450,13 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
/* transition was successful */
pc->ac_state = state;
return_ACPI_STATUS(AE_OK);
+
+ bad:
+ DEBUG_PRINT(TRACE_OBJECTS, ("attempt to set unsupported state D%d\n",
+ state));
+ if (reslist_object)
+ AcpiOsFree(reslist_object);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
OpenPOWER on IntegriCloud