diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-04-08 06:31:48 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-04-08 06:31:48 -0400 |
commit | 077f893bd942b23d8e27c90f8f60018ce21010a0 (patch) | |
tree | df5511c5249cbc2b08edd5546cc32848061a7aac /drivers/acpi | |
parent | 6912897d7574d780994ac9a531f76c5df1669aeb (diff) | |
parent | 75eb2d13acca49c3c4f1c96fb04d6c9fd6013e78 (diff) |
Merge branch 'acpi-pm' into linux-next
* acpi-pm:
ACPI / PM: Fix potential problem in acpi_device_get_power()
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/device_pm.c | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index dd314ef9bff1..96de787e6104 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c | |||
@@ -145,27 +145,36 @@ int acpi_device_get_power(struct acpi_device *device, int *state) | |||
145 | } | 145 | } |
146 | 146 | ||
147 | /* | 147 | /* |
148 | * Get the device's power state either directly (via _PSC) or | 148 | * Get the device's power state from power resources settings and _PSC, |
149 | * indirectly (via power resources). | 149 | * if available. |
150 | */ | 150 | */ |
151 | if (device->power.flags.power_resources) { | ||
152 | int error = acpi_power_get_inferred_state(device, &result); | ||
153 | if (error) | ||
154 | return error; | ||
155 | } | ||
151 | if (device->power.flags.explicit_get) { | 156 | if (device->power.flags.explicit_get) { |
157 | acpi_handle handle = device->handle; | ||
152 | unsigned long long psc; | 158 | unsigned long long psc; |
153 | acpi_status status = acpi_evaluate_integer(device->handle, | 159 | acpi_status status; |
154 | "_PSC", NULL, &psc); | 160 | |
161 | status = acpi_evaluate_integer(handle, "_PSC", NULL, &psc); | ||
155 | if (ACPI_FAILURE(status)) | 162 | if (ACPI_FAILURE(status)) |
156 | return -ENODEV; | 163 | return -ENODEV; |
157 | 164 | ||
158 | result = psc; | 165 | /* |
159 | } | 166 | * The power resources settings may indicate a power state |
160 | /* The test below covers ACPI_STATE_UNKNOWN too. */ | 167 | * shallower than the actual power state of the device. |
161 | if (result <= ACPI_STATE_D2) { | 168 | * |
162 | ; /* Do nothing. */ | 169 | * Moreover, on systems predating ACPI 4.0, if the device |
163 | } else if (device->power.flags.power_resources) { | 170 | * doesn't depend on any power resources and _PSC returns 3, |
164 | int error = acpi_power_get_inferred_state(device, &result); | 171 | * that means "power off". We need to maintain compatibility |
165 | if (error) | 172 | * with those systems. |
166 | return error; | 173 | */ |
167 | } else if (result == ACPI_STATE_D3_HOT) { | 174 | if (psc > result && psc < ACPI_STATE_D3_COLD) |
168 | result = ACPI_STATE_D3; | 175 | result = psc; |
176 | else if (result == ACPI_STATE_UNKNOWN) | ||
177 | result = psc > ACPI_STATE_D2 ? ACPI_STATE_D3_COLD : psc; | ||
169 | } | 178 | } |
170 | 179 | ||
171 | /* | 180 | /* |