diff mbox series

[v7,05/12] clocksource: mips-gic-timer: Always use cluster 0 counter as clocksource

Message ID 20241019071037.145314-6-arikalo@gmail.com (mailing list archive)
State Superseded
Headers show
Series MIPS: Support I6500 multi-cluster configuration | expand

Commit Message

Aleksandar Rikalo Oct. 19, 2024, 7:10 a.m. UTC
From: Paul Burton <paulburton@kernel.org>

In a multi-cluster MIPS system, there are multiple GICs - one in each
cluster - each of which has its independent counter. The counters in
each GIC are not synchronized in any way, so they can drift relative
to one another through the lifetime of the system. This is problematic
for a clock source which ought to be global.

Avoid problems by always accessing cluster 0's counter, using
cross-cluster register access. This adds overhead so it is applied only
on multi-cluster systems.

Signed-off-by: Paul Burton <paulburton@kernel.org>
Signed-off-by: Chao-ying Fu <cfu@wavecomp.com>
Signed-off-by: Dragan Mladjenovic <dragan.mladjenovic@syrmia.com>
Signed-off-by: Aleksandar Rikalo <arikalo@gmail.com>
Tested-by: Serge Semin <fancer.lancer@gmail.com>
---
 drivers/clocksource/mips-gic-timer.c | 39 +++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

Comments

Daniel Lezcano Oct. 28, 2024, 2:54 p.m. UTC | #1
On 19/10/2024 09:10, Aleksandar Rikalo wrote:
> From: Paul Burton <paulburton@kernel.org>
> 
> In a multi-cluster MIPS system, there are multiple GICs - one in each
> cluster - each of which has its independent counter. The counters in
> each GIC are not synchronized in any way, so they can drift relative
> to one another through the lifetime of the system. This is problematic
> for a clock source which ought to be global.
> 
> Avoid problems by always accessing cluster 0's counter, using
> cross-cluster register access. This adds overhead so it is applied only
> on multi-cluster systems.
> 
> Signed-off-by: Paul Burton <paulburton@kernel.org>
> Signed-off-by: Chao-ying Fu <cfu@wavecomp.com>
> Signed-off-by: Dragan Mladjenovic <dragan.mladjenovic@syrmia.com>
> Signed-off-by: Aleksandar Rikalo <arikalo@gmail.com>
> Tested-by: Serge Semin <fancer.lancer@gmail.com>
> ---

May I take this patch through the clocksource tree ?
Thomas Bogendoerfer Oct. 28, 2024, 3:15 p.m. UTC | #2
On Mon, Oct 28, 2024 at 03:54:48PM +0100, Daniel Lezcano wrote:
> On 19/10/2024 09:10, Aleksandar Rikalo wrote:
> > From: Paul Burton <paulburton@kernel.org>
> > 
> > In a multi-cluster MIPS system, there are multiple GICs - one in each
> > cluster - each of which has its independent counter. The counters in
> > each GIC are not synchronized in any way, so they can drift relative
> > to one another through the lifetime of the system. This is problematic
> > for a clock source which ought to be global.
> > 
> > Avoid problems by always accessing cluster 0's counter, using
> > cross-cluster register access. This adds overhead so it is applied only
> > on multi-cluster systems.
> > 
> > Signed-off-by: Paul Burton <paulburton@kernel.org>
> > Signed-off-by: Chao-ying Fu <cfu@wavecomp.com>
> > Signed-off-by: Dragan Mladjenovic <dragan.mladjenovic@syrmia.com>
> > Signed-off-by: Aleksandar Rikalo <arikalo@gmail.com>
> > Tested-by: Serge Semin <fancer.lancer@gmail.com>
> > ---
> 
> May I take this patch through the clocksource tree ?

sure, should be the best option.

Thomas.
Daniel Lezcano Oct. 28, 2024, 3:22 p.m. UTC | #3
On 28/10/2024 16:15, Thomas Bogendoerfer wrote:
> On Mon, Oct 28, 2024 at 03:54:48PM +0100, Daniel Lezcano wrote:
>> On 19/10/2024 09:10, Aleksandar Rikalo wrote:
>>> From: Paul Burton <paulburton@kernel.org>
>>>
>>> In a multi-cluster MIPS system, there are multiple GICs - one in each
>>> cluster - each of which has its independent counter. The counters in
>>> each GIC are not synchronized in any way, so they can drift relative
>>> to one another through the lifetime of the system. This is problematic
>>> for a clock source which ought to be global.
>>>
>>> Avoid problems by always accessing cluster 0's counter, using
>>> cross-cluster register access. This adds overhead so it is applied only
>>> on multi-cluster systems.
>>>
>>> Signed-off-by: Paul Burton <paulburton@kernel.org>
>>> Signed-off-by: Chao-ying Fu <cfu@wavecomp.com>
>>> Signed-off-by: Dragan Mladjenovic <dragan.mladjenovic@syrmia.com>
>>> Signed-off-by: Aleksandar Rikalo <arikalo@gmail.com>
>>> Tested-by: Serge Semin <fancer.lancer@gmail.com>
>>> ---
>>
>> May I take this patch through the clocksource tree ?
> 
> sure, should be the best option.

Ok, thanks

Can you add your tag ?
Thomas Bogendoerfer Oct. 28, 2024, 3:47 p.m. UTC | #4
On Mon, Oct 28, 2024 at 04:22:55PM +0100, Daniel Lezcano wrote:
> On 28/10/2024 16:15, Thomas Bogendoerfer wrote:
> > On Mon, Oct 28, 2024 at 03:54:48PM +0100, Daniel Lezcano wrote:
> > > On 19/10/2024 09:10, Aleksandar Rikalo wrote:
> > > > From: Paul Burton <paulburton@kernel.org>
> > > > 
> > > > In a multi-cluster MIPS system, there are multiple GICs - one in each
> > > > cluster - each of which has its independent counter. The counters in
> > > > each GIC are not synchronized in any way, so they can drift relative
> > > > to one another through the lifetime of the system. This is problematic
> > > > for a clock source which ought to be global.
> > > > 
> > > > Avoid problems by always accessing cluster 0's counter, using
> > > > cross-cluster register access. This adds overhead so it is applied only
> > > > on multi-cluster systems.
> > > > 
> > > > Signed-off-by: Paul Burton <paulburton@kernel.org>
> > > > Signed-off-by: Chao-ying Fu <cfu@wavecomp.com>
> > > > Signed-off-by: Dragan Mladjenovic <dragan.mladjenovic@syrmia.com>
> > > > Signed-off-by: Aleksandar Rikalo <arikalo@gmail.com>
> > > > Tested-by: Serge Semin <fancer.lancer@gmail.com>
> > > > ---
> > > 
> > > May I take this patch through the clocksource tree ?
> > 
> > sure, should be the best option.
> 
> Ok, thanks
> 
> Can you add your tag ?

it's only touching drivers/clocksource, but if you want

Acked-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Daniel Lezcano Oct. 28, 2024, 4:09 p.m. UTC | #5
On 19/10/2024 09:10, Aleksandar Rikalo wrote:
> From: Paul Burton <paulburton@kernel.org>
> 
> In a multi-cluster MIPS system, there are multiple GICs - one in each
> cluster - each of which has its independent counter. The counters in
> each GIC are not synchronized in any way, so they can drift relative
> to one another through the lifetime of the system. This is problematic
> for a clock source which ought to be global.
> 
> Avoid problems by always accessing cluster 0's counter, using
> cross-cluster register access. This adds overhead so it is applied only
> on multi-cluster systems.
> 
> Signed-off-by: Paul Burton <paulburton@kernel.org>
> Signed-off-by: Chao-ying Fu <cfu@wavecomp.com>
> Signed-off-by: Dragan Mladjenovic <dragan.mladjenovic@syrmia.com>
> Signed-off-by: Aleksandar Rikalo <arikalo@gmail.com>
> Tested-by: Serge Semin <fancer.lancer@gmail.com>
> ---


Applied, thanks
diff mbox series

Patch

diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c
index 110347707ff9..7907b740497a 100644
--- a/drivers/clocksource/mips-gic-timer.c
+++ b/drivers/clocksource/mips-gic-timer.c
@@ -166,6 +166,37 @@  static u64 gic_hpt_read(struct clocksource *cs)
 	return gic_read_count();
 }
 
+static u64 gic_hpt_read_multicluster(struct clocksource *cs)
+{
+	unsigned int hi, hi2, lo;
+	u64 count;
+
+	mips_cm_lock_other(0, 0, 0, CM_GCR_Cx_OTHER_BLOCK_GLOBAL);
+
+	if (mips_cm_is64) {
+		count = read_gic_redir_counter();
+		goto out;
+	}
+
+	hi = read_gic_redir_counter_32h();
+	while (true) {
+		lo = read_gic_redir_counter_32l();
+
+		/* If hi didn't change then lo didn't wrap & we're done */
+		hi2 = read_gic_redir_counter_32h();
+		if (hi2 == hi)
+			break;
+
+		/* Otherwise, repeat with the latest hi value */
+		hi = hi2;
+	}
+
+	count = (((u64)hi) << 32) + lo;
+out:
+	mips_cm_unlock_other();
+	return count;
+}
+
 static struct clocksource gic_clocksource = {
 	.name			= "GIC",
 	.read			= gic_hpt_read,
@@ -203,6 +234,11 @@  static int __init __gic_clocksource_init(void)
 		gic_clocksource.rating = 200;
 	gic_clocksource.rating += clamp(gic_frequency / 10000000, 0, 99);
 
+	if (mips_cps_multicluster_cpus()) {
+		gic_clocksource.read = &gic_hpt_read_multicluster;
+		gic_clocksource.vdso_clock_mode = VDSO_CLOCKMODE_NONE;
+	}
+
 	ret = clocksource_register_hz(&gic_clocksource, gic_frequency);
 	if (ret < 0)
 		pr_warn("Unable to register clocksource\n");
@@ -261,7 +297,8 @@  static int __init gic_clocksource_of_init(struct device_node *node)
 	 * stable CPU frequency or on the platforms with CM3 and CPU frequency
 	 * change performed by the CPC core clocks divider.
 	 */
-	if (mips_cm_revision() >= CM_REV_CM3 || !IS_ENABLED(CONFIG_CPU_FREQ)) {
+	if ((mips_cm_revision() >= CM_REV_CM3 || !IS_ENABLED(CONFIG_CPU_FREQ)) &&
+	     !mips_cps_multicluster_cpus()) {
 		sched_clock_register(mips_cm_is64 ?
 				     gic_read_count_64 : gic_read_count_2x32,
 				     gic_count_width, gic_frequency);