From 8f4137588261d7504f4aa022dc9d1a1fd1940e8e Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 30 Jan 2017 15:39:52 +0000 Subject: arm64: Allow checking of a CPU-local erratum this_cpu_has_cap() only checks the feature array, and not the errata one. In order to be able to check for a CPU-local erratum, allow it to inspect the latter as well. This is consistent with cpus_have_cap()'s behaviour, which includes errata already. Acked-by: Thomas Gleixner Acked-by: Daniel Lezcano Reviewed-by: Suzuki K Poulose Signed-off-by: Marc Zyngier --- arch/arm64/kernel/cpufeature.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index abda8e861865..6eb77ae99b79 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -1090,20 +1090,29 @@ static void __init setup_feature_capabilities(void) * Check if the current CPU has a given feature capability. * Should be called from non-preemptible context. */ -bool this_cpu_has_cap(unsigned int cap) +static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array, + unsigned int cap) { const struct arm64_cpu_capabilities *caps; if (WARN_ON(preemptible())) return false; - for (caps = arm64_features; caps->desc; caps++) + for (caps = cap_array; caps->desc; caps++) if (caps->capability == cap && caps->matches) return caps->matches(caps, SCOPE_LOCAL_CPU); return false; } +extern const struct arm64_cpu_capabilities arm64_errata[]; + +bool this_cpu_has_cap(unsigned int cap) +{ + return (__this_cpu_has_cap(arm64_features, cap) || + __this_cpu_has_cap(arm64_errata, cap)); +} + void __init setup_cpu_features(void) { u32 cwg; -- cgit v1.2.3 From 6126ce0588eb5a0752d5c8b5796a7fca324fd887 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 1 Feb 2017 11:48:58 +0000 Subject: arm64: Add CNTVCT_EL0 trap handler Since people seem to make a point in breaking the userspace visible counter, we have no choice but to trap the access. Add the required handler. Acked-by: Thomas Gleixner Acked-by: Mark Rutland Signed-off-by: Marc Zyngier --- arch/arm64/include/asm/esr.h | 2 ++ arch/arm64/kernel/traps.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+) (limited to 'arch') diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index d14c478976d0..ad42e79a5d4d 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -175,6 +175,8 @@ #define ESR_ELx_SYS64_ISS_SYS_CTR_READ (ESR_ELx_SYS64_ISS_SYS_CTR | \ ESR_ELx_SYS64_ISS_DIR_READ) +#define ESR_ELx_SYS64_ISS_SYS_CNTVCT (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \ + ESR_ELx_SYS64_ISS_DIR_READ) #ifndef __ASSEMBLY__ #include diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index e52be6aa44ee..1de444e6c669 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -505,6 +505,14 @@ static void ctr_read_handler(unsigned int esr, struct pt_regs *regs) regs->pc += 4; } +static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs) +{ + int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; + + pt_regs_write_reg(regs, rt, arch_counter_get_cntvct()); + regs->pc += 4; +} + struct sys64_hook { unsigned int esr_mask; unsigned int esr_val; @@ -523,6 +531,12 @@ static struct sys64_hook sys64_hooks[] = { .esr_val = ESR_ELx_SYS64_ISS_SYS_CTR_READ, .handler = ctr_read_handler, }, + { + /* Trap read access to CNTVCT_EL0 */ + .esr_mask = ESR_ELx_SYS64_ISS_SYS_OP_MASK, + .esr_val = ESR_ELx_SYS64_ISS_SYS_CNTVCT, + .handler = cntvct_read_handler, + }, {}, }; -- cgit v1.2.3 From 199fd2bff4040985fbd7853cc39b7245fcf54bb9 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 30 Jan 2017 14:18:49 +0000 Subject: arm64: Define Cortex-A73 MIDR As we're about to introduce a new workaround that is specific to Cortex-A73, let's define the coresponding MIDR. Acked-by: Thomas Gleixner Acked-by: Mark Rutland Signed-off-by: Marc Zyngier --- arch/arm64/include/asm/cputype.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index fc502713ab37..0984d1b3a8f2 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -80,6 +80,7 @@ #define ARM_CPU_PART_FOUNDATION 0xD00 #define ARM_CPU_PART_CORTEX_A57 0xD07 #define ARM_CPU_PART_CORTEX_A53 0xD03 +#define ARM_CPU_PART_CORTEX_A73 0xD09 #define APM_CPU_PART_POTENZA 0x000 @@ -92,6 +93,7 @@ #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53) #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57) +#define MIDR_CORTEX_A73 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A73) #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) #define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1) -- cgit v1.2.3 From 06f1494f837da8997d670a1ba87add7963b08922 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 1 Feb 2017 14:38:46 +0000 Subject: arm64: cpu_errata: Allow an erratum to be match for all revisions of a core Some minor erratum may not be fixed in further revisions of a core, leading to a situation where the workaround needs to be updated each time an updated core is released. Introduce a MIDR_ALL_VERSIONS match helper that will work for all versions of that MIDR, once and for all. Acked-by: Thomas Gleixner Acked-by: Mark Rutland Acked-by: Daniel Lezcano Reviewed-by: Suzuki K Poulose Signed-off-by: Marc Zyngier --- arch/arm64/kernel/cpu_errata.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch') diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index f6cc67e7626e..2be1d1c05303 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -53,6 +53,13 @@ static int cpu_enable_trap_ctr_access(void *__unused) .midr_range_min = min, \ .midr_range_max = max +#define MIDR_ALL_VERSIONS(model) \ + .def_scope = SCOPE_LOCAL_CPU, \ + .matches = is_affected_midr_range, \ + .midr_model = model, \ + .midr_range_min = 0, \ + .midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK) + const struct arm64_cpu_capabilities arm64_errata[] = { #if defined(CONFIG_ARM64_ERRATUM_826319) || \ defined(CONFIG_ARM64_ERRATUM_827319) || \ -- cgit v1.2.3 From eeb1efbcb83c0cfe6d567abbacd675bbddf3d658 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 20 Mar 2017 17:18:06 +0000 Subject: arm64: cpu_errata: Add capability to advertise Cortex-A73 erratum 858921 In order to work around Cortex-A73 erratum 858921 in a subsequent patch, add the required capability that advertise the erratum. As the configuration option it depends on is not present yet, this has no immediate effect. Acked-by: Thomas Gleixner Acked-by: Daniel Lezcano Signed-off-by: Marc Zyngier --- Documentation/arm64/silicon-errata.txt | 1 + arch/arm64/include/asm/cpucaps.h | 3 ++- arch/arm64/kernel/cpu_errata.c | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt index 2f66683500b8..10f2dddbf449 100644 --- a/Documentation/arm64/silicon-errata.txt +++ b/Documentation/arm64/silicon-errata.txt @@ -54,6 +54,7 @@ stable kernels. | ARM | Cortex-A57 | #852523 | N/A | | ARM | Cortex-A57 | #834220 | ARM64_ERRATUM_834220 | | ARM | Cortex-A72 | #853709 | N/A | +| ARM | Cortex-A73 | #858921 | ARM64_ERRATUM_858921 | | ARM | MMU-500 | #841119,#826419 | N/A | | | | | | | Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 | diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index fb78a5d3b60b..b3aab8a17868 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h @@ -37,7 +37,8 @@ #define ARM64_HAS_NO_FPSIMD 16 #define ARM64_WORKAROUND_REPEAT_TLBI 17 #define ARM64_WORKAROUND_QCOM_FALKOR_E1003 18 +#define ARM64_WORKAROUND_858921 19 -#define ARM64_NCAPS 19 +#define ARM64_NCAPS 20 #endif /* __ASM_CPUCAPS_H */ diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 2be1d1c05303..2ed2a7657711 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -157,6 +157,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = { MIDR_CPU_VAR_REV(0, 0), MIDR_CPU_VAR_REV(0, 0)), }, +#endif +#ifdef CONFIG_ARM64_ERRATUM_858921 + { + /* Cortex-A73 all versions */ + .desc = "ARM erratum 858921", + .capability = ARM64_WORKAROUND_858921, + MIDR_ALL_VERSIONS(MIDR_CORTEX_A73), + }, #endif { } -- cgit v1.2.3 From 651bb2e9dca6e6dbad3fba5f6e6086a23575b8b5 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 19 Jan 2017 17:20:59 +0000 Subject: arm64: arch_timer: Add infrastructure for multiple erratum detection methods We're currently stuck with DT when it comes to handling errata, which is pretty restrictive. In order to make things more flexible, let's introduce an infrastructure that could support alternative discovery methods. No change in functionality. Acked-by: Thomas Gleixner Reviewed-by: Hanjun Guo Signed-off-by: Marc Zyngier --- arch/arm64/include/asm/arch_timer.h | 7 ++- drivers/clocksource/arm_arch_timer.c | 83 +++++++++++++++++++++++++++++++----- 2 files changed, 78 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index b4b34004a21e..5cd964e90d11 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -37,9 +37,14 @@ extern struct static_key_false arch_timer_read_ool_enabled; #define needs_unstable_timer_counter_workaround() false #endif +enum arch_timer_erratum_match_type { + ate_match_dt, +}; struct arch_timer_erratum_workaround { - const char *id; /* Indicate the Erratum ID */ + enum arch_timer_erratum_match_type match_type; + const void *id; + const char *desc; u32 (*read_cntp_tval_el0)(void); u32 (*read_cntv_tval_el0)(void); u64 (*read_cntvct_el0)(void); diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 7a8a4117f123..5c5c2af74ad9 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -182,7 +182,9 @@ EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled); static const struct arch_timer_erratum_workaround ool_workarounds[] = { #ifdef CONFIG_FSL_ERRATUM_A008585 { + .match_type = ate_match_dt, .id = "fsl,erratum-a008585", + .desc = "Freescale erratum a005858", .read_cntp_tval_el0 = fsl_a008585_read_cntp_tval_el0, .read_cntv_tval_el0 = fsl_a008585_read_cntv_tval_el0, .read_cntvct_el0 = fsl_a008585_read_cntvct_el0, @@ -190,13 +192,81 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = { #endif #ifdef CONFIG_HISILICON_ERRATUM_161010101 { + .match_type = ate_match_dt, .id = "hisilicon,erratum-161010101", + .desc = "HiSilicon erratum 161010101", .read_cntp_tval_el0 = hisi_161010101_read_cntp_tval_el0, .read_cntv_tval_el0 = hisi_161010101_read_cntv_tval_el0, .read_cntvct_el0 = hisi_161010101_read_cntvct_el0, }, #endif }; + +typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *, + const void *); + +static +bool arch_timer_check_dt_erratum(const struct arch_timer_erratum_workaround *wa, + const void *arg) +{ + const struct device_node *np = arg; + + return of_property_read_bool(np, wa->id); +} + +static const struct arch_timer_erratum_workaround * +arch_timer_iterate_errata(enum arch_timer_erratum_match_type type, + ate_match_fn_t match_fn, + void *arg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ool_workarounds); i++) { + if (ool_workarounds[i].match_type != type) + continue; + + if (match_fn(&ool_workarounds[i], arg)) + return &ool_workarounds[i]; + } + + return NULL; +} + +static +void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa) +{ + timer_unstable_counter_workaround = wa; + static_branch_enable(&arch_timer_read_ool_enabled); +} + +static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type type, + void *arg) +{ + const struct arch_timer_erratum_workaround *wa; + ate_match_fn_t match_fn = NULL; + + if (static_branch_unlikely(&arch_timer_read_ool_enabled)) + return; + + switch (type) { + case ate_match_dt: + match_fn = arch_timer_check_dt_erratum; + break; + default: + WARN_ON(1); + return; + } + + wa = arch_timer_iterate_errata(type, match_fn, arg); + if (!wa) + return; + + arch_timer_enable_workaround(wa); + pr_info("Enabling global workaround for %s\n", wa->desc); +} + +#else +#define arch_timer_check_ool_workaround(t,a) do { } while(0) #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ static __always_inline @@ -960,17 +1030,8 @@ static int __init arch_timer_of_init(struct device_node *np) arch_timer_c3stop = !of_property_read_bool(np, "always-on"); -#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND - for (i = 0; i < ARRAY_SIZE(ool_workarounds); i++) { - if (of_property_read_bool(np, ool_workarounds[i].id)) { - timer_unstable_counter_workaround = &ool_workarounds[i]; - static_branch_enable(&arch_timer_read_ool_enabled); - pr_info("arch_timer: Enabling workaround for %s\n", - timer_unstable_counter_workaround->id); - break; - } - } -#endif + /* Check for globally applicable workarounds */ + arch_timer_check_ool_workaround(ate_match_dt, np); /* * If we cannot rely on firmware initializing the timer registers then -- cgit v1.2.3 From 0064030c6fd4ca6cfab42de037b2a89445beeead Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 20 Mar 2017 16:47:59 +0000 Subject: arm64: arch_timer: Add erratum handler for CPU-specific capability Should we ever have a workaround for an erratum that is detected using a capability and affecting a particular CPU, it'd be nice to have a way to probe them directly. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- arch/arm64/include/asm/arch_timer.h | 1 + drivers/clocksource/arm_arch_timer.c | 28 ++++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index 5cd964e90d11..1b0d7e994e0c 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -39,6 +39,7 @@ extern struct static_key_false arch_timer_read_ool_enabled; enum arch_timer_erratum_match_type { ate_match_dt, + ate_match_local_cap_id, }; struct arch_timer_erratum_workaround { diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 5c5c2af74ad9..532e47fa43b3 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -214,6 +214,13 @@ bool arch_timer_check_dt_erratum(const struct arch_timer_erratum_workaround *wa, return of_property_read_bool(np, wa->id); } +static +bool arch_timer_check_local_cap_erratum(const struct arch_timer_erratum_workaround *wa, + const void *arg) +{ + return this_cpu_has_cap((uintptr_t)wa->id); +} + static const struct arch_timer_erratum_workaround * arch_timer_iterate_errata(enum arch_timer_erratum_match_type type, ate_match_fn_t match_fn, @@ -244,14 +251,16 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t { const struct arch_timer_erratum_workaround *wa; ate_match_fn_t match_fn = NULL; - - if (static_branch_unlikely(&arch_timer_read_ool_enabled)) - return; + bool local = false; switch (type) { case ate_match_dt: match_fn = arch_timer_check_dt_erratum; break; + case ate_match_local_cap_id: + match_fn = arch_timer_check_local_cap_erratum; + local = true; + break; default: WARN_ON(1); return; @@ -261,8 +270,17 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t if (!wa) return; + if (needs_unstable_timer_counter_workaround()) { + if (wa != timer_unstable_counter_workaround) + pr_warn("Can't enable workaround for %s (clashes with %s\n)", + wa->desc, + timer_unstable_counter_workaround->desc); + return; + } + arch_timer_enable_workaround(wa); - pr_info("Enabling global workaround for %s\n", wa->desc); + pr_info("Enabling %s workaround for %s\n", + local ? "local" : "global", wa->desc); } #else @@ -522,6 +540,8 @@ static void __arch_timer_setup(unsigned type, BUG(); } + arch_timer_check_ool_workaround(ate_match_local_cap_id, NULL); + erratum_workaround_set_sne(clk); } else { clk->features |= CLOCK_EVT_FEAT_DYNIRQ; -- cgit v1.2.3 From 01d3e3ff26080040cb02ec4989a0da36d069f1e9 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 27 Jan 2017 10:27:09 +0000 Subject: arm64: arch_timer: Rework the set_next_event workarounds The way we work around errata affecting set_next_event is not very nice, at it imposes this workaround on errata that do not need it. Add new workaround hooks and let the existing workarounds use them. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- arch/arm64/include/asm/arch_timer.h | 4 ++++ drivers/clocksource/arm_arch_timer.c | 31 ++++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index 1b0d7e994e0c..cc1e08127fb4 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -42,6 +42,8 @@ enum arch_timer_erratum_match_type { ate_match_local_cap_id, }; +struct clock_event_device; + struct arch_timer_erratum_workaround { enum arch_timer_erratum_match_type match_type; const void *id; @@ -49,6 +51,8 @@ struct arch_timer_erratum_workaround { u32 (*read_cntp_tval_el0)(void); u32 (*read_cntv_tval_el0)(void); u64 (*read_cntvct_el0)(void); + int (*set_next_event_phys)(unsigned long, struct clock_event_device *); + int (*set_next_event_virt)(unsigned long, struct clock_event_device *); }; extern const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround; diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 2c02e25d1475..a0c9ee80147e 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -282,6 +282,8 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = { .read_cntp_tval_el0 = fsl_a008585_read_cntp_tval_el0, .read_cntv_tval_el0 = fsl_a008585_read_cntv_tval_el0, .read_cntvct_el0 = fsl_a008585_read_cntvct_el0, + .set_next_event_phys = erratum_set_next_event_tval_phys, + .set_next_event_virt = erratum_set_next_event_tval_virt, }, #endif #ifdef CONFIG_HISILICON_ERRATUM_161010101 @@ -292,6 +294,8 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = { .read_cntp_tval_el0 = hisi_161010101_read_cntp_tval_el0, .read_cntv_tval_el0 = hisi_161010101_read_cntv_tval_el0, .read_cntvct_el0 = hisi_161010101_read_cntvct_el0, + .set_next_event_phys = erratum_set_next_event_tval_phys, + .set_next_event_virt = erratum_set_next_event_tval_virt, }, #endif }; @@ -377,11 +381,24 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t local ? "local" : "global", wa->desc); } +#define erratum_handler(fn, r, ...) \ +({ \ + bool __val; \ + if (needs_unstable_timer_counter_workaround() && \ + timer_unstable_counter_workaround->fn) { \ + r = timer_unstable_counter_workaround->fn(__VA_ARGS__); \ + __val = true; \ + } else { \ + __val = false; \ + } \ + __val; \ +}) + #else #define arch_timer_check_ool_workaround(t,a) do { } while(0) #define erratum_set_next_event_tval_virt(...) ({BUG(); 0;}) #define erratum_set_next_event_tval_phys(...) ({BUG(); 0;}) -#define needs_unstable_timer_counter_workaround() ({false;}) +#define erratum_handler(fn, r, ...) ({false;}) #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ static __always_inline irqreturn_t timer_handler(const int access, @@ -474,8 +491,10 @@ static __always_inline void set_next_event(const int access, unsigned long evt, static int arch_timer_set_next_event_virt(unsigned long evt, struct clock_event_device *clk) { - if (needs_unstable_timer_counter_workaround()) - return erratum_set_next_event_tval_virt(evt, clk); + int ret; + + if (erratum_handler(set_next_event_virt, ret, evt, clk)) + return ret; set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk); return 0; @@ -484,8 +503,10 @@ static int arch_timer_set_next_event_virt(unsigned long evt, static int arch_timer_set_next_event_phys(unsigned long evt, struct clock_event_device *clk) { - if (needs_unstable_timer_counter_workaround()) - return erratum_set_next_event_tval_phys(evt, clk); + int ret; + + if (erratum_handler(set_next_event_phys, ret, evt, clk)) + return ret; set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk); return 0; -- cgit v1.2.3 From 8c64621bf9501902a3086a5e38135344b3161128 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 27 Jan 2017 10:34:13 +0000 Subject: arm64: arch_timer: Make workaround methods optional Not all errata need to workaround all access types. Allow them to be optional. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- arch/arm64/include/asm/arch_timer.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index cc1e08127fb4..01917b4c65ca 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -60,8 +60,9 @@ extern const struct arch_timer_erratum_workaround *timer_unstable_counter_workar #define arch_timer_reg_read_stable(reg) \ ({ \ u64 _val; \ - if (needs_unstable_timer_counter_workaround()) \ - _val = timer_unstable_counter_workaround->read_##reg();\ + if (needs_unstable_timer_counter_workaround() && \ + timer_unstable_counter_workaround->read_##reg) \ + _val = timer_unstable_counter_workaround->read_##reg(); \ else \ _val = read_sysreg(reg); \ _val; \ -- cgit v1.2.3 From 6acc71ccac7187fc0ef85f10bd09c2058f21fab5 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 20 Feb 2017 18:34:48 +0000 Subject: arm64: arch_timer: Allows a CPU-specific erratum to only affect a subset of CPUs Instead of applying a CPU-specific workaround to all CPUs in the system, allow it to only affect a subset of them (typical big-little case). This is done by turning the erratum pointer into a per-CPU variable. Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier --- arch/arm64/include/asm/arch_timer.h | 31 ++++++++++++++++---------- drivers/clocksource/arm_arch_timer.c | 42 +++++++++++++++++++++++++----------- 2 files changed, 50 insertions(+), 23 deletions(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index 01917b4c65ca..6bd1a9a1573a 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -55,17 +56,25 @@ struct arch_timer_erratum_workaround { int (*set_next_event_virt)(unsigned long, struct clock_event_device *); }; -extern const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround; - -#define arch_timer_reg_read_stable(reg) \ -({ \ - u64 _val; \ - if (needs_unstable_timer_counter_workaround() && \ - timer_unstable_counter_workaround->read_##reg) \ - _val = timer_unstable_counter_workaround->read_##reg(); \ - else \ - _val = read_sysreg(reg); \ - _val; \ +DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *, + timer_unstable_counter_workaround); + +#define arch_timer_reg_read_stable(reg) \ +({ \ + u64 _val; \ + if (needs_unstable_timer_counter_workaround()) { \ + const struct arch_timer_erratum_workaround *wa; \ + preempt_disable(); \ + wa = __this_cpu_read(timer_unstable_counter_workaround); \ + if (wa && wa->read_##reg) \ + _val = wa->read_##reg(); \ + else \ + _val = read_sysreg(reg); \ + preempt_enable(); \ + } else { \ + _val = read_sysreg(reg); \ + } \ + _val; \ }) /* diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index a0c9ee80147e..4551587bcb44 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -235,7 +235,8 @@ static u64 notrace hisi_161010101_read_cntvct_el0(void) #endif #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND -const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround = NULL; +DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, + timer_unstable_counter_workaround); EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround); DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled); @@ -338,9 +339,18 @@ arch_timer_iterate_errata(enum arch_timer_erratum_match_type type, } static -void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa) +void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa, + bool local) { - timer_unstable_counter_workaround = wa; + int i; + + if (local) { + __this_cpu_write(timer_unstable_counter_workaround, wa); + } else { + for_each_possible_cpu(i) + per_cpu(timer_unstable_counter_workaround, i) = wa; + } + static_branch_enable(&arch_timer_read_ool_enabled); } @@ -369,14 +379,17 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t return; if (needs_unstable_timer_counter_workaround()) { - if (wa != timer_unstable_counter_workaround) + const struct arch_timer_erratum_workaround *__wa; + __wa = __this_cpu_read(timer_unstable_counter_workaround); + if (__wa && wa != __wa) pr_warn("Can't enable workaround for %s (clashes with %s\n)", - wa->desc, - timer_unstable_counter_workaround->desc); - return; + wa->desc, __wa->desc); + + if (__wa) + return; } - arch_timer_enable_workaround(wa); + arch_timer_enable_workaround(wa, local); pr_info("Enabling %s workaround for %s\n", local ? "local" : "global", wa->desc); } @@ -384,10 +397,15 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t #define erratum_handler(fn, r, ...) \ ({ \ bool __val; \ - if (needs_unstable_timer_counter_workaround() && \ - timer_unstable_counter_workaround->fn) { \ - r = timer_unstable_counter_workaround->fn(__VA_ARGS__); \ - __val = true; \ + if (needs_unstable_timer_counter_workaround()) { \ + const struct arch_timer_erratum_workaround *__wa; \ + __wa = __this_cpu_read(timer_unstable_counter_workaround); \ + if (__wa && __wa->fn) { \ + r = __wa->fn(__VA_ARGS__); \ + __val = true; \ + } else { \ + __val = false; \ + } \ } else { \ __val = false; \ } \ -- cgit v1.2.3 From 5a38bcac1f2f0bd0d24700690e36a277ffd0396d Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 21 Feb 2017 14:37:30 +0000 Subject: arm64: arch_timer: Allow erratum matching with ACPI OEM information Just as we're able to identify a broken platform using some DT information, let's enable a way to spot the offenders with ACPI. The difference is that we can only match on some OEM info instead of implementation-specific properties. So in order to avoid the insane multiplication of errata structures, we allow an array of OEM descriptions to be attached to an erratum structure. Acked-by: Thomas Gleixner Tested-by: dann frazier Tested-by: Hanjun Guo Reviewed-by: Hanjun Guo Signed-off-by: Marc Zyngier --- arch/arm64/include/asm/arch_timer.h | 1 + drivers/clocksource/arm_arch_timer.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) (limited to 'arch') diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index 6bd1a9a1573a..74d08e44a651 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -41,6 +41,7 @@ extern struct static_key_false arch_timer_read_ool_enabled; enum arch_timer_erratum_match_type { ate_match_dt, ate_match_local_cap_id, + ate_match_acpi_oem_info, }; struct clock_event_device; diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 8459d19a84f5..887f6d00a71d 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -190,6 +190,12 @@ static struct cyclecounter cyclecounter __ro_after_init = { .mask = CLOCKSOURCE_MASK(56), }; +struct ate_acpi_oem_info { + char oem_id[ACPI_OEM_ID_SIZE + 1]; + char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1]; + u32 oem_revision; +}; + #ifdef CONFIG_FSL_ERRATUM_A008585 /* * The number of retries is an arbitrary value well beyond the highest number @@ -371,6 +377,28 @@ bool arch_timer_check_local_cap_erratum(const struct arch_timer_erratum_workarou return this_cpu_has_cap((uintptr_t)wa->id); } + +static +bool arch_timer_check_acpi_oem_erratum(const struct arch_timer_erratum_workaround *wa, + const void *arg) +{ + static const struct ate_acpi_oem_info empty_oem_info = {}; + const struct ate_acpi_oem_info *info = wa->id; + const struct acpi_table_header *table = arg; + + /* Iterate over the ACPI OEM info array, looking for a match */ + while (memcmp(info, &empty_oem_info, sizeof(*info))) { + if (!memcmp(info->oem_id, table->oem_id, ACPI_OEM_ID_SIZE) && + !memcmp(info->oem_table_id, table->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) && + info->oem_revision == table->oem_revision) + return true; + + info++; + } + + return false; +} + static const struct arch_timer_erratum_workaround * arch_timer_iterate_errata(enum arch_timer_erratum_match_type type, ate_match_fn_t match_fn, @@ -431,6 +459,9 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t match_fn = arch_timer_check_local_cap_erratum; local = true; break; + case ate_match_acpi_oem_info: + match_fn = arch_timer_check_acpi_oem_erratum; + break; default: WARN_ON(1); return; @@ -1277,6 +1308,9 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table) /* Always-on capability */ arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON); + /* Check for globally applicable workarounds */ + arch_timer_check_ool_workaround(ate_match_acpi_oem_info, table); + arch_timer_init(); return 0; } -- cgit v1.2.3 From b72af3462dd8344285f6cc1ba726202b0d4eae20 Mon Sep 17 00:00:00 2001 From: Alexander Kochetkov Date: Tue, 31 Jan 2017 15:43:13 +0300 Subject: ARM: dts: rockchip: Update compatible property for rk322x timer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Property set to '"rockchip,rk3228-timer", "rockchip,rk3288-timer"' to match devicetree bindings. Signed-off-by: Alexander Kochetkov Suggested-by: Heiko Stübner Reviewed-by: Heiko Stuebner Signed-off-by: Daniel Lezcano --- arch/arm/boot/dts/rk322x.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi index 9dff8221112c..641607d9ad29 100644 --- a/arch/arm/boot/dts/rk322x.dtsi +++ b/arch/arm/boot/dts/rk322x.dtsi @@ -325,7 +325,7 @@ }; timer: timer@110c0000 { - compatible = "rockchip,rk3288-timer"; + compatible = "rockchip,rk3228-timer", "rockchip,rk3288-timer"; reg = <0x110c0000 0x20>; interrupts = ; clocks = <&xin24m>, <&cru PCLK_TIMER>; -- cgit v1.2.3 From 627988a66aee3c845aa2f1f874a3ddba8adb89d9 Mon Sep 17 00:00:00 2001 From: Alexander Kochetkov Date: Tue, 31 Jan 2017 15:43:15 +0300 Subject: ARM: dts: rockchip: Add timer entries to rk3188 SoC The patch add two timers to all rk3188 based boards. The first timer is from alive subsystem and it act as a backup for the local timers at sleep time. It act the same as other SoC rockchip timers already present in kernel. The second timer is from CPU subsystem and act as replacement for the arm-global-timer clocksource and sched clock. It run at stable frequency 24MHz. Signed-off-by: Alexander Kochetkov Signed-off-by: Daniel Lezcano Reviewed-by: Heiko Stuebner --- arch/arm/boot/dts/rk3188.dtsi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi index cf91254d0a43..8428faeb9c60 100644 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -106,6 +106,22 @@ }; }; + timer3: timer@2000e000 { + compatible = "rockchip,rk3188-timer", "rockchip,rk3288-timer"; + reg = <0x2000e000 0x20>; + interrupts = ; + clocks = <&cru SCLK_TIMER3>, <&cru PCLK_TIMER3>; + clock-names = "timer", "pclk"; + }; + + timer6: timer@200380a0 { + compatible = "rockchip,rk3188-timer", "rockchip,rk3288-timer"; + reg = <0x200380a0 0x20>; + interrupts = ; + clocks = <&cru SCLK_TIMER6>, <&cru PCLK_TIMER0>; + clock-names = "timer", "pclk"; + }; + i2s0: i2s@1011a000 { compatible = "rockchip,rk3188-i2s", "rockchip,rk3066-i2s"; reg = <0x1011a000 0x2000>; -- cgit v1.2.3 From 500d0aa918a2ea6bb918fee8adcf27dc2912bcd1 Mon Sep 17 00:00:00 2001 From: Alexander Kochetkov Date: Tue, 31 Jan 2017 15:43:16 +0300 Subject: ARM: dts: rockchip: disable arm-global-timer for rk3188 The clocksource and the sched_clock provided by the arm_global_timer are quite unstable because their rates depend on the cpu frequency. On the other side, the arm_global_timer has a higher rating than the rockchip_timer, it will be selected by default by the time framework while we want to use the stable rockchip clocksource. Let's disable the arm_global_timer in order to have the rockchip clocksource selected by default. Signed-off-by: Alexander Kochetkov Signed-off-by: Daniel Lezcano Reviewed-by: Heiko Stuebner --- arch/arm/boot/dts/rk3188.dtsi | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi index 8428faeb9c60..1aff4ad22fc4 100644 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -546,6 +546,7 @@ &global_timer { interrupts = ; + status = "disabled"; }; &local_timer { -- cgit v1.2.3 From 2ac00f17b2e110c67ed2af3713bc04aec62e4608 Mon Sep 17 00:00:00 2001 From: Deepa Dinamani Date: Sun, 26 Mar 2017 12:04:12 -0700 Subject: time: Delete do_sys_setimeofday() struct timespec is not y2038 safe on 32 bit machines and needs to be replaced with struct timespec64. do_sys_timeofday() is just a wrapper function. Replace all calls to this function with direct calls to do_sys_timeofday64() instead and delete do_sys_timeofday(). Signed-off-by: Deepa Dinamani Cc: y2038@lists.linaro.org Cc: john.stultz@linaro.org Cc: arnd@arndb.de Cc: linux-alpha@vger.kernel.org Link: http://lkml.kernel.org/r/1490555058-4603-2-git-send-email-deepa.kernel@gmail.com Signed-off-by: Thomas Gleixner --- arch/alpha/kernel/osf_sys.c | 4 +++- include/linux/timekeeping.h | 15 --------------- kernel/compat.c | 4 ++-- kernel/time/posix-stubs.c | 5 ++++- kernel/time/posix-timers.c | 5 ++++- kernel/time/time.c | 4 ++-- 6 files changed, 15 insertions(+), 22 deletions(-) (limited to 'arch') diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 0b961093ca5c..9de47a9c6df2 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -1016,6 +1016,7 @@ SYSCALL_DEFINE2(osf_gettimeofday, struct timeval32 __user *, tv, SYSCALL_DEFINE2(osf_settimeofday, struct timeval32 __user *, tv, struct timezone __user *, tz) { + struct timespec64 kts64; struct timespec kts; struct timezone ktz; @@ -1023,13 +1024,14 @@ SYSCALL_DEFINE2(osf_settimeofday, struct timeval32 __user *, tv, if (get_tv32((struct timeval *)&kts, tv)) return -EFAULT; kts.tv_nsec *= 1000; + kts64 = timespec_to_timespec64(kts); } if (tz) { if (copy_from_user(&ktz, tz, sizeof(*tz))) return -EFAULT; } - return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); + return do_sys_settimeofday64(tv ? &kts64 : NULL, tz ? &ktz : NULL); } asmlinkage long sys_ni_posix_timers(void); diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index b598cbc7b576..3617a78897bb 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -19,21 +19,6 @@ extern void do_gettimeofday(struct timeval *tv); extern int do_settimeofday64(const struct timespec64 *ts); extern int do_sys_settimeofday64(const struct timespec64 *tv, const struct timezone *tz); -static inline int do_sys_settimeofday(const struct timespec *tv, - const struct timezone *tz) -{ - struct timespec64 ts64; - - if (!tv) - return do_sys_settimeofday64(NULL, tz); - - if (!timespec_valid(tv)) - return -EINVAL; - - ts64 = timespec_to_timespec64(*tv); - return do_sys_settimeofday64(&ts64, tz); -} - /* * Kernel time accessors */ diff --git a/kernel/compat.c b/kernel/compat.c index 19aec5d98108..1eb9e8aad869 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -108,8 +108,8 @@ COMPAT_SYSCALL_DEFINE2(gettimeofday, struct compat_timeval __user *, tv, COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv, struct timezone __user *, tz) { + struct timespec64 new_ts; struct timeval user_tv; - struct timespec new_ts; struct timezone new_tz; if (tv) { @@ -123,7 +123,7 @@ COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv, return -EFAULT; } - return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL); + return do_sys_settimeofday64(tv ? &new_ts : NULL, tz ? &new_tz : NULL); } static int __compat_get_timeval(struct timeval *tv, const struct compat_timeval __user *ctv) diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c index cd6716e115e8..95a1b1fc3968 100644 --- a/kernel/time/posix-stubs.c +++ b/kernel/time/posix-stubs.c @@ -49,13 +49,16 @@ SYS_NI(alarm); SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, const struct timespec __user *, tp) { + struct timespec64 new_tp64; struct timespec new_tp; if (which_clock != CLOCK_REALTIME) return -EINVAL; if (copy_from_user(&new_tp, tp, sizeof (*tp))) return -EFAULT; - return do_sys_settimeofday(&new_tp, NULL); + + new_tp64 = timespec_to_timespec64(new_tp); + return do_sys_settimeofday64(&new_tp64, NULL); } SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 50a6a47020de..f215ef792772 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -214,7 +214,10 @@ static int posix_clock_realtime_get(clockid_t which_clock, struct timespec *tp) static int posix_clock_realtime_set(const clockid_t which_clock, const struct timespec *tp) { - return do_sys_settimeofday(tp, NULL); + struct timespec64 tp64; + + tp64 = timespec_to_timespec64(*tp); + return do_sys_settimeofday64(&tp64, NULL); } static int posix_clock_realtime_adj(const clockid_t which_clock, diff --git a/kernel/time/time.c b/kernel/time/time.c index 25bdd2504571..6574bba44b55 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -193,8 +193,8 @@ int do_sys_settimeofday64(const struct timespec64 *tv, const struct timezone *tz SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv, struct timezone __user *, tz) { + struct timespec64 new_ts; struct timeval user_tv; - struct timespec new_ts; struct timezone new_tz; if (tv) { @@ -212,7 +212,7 @@ SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv, return -EFAULT; } - return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL); + return do_sys_settimeofday64(tv ? &new_ts : NULL, tz ? &new_tz : NULL); } SYSCALL_DEFINE1(adjtimex, struct timex __user *, txc_p) -- cgit v1.2.3 From 3d18d661aaad5a22f4d37a0592acc9d784f2a11b Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 22:06:42 +0200 Subject: x86/xen/time: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the x86 arch's xen clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Boris Ostrovsky Cc: Juergen Gross Cc: "H. Peter Anvin" Cc: x86@kernel.org Cc: xen-devel@lists.xenproject.org Reviewed-by: Boris Ostrovsky Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/x86/xen/time.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 1e69956d7852..7a3089285c59 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -209,7 +209,9 @@ static const struct clock_event_device xen_timerop_clockevent = { .features = CLOCK_EVT_FEAT_ONESHOT, .max_delta_ns = 0xffffffff, + .max_delta_ticks = 0xffffffff, .min_delta_ns = TIMER_SLOP, + .min_delta_ticks = TIMER_SLOP, .mult = 1, .shift = 0, @@ -268,7 +270,9 @@ static const struct clock_event_device xen_vcpuop_clockevent = { .features = CLOCK_EVT_FEAT_ONESHOT, .max_delta_ns = 0xffffffff, + .max_delta_ticks = 0xffffffff, .min_delta_ns = TIMER_SLOP, + .min_delta_ticks = TIMER_SLOP, .mult = 1, .shift = 0, -- cgit v1.2.3 From 33ae7a9b6c23cdffe7449ddf1a992117262b939b Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 21:44:31 +0200 Subject: m68k/coldfire/pit: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the m68k arch's coldfire clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Greg Ungerer CC: Geert Uytterhoeven Cc: linux-m68k@lists.linux-m68k.org Acked-by: Greg Ungerer Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/m68k/coldfire/pit.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/m68k/coldfire/pit.c b/arch/m68k/coldfire/pit.c index 175553d5b8ed..6c0878018b44 100644 --- a/arch/m68k/coldfire/pit.c +++ b/arch/m68k/coldfire/pit.c @@ -149,8 +149,10 @@ void hw_timer_init(irq_handler_t handler) cf_pit_clockevent.mult = div_sc(FREQ, NSEC_PER_SEC, 32); cf_pit_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFF, &cf_pit_clockevent); + cf_pit_clockevent.max_delta_ticks = 0xFFFF; cf_pit_clockevent.min_delta_ns = clockevent_delta2ns(0x3f, &cf_pit_clockevent); + cf_pit_clockevent.min_delta_ticks = 0x3f; clockevents_register_device(&cf_pit_clockevent); setup_irq(MCF_IRQ_PIT1, &pit_irq); -- cgit v1.2.3 From 115631c350bfd3b9cbc0aff75b3975e17c83d3d9 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 21:53:17 +0200 Subject: powerpc/time: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the powerpc arch's clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Oliver O'Halloran Cc: linuxppc-dev@lists.ozlabs.org Acked-by: Michael Ellerman (powerpc) Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/powerpc/kernel/time.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 07b90725855e..2b33cfaac7b8 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -995,8 +995,10 @@ static void __init init_decrementer_clockevent(void) decrementer_clockevent.max_delta_ns = clockevent_delta2ns(decrementer_max, &decrementer_clockevent); + decrementer_clockevent.max_delta_ticks = decrementer_max; decrementer_clockevent.min_delta_ns = clockevent_delta2ns(2, &decrementer_clockevent); + decrementer_clockevent.min_delta_ticks = 2; register_decrementer_clockevent(cpu); } -- cgit v1.2.3 From 7fd534247d1b6fcd399ab70f04db39047724898a Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 21:56:47 +0200 Subject: sparc/time: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the sparc arch's clockevent drivers initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from these drivers. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: "David S. Miller" Cc: sparclinux@vger.kernel.org Acked-by: David S. Miller Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/sparc/kernel/time_32.c | 2 ++ arch/sparc/kernel/time_64.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c index 244062bdaa56..9f575dfc2e41 100644 --- a/arch/sparc/kernel/time_32.c +++ b/arch/sparc/kernel/time_32.c @@ -228,7 +228,9 @@ void register_percpu_ce(int cpu) ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC, ce->shift); ce->max_delta_ns = clockevent_delta2ns(sparc_config.clock_rate, ce); + ce->max_delta_ticks = (unsigned long)sparc_config.clock_rate; ce->min_delta_ns = clockevent_delta2ns(100, ce); + ce->min_delta_ticks = 100; clockevents_register_device(ce); } diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 12a6d3555cb8..98d05de8da66 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -796,8 +796,10 @@ void __init time_init(void) sparc64_clockevent.max_delta_ns = clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent); + sparc64_clockevent.max_delta_ticks = 0x7fffffffffffffffUL; sparc64_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &sparc64_clockevent); + sparc64_clockevent.min_delta_ticks = 0xF; printk("clockevent: mult[%x] shift[%d]\n", sparc64_clockevent.mult, sparc64_clockevent.shift); -- cgit v1.2.3 From b77f41618c2647e80ee45d6609d95b3d4a10e372 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 22:03:41 +0200 Subject: x86/lguest/timer: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the x86 arch's lguest clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Rusty Russell Cc: "H. Peter Anvin" Cc: x86@kernel.org Cc: Paul Bolle Cc: Andy Lutomirski Cc: Juergen Gross Cc: "Luis R. Rodriguez" Cc: lguest@lists.ozlabs.org Acked-by: Rusty Russell Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/x86/lguest/boot.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index d3289d7e78fa..3e4bf887a246 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -994,7 +994,9 @@ static struct clock_event_device lguest_clockevent = { .mult = 1, .shift = 0, .min_delta_ns = LG_CLOCK_MIN_DELTA, + .min_delta_ticks = LG_CLOCK_MIN_DELTA, .max_delta_ns = LG_CLOCK_MAX_DELTA, + .max_delta_ticks = LG_CLOCK_MAX_DELTA, }; /* -- cgit v1.2.3 From a60a9fb8fb52768bd19cd8c0893f4c0432acb10e Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 21:43:32 +0200 Subject: hexagon/time: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the hexagon arch's clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Richard Kuo Cc: linux-hexagon@vger.kernel.org Acked-by: Richard Kuo Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/hexagon/kernel/time.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c index ff4e9bf995e9..29b1f57116c8 100644 --- a/arch/hexagon/kernel/time.c +++ b/arch/hexagon/kernel/time.c @@ -199,7 +199,9 @@ void __init time_init_deferred(void) clockevents_calc_mult_shift(ce_dev, sleep_clk_freq, 4); ce_dev->max_delta_ns = clockevent_delta2ns(0x7fffffff, ce_dev); + ce_dev->max_delta_ticks = 0x7fffffff; ce_dev->min_delta_ns = clockevent_delta2ns(0xf, ce_dev); + ce_dev->min_delta_ticks = 0xf; #ifdef CONFIG_SMP setup_percpu_clockdev(); -- cgit v1.2.3 From e4db9253d6b4c1d927254f1c4bef875573229502 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 21:47:32 +0200 Subject: MIPS: clockevent drivers: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the MIPS arch's clockevent drivers initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from these drivers. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Ralf Baechle Cc: Keguang Zhang Cc: John Crispin Acked-by: Ralf Baechle Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/mips/alchemy/common/time.c | 4 +++- arch/mips/jz4740/time.c | 2 ++ arch/mips/kernel/cevt-bcm1480.c | 2 ++ arch/mips/kernel/cevt-ds1287.c | 2 ++ arch/mips/kernel/cevt-gt641xx.c | 2 ++ arch/mips/kernel/cevt-sb1250.c | 2 ++ arch/mips/kernel/cevt-txx9.c | 2 ++ arch/mips/loongson32/common/time.c | 2 ++ arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c | 2 ++ arch/mips/loongson64/loongson-3/hpet.c | 2 ++ arch/mips/ralink/cevt-rt3352.c | 2 ++ arch/mips/sgi-ip27/ip27-timer.c | 2 ++ 12 files changed, 25 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/alchemy/common/time.c b/arch/mips/alchemy/common/time.c index e1bec5a77c39..32d1333bb243 100644 --- a/arch/mips/alchemy/common/time.c +++ b/arch/mips/alchemy/common/time.c @@ -138,7 +138,9 @@ static int __init alchemy_time_init(unsigned int m2int) cd->shift = 32; cd->mult = div_sc(32768, NSEC_PER_SEC, cd->shift); cd->max_delta_ns = clockevent_delta2ns(0xffffffff, cd); - cd->min_delta_ns = clockevent_delta2ns(9, cd); /* ~0.28ms */ + cd->max_delta_ticks = 0xffffffff; + cd->min_delta_ns = clockevent_delta2ns(9, cd); + cd->min_delta_ticks = 9; /* ~0.28ms */ clockevents_register_device(cd); setup_irq(m2int, &au1x_rtcmatch2_irqaction); diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c index bcf8f8c62737..bb1ad5119da4 100644 --- a/arch/mips/jz4740/time.c +++ b/arch/mips/jz4740/time.c @@ -145,7 +145,9 @@ void __init plat_time_init(void) clockevent_set_clock(&jz4740_clockevent, clk_rate); jz4740_clockevent.min_delta_ns = clockevent_delta2ns(100, &jz4740_clockevent); + jz4740_clockevent.min_delta_ticks = 100; jz4740_clockevent.max_delta_ns = clockevent_delta2ns(0xffff, &jz4740_clockevent); + jz4740_clockevent.max_delta_ticks = 0xffff; jz4740_clockevent.cpumask = cpumask_of(0); clockevents_register_device(&jz4740_clockevent); diff --git a/arch/mips/kernel/cevt-bcm1480.c b/arch/mips/kernel/cevt-bcm1480.c index 940ac00e9129..8f9f2daf06a3 100644 --- a/arch/mips/kernel/cevt-bcm1480.c +++ b/arch/mips/kernel/cevt-bcm1480.c @@ -123,7 +123,9 @@ void sb1480_clockevent_init(void) CLOCK_EVT_FEAT_ONESHOT; clockevent_set_clock(cd, V_SCD_TIMER_FREQ); cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd); + cd->max_delta_ticks = 0x7fffff; cd->min_delta_ns = clockevent_delta2ns(2, cd); + cd->min_delta_ticks = 2; cd->rating = 200; cd->irq = irq; cd->cpumask = cpumask_of(cpu); diff --git a/arch/mips/kernel/cevt-ds1287.c b/arch/mips/kernel/cevt-ds1287.c index 77a5ddf53f57..61ad9079fa16 100644 --- a/arch/mips/kernel/cevt-ds1287.c +++ b/arch/mips/kernel/cevt-ds1287.c @@ -128,7 +128,9 @@ int __init ds1287_clockevent_init(int irq) cd->irq = irq; clockevent_set_clock(cd, 32768); cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); + cd->max_delta_ticks = 0x7fffffff; cd->min_delta_ns = clockevent_delta2ns(0x300, cd); + cd->min_delta_ticks = 0x300; cd->cpumask = cpumask_of(0); clockevents_register_device(&ds1287_clockevent); diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c index 66040051151d..fd90c82dc17d 100644 --- a/arch/mips/kernel/cevt-gt641xx.c +++ b/arch/mips/kernel/cevt-gt641xx.c @@ -152,7 +152,9 @@ static int __init gt641xx_timer0_clockevent_init(void) cd->rating = 200 + gt641xx_base_clock / 10000000; clockevent_set_clock(cd, gt641xx_base_clock); cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); + cd->max_delta_ticks = 0x7fffffff; cd->min_delta_ns = clockevent_delta2ns(0x300, cd); + cd->min_delta_ticks = 0x300; cd->cpumask = cpumask_of(0); clockevents_register_device(>641xx_timer0_clockevent); diff --git a/arch/mips/kernel/cevt-sb1250.c b/arch/mips/kernel/cevt-sb1250.c index 3d860efd63b9..9d1edb5938b8 100644 --- a/arch/mips/kernel/cevt-sb1250.c +++ b/arch/mips/kernel/cevt-sb1250.c @@ -123,7 +123,9 @@ void sb1250_clockevent_init(void) CLOCK_EVT_FEAT_ONESHOT; clockevent_set_clock(cd, V_SCD_TIMER_FREQ); cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd); + cd->max_delta_ticks = 0x7fffff; cd->min_delta_ns = clockevent_delta2ns(2, cd); + cd->min_delta_ticks = 2; cd->rating = 200; cd->irq = irq; cd->cpumask = cpumask_of(cpu); diff --git a/arch/mips/kernel/cevt-txx9.c b/arch/mips/kernel/cevt-txx9.c index aaca60d6ffc3..7b17c8f5009d 100644 --- a/arch/mips/kernel/cevt-txx9.c +++ b/arch/mips/kernel/cevt-txx9.c @@ -196,7 +196,9 @@ void __init txx9_clockevent_init(unsigned long baseaddr, int irq, clockevent_set_clock(cd, TIMER_CLK(imbusclk)); cd->max_delta_ns = clockevent_delta2ns(0xffffffff >> (32 - TXX9_TIMER_BITS), cd); + cd->max_delta_ticks = 0xffffffff >> (32 - TXX9_TIMER_BITS); cd->min_delta_ns = clockevent_delta2ns(0xf, cd); + cd->min_delta_ticks = 0xf; cd->irq = irq; cd->cpumask = cpumask_of(0), clockevents_register_device(cd); diff --git a/arch/mips/loongson32/common/time.c b/arch/mips/loongson32/common/time.c index e6f972d35252..1c4332a26cf1 100644 --- a/arch/mips/loongson32/common/time.c +++ b/arch/mips/loongson32/common/time.c @@ -199,7 +199,9 @@ static void __init ls1x_time_init(void) clockevent_set_clock(cd, mips_hpt_frequency); cd->max_delta_ns = clockevent_delta2ns(0xffffff, cd); + cd->max_delta_ticks = 0xffffff; cd->min_delta_ns = clockevent_delta2ns(0x000300, cd); + cd->min_delta_ticks = 0x000300; cd->cpumask = cpumask_of(smp_processor_id()); clockevents_register_device(cd); diff --git a/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c b/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c index b817d6d3a060..a6adcc4f8960 100644 --- a/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c +++ b/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c @@ -123,7 +123,9 @@ void __init setup_mfgpt0_timer(void) cd->cpumask = cpumask_of(cpu); clockevent_set_clock(cd, MFGPT_TICK_RATE); cd->max_delta_ns = clockevent_delta2ns(0xffff, cd); + cd->max_delta_ticks = 0xffff; cd->min_delta_ns = clockevent_delta2ns(0xf, cd); + cd->min_delta_ticks = 0xf; /* Enable MFGPT0 Comparator 2 Output to the Interrupt Mapper */ _wrmsr(DIVIL_MSR_REG(MFGPT_IRQ), 0, 0x100); diff --git a/arch/mips/loongson64/loongson-3/hpet.c b/arch/mips/loongson64/loongson-3/hpet.c index 24afe364637b..4df9d4b7356a 100644 --- a/arch/mips/loongson64/loongson-3/hpet.c +++ b/arch/mips/loongson64/loongson-3/hpet.c @@ -241,7 +241,9 @@ void __init setup_hpet_timer(void) cd->cpumask = cpumask_of(cpu); clockevent_set_clock(cd, HPET_FREQ); cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); + cd->max_delta_ticks = 0x7fffffff; cd->min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA, cd); + cd->min_delta_ticks = HPET_MIN_PROG_DELTA; clockevents_register_device(cd); setup_irq(HPET_T0_IRQ, &hpet_irq); diff --git a/arch/mips/ralink/cevt-rt3352.c b/arch/mips/ralink/cevt-rt3352.c index f24eee04e16a..b8a1376165b0 100644 --- a/arch/mips/ralink/cevt-rt3352.c +++ b/arch/mips/ralink/cevt-rt3352.c @@ -129,7 +129,9 @@ static int __init ralink_systick_init(struct device_node *np) systick.dev.name = np->name; clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60); systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev); + systick.dev.max_delta_ticks = 0x7fff; systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev); + systick.dev.min_delta_ticks = 0x3; systick.dev.irq = irq_of_parse_and_map(np, 0); if (!systick.dev.irq) { pr_err("%s: request_irq failed", np->name); diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 695c51bdd7dc..a53f0c8c901e 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -113,7 +113,9 @@ void hub_rt_clock_event_init(void) cd->features = CLOCK_EVT_FEAT_ONESHOT; clockevent_set_clock(cd, CYCLES_PER_SEC); cd->max_delta_ns = clockevent_delta2ns(0xfffffffffffff, cd); + cd->max_delta_ticks = 0xfffffffffffff; cd->min_delta_ns = clockevent_delta2ns(0x300, cd); + cd->min_delta_ticks = 0x300; cd->rating = 200; cd->irq = irq; cd->cpumask = cpumask_of(cpu); -- cgit v1.2.3 From 747d04b30e5285d8fc81db6a20b745bde3830798 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Sun, 26 Mar 2017 15:44:03 +0200 Subject: x86/apic/timer: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the x86 arch's apic clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: "H. Peter Anvin" Cc: x86@kernel.org CC: Dou Liyang Cc: Gu Zheng Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/x86/kernel/apic/apic.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 8ccb7ef512e0..875091d4609d 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -731,8 +731,10 @@ static int __init calibrate_APIC_clock(void) TICK_NSEC, lapic_clockevent.shift); lapic_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFF, &lapic_clockevent); + lapic_clockevent.max_delta_ticks = 0x7FFFFF; lapic_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &lapic_clockevent); + lapic_clockevent.min_delta_ticks = 0xF; lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY; return 0; } @@ -778,8 +780,10 @@ static int __init calibrate_APIC_clock(void) lapic_clockevent.shift); lapic_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, &lapic_clockevent); + lapic_clockevent.max_delta_ticks = 0x7FFFFFFF; lapic_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &lapic_clockevent); + lapic_clockevent.min_delta_ticks = 0xF; lapic_timer_frequency = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS; -- cgit v1.2.3 From 18154c5c978bbd3a77f05a66421c362374edca57 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 21:41:09 +0200 Subject: blackfin: time-ts: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the blackfin arch's clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Steven Miao Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/blackfin/kernel/time-ts.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c index 0e9fcf841d67..01350557fbd7 100644 --- a/arch/blackfin/kernel/time-ts.c +++ b/arch/blackfin/kernel/time-ts.c @@ -230,7 +230,9 @@ static void __init bfin_gptmr0_clockevent_init(struct clock_event_device *evt) clock_tick = get_sclk(); evt->mult = div_sc(clock_tick, NSEC_PER_SEC, evt->shift); evt->max_delta_ns = clockevent_delta2ns(-1, evt); + evt->max_delta_ticks = (unsigned long)-1; evt->min_delta_ns = clockevent_delta2ns(100, evt); + evt->min_delta_ticks = 100; evt->cpumask = cpumask_of(0); @@ -344,7 +346,9 @@ void bfin_coretmr_clockevent_init(void) clock_tick = get_cclk() / TIME_SCALE; evt->mult = div_sc(clock_tick, NSEC_PER_SEC, evt->shift); evt->max_delta_ns = clockevent_delta2ns(-1, evt); + evt->max_delta_ticks = (unsigned long)-1; evt->min_delta_ns = clockevent_delta2ns(100, evt); + evt->min_delta_ticks = 100; evt->cpumask = cpumask_of(cpu); -- cgit v1.2.3 From e1e5fc150da4233f2bf9c143068e1a673071a68f Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 21:42:20 +0200 Subject: c6x/timer64: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the c6x arch's clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Mark Salter Cc: Aurelien Jacquiot Cc: linux-c6x-dev@linux-c6x.org Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/c6x/platforms/timer64.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/c6x/platforms/timer64.c b/arch/c6x/platforms/timer64.c index c19901e5f055..0bd0452ded80 100644 --- a/arch/c6x/platforms/timer64.c +++ b/arch/c6x/platforms/timer64.c @@ -234,7 +234,9 @@ void __init timer64_init(void) clockevents_calc_mult_shift(cd, c6x_core_freq / TIMER_DIVISOR, 5); cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); + cd->max_delta_ticks = 0x7fffffff; cd->min_delta_ns = clockevent_delta2ns(250, cd); + cd->min_delta_ticks = 250; cd->cpumask = cpumask_of(smp_processor_id()); -- cgit v1.2.3 From 5f664e2b1bb1325c350192ead3f305742fcc79c7 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 21:48:28 +0200 Subject: mn10300/cevt-mn10300: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the mn10300 arch's clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: David Howells Cc: linux-am33-list@redhat.com Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/mn10300/kernel/cevt-mn10300.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/mn10300/kernel/cevt-mn10300.c b/arch/mn10300/kernel/cevt-mn10300.c index d9b34dd44f04..2b21bbc9efa4 100644 --- a/arch/mn10300/kernel/cevt-mn10300.c +++ b/arch/mn10300/kernel/cevt-mn10300.c @@ -98,7 +98,9 @@ int __init init_clockevents(void) /* Calculate the min / max delta */ cd->max_delta_ns = clockevent_delta2ns(TMJCBR_MAX, cd); + cd->max_delta_ticks = TMJCBR_MAX; cd->min_delta_ns = clockevent_delta2ns(100, cd); + cd->min_delta_ticks = 100; cd->rating = 200; cd->cpumask = cpumask_of(smp_processor_id()); -- cgit v1.2.3 From 06c546110b0dafbc96c6eaf00aaa5835a18408c1 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 21:54:55 +0200 Subject: s390/time: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Currently, the s390's CPU timer clockevent device is initialized as follows: cd->min_delta_ns = 1; cd->max_delta_ns = LONG_MAX; Note that the device's time to cycle conversion factor, i.e. cd->mult / (2^cd->shift), is approx. equal to 4. Hence, this would translate to cd->min_delta_ticks = 4; cd->max_delta_ticks = 4 * LONG_MAX; However, a minimum value of 1ns is in the range of noise anyway and the clockevent core will take care of this by increasing it to 1us or so. Furthermore, 4*LONG_MAX would overflow the unsigned long argument the clockevent devices gets programmed with. Thus, initialize ->min_delta_ticks with 1 and ->max_delta_ticks with ULONG_MAX. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: David Hildenbrand Cc: linux-s390@vger.kernel.org Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/s390/kernel/time.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index c31da46bc037..c3a52f9a69a0 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -158,7 +158,9 @@ void init_cpu_timer(void) cd->mult = 16777; cd->shift = 12; cd->min_delta_ns = 1; + cd->min_delta_ticks = 1; cd->max_delta_ns = LONG_MAX; + cd->max_delta_ticks = ULONG_MAX; cd->rating = 400; cd->cpumask = cpumask_of(cpu); cd->set_next_event = s390_next_event; -- cgit v1.2.3 From c5d710654c0eb9a33d32aadea4863442461cf847 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 21:55:55 +0200 Subject: score/time: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the score arch's clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Chen Liqin Cc: Lennox Wu Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/score/kernel/time.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/score/kernel/time.c b/arch/score/kernel/time.c index 679b8d7b0350..29aafc741f69 100644 --- a/arch/score/kernel/time.c +++ b/arch/score/kernel/time.c @@ -81,8 +81,10 @@ void __init time_init(void) score_clockevent.shift); score_clockevent.max_delta_ns = clockevent_delta2ns((u32)~0, &score_clockevent); + score_clockevent.max_delta_ticks = (u32)~0; score_clockevent.min_delta_ns = clockevent_delta2ns(50, &score_clockevent) + 1; + score_clockevent.min_delta_ticks = 50; score_clockevent.cpumask = cpumask_of(0); clockevents_register_device(&score_clockevent); } -- cgit v1.2.3 From 45b586ef231abf29bff2b91efb74c10d01a0d79c Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 21:57:43 +0200 Subject: tile/time: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Currently, the tile's timer clockevent device is initialized as follows: evt->max_delta_ns = clockevent_delta2ns(MAX_TICK, evt); and .min_delta_ns = 1000, The first one translates to a ->max_delta_ticks value of MAX_TICK. For the latter, note that the clockevent core will superimpose a minimum of 1us by itself -- setting ->min_delta_ticks to 1 is safe here. Initialize ->min_delta_ticks and ->max_delta_ticks with these values. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Chris Metcalf Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/tile/kernel/time.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c index 5bd4e88c7c60..6643ffbc0615 100644 --- a/arch/tile/kernel/time.c +++ b/arch/tile/kernel/time.c @@ -155,6 +155,8 @@ static DEFINE_PER_CPU(struct clock_event_device, tile_timer) = { .name = "tile timer", .features = CLOCK_EVT_FEAT_ONESHOT, .min_delta_ns = 1000, + .min_delta_ticks = 1, + .max_delta_ticks = MAX_TICK, .rating = 100, .irq = -1, .set_next_event = tile_timer_set_next_event, -- cgit v1.2.3 From 8ab3a284a6348f4160a93051d1ed69692589a5c8 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 21:59:42 +0200 Subject: um/time: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the uml arch's clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Richard Weinberger Cc: Jeff Dike Cc: user-mode-linux-devel@lists.sourceforge.net Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/um/kernel/time.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index ba87a27d6715..0b034ebbda2a 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -65,7 +65,9 @@ static struct clock_event_device timer_clockevent = { .set_next_event = itimer_next_event, .shift = 0, .max_delta_ns = 0xffffffff, - .min_delta_ns = TIMER_MIN_DELTA, //microsecond resolution should be enough for anyone, same as 640K RAM + .max_delta_ticks = 0xffffffff, + .min_delta_ns = TIMER_MIN_DELTA, + .min_delta_ticks = TIMER_MIN_DELTA, // microsecond resolution should be enough for anyone, same as 640K RAM .irq = 0, .mult = 1, }; -- cgit v1.2.3 From 16c125b6c2c58a77756f099605724a2b11aea2d1 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 22:01:13 +0200 Subject: unicore32/time: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Make the unicore32 arch's clockevent driver initialize these fields properly. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Guan Xuetao Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/unicore32/kernel/time.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/unicore32/kernel/time.c b/arch/unicore32/kernel/time.c index fceaa673f861..c6b3fa3ee0b6 100644 --- a/arch/unicore32/kernel/time.c +++ b/arch/unicore32/kernel/time.c @@ -91,8 +91,10 @@ void __init time_init(void) ckevt_puv3_osmr0.max_delta_ns = clockevent_delta2ns(0x7fffffff, &ckevt_puv3_osmr0); + ckevt_puv3_osmr0.max_delta_ticks = 0x7fffffff; ckevt_puv3_osmr0.min_delta_ns = clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_puv3_osmr0) + 1; + ckevt_puv3_osmr0.min_delta_ticks = MIN_OSCR_DELTA * 2; ckevt_puv3_osmr0.cpumask = cpumask_of(0); setup_irq(IRQ_TIMER0, &puv3_timer_irq); -- cgit v1.2.3 From 6fc46497a9fb283c4f8e8d04ae4f0bf3c0041f7e Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Thu, 30 Mar 2017 22:04:58 +0200 Subject: x86/uv/time: Set ->min_delta_ticks and ->max_delta_ticks In preparation for making the clockevents core NTP correction aware, all clockevent device drivers must set ->min_delta_ticks and ->max_delta_ticks rather than ->min_delta_ns and ->max_delta_ns: a clockevent device's rate is going to change dynamically and thus, the ratio of ns to ticks ceases to stay invariant. Currently, the x86's uv rtc clockevent device is initialized as follows: clock_event_device_uv.min_delta_ns = NSEC_PER_SEC / sn_rtc_cycles_per_second; clock_event_device_uv.max_delta_ns = clocksource_uv.mask * (NSEC_PER_SEC / sn_rtc_cycles_per_second); This translates to a ->min_delta_ticks value of 1 and a ->max_delta_ticks value of clocksource_uv.mask. Initialize ->min_delta_ticks and ->max_delta_ticks with these values respectively. This patch alone doesn't introduce any change in functionality as the clockevents core still looks exclusively at the (untouched) ->min_delta_ns and ->max_delta_ns. As soon as this has changed, a followup patch will purge the initialization of ->min_delta_ns and ->max_delta_ns from this driver. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Daniel Lezcano Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: "H. Peter Anvin" Cc: x86@kernel.org Cc: Mike Travis Cc: Dimitri Sivanich Signed-off-by: Nicolai Stange Signed-off-by: John Stultz --- arch/x86/platform/uv/uv_time.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/platform/uv/uv_time.c b/arch/x86/platform/uv/uv_time.c index 2ee7632d4916..b082d71b08ee 100644 --- a/arch/x86/platform/uv/uv_time.c +++ b/arch/x86/platform/uv/uv_time.c @@ -390,9 +390,11 @@ static __init int uv_rtc_setup_clock(void) clock_event_device_uv.min_delta_ns = NSEC_PER_SEC / sn_rtc_cycles_per_second; + clock_event_device_uv.min_delta_ticks = 1; clock_event_device_uv.max_delta_ns = clocksource_uv.mask * (NSEC_PER_SEC / sn_rtc_cycles_per_second); + clock_event_device_uv.max_delta_ticks = clocksource_uv.mask; rc = schedule_on_each_cpu(uv_rtc_register_clockevents); if (rc) { -- cgit v1.2.3 From 5f1ae4ebe578319a0cd5dae9591dd426070be106 Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Sat, 1 Apr 2017 01:51:01 +0800 Subject: acpi/arm64: Add GTDT table parse driver This patch adds support for parsing arch timer info in GTDT, provides some kernel APIs to parse all the PPIs and always-on info in GTDT and export them. By this driver, we can simplify arm_arch_timer drivers, and separate the ACPI GTDT knowledge from it. Signed-off-by: Fu Wei Signed-off-by: Hanjun Guo Acked-by: Rafael J. Wysocki Tested-by: Xiongfeng Wang Reviewed-by: Hanjun Guo Tested-by: Hanjun Guo Acked-by: Lorenzo Pieralisi Signed-off-by: Mark Rutland --- arch/arm64/Kconfig | 1 + drivers/acpi/arm64/Kconfig | 3 + drivers/acpi/arm64/Makefile | 1 + drivers/acpi/arm64/gtdt.c | 157 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 6 ++ 5 files changed, 168 insertions(+) create mode 100644 drivers/acpi/arm64/gtdt.c (limited to 'arch') diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 3741859765cf..7e2baec6f23a 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -2,6 +2,7 @@ config ARM64 def_bool y select ACPI_CCA_REQUIRED if ACPI select ACPI_GENERIC_GSI if ACPI + select ACPI_GTDT if ACPI select ACPI_REDUCED_HARDWARE_ONLY if ACPI select ACPI_MCFG if ACPI select ACPI_SPCR_TABLE if ACPI diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig index 4616da4c15be..5a6f80fce0d6 100644 --- a/drivers/acpi/arm64/Kconfig +++ b/drivers/acpi/arm64/Kconfig @@ -4,3 +4,6 @@ config ACPI_IORT bool + +config ACPI_GTDT + bool diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile index 72331f2ce0e9..1017def2ea12 100644 --- a/drivers/acpi/arm64/Makefile +++ b/drivers/acpi/arm64/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_ACPI_IORT) += iort.o +obj-$(CONFIG_ACPI_GTDT) += gtdt.o diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c new file mode 100644 index 000000000000..3d95af8f73c6 --- /dev/null +++ b/drivers/acpi/arm64/gtdt.c @@ -0,0 +1,157 @@ +/* + * ARM Specific GTDT table Support + * + * Copyright (C) 2016, Linaro Ltd. + * Author: Daniel Lezcano + * Fu Wei + * Hanjun Guo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include + +#undef pr_fmt +#define pr_fmt(fmt) "ACPI GTDT: " fmt + +/** + * struct acpi_gtdt_descriptor - Store the key info of GTDT for all functions + * @gtdt: The pointer to the struct acpi_table_gtdt of GTDT table. + * @gtdt_end: The pointer to the end of GTDT table. + * @platform_timer: The pointer to the start of Platform Timer Structure + * + * The struct store the key info of GTDT table, it should be initialized by + * acpi_gtdt_init. + */ +struct acpi_gtdt_descriptor { + struct acpi_table_gtdt *gtdt; + void *gtdt_end; + void *platform_timer; +}; + +static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata; + +static int __init map_gt_gsi(u32 interrupt, u32 flags) +{ + int trigger, polarity; + + trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE + : ACPI_LEVEL_SENSITIVE; + + polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW + : ACPI_ACTIVE_HIGH; + + return acpi_register_gsi(NULL, interrupt, trigger, polarity); +} + +/** + * acpi_gtdt_map_ppi() - Map the PPIs of per-cpu arch_timer. + * @type: the type of PPI. + * + * Note: Secure state is not managed by the kernel on ARM64 systems. + * So we only handle the non-secure timer PPIs, + * ARCH_TIMER_PHYS_SECURE_PPI is treated as invalid type. + * + * Return: the mapped PPI value, 0 if error. + */ +int __init acpi_gtdt_map_ppi(int type) +{ + struct acpi_table_gtdt *gtdt = acpi_gtdt_desc.gtdt; + + switch (type) { + case ARCH_TIMER_PHYS_NONSECURE_PPI: + return map_gt_gsi(gtdt->non_secure_el1_interrupt, + gtdt->non_secure_el1_flags); + case ARCH_TIMER_VIRT_PPI: + return map_gt_gsi(gtdt->virtual_timer_interrupt, + gtdt->virtual_timer_flags); + + case ARCH_TIMER_HYP_PPI: + return map_gt_gsi(gtdt->non_secure_el2_interrupt, + gtdt->non_secure_el2_flags); + default: + pr_err("Failed to map timer interrupt: invalid type.\n"); + } + + return 0; +} + +/** + * acpi_gtdt_c3stop() - Got c3stop info from GTDT according to the type of PPI. + * @type: the type of PPI. + * + * Return: true if the timer HW state is lost when a CPU enters an idle state, + * false otherwise + */ +bool __init acpi_gtdt_c3stop(int type) +{ + struct acpi_table_gtdt *gtdt = acpi_gtdt_desc.gtdt; + + switch (type) { + case ARCH_TIMER_PHYS_NONSECURE_PPI: + return !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON); + + case ARCH_TIMER_VIRT_PPI: + return !(gtdt->virtual_timer_flags & ACPI_GTDT_ALWAYS_ON); + + case ARCH_TIMER_HYP_PPI: + return !(gtdt->non_secure_el2_flags & ACPI_GTDT_ALWAYS_ON); + + default: + pr_err("Failed to get c3stop info: invalid type.\n"); + } + + return false; +} + +/** + * acpi_gtdt_init() - Get the info of GTDT table to prepare for further init. + * @table: The pointer to GTDT table. + * @platform_timer_count: It points to a integer variable which is used + * for storing the number of platform timers. + * This pointer could be NULL, if the caller + * doesn't need this info. + * + * Return: 0 if success, -EINVAL if error. + */ +int __init acpi_gtdt_init(struct acpi_table_header *table, + int *platform_timer_count) +{ + void *platform_timer; + struct acpi_table_gtdt *gtdt; + + gtdt = container_of(table, struct acpi_table_gtdt, header); + acpi_gtdt_desc.gtdt = gtdt; + acpi_gtdt_desc.gtdt_end = (void *)table + table->length; + acpi_gtdt_desc.platform_timer = NULL; + if (platform_timer_count) + *platform_timer_count = 0; + + if (table->revision < 2) { + pr_warn("Revision:%d doesn't support Platform Timers.\n", + table->revision); + return 0; + } + + if (!gtdt->platform_timer_count) { + pr_debug("No Platform Timer.\n"); + return 0; + } + + platform_timer = (void *)gtdt + gtdt->platform_timer_offset; + if (platform_timer < (void *)table + sizeof(struct acpi_table_gtdt)) { + pr_err(FW_BUG "invalid timer data.\n"); + return -EINVAL; + } + acpi_gtdt_desc.platform_timer = platform_timer; + if (platform_timer_count) + *platform_timer_count = gtdt->platform_timer_count; + + return 0; +} diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 9b05886f9773..4b5c146fba97 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -595,6 +595,12 @@ enum acpi_reconfig_event { int acpi_reconfig_notifier_register(struct notifier_block *nb); int acpi_reconfig_notifier_unregister(struct notifier_block *nb); +#ifdef CONFIG_ACPI_GTDT +int acpi_gtdt_init(struct acpi_table_header *table, int *platform_timer_count); +int acpi_gtdt_map_ppi(int type); +bool acpi_gtdt_c3stop(int type); +#endif + #else /* !CONFIG_ACPI */ #define acpi_disabled 1 -- cgit v1.2.3 From 4287adec7212d48fb878a45400fd7e11a198462c Mon Sep 17 00:00:00 2001 From: Matt Redfearn Date: Wed, 19 Apr 2017 13:26:45 +0100 Subject: MIPS/Malta: Probe gic-timer via devicetree The Malta platform is the only platform remaining to probe the GIC clocksource via gic_clocksource_init. This route hardcodes an expected virq number based on MIPS_GIC_IRQ_BASE, which can be fragile to the eventual virq layout. Instread, probe the driver using the preferred and more modern devicetree method. Before the driver is probed, set the "clock-frequency" property of the devicetree node to the value detected by Malta platform code. Signed-off-by: Matt Redfearn Cc: linux-mips@linux-mips.org Cc: James Hogan Cc: Daniel Lezcano Cc: Ralf Baechle Link: http://lkml.kernel.org/r/1492604806-23420-1-git-send-email-matt.redfearn@imgtec.com Signed-off-by: Thomas Gleixner --- arch/mips/mti-malta/malta-time.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index 1829a9031eec..289edcfadd7c 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -207,6 +208,33 @@ static void __init init_rtc(void) CMOS_WRITE(ctrl & ~RTC_SET, RTC_CONTROL); } +#ifdef CONFIG_CLKSRC_MIPS_GIC +static u32 gic_frequency_dt; + +static struct property gic_frequency_prop = { + .name = "clock-frequency", + .length = sizeof(u32), + .value = &gic_frequency_dt, +}; + +static void update_gic_frequency_dt(void) +{ + struct device_node *node; + + gic_frequency_dt = cpu_to_be32(gic_frequency); + + node = of_find_compatible_node(NULL, NULL, "mti,gic-timer"); + if (!node) { + pr_err("mti,gic-timer device node not found\n"); + return; + } + + if (of_update_property(node, &gic_frequency_prop) < 0) + pr_err("error updating gic frequency property\n"); +} + +#endif + void __init plat_time_init(void) { unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK); @@ -236,7 +264,8 @@ void __init plat_time_init(void) printk("GIC frequency %d.%02d MHz\n", freq/1000000, (freq%1000000)*100/1000000); #ifdef CONFIG_CLKSRC_MIPS_GIC - gic_clocksource_init(gic_frequency); + update_gic_frequency_dt(); + clocksource_probe(); #endif } #endif -- cgit v1.2.3