diff options
author | Maarten Lankhorst <maarten.lankhorst@linux.intel.com> | 2020-06-29 12:15:51 +0200 |
---|---|---|
committer | Maarten Lankhorst <maarten.lankhorst@linux.intel.com> | 2020-06-29 12:16:26 +0200 |
commit | 60e9eabf41fa916d2ef68c5bf929197975917578 (patch) | |
tree | 39ce456390ed34d2624aed1260203f43fff94d38 /drivers/clocksource/mips-gic-timer.c | |
parent | 84e543bc9d1dc550132ba25b72df28d40cc44333 (diff) | |
parent | 0a19b068acc47d05212f03e494381926dc0381e2 (diff) |
Backmerge remote-tracking branch 'drm/drm-next' into drm-misc-next
Some conflicts with ttm_bo->offset removal, but drm-misc-next needs updating to v5.8.
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Diffstat (limited to 'drivers/clocksource/mips-gic-timer.c')
-rw-r--r-- | drivers/clocksource/mips-gic-timer.c | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c index 8b5f8ae723cb..be4175f415ba 100644 --- a/drivers/clocksource/mips-gic-timer.c +++ b/drivers/clocksource/mips-gic-timer.c @@ -16,6 +16,7 @@ #include <linux/notifier.h> #include <linux/of_irq.h> #include <linux/percpu.h> +#include <linux/sched_clock.h> #include <linux/smp.h> #include <linux/time.h> #include <asm/mips-cps.h> @@ -23,14 +24,14 @@ static DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device); static int gic_timer_irq; static unsigned int gic_frequency; +static bool __read_mostly gic_clock_unstable; -static u64 notrace gic_read_count(void) +static void gic_clocksource_unstable(char *reason); + +static u64 notrace gic_read_count_2x32(void) { unsigned int hi, hi2, lo; - if (mips_cm_is64) - return read_gic_counter(); - do { hi = read_gic_counter_32h(); lo = read_gic_counter_32l(); @@ -40,6 +41,19 @@ static u64 notrace gic_read_count(void) return (((u64) hi) << 32) + lo; } +static u64 notrace gic_read_count_64(void) +{ + return read_gic_counter(); +} + +static u64 notrace gic_read_count(void) +{ + if (mips_cm_is64) + return gic_read_count_64(); + + return gic_read_count_2x32(); +} + static int gic_next_event(unsigned long delta, struct clock_event_device *evt) { int cpu = cpumask_first(evt->cpumask); @@ -114,8 +128,10 @@ static int gic_clk_notifier(struct notifier_block *nb, unsigned long action, { struct clk_notifier_data *cnd = data; - if (action == POST_RATE_CHANGE) + if (action == POST_RATE_CHANGE) { + gic_clocksource_unstable("ref clock rate change"); on_each_cpu(gic_update_frequency, (void *)cnd->new_rate, 1); + } return NOTIFY_OK; } @@ -161,6 +177,18 @@ static struct clocksource gic_clocksource = { .vdso_clock_mode = VDSO_CLOCKMODE_GIC, }; +static void gic_clocksource_unstable(char *reason) +{ + if (gic_clock_unstable) + return; + + gic_clock_unstable = true; + + pr_info("GIC timer is unstable due to %s\n", reason); + + clocksource_mark_unstable(&gic_clocksource); +} + static int __init __gic_clocksource_init(void) { unsigned int count_width; @@ -228,6 +256,18 @@ static int __init gic_clocksource_of_init(struct device_node *node) /* And finally start the counter */ clear_gic_config(GIC_CONFIG_COUNTSTOP); + /* + * It's safe to use the MIPS GIC timer as a sched clock source only if + * its ticks are stable, which is true on either the platforms with + * 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)) { + sched_clock_register(mips_cm_is64 ? + gic_read_count_64 : gic_read_count_2x32, + 64, gic_frequency); + } + return 0; } TIMER_OF_DECLARE(mips_gic_timer, "mti,gic-timer", |