diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 8 | ||||
-rw-r--r-- | drivers/acpi/bus.c | 14 | ||||
-rw-r--r-- | drivers/acpi/power.c | 42 | ||||
-rw-r--r-- | include/acpi/acpi_drivers.h | 1 |
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." | ||
62 | int acpi_power_nocheck; | ||
63 | module_param_named(power_nocheck, acpi_power_nocheck, bool, 000); | ||
64 | |||
57 | static int acpi_power_add(struct acpi_device *device); | 65 | static int acpi_power_add(struct acpi_device *device); |
58 | static int acpi_power_remove(struct acpi_device *device, int type); | 66 | static int acpi_power_remove(struct acpi_device *device, int type); |
59 | static int acpi_power_resume(struct acpi_device *device); | 67 | static 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); | |||
93 | int acpi_disable_wakeup_device_power(struct acpi_device *dev); | 93 | int acpi_disable_wakeup_device_power(struct acpi_device *dev); |
94 | int acpi_power_get_inferred_state(struct acpi_device *device); | 94 | int acpi_power_get_inferred_state(struct acpi_device *device); |
95 | int acpi_power_transition(struct acpi_device *device, int state); | 95 | int acpi_power_transition(struct acpi_device *device, int state); |
96 | extern int acpi_power_nocheck; | ||
96 | #endif | 97 | #endif |
97 | 98 | ||
98 | /* -------------------------------------------------------------------------- | 99 | /* -------------------------------------------------------------------------- |