Skip to content

Commit 1b35cd8

Browse files
atishp04palmer-dabbelt
authored andcommitted
RISCV: Register clocksource and events correctly
Currently, timer_probe() is called for every cpu and clocksource is registered multiple times for each cpu which is wrong. Probe timer only once during init and register the clock source at that time. Move the clock event registration cpu online notification callback. Take this opportunity to remove redundant functions as well. Signed-off-by: Atish Patra <[email protected]> Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 3054034 commit 1b35cd8

File tree

4 files changed

+32
-24
lines changed

4 files changed

+32
-24
lines changed

arch/riscv/include/asm/smp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#ifdef CONFIG_SMP
2626

2727
/* SMP initialization hook for setup_arch */
28-
void __init init_clockevent(void);
28+
void init_clockevent(void);
2929

3030
/* SMP initialization hook for setup_arch */
3131
void __init setup_smp(void);

arch/riscv/kernel/time.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,6 @@ void riscv_timer_interrupt(void)
3939
#endif
4040
}
4141

42-
void __init init_clockevent(void)
43-
{
44-
timer_probe();
45-
csr_set(sie, SIE_STIE);
46-
}
47-
48-
4942
static long __init timebase_frequency(void)
5043
{
5144
struct device_node *cpu;
@@ -65,5 +58,5 @@ void __init time_init(void)
6558
{
6659
riscv_timebase = timebase_frequency();
6760
lpj_fine = riscv_timebase / HZ;
68-
init_clockevent();
61+
timer_probe();
6962
}

drivers/clocksource/riscv_timer.c

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/delay.h>
1818
#include <linux/timer_riscv.h>
1919
#include <linux/sched_clock.h>
20+
#include <linux/cpu.h>
2021
#include <asm/sbi.h>
2122

2223
#define MINDELTA 100
@@ -71,16 +72,6 @@ DEFINE_PER_CPU(struct clocksource, riscv_clocksource) = {
7172
.read = rdtime,
7273
};
7374

74-
void timer_riscv_init(int cpu_id,
75-
unsigned long riscv_timebase,
76-
int (*next)(unsigned long, struct clock_event_device*))
77-
{
78-
struct clock_event_device *ce = per_cpu_ptr(&riscv_clock_event, cpu_id);
79-
80-
ce->cpumask = cpumask_of(cpu_id);
81-
clockevents_config_and_register(ce, riscv_timebase, MINDELTA, MAXDELTA);
82-
}
83-
8475
static int hart_of_timer(struct device_node *dev)
8576
{
8677
u32 hart;
@@ -100,21 +91,44 @@ static u64 notrace timer_riscv_sched_read(void)
10091
return get_cycles64();
10192
}
10293

94+
static int timer_riscv_starting_cpu(unsigned int cpu)
95+
{
96+
struct clock_event_device *ce = per_cpu_ptr(&riscv_clock_event, cpu);
97+
98+
ce->cpumask = cpumask_of(cpu);
99+
clockevents_config_and_register(ce, riscv_timebase, MINDELTA, MAXDELTA);
100+
/* Enable timer interrupt for this cpu */
101+
csr_set(sie, SIE_STIE);
102+
103+
return 0;
104+
}
105+
106+
static int timer_riscv_dying_cpu(unsigned int cpu)
107+
{
108+
/* Disable timer interrupt for this cpu */
109+
csr_clear(sie, SIE_STIE);
110+
111+
return 0;
112+
}
113+
103114
static int __init timer_riscv_init_dt(struct device_node *n)
104115
{
116+
int err = 0;
105117
int cpu_id = hart_of_timer(n);
106-
struct clock_event_device *ce = per_cpu_ptr(&riscv_clock_event, cpu_id);
107118
struct clocksource *cs = per_cpu_ptr(&riscv_clocksource, cpu_id);
108119

109120
if (cpu_id == smp_processor_id()) {
110121
clocksource_register_hz(cs, riscv_timebase);
111122
sched_clock_register(timer_riscv_sched_read, 64, riscv_timebase);
112123

113-
ce->cpumask = cpumask_of(cpu_id);
114-
clockevents_config_and_register(ce, riscv_timebase, MINDELTA, MAXDELTA);
124+
err = cpuhp_setup_state(CPUHP_AP_RISCV_TIMER_STARTING,
125+
"clockevents/riscv/timer:starting",
126+
timer_riscv_starting_cpu, timer_riscv_dying_cpu);
127+
if (err)
128+
pr_err("RISCV timer register failed [%d] for cpu = [%d]\n",
129+
err, cpu_id);
115130
}
116-
117-
return 0;
131+
return err;
118132
}
119133

120134
TIMER_OF_DECLARE(riscv_timer, "riscv", timer_riscv_init_dt);

include/linux/cpuhotplug.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ enum cpuhp_state {
125125
CPUHP_AP_MARCO_TIMER_STARTING,
126126
CPUHP_AP_MIPS_GIC_TIMER_STARTING,
127127
CPUHP_AP_ARC_TIMER_STARTING,
128+
CPUHP_AP_RISCV_TIMER_STARTING,
128129
CPUHP_AP_KVM_STARTING,
129130
CPUHP_AP_KVM_ARM_VGIC_INIT_STARTING,
130131
CPUHP_AP_KVM_ARM_VGIC_STARTING,

0 commit comments

Comments
 (0)