diff options
| author | Matthew Garrett <mjg@redhat.com> | 2010-05-11 13:49:25 -0400 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2010-05-12 01:12:18 -0400 |
| commit | b6dacf63e9fb2e7a1369843d6cef332f76fca6a3 (patch) | |
| tree | 4b7fbde0071172718270a5646f1168edb6d07023 | |
| parent | b430acbd7c4b919886fa7fd92eeb7a695f1940d3 (diff) | |
ACPI: Unconditionally set SCI_EN on resume
The ACPI spec tells us that the firmware will reenable SCI_EN on resume.
Reality disagrees in some cases. The ACPI spec tells us that the only way
to set SCI_EN is via an SMM call.
https://bugzilla.kernel.org/show_bug.cgi?id=13745 shows us that doing so
may break machines. Tracing the ACPI calls made by Windows shows that it
unconditionally sets SCI_EN on resume with a direct register write, and
therefore the overwhelming probability is that everything is fine with
this behaviour.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Tested-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Len Brown <len.brown@intel.com>
| -rw-r--r-- | arch/x86/kernel/acpi/sleep.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/sleep.c | 157 | ||||
| -rw-r--r-- | include/linux/acpi.h | 1 |
3 files changed, 2 insertions, 158 deletions
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index f9961034e557..82e508677b91 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c | |||
| @@ -162,8 +162,6 @@ static int __init acpi_sleep_setup(char *str) | |||
| 162 | #endif | 162 | #endif |
| 163 | if (strncmp(str, "old_ordering", 12) == 0) | 163 | if (strncmp(str, "old_ordering", 12) == 0) |
| 164 | acpi_old_suspend_ordering(); | 164 | acpi_old_suspend_ordering(); |
| 165 | if (strncmp(str, "sci_force_enable", 16) == 0) | ||
| 166 | acpi_set_sci_en_on_resume(); | ||
| 167 | str = strchr(str, ','); | 165 | str = strchr(str, ','); |
| 168 | if (str != NULL) | 166 | if (str != NULL) |
| 169 | str += strspn(str, ", \t"); | 167 | str += strspn(str, ", \t"); |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index baa76bbf244a..4ab2275b4461 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
| @@ -80,22 +80,6 @@ static int acpi_sleep_prepare(u32 acpi_state) | |||
| 80 | 80 | ||
| 81 | #ifdef CONFIG_ACPI_SLEEP | 81 | #ifdef CONFIG_ACPI_SLEEP |
| 82 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; | 82 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; |
| 83 | /* | ||
| 84 | * According to the ACPI specification the BIOS should make sure that ACPI is | ||
| 85 | * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, | ||
| 86 | * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI | ||
| 87 | * on such systems during resume. Unfortunately that doesn't help in | ||
| 88 | * particularly pathological cases in which SCI_EN has to be set directly on | ||
| 89 | * resume, although the specification states very clearly that this flag is | ||
| 90 | * owned by the hardware. The set_sci_en_on_resume variable will be set in such | ||
| 91 | * cases. | ||
| 92 | */ | ||
| 93 | static bool set_sci_en_on_resume; | ||
| 94 | |||
| 95 | void __init acpi_set_sci_en_on_resume(void) | ||
| 96 | { | ||
| 97 | set_sci_en_on_resume = true; | ||
| 98 | } | ||
| 99 | 83 | ||
| 100 | /* | 84 | /* |
| 101 | * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the | 85 | * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the |
| @@ -253,11 +237,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
| 253 | break; | 237 | break; |
| 254 | } | 238 | } |
| 255 | 239 | ||
| 256 | /* If ACPI is not enabled by the BIOS, we need to enable it here. */ | 240 | /* This violates the spec but is required for bug compatibility. */ |
| 257 | if (set_sci_en_on_resume) | 241 | acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); |
| 258 | acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); | ||
| 259 | else | ||
| 260 | acpi_enable(); | ||
| 261 | 242 | ||
| 262 | /* Reprogram control registers and execute _BFS */ | 243 | /* Reprogram control registers and execute _BFS */ |
| 263 | acpi_leave_sleep_state_prep(acpi_state); | 244 | acpi_leave_sleep_state_prep(acpi_state); |
| @@ -346,12 +327,6 @@ static int __init init_old_suspend_ordering(const struct dmi_system_id *d) | |||
| 346 | return 0; | 327 | return 0; |
| 347 | } | 328 | } |
| 348 | 329 | ||
| 349 | static int __init init_set_sci_en_on_resume(const struct dmi_system_id *d) | ||
| 350 | { | ||
| 351 | set_sci_en_on_resume = true; | ||
| 352 | return 0; | ||
| 353 | } | ||
| 354 | |||
| 355 | static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | 330 | static struct dmi_system_id __initdata acpisleep_dmi_table[] = { |
| 356 | { | 331 | { |
| 357 | .callback = init_old_suspend_ordering, | 332 | .callback = init_old_suspend_ordering, |
| @@ -370,22 +345,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
| 370 | }, | 345 | }, |
| 371 | }, | 346 | }, |
| 372 | { | 347 | { |
| 373 | .callback = init_set_sci_en_on_resume, | ||
| 374 | .ident = "Apple MacBook 1,1", | ||
| 375 | .matches = { | ||
| 376 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), | ||
| 377 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), | ||
| 378 | }, | ||
| 379 | }, | ||
| 380 | { | ||
| 381 | .callback = init_set_sci_en_on_resume, | ||
| 382 | .ident = "Apple MacMini 1,1", | ||
| 383 | .matches = { | ||
| 384 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), | ||
| 385 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), | ||
| 386 | }, | ||
| 387 | }, | ||
| 388 | { | ||
| 389 | .callback = init_old_suspend_ordering, | 348 | .callback = init_old_suspend_ordering, |
| 390 | .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", | 349 | .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", |
| 391 | .matches = { | 350 | .matches = { |
| @@ -394,94 +353,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
| 394 | }, | 353 | }, |
| 395 | }, | 354 | }, |
| 396 | { | 355 | { |
| 397 | .callback = init_set_sci_en_on_resume, | ||
| 398 | .ident = "Toshiba Satellite L300", | ||
| 399 | .matches = { | ||
| 400 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
| 401 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"), | ||
| 402 | }, | ||
| 403 | }, | ||
| 404 | { | ||
| 405 | .callback = init_set_sci_en_on_resume, | ||
| 406 | .ident = "Hewlett-Packard HP G7000 Notebook PC", | ||
| 407 | .matches = { | ||
| 408 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 409 | DMI_MATCH(DMI_PRODUCT_NAME, "HP G7000 Notebook PC"), | ||
| 410 | }, | ||
| 411 | }, | ||
| 412 | { | ||
| 413 | .callback = init_set_sci_en_on_resume, | ||
| 414 | .ident = "Hewlett-Packard HP Pavilion dv3 Notebook PC", | ||
| 415 | .matches = { | ||
| 416 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 417 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv3 Notebook PC"), | ||
| 418 | }, | ||
| 419 | }, | ||
| 420 | { | ||
| 421 | .callback = init_set_sci_en_on_resume, | ||
| 422 | .ident = "Hewlett-Packard Pavilion dv4", | ||
| 423 | .matches = { | ||
| 424 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 425 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4"), | ||
| 426 | }, | ||
| 427 | }, | ||
| 428 | { | ||
| 429 | .callback = init_set_sci_en_on_resume, | ||
| 430 | .ident = "Hewlett-Packard Pavilion dv7", | ||
| 431 | .matches = { | ||
| 432 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 433 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7"), | ||
| 434 | }, | ||
| 435 | }, | ||
| 436 | { | ||
| 437 | .callback = init_set_sci_en_on_resume, | ||
| 438 | .ident = "Hewlett-Packard Compaq Presario C700 Notebook PC", | ||
| 439 | .matches = { | ||
| 440 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 441 | DMI_MATCH(DMI_PRODUCT_NAME, "Compaq Presario C700 Notebook PC"), | ||
| 442 | }, | ||
| 443 | }, | ||
| 444 | { | ||
| 445 | .callback = init_set_sci_en_on_resume, | ||
| 446 | .ident = "Hewlett-Packard Compaq Presario CQ40 Notebook PC", | ||
| 447 | .matches = { | ||
| 448 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 449 | DMI_MATCH(DMI_PRODUCT_NAME, "Compaq Presario CQ40 Notebook PC"), | ||
| 450 | }, | ||
| 451 | }, | ||
| 452 | { | ||
| 453 | .callback = init_set_sci_en_on_resume, | ||
| 454 | .ident = "Lenovo ThinkPad T410", | ||
| 455 | .matches = { | ||
| 456 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 457 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T410"), | ||
| 458 | }, | ||
| 459 | }, | ||
| 460 | { | ||
| 461 | .callback = init_set_sci_en_on_resume, | ||
| 462 | .ident = "Lenovo ThinkPad T510", | ||
| 463 | .matches = { | ||
| 464 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 465 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T510"), | ||
| 466 | }, | ||
| 467 | }, | ||
| 468 | { | ||
| 469 | .callback = init_set_sci_en_on_resume, | ||
| 470 | .ident = "Lenovo ThinkPad W510", | ||
| 471 | .matches = { | ||
| 472 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 473 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W510"), | ||
| 474 | }, | ||
| 475 | }, | ||
| 476 | { | ||
| 477 | .callback = init_set_sci_en_on_resume, | ||
| 478 | .ident = "Lenovo ThinkPad X201[s]", | ||
| 479 | .matches = { | ||
| 480 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 481 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201"), | ||
| 482 | }, | ||
| 483 | }, | ||
| 484 | { | ||
| 485 | .callback = init_old_suspend_ordering, | 356 | .callback = init_old_suspend_ordering, |
| 486 | .ident = "Panasonic CF51-2L", | 357 | .ident = "Panasonic CF51-2L", |
| 487 | .matches = { | 358 | .matches = { |
| @@ -490,30 +361,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
| 490 | DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), | 361 | DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), |
| 491 | }, | 362 | }, |
| 492 | }, | 363 | }, |
| 493 | { | ||
| 494 | .callback = init_set_sci_en_on_resume, | ||
| 495 | .ident = "Dell Studio 1558", | ||
| 496 | .matches = { | ||
| 497 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
| 498 | DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1558"), | ||
| 499 | }, | ||
| 500 | }, | ||
| 501 | { | ||
| 502 | .callback = init_set_sci_en_on_resume, | ||
| 503 | .ident = "Dell Studio 1557", | ||
| 504 | .matches = { | ||
| 505 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
| 506 | DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1557"), | ||
| 507 | }, | ||
| 508 | }, | ||
| 509 | { | ||
| 510 | .callback = init_set_sci_en_on_resume, | ||
| 511 | .ident = "Dell Studio 1555", | ||
| 512 | .matches = { | ||
| 513 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
| 514 | DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1555"), | ||
| 515 | }, | ||
| 516 | }, | ||
| 517 | {}, | 364 | {}, |
| 518 | }; | 365 | }; |
| 519 | #endif /* CONFIG_SUSPEND */ | 366 | #endif /* CONFIG_SUSPEND */ |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index b926afe8c03e..87ca4913294c 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
| @@ -251,7 +251,6 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n, | |||
| 251 | void __init acpi_no_s4_hw_signature(void); | 251 | void __init acpi_no_s4_hw_signature(void); |
| 252 | void __init acpi_old_suspend_ordering(void); | 252 | void __init acpi_old_suspend_ordering(void); |
| 253 | void __init acpi_s4_no_nvs(void); | 253 | void __init acpi_s4_no_nvs(void); |
| 254 | void __init acpi_set_sci_en_on_resume(void); | ||
| 255 | #endif /* CONFIG_PM_SLEEP */ | 254 | #endif /* CONFIG_PM_SLEEP */ |
| 256 | 255 | ||
| 257 | struct acpi_osc_context { | 256 | struct acpi_osc_context { |
