fix APM notify of apmd for on-AC/on-battery transitions
PATCH 1/1 fix APM notify of apmd for on-AC/on-battery transitions
This patch fixes a problem with Sony Vaio laptops where they don't notify the kernel of power source change events. That means apmd is never told and many of the apmd features can't be used.
The Sony Vaio that I have doesn't send APM events to the kernel telling it about 'going on battery' or 'going on AC power' events. It will register them correctly if they're queried but it won't asynchronously send an event so the kernel never tells apmd about it.
This patch fixes the situation by checking against the last known power state (and power source) in the check_status() call.
This was tested on a Sony Vaio z505js, model PCG-5201 and it works beautifully. I'm told other Vaio notebooks have this same problem. Now, Vaio users can setup apmd to aggressively try to save power when on battery or perform other crazy tasks.
This patch is against v2.4.16 but applies to newer kernels as well.
arch/i386/kernel/apm.c +28 -0
@@ -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 <[email protected]> +*/ +if ( is_sony_vaio_laptop ) { +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 )
Quoted 2 lines · Cort Dougan
This was tested on a Sony Vaio z505js, model PCG-5201 and it works beautifully. I'm told other Vaio notebooks have this same problem.
But not all Vaio's. My z600 (which is what they sold the z505 series as in .eu) for example behaves correctly when I plug in/pull out the power cord repeatedly.
We might be better off special casing 'known bad' models in the DMI blacklist instead of assuming carte blanche that all vaio's are bad. Might even come down to a specific BIOS version that's at fault.
Dave
Signature · 2 lines
| Dave Jones. http://www.codemonkey.org.uk | SuSE Labs
Fine with me. As long as my vaio model works right :)
I can dig through there and create a blacklist that has one entry for now.
} But not all Vaio's. My z600 (which is what they sold the z505 series as in .eu) } for example behaves correctly when I plug in/pull out the power cord } repeatedly.
}
} We might be better off special casing 'known bad' models in the
} DMI blacklist instead of assuming carte blanche that all vaio's are bad. } Might even come down to a specific BIOS version that's at fault.
unsubscribe linux-kernel
Can you check to make sure for me? If you stick a 'wall my power changed $*' into /etc/apmd_proxy or /etc/sysconfig/apm-scripts/scripts (or where-ever SuSE puts it) then pull the power from your Vaio what does it give you? I can get the 'apm' commant to tell me the power state (same with the gnome applets) but apmd is never asynchronously notified.
I'm trying to find which versions/models do this so I can properly characterize the check agains the DMI data.
} But not all Vaio's. My z600 (which is what they sold the z505 series as in .eu) } for example behaves correctly when I plug in/pull out the power cord } repeatedly.
}
} We might be better off special casing 'known bad' models in the
} DMI blacklist instead of assuming carte blanche that all vaio's are bad. } Might even come down to a specific BIOS version that's at fault.
}
} Dave
}
} --
} | Dave Jones. http://www.codemonkey.org.uk
} | SuSE Labs
Quoted 5 lines · Cort Dougan
Can you check to make sure for me? If you stick a 'wall my power changed $*' into
/etc/apmd_proxyor/etc/sysconfig/apm-scripts/scripts(or where-ever SuSE puts it) then pull the power from your Vaio what does it give you? I can get the 'apm' commant to tell me the power state (same with the gnome applets) but apmd is never asynchronously notified.
Ah, I completely misunderstood the problem. The Gnome-applets are polling, and hence seeing the change I guess. Your suspicion seems to be correct, and I was wrong, my z600 needs your patch too.
Dave (eating words)
Signature · 2 lines
| Dave Jones. http://www.codemonkey.org.uk | SuSE Labs
I tried it on another Vaio here and found my explanation was unclear when he misunderstood me, too.
} Ah, I completely misunderstood the problem. The Gnome-applets are } polling, and hence seeing the change I guess. Your suspicion seems to } be correct, and I was wrong, my z600 needs your patch too.
The patch with the DMI checking is below. It's probably better done this way anyway since there are likely other systems out there that do this as well. It's a rarely used feature it seems.
If you could try it out and see if it works for you I'd appreciate it. I'd like to get it included in 2.4 with Marcelo so I don't have to keep it around.
arch/i386/kernel/apm.c +28 -0
@@ -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 <[email protected]> +*/ +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 )
arch/i386/kernel/dmi_scan.c +28 -0
@@ -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 <[email protected]> +*/ +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, }
include/asm-i386/system.h +1 -0
@@ -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