avoid hang with speedstep-smi on Dell Latitude C600
PATCH 1/1 avoid hang with speedstep-smi on Dell Latitude C600
[ http://bugme.osdl.org/show_bug.cgi?id=1422 ]
The speedstep_smi_get_freqs call caused a hang on a Dell C600. On some other systems, the speedstep_smi_get_freqs call fails even though this cpufreq driver works fine otherwise. All these systems have one thing in common: ist_info.event is either 0x00000000 or 0x00ff0000. So, don't call speedstep_smi_get_freqs on these systems.
arch/i386/kernel/cpu/cpufreq/speedstep-smi.c +14 -6
@@ -86,6 +86,9 @@/** * speedstep_smi_get_freqs - get SpeedStep preferred & current freq. * +* Only available on later SpeedStep-enabled systems, returns false results or +* even hangs [cf. bugme.osdl.org # 1422] on earlier systems. Empirical testing +* shows that the latter occurs if !(ist_info.event & 0xFFFF). */ static int speedstep_smi_get_freqs (unsigned int *low,unsigned int *high) {
@@ -226,17 +229,23 @@ result =speedstep_smi_ownership (); -if (result) +if (result) {dprintk (KERN_INFO "cpufreq: fails an aquiring ownership of a SMI interface.\n" ); +return -EINVAL ; + }/* detect low and high frequency */ - result =speedstep_smi_get_freqs (&speedstep_freqs[SPEEDSTEP_LOW ].frequency, +if (ist_info.event &0xFFFF ) { + result =speedstep_smi_get_freqs (&speedstep_freqs[SPEEDSTEP_LOW ].frequency, &speedstep_freqs[SPEEDSTEP_HIGH ].frequency); -if (result) { +if (result) { + dprintk(KERN_INFO PFX "could not detect low and high frequencies by SMI call.\n"); + } + } +if ((result) || !(ist_info.event &0xFFFF )) {/* fall back to speedstep_lib.c dection mechanism: try both states out */ unsigned int speedstep_processor =speedstep_detect_processor (); - dprintk(KERN_INFO PFX "could not detect low and high frequencies by SMI call.\n");if (!speedstep_processor)return -ENODEV ;
@@ -248,8 +257,7 @@if (result) { dprintk(KERN_INFO PFX "could not detect two different speeds -- aborting.\n");return result; - }else - dprintk(KERN_INFO PFX "workaround worked.\n"); + } }/* get current speed setting */