diff -Nru a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c --- a/arch/i386/kernel/apm.c Fri Jul 26 16:48:55 2002 +++ b/arch/i386/kernel/apm.c Fri Jul 26 16:48:55 2002 @@ -1313,6 +1313,34 @@ break; } } + + /* + * The Sony Vaio doesn't seem to want to send us a notify + * about AC line power status changes. So, we have to keep track + * of it by hand and emulate it here. + * -- Cort + */ + if ( apm_bios_power_change_bug ) { + static int last_status = 0; + u_short status, bat, life; + + /* get the current power state */ + if ( apm_get_power_status(&status, &bat, &life) != + APM_SUCCESS ) { + printk("%s:%s error checking power status\n", + __FILE__,__FUNCTION__); + } + + /* has the status changed since we were last here? */ + if (((status >> 8) & 0xff) != last_status) { + last_status = (status >> 8) & 0xff; + + /* fake a APM_POWER_STATUS_CHANGE event */ + send_event(APM_POWER_STATUS_CHANGE); + queue_event(APM_POWER_STATUS_CHANGE, NULL); + } + + } } static void apm_event_handler(void) diff -Nru a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c --- a/arch/i386/kernel/dmi_scan.c Fri Jul 26 16:48:55 2002 +++ b/arch/i386/kernel/dmi_scan.c Fri Jul 26 16:48:55 2002 @@ -12,6 +12,7 @@ unsigned long dmi_broken; int is_sony_vaio_laptop; +int apm_bios_power_change_bug = 0; struct dmi_header { @@ -346,6 +347,27 @@ return 0; } + +/* + * Some Vaio laptops don't notify the kernel of a power status change + * such as on-AC/on-battery. This detects some of the faulty machines + * and sets a variable that lets arch/i386/kernel/apm.c deal with it. + * + * I've seen this with the Vaio z505js PCG-5201 and PCG-SR33: + + * model PCG-Z505JS(UC), bios Phoenix Technologies LTD version R0121Z1 + * model PCG-SR33(UC), bios Phoenix Technologies LTD version R0211D1 + * -- Cort + */ +static __init int sony_vaio_apm_change(struct dmi_blacklist *d) +{ + apm_bios_power_change_bug = 1; + printk(KERN_WARNING "%s detected: APM power status change workaround enabled\n", + d->ident); + return 0; +} + + /* * The Intel 440GX hall of shame. * @@ -611,6 +633,12 @@ { set_apm_ints, "IBM", { /* Allow interrupts during suspend on IBM laptops */ MATCH(DMI_SYS_VENDOR, "IBM"), NO_MATCH, NO_MATCH, NO_MATCH + } }, + + { sony_vaio_apm_change, "Sony Vaio", { /* APM won't send power change events */ + MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + NO_MATCH, NO_MATCH } }, { NULL, } diff -Nru a/include/asm-i386/system.h b/include/asm-i386/system.h --- a/include/asm-i386/system.h Fri Jul 26 16:48:55 2002 +++ b/include/asm-i386/system.h Fri Jul 26 16:48:55 2002 @@ -356,6 +356,7 @@ extern unsigned long dmi_broken; extern int is_sony_vaio_laptop; +extern int apm_bios_power_change_bug; #define BROKEN_ACPI_Sx 0x0001 #define BROKEN_INIT_AFTER_S1 0x0002