aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorZhao Yakui <yakui.zhao@intel.com>2008-08-11 02:57:50 -0400
committerLen Brown <len.brown@intel.com>2008-10-22 17:59:57 -0400
commitf5adfaa372c76423b6e8e4727a9701330374f364 (patch)
treeb7783111c8f027d954506d7440d806817de13f6b /drivers/acpi
parenteab4b645769fa2f8703f5a3cb0cc4ac090d347af (diff)
ACPI: Add "acpi.power_nocheck=1" to disable power state check in power transition
Maybe the incorrect power state is returned on the bogus bios, which is different with the real power state. For example: the bios returns D0 state and the real power state is D3. OS expects to set the device to D0 state. In such case if OS uses the power state returned by the BIOS and checks the device power state very strictly in power transition, the device can't be transited to the correct power state. So the boot option of "acpi.power_nocheck=1" is added to avoid checking the device power in the course of device power transition. http://bugzilla.kernel.org/show_bug.cgi?id=8049 http://bugzilla.kernel.org/show_bug.cgi?id=11000 Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Li Shaohua <shaohua.li@intel.com> Signed-off-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/bus.c14
-rw-r--r--drivers/acpi/power.c42
2 files changed, 44 insertions, 12 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index ccae305ee55d..91bdeb3b081e 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -223,7 +223,19 @@ int acpi_bus_set_power(acpi_handle handle, int state)
223 /* 223 /*
224 * Get device's current power state 224 * Get device's current power state
225 */ 225 */
226 acpi_bus_get_power(device->handle, &device->power.state); 226 if (!acpi_power_nocheck) {
227 /*
228 * Maybe the incorrect power state is returned on the bogus
229 * bios, which is different with the real power state.
230 * For example: the bios returns D0 state and the real power
231 * state is D3. OS expects to set the device to D0 state. In
232 * such case if OS uses the power state returned by the BIOS,
233 * the device can't be transisted to the correct power state.
234 * So if the acpi_power_nocheck is set, it is unnecessary to
235 * get the power state by calling acpi_bus_get_power.
236 */
237 acpi_bus_get_power(device->handle, &device->power.state);
238 }
227 if ((state == device->power.state) && !device->flags.force_power_state) { 239 if ((state == device->power.state) && !device->flags.force_power_state) {
228 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", 240 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
229 state)); 241 state));
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index e7bab75075a9..7ff7349c0c52 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -54,6 +54,14 @@ ACPI_MODULE_NAME("power");
54#define ACPI_POWER_RESOURCE_STATE_OFF 0x00 54#define ACPI_POWER_RESOURCE_STATE_OFF 0x00
55#define ACPI_POWER_RESOURCE_STATE_ON 0x01 55#define ACPI_POWER_RESOURCE_STATE_ON 0x01
56#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF 56#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
57
58#ifdef MODULE_PARAM_PREFIX
59#undef MODULE_PARAM_PREFIX
60#endif
61#define MODULE_PARAM_PREFIX "acpi."
62int acpi_power_nocheck;
63module_param_named(power_nocheck, acpi_power_nocheck, bool, 000);
64
57static int acpi_power_add(struct acpi_device *device); 65static int acpi_power_add(struct acpi_device *device);
58static int acpi_power_remove(struct acpi_device *device, int type); 66static int acpi_power_remove(struct acpi_device *device, int type);
59static int acpi_power_resume(struct acpi_device *device); 67static int acpi_power_resume(struct acpi_device *device);
@@ -228,12 +236,18 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
228 if (ACPI_FAILURE(status)) 236 if (ACPI_FAILURE(status))
229 return -ENODEV; 237 return -ENODEV;
230 238
231 result = acpi_power_get_state(resource->device->handle, &state); 239 if (!acpi_power_nocheck) {
232 if (result) 240 /*
233 return result; 241 * If acpi_power_nocheck is set, it is unnecessary to check
234 if (state != ACPI_POWER_RESOURCE_STATE_ON) 242 * the power state after power transition.
235 return -ENOEXEC; 243 */
236 244 result = acpi_power_get_state(resource->device->handle,
245 &state);
246 if (result)
247 return result;
248 if (state != ACPI_POWER_RESOURCE_STATE_ON)
249 return -ENOEXEC;
250 }
237 /* Update the power resource's _device_ power state */ 251 /* Update the power resource's _device_ power state */
238 resource->device->power.state = ACPI_STATE_D0; 252 resource->device->power.state = ACPI_STATE_D0;
239 253
@@ -279,11 +293,17 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
279 if (ACPI_FAILURE(status)) 293 if (ACPI_FAILURE(status))
280 return -ENODEV; 294 return -ENODEV;
281 295
282 result = acpi_power_get_state(handle, &state); 296 if (!acpi_power_nocheck) {
283 if (result) 297 /*
284 return result; 298 * If acpi_power_nocheck is set, it is unnecessary to check
285 if (state != ACPI_POWER_RESOURCE_STATE_OFF) 299 * the power state after power transition.
286 return -ENOEXEC; 300 */
301 result = acpi_power_get_state(handle, &state);
302 if (result)
303 return result;
304 if (state != ACPI_POWER_RESOURCE_STATE_OFF)
305 return -ENOEXEC;
306 }
287 307
288 /* Update the power resource's _device_ power state */ 308 /* Update the power resource's _device_ power state */
289 resource->device->power.state = ACPI_STATE_D3; 309 resource->device->power.state = ACPI_STATE_D3;