diff options
| author | Benoît Monin <benoit.monin@bootlin.com> | 2026-09-29 14:14:12 +0200 |
|---|---|---|
| committer | Daniel Lezcano <daniel.lezcano@kernel.org> | 2026-10-02 12:01:11 +0200 |
| commit | a2cab84d6601d92f8b67b9dbdae568f5276bf841 (patch) | |
| tree | 2252a8de02eb341db47ea2704ff936efe15d9fba /include/linux/platform_data | |
| parent | a05997891e64b8e32733c0e062a062dcc3617a12 (diff) | |
| download | linux-next-a2cab84d6601d92f8b67b9dbdae568f5276bf841.tar.gz linux-next-a2cab84d6601d92f8b67b9dbdae568f5276bf841.zip | |
clocksource/drivers/mips-gic-timer: Use local counter on synced multi-cluster systems
In a multi-cluster MIPS system there is one GIC per cluster, each with
its own independent counter. These counters are not synchronized in
hardware and can drift relative to one another, which is why multi-
cluster systems currently fall back to gic_hpt_read_multicluster():
every clocksource read is redirected to cluster 0's counter via a
cross-cluster register access.
Instead, actively synchronize the counter of each secondary cluster
to cluster 0's counter as its CPUs come online. When the first CPU of
a cluster starts and the GIC counter is stopped, gic_sync_counter_64()
is used to align the local counter with cluster 0 on systems using 64-bit
CM accesses:
- the local counter is stopped, loaded with cluster 0's counter value
plus an accumulated offset, and restarted;
- the alignment is checked by reading the local counter, cluster 0's
counter and the local counter again (t0, t1, t2). If t1 lies between
t0 and t2 the two counters are considered in sync;
- otherwise the offset is refined by half of the measured error to
compensate for the cross-cluster access latency, and the process is
retried.
After a short delay the alignment is re-checked to confirm the counters
have not drifted apart, and only then is the cluster recorded as
synchronized in gic_synced_cl_map. Clusters with no cores and cluster
0 itself are marked synchronized up-front.
Once every cluster is synchronized, gic_clocksource_promote() sets
gic_use_local_counter so that gic_hpt_read() stops redirecting reads to
cluster 0 and uses the local counter instead. It also re-enables the GIC
VDSO clock mode and registers the GIC counter as the sched_clock. Systems
where synchronization cannot be achieved keep using the safe cross-cluster
read path.
The promotion is deferred to a workqueue because it is triggered from the
CPU hotplug STARTING callback, which runs with interrupts disabled, while
registering the sched_clock and switching the VDSO clock mode should be
done from process context.
Note that the clocksource is only promoted once when all clusters are
first online and all GIC counters are in sync. It is assumed that
even if a cluster is fully powered off and later powered on again,
gic_sync_counter_64() will be able to re-synchronize it. Said differently:
there is no support to "demote" the clocksource.
On the dual-cluster Mobileye EyeQ6H SoC, this allows four times faster
clock_gettime(CLOCK_MONOTONIC) and a much higher precision sched_clock
instead of jiffies.
Signed-off-by: Benoît Monin <benoit.monin@bootlin.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@kernel.org>
Reviewed-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Link: https://patch.msgid.link/20260929-sync-gic-counters-v4-5-ec70c4b60434@bootlin.com
Diffstat (limited to 'include/linux/platform_data')
0 files changed, 0 insertions, 0 deletions
