Thread (32 messages) 32 messages, 5 authors, 2011-06-29

[PATCHv2] omap2+: pm: cpufreq: Fix loops_per_jiffy calculation

From: Colin Cross <hidden>
Date: 2011-06-29 16:57:18
Also in: linux-omap

On Wed, Jun 29, 2011 at 7:00 AM, Russell King - ARM Linux
[off-list ref] wrote:
On Tue, Jun 28, 2011 at 04:59:57PM -0700, Colin Cross wrote:
quoted
On Tue, Jun 28, 2011 at 4:46 PM, Russell King - ARM Linux
[off-list ref] wrote:
quoted
On Tue, Jun 28, 2011 at 04:37:08PM -0700, Colin Cross wrote:
quoted
I don't think it affects bogomips - loops_per_jiffy can still be
calibrated and updated by cpufreq, udelay just wont use them.
No, you can't avoid it. ?__delay(), udelay(), and the global
loops_per_jiffy are all linked together - for instance this is how
the spinlock code has a 1s timeout:

static void __spin_lock_debug(raw_spinlock_t *lock)
{
? ? ? ?u64 loops = loops_per_jiffy * HZ;
? ? ? ?int print_once = 1;

? ? ? ?for (;;) {
? ? ? ? ? ? ? ?for (i = 0; i < loops; i++) {
? ? ? ? ? ? ? ? ? ? ? ?if (arch_spin_trylock(&lock->raw_lock))
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?return;
? ? ? ? ? ? ? ? ? ? ? ?__delay(1);
? ? ? ? ? ? ? ?}

which goes wrong for all the same reasons you're pointing out about
udelay(). ?So just restricting your argument to udelay() is not
realistic.
True, there are a few other users of loops_per_jiffy and __delay, but
it looks like __spin_lock_debug is the only one worth worrying about,
and it's timing is not as critical as udelay - worst case here is that
the warning occurs after 250 ms instead of 1s. ?Leaving
loops_per_jiffy and __delay intact, and fixing udelay, would still be
a net gain.
Other users of loops_per_jiffy are incorrect in any case:
The same conclusion I came to on a quick scan of other uses of
loops_per_jiffy...

<snip>
And strangely the major offender of this stuff are ARM drivers, not other
peoples stuff and not stuff in drivers/staging.

So I don't think its sane to ignore loops_per_jiffy and __delay, and just
concentrate on udelay().
But this I don't understand.  Every other use I found of
loops_per_jiffy is incorrect and should be changed.  Fixing udelay now
would not make them any worse - they would stay just as broken as they
were, so there is no need to couple a fix to udelay with fixing other
users of loops_per_jiffy.  Why block a legitimate fix because some
other broken code uses a variable whose behavior would not change?

If you are requesting an alternate change that would allow __delay to
continue to be used to time loops while irqs are off and jiffies is
not being updated, but also allows loops_per_jiffy to change in the
middle of a loop, while not increasing the number of instructions
executed in __delay, I don't think that is possible.  You could
replace __delay with a function that tests against a timer, and
loops_per_jiffy with the frequency of the counter divided by HZ, but
that would limit your spinlock spins to the frequency of the counter -
1MHz on Tegra.

Are there ever other legitimate uses of loops_per_jiffy/__delay?  I
don't think even the spinlock_debug use is correct - the number of
instructions executed in the loop before the __delay call (I count 17)
is going to be much higher than the instructions in the __delay(1)
call (3 instructions).  The spinlock debug timeout is already going to
be much longer than expected.  It looks to me like the only legitimate
use of loops_per_jiffy is to calculate the number of loops and call
__delay(loops) (exactly what udelay does), the overhead of doing
anything else will swamp the __delay call.  spinlock debug can get
away with its incorrect usage, because it doesn't really care how long
the delay is, and must have a minimum overhead.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help