linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] R4000 clock enhancements for Loongson
@ 2020-08-17  3:46 Jiaxun Yang
  2020-08-17  3:46 ` [PATCH 1/7] MIPS: sync-r4k: Rework to be many cores firendly Jiaxun Yang
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Jiaxun Yang @ 2020-08-17  3:46 UTC (permalink / raw)
  To: linux-mips
  Cc: Jiaxun Yang, Thomas Bogendoerfer, Huacai Chen,
	Aleksandar Markovic, Serge Semin, Paul Burton, WANG Xuerui,
	周琰杰 (Zhou Yanjie),
	Liangliang Huang, afzal mohammed, Peter Zijlstra (Intel),
	Peter Xu, Sergey Korolev, Alexey Malahov, Marc Zyngier,
	Anup Patel, Ming Lei, Thomas Gleixner, Atish Patra, Ulf Hansson,
	Daniel Jordan, Steven Price, Mike Leach, Michael Kelley,
	linux-kernel, kvm

Jiaxun Yang (7):
  MIPS: sync-r4k: Rework to be many cores firendly
  MIPS: time: Use CPUHUP to handle r4k timer
  MIPS: Kconfig: Always select SYNC_R4K if both SMP and r4k timer is
    enabled
  MIPS: Loongson64: Remove custom count sync procudure
  MIPS: cevt-r4k: Don't handle IRQ if clockevent is not enabled
  MIPS: cevt-r4k: Enable intimer for Loongson CPUs with extimer
  MIPS: KVM: Don't use htimer when INTIMER is disabled

 arch/mips/Kconfig                    |  10 +-
 arch/mips/include/asm/cpu-features.h |   4 +
 arch/mips/include/asm/cpu.h          |   1 +
 arch/mips/include/asm/r4k-timer.h    |   5 -
 arch/mips/include/asm/smp.h          |   1 -
 arch/mips/include/asm/time.h         |  28 +++---
 arch/mips/kernel/cevt-r4k.c          |  65 ++++++++++--
 arch/mips/kernel/cpu-probe.c         |   6 +-
 arch/mips/kernel/smp.c               |   5 -
 arch/mips/kernel/sync-r4k.c          | 143 ++++++++++++---------------
 arch/mips/kernel/time.c              |  22 ++++-
 arch/mips/kvm/vz.c                   |   6 ++
 arch/mips/loongson64/smp.c           |  32 +-----
 include/linux/cpuhotplug.h           |   1 +
 14 files changed, 173 insertions(+), 156 deletions(-)

-- 
2.28.0.rc1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/7] MIPS: sync-r4k: Rework to be many cores firendly
  2020-08-17  3:46 [PATCH 0/7] R4000 clock enhancements for Loongson Jiaxun Yang
@ 2020-08-17  3:46 ` Jiaxun Yang
  2020-08-17  7:55   ` peterz
  2020-08-17  3:46 ` [PATCH 2/7] MIPS: time: Use CPUHUP to handle r4k timer Jiaxun Yang
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 9+ messages in thread
From: Jiaxun Yang @ 2020-08-17  3:46 UTC (permalink / raw)
  To: linux-mips
  Cc: Jiaxun Yang, Thomas Bogendoerfer, Huacai Chen,
	Aleksandar Markovic, Paul Burton, Serge Semin, WANG Xuerui,
	周琰杰 (Zhou Yanjie),
	Liangliang Huang, afzal mohammed, Ingo Molnar, Peter Xu,
	Peter Zijlstra (Intel),
	Sergey Korolev, Alexey Malahov, Marc Zyngier, Anup Patel,
	Palmer Dabbelt, Atish Patra, Michael Kelley, Steven Price,
	Daniel Jordan, Ming Lei, Ulf Hansson, Mike Leach, linux-kernel,
	kvm

The original sync-r4k did a good job on reducing jitter by determine
the "next time value", but it has a limitation that when we have lots
of cores, the timewrap on CPU0 will become unaccpetable. That will also
happen when CPU Hotplug is enabled and the counter needs to be synchronised
at every plug event.

Here we reworked the whole procdure. Now the synchronise event on CPU0
is triggered by smp call function, and we won't touch the count on CPU0
at all.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/include/asm/r4k-timer.h |   5 --
 arch/mips/kernel/smp.c            |   2 -
 arch/mips/kernel/sync-r4k.c       | 143 +++++++++++++-----------------
 3 files changed, 61 insertions(+), 89 deletions(-)

diff --git a/arch/mips/include/asm/r4k-timer.h b/arch/mips/include/asm/r4k-timer.h
index afe9e0e03fe9..2789d2fc5e23 100644
--- a/arch/mips/include/asm/r4k-timer.h
+++ b/arch/mips/include/asm/r4k-timer.h
@@ -12,15 +12,10 @@
 
 #ifdef CONFIG_SYNC_R4K
 
-extern void synchronise_count_master(int cpu);
 extern void synchronise_count_slave(int cpu);
 
 #else
 
-static inline void synchronise_count_master(int cpu)
-{
-}
-
 static inline void synchronise_count_slave(int cpu)
 {
 }
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 48d84d5fcc36..ead9ac883241 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -444,8 +444,6 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
 		return -EIO;
 	}
 
-	synchronise_count_master(cpu);
-
 	/* Wait for CPU to finish startup & mark itself online before return */
 	wait_for_completion(&cpu_running);
 	return 0;
diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c
index abdd7aaa3311..c3e36d6d57fa 100644
--- a/arch/mips/kernel/sync-r4k.c
+++ b/arch/mips/kernel/sync-r4k.c
@@ -1,122 +1,101 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Count register synchronisation.
- *
- * All CPUs will have their count registers synchronised to the CPU0 next time
- * value. This can cause a small timewarp for CPU0. All other CPU's should
- * not have done anything significant (but they may have had interrupts
- * enabled briefly - prom_smp_finish() should not be responsible for enabling
- * interrupts...)
  */
 
 #include <linux/kernel.h>
 #include <linux/irqflags.h>
 #include <linux/cpumask.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
 
 #include <asm/r4k-timer.h>
 #include <linux/atomic.h>
 #include <asm/barrier.h>
 #include <asm/mipsregs.h>
 
-static unsigned int initcount = 0;
-static atomic_t count_count_start = ATOMIC_INIT(0);
-static atomic_t count_count_stop = ATOMIC_INIT(0);
+#define STAGE_START		0
+#define STAGE_MASTER_READY	1
+#define STAGE_SLAVE_SYNCED	2
 
-#define COUNTON 100
-#define NR_LOOPS 3
+static unsigned int cur_count;
+static unsigned int fini_count;
+static atomic_t sync_stage = ATOMIC_INIT(0);
+static DEFINE_RAW_SPINLOCK(sync_r4k_lock);
 
-void synchronise_count_master(int cpu)
+#define MAX_LOOPS	1000
+
+void synchronise_count_master(void *unused)
 {
-	int i;
 	unsigned long flags;
+	long delta;
+	int i;
 
-	pr_info("Synchronize counters for CPU %u: ", cpu);
+	if (atomic_read(&sync_stage) != STAGE_START)
+		BUG();
 
 	local_irq_save(flags);
 
-	/*
-	 * We loop a few times to get a primed instruction cache,
-	 * then the last pass is more or less synchronised and
-	 * the master and slaves each set their cycle counters to a known
-	 * value all at once. This reduces the chance of having random offsets
-	 * between the processors, and guarantees that the maximum
-	 * delay between the cycle counters is never bigger than
-	 * the latency of information-passing (cachelines) between
-	 * two CPUs.
-	 */
-
-	for (i = 0; i < NR_LOOPS; i++) {
-		/* slaves loop on '!= 2' */
-		while (atomic_read(&count_count_start) != 1)
-			mb();
-		atomic_set(&count_count_stop, 0);
-		smp_wmb();
+	cur_count = read_c0_count();
+	smp_wmb();
+	atomic_inc(&sync_stage); /* inc to STAGE_MASTER_READY */
 
-		/* Let the slave writes its count register */
-		atomic_inc(&count_count_start);
-
-		/* Count will be initialised to current timer */
-		if (i == 1)
-			initcount = read_c0_count();
-
-		/*
-		 * Everyone initialises count in the last loop:
-		 */
-		if (i == NR_LOOPS-1)
-			write_c0_count(initcount);
-
-		/*
-		 * Wait for slave to leave the synchronization point:
-		 */
-		while (atomic_read(&count_count_stop) != 1)
-			mb();
-		atomic_set(&count_count_start, 0);
+	for (i = 0; i < MAX_LOOPS; i++) {
+		cur_count = read_c0_count();
 		smp_wmb();
-		atomic_inc(&count_count_stop);
+		if (atomic_read(&sync_stage) == STAGE_SLAVE_SYNCED)
+			break;
 	}
-	/* Arrange for an interrupt in a short while */
-	write_c0_compare(read_c0_count() + COUNTON);
+
+	delta = read_c0_count() - fini_count;
 
 	local_irq_restore(flags);
 
-	/*
-	 * i386 code reported the skew here, but the
-	 * count registers were almost certainly out of sync
-	 * so no point in alarming people
-	 */
-	pr_cont("done.\n");
+	if (i == MAX_LOOPS)
+		pr_err("sync-r4k: Master: synchronise timeout\n");
+	else
+		pr_info("sync-r4k: Master: synchronise succeed, maximum delta: %ld\n", delta);
+
+	return;
 }
 
 void synchronise_count_slave(int cpu)
 {
 	int i;
 	unsigned long flags;
+	call_single_data_t csd;
 
-	local_irq_save(flags);
+	raw_spin_lock(&sync_r4k_lock);
 
-	/*
-	 * Not every cpu is online at the time this gets called,
-	 * so we first wait for the master to say everyone is ready
-	 */
-
-	for (i = 0; i < NR_LOOPS; i++) {
-		atomic_inc(&count_count_start);
-		while (atomic_read(&count_count_start) != 2)
-			mb();
-
-		/*
-		 * Everyone initialises count in the last loop:
-		 */
-		if (i == NR_LOOPS-1)
-			write_c0_count(initcount);
-
-		atomic_inc(&count_count_stop);
-		while (atomic_read(&count_count_stop) != 2)
-			mb();
+	/* Let variables get attention from cache */
+	for (i = 0; i < MAX_LOOPS; i++) {
+		cur_count++;
+		fini_count += cur_count;
+		cur_count += fini_count;
 	}
-	/* Arrange for an interrupt in a short while */
-	write_c0_compare(read_c0_count() + COUNTON);
+
+	atomic_set(&sync_stage, STAGE_START);
+	csd.func = synchronise_count_master;
+
+	/* Master count is always CPU0 */
+	if (smp_call_function_single_async(0, &csd)) {
+		pr_err("sync-r4k: Salve: Failed to call master\n");
+		raw_spin_unlock(&sync_r4k_lock);
+		return;
+	}
+
+	local_irq_save(flags);
+
+	/* Wait until master ready */
+	while (atomic_read(&sync_stage) != STAGE_MASTER_READY)
+		cpu_relax();
+
+	write_c0_count(cur_count);
+	fini_count = read_c0_count();
+	smp_wmb();
+	atomic_inc(&sync_stage); /* inc to STAGE_SLAVE_SYNCED */
 
 	local_irq_restore(flags);
+
+	raw_spin_unlock(&sync_r4k_lock);
 }
-#undef NR_LOOPS
-- 
2.28.0.rc1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/7] MIPS: time: Use CPUHUP to handle r4k timer
  2020-08-17  3:46 [PATCH 0/7] R4000 clock enhancements for Loongson Jiaxun Yang
  2020-08-17  3:46 ` [PATCH 1/7] MIPS: sync-r4k: Rework to be many cores firendly Jiaxun Yang
@ 2020-08-17  3:46 ` Jiaxun Yang
  2020-08-17  3:46 ` [PATCH 3/7] MIPS: Kconfig: Always select SYNC_R4K if both SMP and r4k timer is enabled Jiaxun Yang
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jiaxun Yang @ 2020-08-17  3:46 UTC (permalink / raw)
  To: linux-mips
  Cc: Jiaxun Yang, Thomas Bogendoerfer, Huacai Chen,
	Aleksandar Markovic, Serge Semin, Paul Burton, WANG Xuerui,
	周琰杰 (Zhou Yanjie),
	Liangliang Huang, afzal mohammed, Peter Xu, Ingo Molnar,
	Peter Zijlstra (Intel),
	Sergey Korolev, Alexey Malahov, Anup Patel, Marc Zyngier,
	Michael Kelley, Greg Kroah-Hartman, Daniel Wagner, Mike Leach,
	Atish Patra, Ming Lei, Steven Price, linux-kernel, kvm

There is no need to hijack initialization procudre to take care of
r4k timer we have CPUHP framework to deal with the CPU plug sequence.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/include/asm/time.h | 28 +++++++++++++++-------------
 arch/mips/kernel/cevt-r4k.c  | 30 ++++++++++++++++++++++--------
 arch/mips/kernel/smp.c       |  3 ---
 arch/mips/kernel/time.c      | 22 ++++++++++++++++++++--
 include/linux/cpuhotplug.h   |  1 +
 5 files changed, 58 insertions(+), 26 deletions(-)

diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h
index e855a3611d92..d00a5b05a420 100644
--- a/arch/mips/include/asm/time.h
+++ b/arch/mips/include/asm/time.h
@@ -39,30 +39,32 @@ extern int __weak get_c0_perfcount_int(void);
  * Initialize the calling CPU's compare interrupt as clockevent device
  */
 extern unsigned int get_c0_compare_int(void);
-extern int r4k_clockevent_init(void);
 
-static inline int mips_clockevent_init(void)
-{
 #ifdef CONFIG_CEVT_R4K
-	return r4k_clockevent_init();
+extern int r4k_clockevent_init(void);
+extern int r4k_clockevent_percpu_init(int cpu);
 #else
-	return -ENXIO;
-#endif
+static inline int r4k_clockevent_init(void)
+{
+	return -ENODEV;
+}
+static inline int r4k_clockevent_percpu_init(int cpu)
+{
+	return -ENODEV;
 }
+#endif
 
 /*
  * Initialize the count register as a clocksource
  */
-extern int init_r4k_clocksource(void);
-
-static inline int init_mips_clocksource(void)
-{
 #ifdef CONFIG_CSRC_R4K
-	return init_r4k_clocksource();
+extern int init_r4k_clocksource(void);
 #else
-	return 0;
-#endif
+static inline int init_r4k_clocksource(void)
+{
+	return -ENODEV;
 }
+#endif
 
 static inline void clockevent_set_clock(struct clock_event_device *cd,
 					unsigned int clock)
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 995ad9e69ded..f0c52d751d0a 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -294,10 +294,8 @@ core_initcall(r4k_register_cpufreq_notifier);
 
 #endif /* !CONFIG_CPU_FREQ */
 
-int r4k_clockevent_init(void)
+int r4k_clockevent_percpu_init(int cpu)
 {
-	unsigned long flags = IRQF_PERCPU | IRQF_TIMER | IRQF_SHARED;
-	unsigned int cpu = smp_processor_id();
 	struct clock_event_device *cd;
 	unsigned int irq, min_delta;
 
@@ -307,11 +305,6 @@ int r4k_clockevent_init(void)
 	if (!c0_compare_int_usable())
 		return -ENXIO;
 
-	/*
-	 * With vectored interrupts things are getting platform specific.
-	 * get_c0_compare_int is a hook to allow a platform to return the
-	 * interrupt number of its liking.
-	 */
 	irq = get_c0_compare_int();
 
 	cd = &per_cpu(mips_clockevent_device, cpu);
@@ -331,9 +324,30 @@ int r4k_clockevent_init(void)
 
 	clockevents_config_and_register(cd, mips_hpt_frequency, min_delta, 0x7fffffff);
 
+	return 0;
+}
+
+int r4k_clockevent_init(void)
+{
+	int ret;
+	unsigned int irq;
+	unsigned long flags = IRQF_PERCPU | IRQF_TIMER | IRQF_SHARED;
+
+	ret = r4k_clockevent_percpu_init(0);
+	if (ret)
+		return ret;
+
+
 	if (cp0_timer_irq_installed)
 		return 0;
 
+	/*
+	 * With vectored interrupts things are getting platform specific.
+	 * get_c0_compare_int is a hook to allow a platform to return the
+	 * interrupt number of its liking.
+	 */
+	irq = get_c0_compare_int();
+
 	cp0_timer_irq_installed = 1;
 
 	if (request_irq(irq, c0_compare_interrupt, flags, "timer",
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index ead9ac883241..0ca4f7cf6402 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -337,7 +337,6 @@ asmlinkage void start_secondary(void)
 
 	cpu_probe();
 	per_cpu_trap_init(false);
-	mips_clockevent_init();
 	mp_ops->init_secondary();
 	cpu_report();
 	maar_init();
@@ -358,8 +357,6 @@ asmlinkage void start_secondary(void)
 	/* Notify boot CPU that we're starting & ready to sync counters */
 	complete(&cpu_starting);
 
-	synchronise_count_slave(cpu);
-
 	/* The CPU is running and counters synchronised, now mark it online */
 	set_cpu_online(cpu, true);
 
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index caa01457dce6..9b16e60aaa30 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -8,6 +8,7 @@
  */
 #include <linux/bug.h>
 #include <linux/clockchips.h>
+#include <linux/cpuhotplug.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -24,6 +25,7 @@
 #include <asm/cpu-features.h>
 #include <asm/cpu-type.h>
 #include <asm/div64.h>
+#include <asm/r4k-timer.h>
 #include <asm/time.h>
 
 #ifdef CONFIG_CPU_FREQ
@@ -155,6 +157,16 @@ static __init int cpu_has_mfc0_count_bug(void)
 	return 0;
 }
 
+#if defined(CONFIG_CEVT_R4K) || defined(CONFIG_CSRC_R4K)
+static int mips_r4k_timer_starting_cpu(unsigned int cpu)
+{
+	synchronise_count_slave(cpu);
+	r4k_clockevent_percpu_init(cpu);
+
+	return 0;
+}
+#endif
+
 void __init time_init(void)
 {
 	plat_time_init();
@@ -167,6 +179,12 @@ void __init time_init(void)
 	 * timer interrupt isn't reliable; the interference doesn't
 	 * matter then, because we don't use the interrupt.
 	 */
-	if (mips_clockevent_init() != 0 || !cpu_has_mfc0_count_bug())
-		init_mips_clocksource();
+	if (r4k_clockevent_init() != 0 || !cpu_has_mfc0_count_bug())
+		init_r4k_clocksource();
+
+#if defined(CONFIG_CEVT_R4K) || defined(CONFIG_CSRC_R4K)
+	cpuhp_setup_state_nocalls(CPUHP_AP_MIPS_R4K_TIMER_STARTING,
+			  "clockevents/mips/r4k/timer:starting",
+			  mips_r4k_timer_starting_cpu, NULL);
+#endif
 }
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 191772d4a4d7..163288803cd4 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -129,6 +129,7 @@ enum cpuhp_state {
 	CPUHP_AP_TEGRA_TIMER_STARTING,
 	CPUHP_AP_ARMADA_TIMER_STARTING,
 	CPUHP_AP_MARCO_TIMER_STARTING,
+	CPUHP_AP_MIPS_R4K_TIMER_STARTING,
 	CPUHP_AP_MIPS_GIC_TIMER_STARTING,
 	CPUHP_AP_ARC_TIMER_STARTING,
 	CPUHP_AP_RISCV_TIMER_STARTING,
-- 
2.28.0.rc1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/7] MIPS: Kconfig: Always select SYNC_R4K if both SMP and r4k timer is enabled
  2020-08-17  3:46 [PATCH 0/7] R4000 clock enhancements for Loongson Jiaxun Yang
  2020-08-17  3:46 ` [PATCH 1/7] MIPS: sync-r4k: Rework to be many cores firendly Jiaxun Yang
  2020-08-17  3:46 ` [PATCH 2/7] MIPS: time: Use CPUHUP to handle r4k timer Jiaxun Yang
@ 2020-08-17  3:46 ` Jiaxun Yang
  2020-08-17  3:46 ` [PATCH 4/7] MIPS: Loongson64: Remove custom count sync procudure Jiaxun Yang
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jiaxun Yang @ 2020-08-17  3:46 UTC (permalink / raw)
  To: linux-mips
  Cc: Jiaxun Yang, Thomas Bogendoerfer, Huacai Chen,
	Aleksandar Markovic, Serge Semin, Paul Burton, WANG Xuerui,
	周琰杰 (Zhou Yanjie),
	Liangliang Huang, afzal mohammed, Peter Xu, Ingo Molnar,
	Sergey Korolev, Alexey Malahov, Anup Patel, Marc Zyngier,
	Daniel Jordan, Michael Kelley, Palmer Dabbelt, Ulf Hansson,
	Steven Price, Atish Patra, Ming Lei, linux-kernel, kvm

Now all platforms are sharing sync-r4k procdure, there is no need to let
platform to select it.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/Kconfig | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 880680c0df31..7674f4379d39 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -234,7 +234,6 @@ config BMIPS_GENERIC
 	select USE_OF
 	select CEVT_R4K
 	select CSRC_R4K
-	select SYNC_R4K
 	select COMMON_CLK
 	select BCM6345_L1_IRQ
 	select BCM7038_L1_IRQ
@@ -291,7 +290,6 @@ config BCM63XX
 	select BOOT_RAW
 	select CEVT_R4K
 	select CSRC_R4K
-	select SYNC_R4K
 	select DMA_NONCOHERENT
 	select IRQ_MIPS_CPU
 	select SYS_SUPPORTS_32BIT_KERNEL
@@ -726,7 +724,6 @@ config SGI_IP30
 	select BOOT_ELF64
 	select CEVT_R4K
 	select CSRC_R4K
-	select SYNC_R4K if SMP
 	select ZONE_DMA32
 	select HAVE_PCI
 	select IRQ_MIPS_CPU
@@ -979,7 +976,6 @@ config NLM_XLR_BOARD
 	select CSRC_R4K
 	select IRQ_MIPS_CPU
 	select ZONE_DMA32 if 64BIT
-	select SYNC_R4K
 	select SYS_HAS_EARLY_PRINTK
 	select SYS_SUPPORTS_ZBOOT
 	select SYS_SUPPORTS_ZBOOT_UART16550
@@ -1006,7 +1002,6 @@ config NLM_XLP_BOARD
 	select CSRC_R4K
 	select IRQ_MIPS_CPU
 	select ZONE_DMA32 if 64BIT
-	select SYNC_R4K
 	select SYS_HAS_EARLY_PRINTK
 	select USE_OF
 	select SYS_SUPPORTS_ZBOOT
@@ -1076,6 +1071,7 @@ config CEVT_GT641XX
 	bool
 
 config CEVT_R4K
+	select SYNC_R4K if SMP
 	bool
 
 config CEVT_SB1250
@@ -1091,6 +1087,7 @@ config CSRC_IOASIC
 	bool
 
 config CSRC_R4K
+	select SYNC_R4K if SMP
 	select CLOCKSOURCE_WATCHDOG if CPU_FREQ
 	bool
 
@@ -2361,7 +2358,6 @@ config MIPS_MT_SMP
 	depends on SYS_SUPPORTS_MULTITHREADING && !CPU_MIPSR6 && !CPU_MICROMIPS
 	select CPU_MIPSR2_IRQ_VI
 	select CPU_MIPSR2_IRQ_EI
-	select SYNC_R4K
 	select MIPS_MT
 	select SMP
 	select SMP_UP
@@ -2465,7 +2461,6 @@ config MIPS_CMP
 	bool "MIPS CMP framework support (DEPRECATED)"
 	depends on SYS_SUPPORTS_MIPS_CMP && !CPU_MIPSR6
 	select SMP
-	select SYNC_R4K
 	select SYS_SUPPORTS_SMP
 	select WEAK_ORDERING
 	default n
@@ -2483,7 +2478,6 @@ config MIPS_CPS
 	select MIPS_CM
 	select MIPS_CPS_PM if HOTPLUG_CPU
 	select SMP
-	select SYNC_R4K if (CEVT_R4K || CSRC_R4K)
 	select SYS_SUPPORTS_HOTPLUG_CPU
 	select SYS_SUPPORTS_SCHED_SMT if CPU_MIPSR6
 	select SYS_SUPPORTS_SMP
-- 
2.28.0.rc1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/7] MIPS: Loongson64: Remove custom count sync procudure
  2020-08-17  3:46 [PATCH 0/7] R4000 clock enhancements for Loongson Jiaxun Yang
                   ` (2 preceding siblings ...)
  2020-08-17  3:46 ` [PATCH 3/7] MIPS: Kconfig: Always select SYNC_R4K if both SMP and r4k timer is enabled Jiaxun Yang
@ 2020-08-17  3:46 ` Jiaxun Yang
  2020-08-17  3:46 ` [PATCH 5/7] MIPS: cevt-r4k: Don't handle IRQ if clockevent is not enabled Jiaxun Yang
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jiaxun Yang @ 2020-08-17  3:46 UTC (permalink / raw)
  To: linux-mips
  Cc: Jiaxun Yang, Thomas Bogendoerfer, Huacai Chen,
	Aleksandar Markovic, Paul Burton, Serge Semin, WANG Xuerui,
	周琰杰 (Zhou Yanjie),
	Liangliang Huang, afzal mohammed, Peter Xu,
	Peter Zijlstra (Intel),
	Sergey Korolev, Alexey Malahov, Anup Patel, Marc Zyngier,
	Rafael J. Wysocki, Michael Kelley, Steven Price, Atish Patra,
	Ming Lei, Daniel Jordan, Mike Leach, linux-kernel, kvm

Now we have hotplug aware reliable sync-r4k, we can simply use
that instead of our IPI based implementation.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/include/asm/smp.h |  1 -
 arch/mips/loongson64/smp.c  | 32 ++------------------------------
 2 files changed, 2 insertions(+), 31 deletions(-)

diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index 5d9ff61004ca..2300cc0bba34 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -52,7 +52,6 @@ extern int __cpu_logical_map[NR_CPUS];
 #define SMP_CALL_FUNCTION	0x2
 /* Octeon - Tell another core to flush its icache */
 #define SMP_ICACHE_FLUSH	0x4
-#define SMP_ASK_C0COUNT		0x8
 
 /* Mask of CPUs which are currently definitely operating coherently */
 extern cpumask_t cpu_coherent_mask;
diff --git a/arch/mips/loongson64/smp.c b/arch/mips/loongson64/smp.c
index e744e1bee49e..d6a3a7c3d1b2 100644
--- a/arch/mips/loongson64/smp.c
+++ b/arch/mips/loongson64/smp.c
@@ -32,7 +32,6 @@ static void *ipi_clear0_regs[16];
 static void *ipi_status0_regs[16];
 static void *ipi_en0_regs[16];
 static void *ipi_mailbox_buf[16];
-static uint32_t core0_c0count[NR_CPUS];
 
 /* read a 32bit value from ipi register */
 #define loongson3_ipi_read32(addr) readl(addr)
@@ -307,8 +306,8 @@ loongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action)
 
 static irqreturn_t loongson3_ipi_interrupt(int irq, void *dev_id)
 {
-	int i, cpu = smp_processor_id();
-	unsigned int action, c0count;
+	int cpu = smp_processor_id();
+	unsigned int action;
 
 	action = ipi_read_clear(cpu);
 
@@ -321,15 +320,6 @@ static irqreturn_t loongson3_ipi_interrupt(int irq, void *dev_id)
 		irq_exit();
 	}
 
-	if (action & SMP_ASK_C0COUNT) {
-		BUG_ON(cpu != 0);
-		c0count = read_c0_count();
-		c0count = c0count ? c0count : 1;
-		for (i = 1; i < nr_cpu_ids; i++)
-			core0_c0count[i] = c0count;
-		__wbflush(); /* Let others see the result ASAP */
-	}
-
 	return IRQ_HANDLED;
 }
 
@@ -340,7 +330,6 @@ static irqreturn_t loongson3_ipi_interrupt(int irq, void *dev_id)
 static void loongson3_init_secondary(void)
 {
 	int i;
-	uint32_t initcount;
 	unsigned int cpu = smp_processor_id();
 	unsigned int imask = STATUSF_IP7 | STATUSF_IP6 |
 			     STATUSF_IP3 | STATUSF_IP2;
@@ -356,23 +345,6 @@ static void loongson3_init_secondary(void)
 		     cpu_logical_map(cpu) % loongson_sysconf.cores_per_package);
 	cpu_data[cpu].package =
 		cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
-
-	i = 0;
-	core0_c0count[cpu] = 0;
-	loongson3_send_ipi_single(0, SMP_ASK_C0COUNT);
-	while (!core0_c0count[cpu]) {
-		i++;
-		cpu_relax();
-	}
-
-	if (i > MAX_LOOPS)
-		i = MAX_LOOPS;
-	if (cpu_data[cpu].package)
-		initcount = core0_c0count[cpu] + i;
-	else /* Local access is faster for loops */
-		initcount = core0_c0count[cpu] + i/2;
-
-	write_c0_count(initcount);
 }
 
 static void loongson3_smp_finish(void)
-- 
2.28.0.rc1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/7] MIPS: cevt-r4k: Don't handle IRQ if clockevent is not enabled
  2020-08-17  3:46 [PATCH 0/7] R4000 clock enhancements for Loongson Jiaxun Yang
                   ` (3 preceding siblings ...)
  2020-08-17  3:46 ` [PATCH 4/7] MIPS: Loongson64: Remove custom count sync procudure Jiaxun Yang
@ 2020-08-17  3:46 ` Jiaxun Yang
  2020-08-17  3:46 ` [PATCH 6/7] MIPS: cevt-r4k: Enable intimer for Loongson CPUs with extimer Jiaxun Yang
  2020-08-17  3:46 ` [PATCH 7/7] MIPS: KVM: Don't use htimer when INTIMER is disabled Jiaxun Yang
  6 siblings, 0 replies; 9+ messages in thread
From: Jiaxun Yang @ 2020-08-17  3:46 UTC (permalink / raw)
  To: linux-mips
  Cc: Jiaxun Yang, Thomas Bogendoerfer, Huacai Chen,
	Aleksandar Markovic, Serge Semin, Paul Burton, WANG Xuerui,
	Alexey Malahov, 周琰杰 (Zhou Yanjie),
	Liangliang Huang, afzal mohammed, Peter Zijlstra (Intel),
	Peter Xu, Sergey Korolev, Marc Zyngier, Anup Patel, Herbert Xu,
	Steven Price, Atish Patra, Ming Lei, Daniel Jordan, Mike Leach,
	Ulf Hansson, linux-kernel, kvm

Some platforms may have shared Cause.TI, bailing out in IRQ handler
when clock event is not enabled can give another clock device a chance.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/kernel/cevt-r4k.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index f0c52d751d0a..d396b1011fee 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -142,6 +142,15 @@ irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
 	if (handle_perf_irq(r2))
 		return IRQ_HANDLED;
 
+	cd = &per_cpu(mips_clockevent_device, cpu);
+	/*
+	 * If the clockevent have not enabled, then no need to check the rest.
+	 * Some platforms may have shared Cause.TI, bailing out here can
+	 * give another clock device a chance.
+	 */
+	if (clockevent_state_detached(cd) || clockevent_state_shutdown(cd))
+		return IRQ_NONE;
+
 	/*
 	 * The same applies to performance counter interrupts.	But with the
 	 * above we now know that the reason we got here must be a timer
@@ -150,7 +159,6 @@ irqreturn_t c0_compare_interrupt(int irq, void *dev_id)
 	if (!r2 || (read_c0_cause() & CAUSEF_TI)) {
 		/* Clear Count/Compare Interrupt */
 		write_c0_compare(read_c0_compare());
-		cd = &per_cpu(mips_clockevent_device, cpu);
 		cd->event_handler(cd);
 
 		return IRQ_HANDLED;
-- 
2.28.0.rc1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/7] MIPS: cevt-r4k: Enable intimer for Loongson CPUs with extimer
  2020-08-17  3:46 [PATCH 0/7] R4000 clock enhancements for Loongson Jiaxun Yang
                   ` (4 preceding siblings ...)
  2020-08-17  3:46 ` [PATCH 5/7] MIPS: cevt-r4k: Don't handle IRQ if clockevent is not enabled Jiaxun Yang
@ 2020-08-17  3:46 ` Jiaxun Yang
  2020-08-17  3:46 ` [PATCH 7/7] MIPS: KVM: Don't use htimer when INTIMER is disabled Jiaxun Yang
  6 siblings, 0 replies; 9+ messages in thread
From: Jiaxun Yang @ 2020-08-17  3:46 UTC (permalink / raw)
  To: linux-mips
  Cc: Jiaxun Yang, Thomas Bogendoerfer, Huacai Chen,
	Aleksandar Markovic, Serge Semin, Paul Burton, WANG Xuerui,
	周琰杰 (Zhou Yanjie),
	Liangliang Huang, afzal mohammed, Peter Xu,
	Peter Zijlstra (Intel),
	Ingo Molnar, Sergey Korolev, Alexey Malahov, Marc Zyngier,
	Anup Patel, Daniel Jordan, Ulf Hansson, Atish Patra,
	Steven Price, Mike Leach, Ming Lei, Michael Kelley, linux-kernel,
	kvm

Loongson64C and Loongson64G have extimer feature, which is sharing
Cause.TI with intimer (which is cevt-r4k).

To ensure the cevt-r4k's usability, we need to add a callback for
clock device to ensure intimer is enabled when cevt-r4k is enabled.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/include/asm/cpu-features.h |  4 ++++
 arch/mips/include/asm/cpu.h          |  1 +
 arch/mips/kernel/cevt-r4k.c          | 25 +++++++++++++++++++++++++
 arch/mips/kernel/cpu-probe.c         |  6 +++++-
 4 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 78cf7e300f12..aec458eee2a5 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -576,6 +576,10 @@
 # define cpu_has_gsexcex	__opt(MIPS_CPU_GSEXCEX)
 #endif
 
+#ifndef cpu_has_extimer
+# define cpu_has_extimer	__opt(MIPS_CPU_EXTIMER)
+#endif
+
 #ifdef CONFIG_SMP
 /*
  * Some systems share FTLB RAMs between threads within a core (siblings in
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 388a82f28a87..854e1b44254b 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -429,6 +429,7 @@ enum cpu_type_enum {
 #define MIPS_CPU_MAC_2008_ONLY	BIT_ULL(60)	/* CPU Only support MAC2008 Fused multiply-add instruction */
 #define MIPS_CPU_FTLBPAREX	BIT_ULL(61)	/* CPU has FTLB parity exception */
 #define MIPS_CPU_GSEXCEX	BIT_ULL(62)	/* CPU has GSExc exception */
+#define MIPS_CPU_EXTIMER	BIT_ULL(63)	/* CPU has External Timer (Loongson) */
 
 /*
  * CPU ASE encodings
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index d396b1011fee..a6e56e9d4e70 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -15,6 +15,8 @@
 
 #include <asm/time.h>
 #include <asm/cevt-r4k.h>
+#include <asm/cpu-features.h>
+#include <asm/mipsregs.h>
 
 static int mips_next_event(unsigned long delta,
 			   struct clock_event_device *evt)
@@ -302,6 +304,24 @@ core_initcall(r4k_register_cpufreq_notifier);
 
 #endif /* !CONFIG_CPU_FREQ */
 
+#ifdef CONFIG_CPU_LOONGSON64
+static int c0_compare_int_enable(struct clock_event_device *cd)
+{
+	if (cpu_has_extimer)
+		set_c0_config6(LOONGSON_CONF6_INTIMER);
+
+	return 0;
+}
+
+static int c0_compare_int_disable(struct clock_event_device *cd)
+{
+	if (cpu_has_extimer)
+		clear_c0_config6(LOONGSON_CONF6_INTIMER);
+
+	return 0;
+}
+#endif
+
 int r4k_clockevent_percpu_init(int cpu)
 {
 	struct clock_event_device *cd;
@@ -330,6 +350,11 @@ int r4k_clockevent_percpu_init(int cpu)
 	cd->set_next_event	= mips_next_event;
 	cd->event_handler	= mips_event_handler;
 
+#ifdef CONFIG_CPU_LOONGSON64
+	cd->set_state_oneshot = c0_compare_int_enable;
+	cd->set_state_shutdown = c0_compare_int_disable;
+#endif
+
 	clockevents_config_and_register(cd, mips_hpt_frequency, min_delta, 0x7fffffff);
 
 	return 0;
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index e2955f1f6316..f41e8d4f6d84 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -2030,6 +2030,9 @@ static inline void decode_cpucfg(struct cpuinfo_mips *c)
 	if (cfg2 & LOONGSON_CFG2_LEXT2)
 		c->ases |= MIPS_ASE_LOONGSON_EXT2;
 
+	if (cfg2 & LOONGSON_CFG2_LLFTP)
+		c->options |= MIPS_CPU_EXTIMER;
+
 	if (cfg2 & LOONGSON_CFG2_LSPW) {
 		c->options |= MIPS_CPU_LDPTE;
 		c->guest.options |= MIPS_CPU_LDPTE;
@@ -2088,7 +2091,8 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
 		 * Also some early Loongson-3A2000 had wrong TLB type in Config
 		 * register, we correct it here.
 		 */
-		c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE;
+		c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE |
+			      MIPS_CPU_EXTIMER;
 		c->writecombine = _CACHE_UNCACHED_ACCELERATED;
 		c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
 			MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
-- 
2.28.0.rc1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 7/7] MIPS: KVM: Don't use htimer when INTIMER is disabled
  2020-08-17  3:46 [PATCH 0/7] R4000 clock enhancements for Loongson Jiaxun Yang
                   ` (5 preceding siblings ...)
  2020-08-17  3:46 ` [PATCH 6/7] MIPS: cevt-r4k: Enable intimer for Loongson CPUs with extimer Jiaxun Yang
@ 2020-08-17  3:46 ` Jiaxun Yang
  6 siblings, 0 replies; 9+ messages in thread
From: Jiaxun Yang @ 2020-08-17  3:46 UTC (permalink / raw)
  To: linux-mips
  Cc: Jiaxun Yang, Thomas Bogendoerfer, Huacai Chen,
	Aleksandar Markovic, Paul Burton, Serge Semin, WANG Xuerui,
	周琰杰 (Zhou Yanjie),
	Liangliang Huang, afzal mohammed, Ingo Molnar, Peter Xu,
	Peter Zijlstra (Intel),
	Sergey Korolev, Alexey Malahov, Anup Patel, Marc Zyngier,
	Rafael J. Wysocki, Jens Axboe, Steven Price, Michael Kelley,
	Mike Leach, Ulf Hansson, Atish Patra, Ming Lei, linux-kernel,
	kvm

When INTIMER is disabled by host, the GT compare interrupt
will be ignored.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/kvm/vz.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/mips/kvm/vz.c b/arch/mips/kvm/vz.c
index 9d03bd0a604a..1d2140f7461a 100644
--- a/arch/mips/kvm/vz.c
+++ b/arch/mips/kvm/vz.c
@@ -341,6 +341,12 @@ static bool kvm_vz_should_use_htimer(struct kvm_vcpu *vcpu)
 	if (kvm_mips_count_disabled(vcpu))
 		return false;
 
+	if (cpu_has_extimer) {
+		/* Guest htimer compare interrupt will be ignored if INTIMER is disabled */
+		if (!(read_c0_config6() & LOONGSON_CONF6_INTIMER))
+			return false;
+	}
+
 	/* Chosen frequency must match real frequency */
 	if (mips_hpt_frequency != vcpu->arch.count_hz)
 		return false;
-- 
2.28.0.rc1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/7] MIPS: sync-r4k: Rework to be many cores firendly
  2020-08-17  3:46 ` [PATCH 1/7] MIPS: sync-r4k: Rework to be many cores firendly Jiaxun Yang
@ 2020-08-17  7:55   ` peterz
  0 siblings, 0 replies; 9+ messages in thread
From: peterz @ 2020-08-17  7:55 UTC (permalink / raw)
  To: Jiaxun Yang
  Cc: linux-mips, Thomas Bogendoerfer, Huacai Chen,
	Aleksandar Markovic, Paul Burton, Serge Semin, WANG Xuerui,
	周琰杰,
	Liangliang Huang, afzal mohammed, Ingo Molnar, Peter Xu,
	Sergey Korolev, Alexey Malahov, Marc Zyngier, Anup Patel,
	Palmer Dabbelt, Atish Patra, Michael Kelley, Steven Price,
	Daniel Jordan, Ming Lei, Ulf Hansson, Mike Leach, linux-kernel,
	kvm

On Mon, Aug 17, 2020 at 11:46:40AM +0800, Jiaxun Yang wrote:
> Here we reworked the whole procdure. Now the synchronise event on CPU0
> is triggered by smp call function, and we won't touch the count on CPU0
> at all.

Are you telling me, that in 2020 you're building chips that need
horrible crap like this ?!?

> +#define MAX_LOOPS	1000
> +
> +void synchronise_count_master(void *unused)
>  {
>  	unsigned long flags;
> +	long delta;
> +	int i;
>  
> +	if (atomic_read(&sync_stage) != STAGE_START)
> +		BUG();

	BUG_ON(atomic_read(&sync_state) != STAGE_START);

>  
>  	local_irq_save(flags);

That's silly, replace with: lockdep_assert_hardirqs_disabled().

>  
> +	cur_count = read_c0_count();
> +	smp_wmb();
> +	atomic_inc(&sync_stage); /* inc to STAGE_MASTER_READY */

memory barriers require a comment that describes the ordering. This
includes at least 2 variables and at least 2 code paths (*) -- afaict
your code does NOT have a matching barrier, see below.

>  
> +	for (i = 0; i < MAX_LOOPS; i++) {
> +		cur_count = read_c0_count();
>  		smp_wmb();
> -		atomic_inc(&count_count_stop);
> +		if (atomic_read(&sync_stage) == STAGE_SLAVE_SYNCED)
> +			break;
>  	}
> +
> +	delta = read_c0_count() - fini_count;
>  
>  	local_irq_restore(flags);
>  
> +	if (i == MAX_LOOPS)
> +		pr_err("sync-r4k: Master: synchronise timeout\n");
> +	else
> +		pr_info("sync-r4k: Master: synchronise succeed, maximum delta: %ld\n", delta);
> +
> +	return;
>  }
>  
>  void synchronise_count_slave(int cpu)
>  {
>  	int i;
>  	unsigned long flags;
> +	call_single_data_t csd;
>  
> +	raw_spin_lock(&sync_r4k_lock);

Why should this be a raw_spnilock_t ?

>  
> +	/* Let variables get attention from cache */
> +	for (i = 0; i < MAX_LOOPS; i++) {
> +		cur_count++;
> +		fini_count += cur_count;
> +		cur_count += fini_count;
>  	}

What does this actually do? You're going to bounce those variables
between this CPU and CPU-0.

> +
> +	atomic_set(&sync_stage, STAGE_START);
> +	csd.func = synchronise_count_master;
> +
> +	/* Master count is always CPU0 */
> +	if (smp_call_function_single_async(0, &csd)) {

This is diguisting.

It also requires a comment on how the on-stack csd is correct (it is,
but it really needs a comment).

> +		pr_err("sync-r4k: Salve: Failed to call master\n");
> +		raw_spin_unlock(&sync_r4k_lock);
> +		return;
> +	}
> +
> +	local_irq_save(flags);
> +
> +	/* Wait until master ready */
> +	while (atomic_read(&sync_stage) != STAGE_MASTER_READY)
> +		cpu_relax();

This really wants to be:

	atomic_cond_read_acquire(&&sync_stage, VAL == STAGE_MASTER_READY);

Because, afaict the smp_wmb() (*) in synchronize_count_master() order
against this here and we need to guarantee we read @sync_stage _before_
@cur_count.

> +
> +	write_c0_count(cur_count);
> +	fini_count = read_c0_count();
> +	smp_wmb();
> +	atomic_inc(&sync_stage); /* inc to STAGE_SLAVE_SYNCED */
>  
>  	local_irq_restore(flags);
> +
> +	raw_spin_unlock(&sync_r4k_lock);
>  }


Furthermore, afaict there isn't actually any concurrency on @sync_stage,
so atomic_t isn't required, Using smp_store_release() to change state
might be far more natural.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2020-08-17  7:56 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-17  3:46 [PATCH 0/7] R4000 clock enhancements for Loongson Jiaxun Yang
2020-08-17  3:46 ` [PATCH 1/7] MIPS: sync-r4k: Rework to be many cores firendly Jiaxun Yang
2020-08-17  7:55   ` peterz
2020-08-17  3:46 ` [PATCH 2/7] MIPS: time: Use CPUHUP to handle r4k timer Jiaxun Yang
2020-08-17  3:46 ` [PATCH 3/7] MIPS: Kconfig: Always select SYNC_R4K if both SMP and r4k timer is enabled Jiaxun Yang
2020-08-17  3:46 ` [PATCH 4/7] MIPS: Loongson64: Remove custom count sync procudure Jiaxun Yang
2020-08-17  3:46 ` [PATCH 5/7] MIPS: cevt-r4k: Don't handle IRQ if clockevent is not enabled Jiaxun Yang
2020-08-17  3:46 ` [PATCH 6/7] MIPS: cevt-r4k: Enable intimer for Loongson CPUs with extimer Jiaxun Yang
2020-08-17  3:46 ` [PATCH 7/7] MIPS: KVM: Don't use htimer when INTIMER is disabled Jiaxun Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).