[PATCH] LoongArch: Clear the pending timer interrupt when the clockevent stops

Wentao Guan posted 1 patch 1 week, 2 days ago
arch/loongarch/kernel/time.c | 23 +++--------------------
include/linux/cpuhotplug.h   |  1 -
2 files changed, 3 insertions(+), 21 deletions(-)
[PATCH] LoongArch: Clear the pending timer interrupt when the clockevent stops
Posted by Wentao Guan 1 week, 2 days ago
commit 8ef7f3132e40 ("LoongArch: Add cpuhotplug hooks to fix high cpu
usage of vCPU threads") clears a latched timer interrupt from a cpuhp
teardown callback, because a pending timer interrupt keeps waking an
offline CPU up again right after it entered the idle instruction.
Clearing a pending timer interrupt is part of stopping a clockevent
device on other architectures: lapic_timer_shutdown() masks the local
APIC timer and zeroes its counter, and riscv_clock_shutdown() calls
riscv_clock_event_stop(), which clears the timer interrupt.

Clear the pending timer interrupt in constant_set_state_shutdown()
instead. The clockevents core already stops the device before the CPU
is parked, through the generic tick teardown (tick_cpu_dying(),
registered on CPUHP_AP_TICK_DYING), so the cpuhp hooks have nothing
left to do: the startup callback only repeats what
loongson_init_secondary() does on every bring-up, and the teardown
callback only did the write_csr_tintclear() that now happens when the
device is stopped. CPUHP_AP_LOONGARCH_ARCH_TIMER_STARTING is not
needed any more and is removed.

Assisted-by: atomcode:deepseek-v4.1-flash
Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
---
 arch/loongarch/kernel/time.c | 23 +++--------------------
 include/linux/cpuhotplug.h   |  1 -
 2 files changed, 3 insertions(+), 21 deletions(-)

diff --git a/arch/loongarch/kernel/time.c b/arch/loongarch/kernel/time.c
index dbaaabcaf6f09..64136a541b049 100644
--- a/arch/loongarch/kernel/time.c
+++ b/arch/loongarch/kernel/time.c
@@ -5,7 +5,6 @@
  * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
  */
 #include <linux/clockchips.h>
-#include <linux/cpuhotplug.h>
 #include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/init.h>
@@ -88,6 +87,9 @@ static int constant_set_state_shutdown(struct clock_event_device *evt)
 	timer_config &= ~CSR_TCFG_EN;
 	csr_write(timer_config, LOONGARCH_CSR_TCFG);
 
+	/* Clear Timer Interrupt */
+	write_csr_tintclear(CSR_TINTCLR_TI);
+
 	raw_spin_unlock(&state_lock);
 
 	return 0;
@@ -104,21 +106,6 @@ static int constant_timer_next_event(unsigned long delta, struct clock_event_dev
 	return 0;
 }
 
-static int arch_timer_starting(unsigned int cpu)
-{
-	set_csr_ecfg(ECFGF_TIMER);
-
-	return 0;
-}
-
-static int arch_timer_dying(unsigned int cpu)
-{
-	/* Clear Timer Interrupt */
-	write_csr_tintclear(CSR_TINTCLR_TI);
-
-	return 0;
-}
-
 static unsigned long get_loops_per_jiffy(void)
 {
 	u64 lpj = const_clock_freq;
@@ -189,10 +176,6 @@ int constant_clockevent_init(void)
 	lpj_fine = get_loops_per_jiffy();
 	pr_info("Constant clock event device register\n");
 
-	cpuhp_setup_state(CPUHP_AP_LOONGARCH_ARCH_TIMER_STARTING,
-			  "clockevents/loongarch/timer:starting",
-			  arch_timer_starting, arch_timer_dying);
-
 	return 0;
 }
 
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 0fb3a2a62eb00..6e4bac0bf811a 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -167,7 +167,6 @@ enum cpuhp_state {
 	CPUHP_AP_QCOM_TIMER_STARTING,
 	CPUHP_AP_TEGRA_TIMER_STARTING,
 	CPUHP_AP_ARMADA_TIMER_STARTING,
-	CPUHP_AP_LOONGARCH_ARCH_TIMER_STARTING,
 	CPUHP_AP_MIPS_GIC_TIMER_STARTING,
 	CPUHP_AP_ARC_TIMER_STARTING,
 	CPUHP_AP_REALTEK_TIMER_STARTING,
-- 
2.30.2