[Letux-kernel] jz4730-i2c - clocksource

H. Nikolaus Schaller hns at goldelico.com
Sat Mar 6 08:52:57 CET 2021


Hi Paul,
after reading chapters 1-5 of

	https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-1.html
	(really good material and fluent to read!!!)

I got a much better understanding how these pieces work together.
Like jiffies, clocksource, clock_event_device, timer, ktime_get, set_next_event, interrupts...

This made me come to the conclusion that part of the problem may be from non-monotonic behaviour of the
clocksource. This would make some calculations go wrong and the kernel missing some interrupts and not
waking up from idle.

Two reasons could exist for non-monotinic behaviour:
* timer counter readout has glitches as indicated by the data sheet
* timer is overrunning too fast loosing cycles

But with one test I think I have some breakthrough. I extended the clocksource timer to 26 bits to make
it overrun only every 18.6 seconds (assuming 3.6 MHz clock). This makes my code to printk that an overrun
did occur happen every ca. 20 seconds.

What I observed is that sometimes the timer jumps back to quite high values indicating a latency of up
to 0.3 seconds. This would indeed not be covered by a 16 bit counter.

sysbench --num-threads=1 --test=cpu --cpu-max-prime=1 run

also works now - with ingenic-timer:

root at letux:~# 
root at letux:~# sysbench --num-threads=1 --test=cpu --cpu-max-prime=1 run
sysbench 0.4.12:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1

Doing CPU performance benchmark

Threads started!
[ 4514.684433] ingenic_tcu_timer_read: 67108350 -> 2753
[ 4514.694391] ingenic_tcu_timer_read: 67108350 -> 2789
Done.

Maximum prime number checked in CPU test: 1


Test execution summary:
    total time:                          16.4396s
    total number of events:              10000
    total time taken by event execution: 16.2797
    per-request statistics:
         min:                                  1.30ms
         avg:                                  1.63ms
         max:                                 24.03ms
[ 4532.893411] ingenic_tcu_timer_read: 67091847 -> 19467
[ 4532.903534] ingenic_tcu_timer_read: 67091847 -> 19503
         approx.  95 percentile:               0.02ms

Threads fairness:
    events (avg/stddev):           10000.0000/0.00
    execution time (avg/stddev):   16.2797/0.00

root at letux:~# 

for comparison some ARM:

root at letux:~# sysbench --num-threads=1 --test=cpu --cpu-max-prime=1 run
sysbench 0.4.12:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1

Doing CPU performance benchmark

Threads started!
Done.

Maximum prime number checked in CPU test: 1


Test execution summary:
    total time:                          0.0558s
    total number of events:              10000
    total time taken by event execution: 0.0403
    per-request statistics:
         min:                                  0.00ms
         avg:                                  0.00ms
         max:                                  0.31ms
         approx.  95 percentile:               0.00ms

Threads fairness:
    events (avg/stddev):           10000.0000/0.00
    execution time (avg/stddev):   0.0403/0.00

root at letux:~# 

So that is still quite a factor in speed which can not be explained
by MIPS vs. ARM and different clock speed (300 MHz vs. 800 MHz)...

So the combination of more bits for the clocksource (but not 32)
with bypassing regmap seems to make the ingenic-timer finally work.

and makes the sysbench succeed (which was the initial problem that
it did not work at all).

But the whole system is still horribly slow when starting X11
or running sysbench.

I still wonder if we could be running without cache for example?
Any idea how to check that? Maybe U-Boot did not enable it?

BR,
Nikolaus


> Am 03.03.2021 um 23:35 schrieb Paul Boddie <paul at boddie.org.uk>:
> 
> Nikolaus,
> 
> Sorry not to have responded recently! I have been reading the messages, but I 
> don't have many ideas at the moment.
> 
>> I have added another piece of trace code.
>> 
>> There was another bug that ingenic_tcu_clocksource_init()
>> did disable the timer underrun interrupt. And it was nowhere
>> enabled in the driver.
>> 
>> See
>> 
>> 	https://git.goldelico.com/?p=letux-kernel.git;a=blob;f=drivers/clocksource/
>> ingenic-timer.c;h=c6c17c856a15078f9da8e10fe57ca6a5adc0c68a;hb=refs/heads/let
>> ux/jz4730-v5#l263
>> 
>> The mask also resets TCU_JZ4730_TCSR_EN to 0 disabling underflow interrupts.
> 
> Here, it is possible that the mismatch between JZ4730 and JZ4740 confuses 
> things. TCSR on the JZ4730 includes interrupt control bits, whereas TCSR on 
> the JZ4740 only concerns itself with configuring and enabling the timer.
> 
> So, the timer initialisation code is aiming to reset the timer to a base 
> state, but on the JZ4740 it will not change the interrupt configuration. 
> However, the code for the JZ4730 (as I wrote it, I guess) will also disable 
> the interrupts.
> 
>> Now with my logging code I can see that the timer is decrementing
>> and when underrunning, OST0 is flagged in ICSR and IPSR.
>> 
>> But this does not trigger any interrupt handler, the bit remains set
>> and nothing happens.
> 
> Looking at the Fiasco support for the Minibook, useful as a checklist, I do 
> the following to get the OST/TCU working:
> 
> * Clear the IRQ underflow flag in TCSR
> * Set the IRQ enable flag in TCSR
> * Set the enable flag in TER
> 
> The equivalent for the JZ4740-based Ben NanoNote involves this:
> 
> * Clear the "full" IRQ flag using TFCR (the clearing variant of TFR)
> * Clear the "full" IRQ mask flag using TMCR (the clearing variant of TMR)
> * Set the enable flag using TESR (the setting variant of TER)
> 
> Oddly, I don't see any use of the mask registers in the Linux drivers, but the 
> masks will be clear by default and thus cause interrupts to be delivered, 
> anyway. Meanwhile, the JZ4730 will not have the interrupts enabled in TCSR by 
> default.
> 
> I don't really find much of this easy to follow, but it is very possible that 
> we (mostly I) missed something earlier and we (mostly you) are having to track 
> down what that was. Obviously, I am rather sorry about that!
> 
> Thanks for keeping going, though!
> 
> Paul
> 
> P.S. I just fetched your updated code, so I will try and find some time to 
> take a look in the near future.
> 
> 



More information about the Letux-kernel mailing list