[Galaxy S II Original Android Development] Entropy512:
I've been instrumenting more things including each of the conditional branches in exynos4210_set_frequency and s5p_get_pll45xx (which is what does getspeed), this is interesting:

<4>[ 77.878658] s5p_get_pll45xx: baseclk = 24000000, mdiv=250, pdiv=6, sdiv=0
<3>[ 77.975015] [TSP] Up[0]
<7>[ 78.002277] setting new policy for CPU 0: 200000 - 800000 kHz
<4>[ 78.002331] s5p_get_pll45xx: baseclk = 24000000, mdiv=250, pdiv=6, sdiv=0
<4>[ 78.002369] ++exynos_target current hw freq is 1000 MHz
<4>[ 78.002399] exynos_target: target_freq=200000, freqs.new=200000, freqs.old=1000000, freqs.cpu=0, safe_arm_volt=0, arm_volt=950000
<7>[ 78.002454] notification 0 of frequency transition to 200000 kHz
<4>[ 78.002509] exynos4210_set_frequency: no p/m/s change, frequency decrease
<7>[ 78.002555] notification 1 of frequency transition to 200000 kHz
<7>[ 78.002625] scaling loops_per_jiffy to 995328 for frequency 200000 kHz
<7>[ 78.002695] FREQ: 200000 - CPU: 0
<7>[ 78.002757] FREQ: Changing cur freq, new freq is 200000s5p_get_pll45xx: baseclk = 24000000, mdiv=250, pdiv=6, sdiv=2
<4>[ 78.003786] --exynos_target current hw freq is 250 MHz
<4>[ 78.003882] s5p_get_pll45xx: baseclk = 24000000, mdiv=250, pdiv=6, sdiv=2
<4>[ 78.003980] ++exynos_target current hw freq is 250 MHz
<4>[ 78.004066] exynos_target: target_freq=800000, freqs.new=800000, freqs.old=1000000, freqs.cpu=0, safe_arm_volt=0, arm_volt=1075000
<7>[ 78.004215] notification 0 of frequency transition to 800000 kHz
<7>[ 78.004301] Warning: CPU frequency is 1000000, cpufreq assumed 200000 kHz.
<7>[ 78.004433] scaling loops_per_jiffy to 3981312 for frequency 800000 kHz
<7>[ 78.005874] notification 1 of frequency transition to 800000 kHz
<7>[ 78.005953] FREQ: 800000 - CPU: 0
<7>[ 78.006701] FREQ: Changing cur freq, new freq is 800000s5p_get_pll45xx: baseclk = 24000000, mdiv=250, pdiv=6, sdiv=2
<4>[ 78.006888] --exynos_target current hw freq is 250 MHz
<7>[ 78.007039] new min and max freqs are 200000 - 800000 kHz
<7>[ 78.007126] governor: change or update limits
<7>[ 78.007187] __cpufreq_governor for CPU 0, event 3
<7>[ 78.020347] target for CPU 0: 800000 kHz, relation 1
<4>[ 78.020449] s5p_get_pll45xx: baseclk = 24000000, mdiv=250, pdiv=6, sdiv=2
<4>[ 78.020549] ++exynos_target current hw freq is 250 MHz
<4>[ 78.020631] exynos_target: target_freq=800000, freqs.new=800000, freqs.old=800000, freqs.cpu=0, safe_arm_volt=0, arm_volt=1075000
<7>[ 78.020768] notification 0 of frequency transition to 800000 kHz
<7>[ 78.020900] notification 1 of frequency transition to 800000 kHz
<7>[ 78.020974] FREQ: 800000 - CPU: 0
<7>[ 78.022448] FREQ: Changing cur freq, new freq is 800000s5p_get_pll45xx: baseclk = 24000000, mdiv=250, pdiv=6, sdiv=2
<4>[ 78.022629] --exynos_target current hw freq is 250 MHz
<7>[ 78.034731] setting new policy for CPU 0: 200000 - 800000 kHz
<7>[ 78.034830] new min and max freqs are 200000 - 800000 kHz
<7>[ 78.034895] governor: change or update limits
<7>[ 78.034958] __cpufreq_governor for CPU 0, event 3
<4>[ 78.040284] s5p_get_pll45xx: baseclk = 24000000, mdiv=250, pdiv=6, sdiv=2
<7>[ 78.054678] setting new policy for CPU 0: 200000 - 800000 kHz
<7>[ 78.054766] new min and max freqs are 200000 - 800000 kHz
<7>[ 78.054826] governor: change or update limits
<7>[ 78.054879] __cpufreq_governor for CPU 0, event 3
<7>[ 78.067747] setting new policy for CPU 0: 200000 - 800000 kHz
<7>[ 78.067833] new min and max freqs are 200000 - 800000 kHz
<7>[ 78.067893] governor: change or update limits
<7>[ 78.067946] __cpufreq_governor for CPU 0, event 3
<4>[ 78.112224] s5p_get_pll45xx: baseclk = 24000000, mdiv=250, pdiv=6, sdiv=2
<7>[ 78.112313] Warning: CPU frequency out of sync: cpufreq and timing core thinks of 800000, is 250000 kHz.

Here, for some reason, when going from 1000 MHz to 200, it decided that it only needed to change the s value of the m/p/s table.

But the divider values are:

1000 MHz: m=250, p=6, s=0

200 MHz: m=200, p=6, s=2

What we got was:

250 MHz: m=250, p=6, s=2

So it looks like exynos4210_pms_change is ****ed... or in some case, the wrong old_index is getting passed.

Edit: Yup, after more instrumentation, things I'm seeing:

When the frequency is 1 GHz, exynos_target decides that old_index is 3... that's 800 MHz!!!!

I think our problem is here in exynos_target:

if (cpufreq_frequency_table_target(policy, freq_table,
freqs.old, relation, &old_index)) {
ret = -EINVAL;
goto out;
}

But I need to head out to a birthday party.

OH THAT'S IT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

This returns a bogus index because old_freq is higher than policy->max. In the Gingerbread code, freqs.old was obtained via s5pv310_getspeed - in ICS code, it's via policy->cur

So that difference in how freqs.old was obtained is likely why we have more robustness in GB - but this was broken in Gingerbread too.