aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/kernel-parameters.txt8
-rw-r--r--drivers/acpi/bus.c14
-rw-r--r--drivers/acpi/power.c42
-rw-r--r--include/acpi/acpi_drivers.h1
4 files changed, 53 insertions, 12 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 44d1bd142edf..99cf83fd6947 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -251,6 +251,14 @@ and is between 256 and 4096 characters. It is defined in the file
251 Warning: Many of these options can produce a lot of 251 Warning: Many of these options can produce a lot of
252 output and make your system unusable. Be very careful. 252 output and make your system unusable. Be very careful.
253 253
254 acpi.power_nocheck= [HW,ACPI]
255 Format: 1/0 enable/disable the check of power state.
256 On some bogus BIOS the _PSC object/_STA object of
257 power resource can't return the correct device power
258 state. In such case it is unneccessary to check its
259 power state again in power transition.
260 1 : disable the power state check
261
254 acpi_pm_good [X86-32,X86-64] 262 acpi_pm_good [X86-32,X86-64]
255 Override the pmtimer bug detection: force the kernel 263 Override the pmtimer bug detection: force the kernel
256 to assume that this machine's pmtimer latches its value 264 to assume that this machine's pmtimer latches its value
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;
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index e5f38e5ce86f..efbaa271ee11 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -93,6 +93,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state);
93int acpi_disable_wakeup_device_power(struct acpi_device *dev); 93int acpi_disable_wakeup_device_power(struct acpi_device *dev);
94int acpi_power_get_inferred_state(struct acpi_device *device); 94int acpi_power_get_inferred_state(struct acpi_device *device);
95int acpi_power_transition(struct acpi_device *device, int state); 95int acpi_power_transition(struct acpi_device *device, int state);
96extern int acpi_power_nocheck;
96#endif 97#endif
97 98
98/* -------------------------------------------------------------------------- 99/* --------------------------------------------------------------------------