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 /drivers/acpi | |
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>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/sleep.c | 157 |
1 files changed, 2 insertions, 155 deletions
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 */ |