--- zzzz-none-000/linux-4.9.276/drivers/clocksource/mips-gic-timer.c 2021-07-20 14:21:16.000000000 +0000 +++ falcon-5530-750/linux-4.9.276/drivers/clocksource/mips-gic-timer.c 2023-04-05 08:19:01.000000000 +0000 @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,8 @@ #include #include #include +#include +#include static DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device); static int gic_timer_irq; @@ -25,10 +28,13 @@ { u64 cnt; int res; + unsigned long flags; + local_irq_save(flags); cnt = gic_read_count(); cnt += (u64)delta; gic_write_cpu_compare(cnt, cpumask_first(evt->cpumask)); + local_irq_restore(flags); res = ((int)(gic_read_count() - cnt) >= 0) ? -ETIME : 0; return res; } @@ -52,6 +58,9 @@ static void gic_clockevent_cpu_init(unsigned int cpu, struct clock_event_device *cd) { + unsigned long max_d = 0x7fffffff; + unsigned long min_d = 0x600; + cd->name = "MIPS GIC"; cd->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP; @@ -61,8 +70,15 @@ cd->cpumask = cpumask_of(cpu); cd->set_next_event = gic_next_event; - clockevents_config_and_register(cd, gic_frequency, 0x300, 0x7fffffff); + /* + * The min_delta is sensitive to the number of hardware threads in + * the core. With more threads each thread will, on average, get + * less instructions executed per clock. To account for this, we + * scale the min delta based on the number of threads per core. + */ + min_d *= smp_num_siblings; + clockevents_config_and_register(cd, gic_frequency, min_d, max_d); enable_percpu_irq(gic_timer_irq, IRQ_TYPE_NONE); } @@ -137,6 +153,11 @@ .archdata = { .vdso_clock_mode = VDSO_CLOCK_GIC }, }; +static u64 notrace gic_read_sched_clock(void) +{ + return gic_read_count(); +} + static int __init __gic_clocksource_init(void) { int ret; @@ -150,6 +171,8 @@ ret = clocksource_register_hz(&gic_clocksource, gic_frequency); if (ret < 0) pr_warn("GIC: Unable to register clocksource\n"); + sched_clock_register(gic_read_sched_clock, gic_get_count_width(), + gic_frequency); return ret; } @@ -215,3 +238,31 @@ } CLOCKSOURCE_OF_DECLARE(mips_gic_timer, "mti,gic-timer", gic_clocksource_of_init); +static int +gic_cpufreq_notifier(struct notifier_block *nb, unsigned long event, void *data) +{ + struct cpufreq_freqs *freq = data; + + if (event == CPUFREQ_POSTCHANGE) { + if (gic_frequency == freq->new * 1000) + return 0; + + gic_frequency = freq->new * 1000; + __clocksource_update_freq_hz(&gic_clocksource, gic_frequency); + on_each_cpu(gic_update_frequency, (void *)gic_frequency, 1); + timekeeping_notify(&gic_clocksource); + } + + return 0; +} + +static struct notifier_block gic_cpufreq_nb = { + .notifier_call = gic_cpufreq_notifier, +}; + +static int __init cpufreq_register_gic_scaling(void) +{ + cpufreq_register_notifier(&gic_cpufreq_nb, CPUFREQ_TRANSITION_NOTIFIER); + return 0; +} +device_initcall(cpufreq_register_gic_scaling);