aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-04-08 06:31:48 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-04-08 06:31:48 -0400
commit077f893bd942b23d8e27c90f8f60018ce21010a0 (patch)
treedf5511c5249cbc2b08edd5546cc32848061a7aac /drivers/acpi
parent6912897d7574d780994ac9a531f76c5df1669aeb (diff)
parent75eb2d13acca49c3c4f1c96fb04d6c9fd6013e78 (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.c39
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 /*