Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'timers-core-2024-07-14' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timer updates from Thomas Gleixner:
"Updates for timers, timekeeping and related functionality:

Core:

- Make the takeover of a hrtimer based broadcast timer reliable
during CPU hot-unplug. The current implementation suffers from a
race which can lead to broadcast timer starvation in the worst
case.

- VDSO related cleanups and simplifications

- Small cleanups and enhancements all over the place

PTP:

- Replace the architecture specific base clock to clocksource, e.g.
ART to TSC, conversion function with generic functionality to avoid
exposing such internals to drivers and convert all existing drivers
over. This also allows to provide functionality which converts the
other way round in the core code based on the same parameter set.

- Provide a function to convert CLOCK_REALTIME to the base clock to
support the upcoming PPS output driver on Intel platforms.

Drivers:

- A set of Device Tree bindings for new hardware

- Cleanups and enhancements all over the place"

* tag 'timers-core-2024-07-14' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (30 commits)
clocksource/drivers/realtek: Add timer driver for rtl-otto platforms
dt-bindings: timer: Add schema for realtek,otto-timer
dt-bindings: timer: Add SOPHGO SG2002 clint
dt-bindings: timer: renesas,tmu: Add R-Car Gen2 support
dt-bindings: timer: renesas,tmu: Add RZ/G1 support
dt-bindings: timer: renesas,tmu: Add R-Mobile APE6 support
clocksource/drivers/mips-gic-timer: Correct sched_clock width
clocksource/drivers/mips-gic-timer: Refine rating computation
clocksource/drivers/sh_cmt: Address race condition for clock events
clocksource/driver/arm_global_timer: Remove unnecessary ‘0’ values from err
clocksource/drivers/arm_arch_timer: Remove unnecessary ‘0’ values from irq
tick/broadcast: Make takeover of broadcast hrtimer reliable
tick/sched: Combine WARN_ON_ONCE and print_once
x86/vdso: Remove unused include
x86/vgtod: Remove unused typedef gtod_long_t
x86/vdso: Fix function reference in comment
vdso: Add comment about reason for vdso struct ordering
vdso/gettimeofday: Clarify comment about open coded function
timekeeping: Add missing kernel-doc function comments
tick: Remove unnused tick_nohz_get_idle_calls()
...

+647 -131
+63
Documentation/devicetree/bindings/timer/realtek,otto-timer.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/timer/realtek,otto-timer.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Realtek Otto SoCs Timer/Counter 8 + 9 + description: 10 + Realtek SoCs support a number of timers/counters. These are used 11 + as a per CPU clock event generator and an overall CPU clocksource. 12 + 13 + maintainers: 14 + - Chris Packham <chris.packham@alliedtelesis.co.nz> 15 + 16 + properties: 17 + $nodename: 18 + pattern: "^timer@[0-9a-f]+$" 19 + 20 + compatible: 21 + items: 22 + - enum: 23 + - realtek,rtl9302-timer 24 + - const: realtek,otto-timer 25 + 26 + reg: 27 + items: 28 + - description: timer0 registers 29 + - description: timer1 registers 30 + - description: timer2 registers 31 + - description: timer3 registers 32 + - description: timer4 registers 33 + 34 + clocks: 35 + maxItems: 1 36 + 37 + interrupts: 38 + items: 39 + - description: timer0 interrupt 40 + - description: timer1 interrupt 41 + - description: timer2 interrupt 42 + - description: timer3 interrupt 43 + - description: timer4 interrupt 44 + 45 + required: 46 + - compatible 47 + - reg 48 + - clocks 49 + - interrupts 50 + 51 + additionalProperties: false 52 + 53 + examples: 54 + - | 55 + timer@3200 { 56 + compatible = "realtek,rtl9302-timer", "realtek,otto-timer"; 57 + reg = <0x3200 0x10>, <0x3210 0x10>, <0x3220 0x10>, 58 + <0x3230 0x10>, <0x3240 0x10>; 59 + 60 + interrupt-parent = <&intc>; 61 + interrupts = <7>, <8>, <9>, <10>, <11>; 62 + clocks = <&lx_clk>; 63 + };
+12
Documentation/devicetree/bindings/timer/renesas,tmu.yaml
··· 21 21 compatible: 22 22 items: 23 23 - enum: 24 + - renesas,tmu-r8a73a4 # R-Mobile APE6 24 25 - renesas,tmu-r8a7740 # R-Mobile A1 26 + - renesas,tmu-r8a7742 # RZ/G1H 27 + - renesas,tmu-r8a7743 # RZ/G1M 28 + - renesas,tmu-r8a7744 # RZ/G1N 29 + - renesas,tmu-r8a7745 # RZ/G1E 30 + - renesas,tmu-r8a77470 # RZ/G1C 25 31 - renesas,tmu-r8a774a1 # RZ/G2M 26 32 - renesas,tmu-r8a774b1 # RZ/G2N 27 33 - renesas,tmu-r8a774c0 # RZ/G2E 28 34 - renesas,tmu-r8a774e1 # RZ/G2H 29 35 - renesas,tmu-r8a7778 # R-Car M1A 30 36 - renesas,tmu-r8a7779 # R-Car H1 37 + - renesas,tmu-r8a7790 # R-Car H2 38 + - renesas,tmu-r8a7791 # R-Car M2-W 39 + - renesas,tmu-r8a7792 # R-Car V2H 40 + - renesas,tmu-r8a7793 # R-Car M2-N 41 + - renesas,tmu-r8a7794 # R-Car E2 31 42 - renesas,tmu-r8a7795 # R-Car H3 32 43 - renesas,tmu-r8a7796 # R-Car M3-W 33 44 - renesas,tmu-r8a77961 # R-Car M3-W+ ··· 105 94 compatible: 106 95 contains: 107 96 enum: 97 + - renesas,tmu-r8a73a4 108 98 - renesas,tmu-r8a7740 109 99 - renesas,tmu-r8a7778 110 100 - renesas,tmu-r8a7779
+1
Documentation/devicetree/bindings/timer/sifive,clint.yaml
··· 40 40 - allwinner,sun20i-d1-clint 41 41 - sophgo,cv1800b-clint 42 42 - sophgo,cv1812h-clint 43 + - sophgo,sg2002-clint 43 44 - thead,th1520-clint 44 45 - const: thead,c900-clint 45 46 - items:
-3
arch/x86/include/asm/tsc.h
··· 28 28 } 29 29 #define get_cycles get_cycles 30 30 31 - extern struct system_counterval_t convert_art_to_tsc(u64 art); 32 - extern struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns); 33 - 34 31 extern void tsc_early_init(void); 35 32 extern void tsc_init(void); 36 33 extern void mark_tsc_unstable(char *reason);
+2 -3
arch/x86/include/asm/vdso/gettimeofday.h
··· 328 328 * due to unsigned comparison. 329 329 * 330 330 * Due to the MSB/Sign-bit being used as invalid marker (see 331 - * arch_vdso_cycles_valid() above), the effective mask is S64_MAX, 332 - * but that case is also unlikely and will also take the unlikely path 333 - * here. 331 + * arch_vdso_cycles_ok() above), the effective mask is S64_MAX, but that 332 + * case is also unlikely and will also take the unlikely path here. 334 333 */ 335 334 if (unlikely(delta > vd->max_cycles)) { 336 335 /*
-1
arch/x86/include/asm/vdso/vsyscall.h
··· 4 4 5 5 #ifndef __ASSEMBLY__ 6 6 7 - #include <linux/hrtimer.h> 8 7 #include <linux/timekeeper_internal.h> 9 8 #include <vdso/datapage.h> 10 9 #include <asm/vgtod.h>
-5
arch/x86/include/asm/vgtod.h
··· 14 14 15 15 #include <uapi/linux/time.h> 16 16 17 - #ifdef BUILD_VDSO32_64 18 - typedef u64 gtod_long_t; 19 - #else 20 - typedef unsigned long gtod_long_t; 21 - #endif 22 17 #endif /* CONFIG_GENERIC_GETTIMEOFDAY */ 23 18 24 19 #endif /* _ASM_X86_VGTOD_H */
+19 -73
arch/x86/kernel/tsc.c
··· 50 50 51 51 static int __read_mostly tsc_force_recalibrate; 52 52 53 - static u32 art_to_tsc_numerator; 54 - static u32 art_to_tsc_denominator; 55 - static u64 art_to_tsc_offset; 53 + static struct clocksource_base art_base_clk = { 54 + .id = CSID_X86_ART, 55 + }; 56 56 static bool have_art; 57 57 58 58 struct cyc2ns { ··· 1074 1074 */ 1075 1075 static void __init detect_art(void) 1076 1076 { 1077 - unsigned int unused[2]; 1077 + unsigned int unused; 1078 1078 1079 1079 if (boot_cpu_data.cpuid_level < ART_CPUID_LEAF) 1080 1080 return; ··· 1089 1089 tsc_async_resets) 1090 1090 return; 1091 1091 1092 - cpuid(ART_CPUID_LEAF, &art_to_tsc_denominator, 1093 - &art_to_tsc_numerator, unused, unused+1); 1092 + cpuid(ART_CPUID_LEAF, &art_base_clk.denominator, 1093 + &art_base_clk.numerator, &art_base_clk.freq_khz, &unused); 1094 1094 1095 - if (art_to_tsc_denominator < ART_MIN_DENOMINATOR) 1095 + art_base_clk.freq_khz /= KHZ; 1096 + if (art_base_clk.denominator < ART_MIN_DENOMINATOR) 1096 1097 return; 1097 1098 1098 - rdmsrl(MSR_IA32_TSC_ADJUST, art_to_tsc_offset); 1099 + rdmsrl(MSR_IA32_TSC_ADJUST, art_base_clk.offset); 1099 1100 1100 1101 /* Make this sticky over multiple CPU init calls */ 1101 1102 setup_force_cpu_cap(X86_FEATURE_ART); ··· 1297 1296 return 0; 1298 1297 } 1299 1298 1300 - /* 1301 - * Convert ART to TSC given numerator/denominator found in detect_art() 1302 - */ 1303 - struct system_counterval_t convert_art_to_tsc(u64 art) 1304 - { 1305 - u64 tmp, res, rem; 1306 - 1307 - rem = do_div(art, art_to_tsc_denominator); 1308 - 1309 - res = art * art_to_tsc_numerator; 1310 - tmp = rem * art_to_tsc_numerator; 1311 - 1312 - do_div(tmp, art_to_tsc_denominator); 1313 - res += tmp + art_to_tsc_offset; 1314 - 1315 - return (struct system_counterval_t) { 1316 - .cs_id = have_art ? CSID_X86_TSC : CSID_GENERIC, 1317 - .cycles = res, 1318 - }; 1319 - } 1320 - EXPORT_SYMBOL(convert_art_to_tsc); 1321 - 1322 - /** 1323 - * convert_art_ns_to_tsc() - Convert ART in nanoseconds to TSC. 1324 - * @art_ns: ART (Always Running Timer) in unit of nanoseconds 1325 - * 1326 - * PTM requires all timestamps to be in units of nanoseconds. When user 1327 - * software requests a cross-timestamp, this function converts system timestamp 1328 - * to TSC. 1329 - * 1330 - * This is valid when CPU feature flag X86_FEATURE_TSC_KNOWN_FREQ is set 1331 - * indicating the tsc_khz is derived from CPUID[15H]. Drivers should check 1332 - * that this flag is set before conversion to TSC is attempted. 1333 - * 1334 - * Return: 1335 - * struct system_counterval_t - system counter value with the ID of the 1336 - * corresponding clocksource: 1337 - * cycles: System counter value 1338 - * cs_id: The clocksource ID for validating comparability 1339 - */ 1340 - 1341 - struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns) 1342 - { 1343 - u64 tmp, res, rem; 1344 - 1345 - rem = do_div(art_ns, USEC_PER_SEC); 1346 - 1347 - res = art_ns * tsc_khz; 1348 - tmp = rem * tsc_khz; 1349 - 1350 - do_div(tmp, USEC_PER_SEC); 1351 - res += tmp; 1352 - 1353 - return (struct system_counterval_t) { 1354 - .cs_id = have_art ? CSID_X86_TSC : CSID_GENERIC, 1355 - .cycles = res, 1356 - }; 1357 - } 1358 - EXPORT_SYMBOL(convert_art_ns_to_tsc); 1359 - 1360 - 1361 1299 static void tsc_refine_calibration_work(struct work_struct *work); 1362 1300 static DECLARE_DELAYED_WORK(tsc_irqwork, tsc_refine_calibration_work); 1363 1301 /** ··· 1398 1458 if (tsc_unstable) 1399 1459 goto unreg; 1400 1460 1401 - if (boot_cpu_has(X86_FEATURE_ART)) 1461 + if (boot_cpu_has(X86_FEATURE_ART)) { 1402 1462 have_art = true; 1463 + clocksource_tsc.base = &art_base_clk; 1464 + } 1403 1465 clocksource_register_khz(&clocksource_tsc, tsc_khz); 1404 1466 unreg: 1405 1467 clocksource_unregister(&clocksource_tsc_early); ··· 1426 1484 * the refined calibration and directly register it as a clocksource. 1427 1485 */ 1428 1486 if (boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ)) { 1429 - if (boot_cpu_has(X86_FEATURE_ART)) 1487 + if (boot_cpu_has(X86_FEATURE_ART)) { 1430 1488 have_art = true; 1489 + clocksource_tsc.base = &art_base_clk; 1490 + } 1431 1491 clocksource_register_khz(&clocksource_tsc, tsc_khz); 1432 1492 clocksource_unregister(&clocksource_tsc_early); 1433 1493 ··· 1453 1509 1454 1510 if (early) { 1455 1511 cpu_khz = x86_platform.calibrate_cpu(); 1456 - if (tsc_early_khz) 1512 + if (tsc_early_khz) { 1457 1513 tsc_khz = tsc_early_khz; 1458 - else 1514 + } else { 1459 1515 tsc_khz = x86_platform.calibrate_tsc(); 1516 + clocksource_tsc.freq_khz = tsc_khz; 1517 + } 1460 1518 } else { 1461 1519 /* We should not be here with non-native cpu calibration */ 1462 1520 WARN_ON(x86_platform.calibrate_cpu != native_calibrate_cpu);
+10
drivers/clocksource/Kconfig
··· 134 134 help 135 135 Enables the support for the RDA Micro timer driver. 136 136 137 + config REALTEK_OTTO_TIMER 138 + bool "Clocksource/timer for the Realtek Otto platform" if COMPILE_TEST 139 + select TIMER_OF 140 + help 141 + This driver adds support for the timers found in the Realtek RTL83xx 142 + and RTL93xx SoCs series. This includes chips such as RTL8380, RTL8381 143 + and RTL832, as well as chips from the RTL839x series, such as RTL8390 144 + RT8391, RTL8392, RTL8393 and RTL8396 and chips of the RTL930x series 145 + such as RTL9301, RTL9302 or RTL9303. 146 + 137 147 config SUN4I_TIMER 138 148 bool "Sun4i timer driver" if COMPILE_TEST 139 149 depends on HAS_IOMEM
+1
drivers/clocksource/Makefile
··· 59 59 obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o 60 60 obj-$(CONFIG_NPCM7XX_TIMER) += timer-npcm7xx.o 61 61 obj-$(CONFIG_RDA_TIMER) += timer-rda.o 62 + obj-$(CONFIG_REALTEK_OTTO_TIMER) += timer-rtl-otto.o 62 63 63 64 obj-$(CONFIG_ARC_TIMERS) += arc_timer.o 64 65 obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
+1 -1
drivers/clocksource/arm_arch_timer.c
··· 1556 1556 arch_timer_mem_frame_register(struct arch_timer_mem_frame *frame) 1557 1557 { 1558 1558 void __iomem *base; 1559 - int ret, irq = 0; 1559 + int ret, irq; 1560 1560 1561 1561 if (arch_timer_mem_use_virtual) 1562 1562 irq = frame->virt_irq;
+1 -1
drivers/clocksource/arm_global_timer.c
··· 343 343 { 344 344 struct clk *gt_clk; 345 345 static unsigned long gt_clk_rate; 346 - int err = 0; 346 + int err; 347 347 348 348 /* 349 349 * In A9 r2p0 the comparators for each processor with the global timer
+12 -8
drivers/clocksource/mips-gic-timer.c
··· 19 19 static DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device); 20 20 static int gic_timer_irq; 21 21 static unsigned int gic_frequency; 22 + static unsigned int gic_count_width; 22 23 static bool __read_mostly gic_clock_unstable; 23 24 24 25 static void gic_clocksource_unstable(char *reason); ··· 187 186 188 187 static int __init __gic_clocksource_init(void) 189 188 { 190 - unsigned int count_width; 191 189 int ret; 192 190 193 191 /* Set clocksource mask. */ 194 - count_width = read_gic_config() & GIC_CONFIG_COUNTBITS; 195 - count_width >>= __ffs(GIC_CONFIG_COUNTBITS); 196 - count_width *= 4; 197 - count_width += 32; 198 - gic_clocksource.mask = CLOCKSOURCE_MASK(count_width); 192 + gic_count_width = read_gic_config() & GIC_CONFIG_COUNTBITS; 193 + gic_count_width >>= __ffs(GIC_CONFIG_COUNTBITS); 194 + gic_count_width *= 4; 195 + gic_count_width += 32; 196 + gic_clocksource.mask = CLOCKSOURCE_MASK(gic_count_width); 199 197 200 198 /* Calculate a somewhat reasonable rating value. */ 201 - gic_clocksource.rating = 200 + gic_frequency / 10000000; 199 + if (mips_cm_revision() >= CM_REV_CM3 || !IS_ENABLED(CONFIG_CPU_FREQ)) 200 + gic_clocksource.rating = 300; /* Good when frequecy is stable */ 201 + else 202 + gic_clocksource.rating = 200; 203 + gic_clocksource.rating += clamp(gic_frequency / 10000000, 0, 99); 202 204 203 205 ret = clocksource_register_hz(&gic_clocksource, gic_frequency); 204 206 if (ret < 0) ··· 264 260 if (mips_cm_revision() >= CM_REV_CM3 || !IS_ENABLED(CONFIG_CPU_FREQ)) { 265 261 sched_clock_register(mips_cm_is64 ? 266 262 gic_read_count_64 : gic_read_count_2x32, 267 - 64, gic_frequency); 263 + gic_count_width, gic_frequency); 268 264 } 269 265 270 266 return 0;
+12 -1
drivers/clocksource/sh_cmt.c
··· 528 528 static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) 529 529 { 530 530 struct sh_cmt_channel *ch = dev_id; 531 + unsigned long flags; 531 532 532 533 /* clear flags */ 533 534 sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) & ··· 559 558 560 559 ch->flags &= ~FLAG_SKIPEVENT; 561 560 561 + raw_spin_lock_irqsave(&ch->lock, flags); 562 + 562 563 if (ch->flags & FLAG_REPROGRAM) { 563 564 ch->flags &= ~FLAG_REPROGRAM; 564 565 sh_cmt_clock_event_program_verify(ch, 1); ··· 572 569 } 573 570 574 571 ch->flags &= ~FLAG_IRQCONTEXT; 572 + 573 + raw_spin_unlock_irqrestore(&ch->lock, flags); 575 574 576 575 return IRQ_HANDLED; 577 576 } ··· 785 780 struct clock_event_device *ced) 786 781 { 787 782 struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); 783 + unsigned long flags; 788 784 789 785 BUG_ON(!clockevent_state_oneshot(ced)); 786 + 787 + raw_spin_lock_irqsave(&ch->lock, flags); 788 + 790 789 if (likely(ch->flags & FLAG_IRQCONTEXT)) 791 790 ch->next_match_value = delta - 1; 792 791 else 793 - sh_cmt_set_next(ch, delta - 1); 792 + __sh_cmt_set_next(ch, delta - 1); 793 + 794 + raw_spin_unlock_irqrestore(&ch->lock, flags); 794 795 795 796 return 0; 796 797 }
+291
drivers/clocksource/timer-rtl-otto.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 4 + 5 + #include <linux/clk.h> 6 + #include <linux/clockchips.h> 7 + #include <linux/cpu.h> 8 + #include <linux/cpuhotplug.h> 9 + #include <linux/cpumask.h> 10 + #include <linux/interrupt.h> 11 + #include <linux/io.h> 12 + #include <linux/jiffies.h> 13 + #include <linux/printk.h> 14 + #include <linux/sched_clock.h> 15 + #include "timer-of.h" 16 + 17 + #define RTTM_DATA 0x0 18 + #define RTTM_CNT 0x4 19 + #define RTTM_CTRL 0x8 20 + #define RTTM_INT 0xc 21 + 22 + #define RTTM_CTRL_ENABLE BIT(28) 23 + #define RTTM_INT_PENDING BIT(16) 24 + #define RTTM_INT_ENABLE BIT(20) 25 + 26 + /* 27 + * The Otto platform provides multiple 28 bit timers/counters with the following 28 + * operating logic. If enabled the timer counts up. Per timer one can set a 29 + * maximum counter value as an end marker. If end marker is reached the timer 30 + * fires an interrupt. If the timer "overflows" by reaching the end marker or 31 + * by adding 1 to 0x0fffffff the counter is reset to 0. When this happens and 32 + * the timer is in operating mode COUNTER it stops. In mode TIMER it will 33 + * continue to count up. 34 + */ 35 + #define RTTM_CTRL_COUNTER 0 36 + #define RTTM_CTRL_TIMER BIT(24) 37 + 38 + #define RTTM_BIT_COUNT 28 39 + #define RTTM_MIN_DELTA 8 40 + #define RTTM_MAX_DELTA CLOCKSOURCE_MASK(28) 41 + 42 + /* 43 + * Timers are derived from the LXB clock frequency. Usually this is a fixed 44 + * multiple of the 25 MHz oscillator. The 930X SOC is an exception from that. 45 + * Its LXB clock has only dividers and uses the switch PLL of 2.45 GHz as its 46 + * base. The only meaningful frequencies we can achieve from that are 175.000 47 + * MHz and 153.125 MHz. The greatest common divisor of all explained possible 48 + * speeds is 3125000. Pin the timers to this 3.125 MHz reference frequency. 49 + */ 50 + #define RTTM_TICKS_PER_SEC 3125000 51 + 52 + struct rttm_cs { 53 + struct timer_of to; 54 + struct clocksource cs; 55 + }; 56 + 57 + /* Simple internal register functions */ 58 + static inline void rttm_set_counter(void __iomem *base, unsigned int counter) 59 + { 60 + iowrite32(counter, base + RTTM_CNT); 61 + } 62 + 63 + static inline unsigned int rttm_get_counter(void __iomem *base) 64 + { 65 + return ioread32(base + RTTM_CNT); 66 + } 67 + 68 + static inline void rttm_set_period(void __iomem *base, unsigned int period) 69 + { 70 + iowrite32(period, base + RTTM_DATA); 71 + } 72 + 73 + static inline void rttm_disable_timer(void __iomem *base) 74 + { 75 + iowrite32(0, base + RTTM_CTRL); 76 + } 77 + 78 + static inline void rttm_enable_timer(void __iomem *base, u32 mode, u32 divisor) 79 + { 80 + iowrite32(RTTM_CTRL_ENABLE | mode | divisor, base + RTTM_CTRL); 81 + } 82 + 83 + static inline void rttm_ack_irq(void __iomem *base) 84 + { 85 + iowrite32(ioread32(base + RTTM_INT) | RTTM_INT_PENDING, base + RTTM_INT); 86 + } 87 + 88 + static inline void rttm_enable_irq(void __iomem *base) 89 + { 90 + iowrite32(RTTM_INT_ENABLE, base + RTTM_INT); 91 + } 92 + 93 + static inline void rttm_disable_irq(void __iomem *base) 94 + { 95 + iowrite32(0, base + RTTM_INT); 96 + } 97 + 98 + /* Aggregated control functions for kernel clock framework */ 99 + #define RTTM_DEBUG(base) \ 100 + pr_debug("------------- %d %p\n", \ 101 + smp_processor_id(), base) 102 + 103 + static irqreturn_t rttm_timer_interrupt(int irq, void *dev_id) 104 + { 105 + struct clock_event_device *clkevt = dev_id; 106 + struct timer_of *to = to_timer_of(clkevt); 107 + 108 + rttm_ack_irq(to->of_base.base); 109 + RTTM_DEBUG(to->of_base.base); 110 + clkevt->event_handler(clkevt); 111 + 112 + return IRQ_HANDLED; 113 + } 114 + 115 + static void rttm_stop_timer(void __iomem *base) 116 + { 117 + rttm_disable_timer(base); 118 + rttm_ack_irq(base); 119 + } 120 + 121 + static void rttm_start_timer(struct timer_of *to, u32 mode) 122 + { 123 + rttm_set_counter(to->of_base.base, 0); 124 + rttm_enable_timer(to->of_base.base, mode, to->of_clk.rate / RTTM_TICKS_PER_SEC); 125 + } 126 + 127 + static int rttm_next_event(unsigned long delta, struct clock_event_device *clkevt) 128 + { 129 + struct timer_of *to = to_timer_of(clkevt); 130 + 131 + RTTM_DEBUG(to->of_base.base); 132 + rttm_stop_timer(to->of_base.base); 133 + rttm_set_period(to->of_base.base, delta); 134 + rttm_start_timer(to, RTTM_CTRL_COUNTER); 135 + 136 + return 0; 137 + } 138 + 139 + static int rttm_state_oneshot(struct clock_event_device *clkevt) 140 + { 141 + struct timer_of *to = to_timer_of(clkevt); 142 + 143 + RTTM_DEBUG(to->of_base.base); 144 + rttm_stop_timer(to->of_base.base); 145 + rttm_set_period(to->of_base.base, RTTM_TICKS_PER_SEC / HZ); 146 + rttm_start_timer(to, RTTM_CTRL_COUNTER); 147 + 148 + return 0; 149 + } 150 + 151 + static int rttm_state_periodic(struct clock_event_device *clkevt) 152 + { 153 + struct timer_of *to = to_timer_of(clkevt); 154 + 155 + RTTM_DEBUG(to->of_base.base); 156 + rttm_stop_timer(to->of_base.base); 157 + rttm_set_period(to->of_base.base, RTTM_TICKS_PER_SEC / HZ); 158 + rttm_start_timer(to, RTTM_CTRL_TIMER); 159 + 160 + return 0; 161 + } 162 + 163 + static int rttm_state_shutdown(struct clock_event_device *clkevt) 164 + { 165 + struct timer_of *to = to_timer_of(clkevt); 166 + 167 + RTTM_DEBUG(to->of_base.base); 168 + rttm_stop_timer(to->of_base.base); 169 + 170 + return 0; 171 + } 172 + 173 + static void rttm_setup_timer(void __iomem *base) 174 + { 175 + RTTM_DEBUG(base); 176 + rttm_stop_timer(base); 177 + rttm_set_period(base, 0); 178 + } 179 + 180 + static u64 rttm_read_clocksource(struct clocksource *cs) 181 + { 182 + struct rttm_cs *rcs = container_of(cs, struct rttm_cs, cs); 183 + 184 + return rttm_get_counter(rcs->to.of_base.base); 185 + } 186 + 187 + /* Module initialization part. */ 188 + static DEFINE_PER_CPU(struct timer_of, rttm_to) = { 189 + .flags = TIMER_OF_BASE | TIMER_OF_CLOCK | TIMER_OF_IRQ, 190 + .of_irq = { 191 + .flags = IRQF_PERCPU | IRQF_TIMER, 192 + .handler = rttm_timer_interrupt, 193 + }, 194 + .clkevt = { 195 + .rating = 400, 196 + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 197 + .set_state_periodic = rttm_state_periodic, 198 + .set_state_shutdown = rttm_state_shutdown, 199 + .set_state_oneshot = rttm_state_oneshot, 200 + .set_next_event = rttm_next_event 201 + }, 202 + }; 203 + 204 + static int rttm_enable_clocksource(struct clocksource *cs) 205 + { 206 + struct rttm_cs *rcs = container_of(cs, struct rttm_cs, cs); 207 + 208 + rttm_disable_irq(rcs->to.of_base.base); 209 + rttm_setup_timer(rcs->to.of_base.base); 210 + rttm_enable_timer(rcs->to.of_base.base, RTTM_CTRL_TIMER, 211 + rcs->to.of_clk.rate / RTTM_TICKS_PER_SEC); 212 + 213 + return 0; 214 + } 215 + 216 + struct rttm_cs rttm_cs = { 217 + .to = { 218 + .flags = TIMER_OF_BASE | TIMER_OF_CLOCK, 219 + }, 220 + .cs = { 221 + .name = "realtek_otto_timer", 222 + .rating = 400, 223 + .mask = CLOCKSOURCE_MASK(RTTM_BIT_COUNT), 224 + .flags = CLOCK_SOURCE_IS_CONTINUOUS, 225 + .read = rttm_read_clocksource, 226 + } 227 + }; 228 + 229 + static u64 notrace rttm_read_clock(void) 230 + { 231 + return rttm_get_counter(rttm_cs.to.of_base.base); 232 + } 233 + 234 + static int rttm_cpu_starting(unsigned int cpu) 235 + { 236 + struct timer_of *to = per_cpu_ptr(&rttm_to, cpu); 237 + 238 + RTTM_DEBUG(to->of_base.base); 239 + to->clkevt.cpumask = cpumask_of(cpu); 240 + irq_force_affinity(to->of_irq.irq, to->clkevt.cpumask); 241 + clockevents_config_and_register(&to->clkevt, RTTM_TICKS_PER_SEC, 242 + RTTM_MIN_DELTA, RTTM_MAX_DELTA); 243 + rttm_enable_irq(to->of_base.base); 244 + 245 + return 0; 246 + } 247 + 248 + static int __init rttm_probe(struct device_node *np) 249 + { 250 + unsigned int cpu, cpu_rollback; 251 + struct timer_of *to; 252 + unsigned int clkidx = num_possible_cpus(); 253 + 254 + /* Use the first n timers as per CPU clock event generators */ 255 + for_each_possible_cpu(cpu) { 256 + to = per_cpu_ptr(&rttm_to, cpu); 257 + to->of_irq.index = to->of_base.index = cpu; 258 + if (timer_of_init(np, to)) { 259 + pr_err("setup of timer %d failed\n", cpu); 260 + goto rollback; 261 + } 262 + rttm_setup_timer(to->of_base.base); 263 + } 264 + 265 + /* Activate the n'th + 1 timer as a stable CPU clocksource. */ 266 + to = &rttm_cs.to; 267 + to->of_base.index = clkidx; 268 + timer_of_init(np, to); 269 + if (rttm_cs.to.of_base.base && rttm_cs.to.of_clk.rate) { 270 + rttm_enable_clocksource(&rttm_cs.cs); 271 + clocksource_register_hz(&rttm_cs.cs, RTTM_TICKS_PER_SEC); 272 + sched_clock_register(rttm_read_clock, RTTM_BIT_COUNT, RTTM_TICKS_PER_SEC); 273 + } else 274 + pr_err(" setup of timer %d as clocksource failed", clkidx); 275 + 276 + return cpuhp_setup_state(CPUHP_AP_REALTEK_TIMER_STARTING, 277 + "timer/realtek:online", 278 + rttm_cpu_starting, NULL); 279 + rollback: 280 + pr_err("timer registration failed\n"); 281 + for_each_possible_cpu(cpu_rollback) { 282 + if (cpu_rollback == cpu) 283 + break; 284 + to = per_cpu_ptr(&rttm_to, cpu_rollback); 285 + timer_of_cleanup(to); 286 + } 287 + 288 + return -EINVAL; 289 + } 290 + 291 + TIMER_OF_DECLARE(otto_timer, "realtek,otto-timer", rttm_probe);
+2 -1
drivers/net/ethernet/intel/e1000e/ptp.c
··· 124 124 sys_cycles = er32(PLTSTMPH); 125 125 sys_cycles <<= 32; 126 126 sys_cycles |= er32(PLTSTMPL); 127 - *system = convert_art_to_tsc(sys_cycles); 127 + system->cycles = sys_cycles; 128 + system->cs_id = CSID_X86_ART; 128 129 129 130 return 0; 130 131 }
+2 -1
drivers/net/ethernet/intel/ice/ice_ptp.c
··· 2156 2156 hh_ts_lo = rd32(hw, GLHH_ART_TIME_L); 2157 2157 hh_ts_hi = rd32(hw, GLHH_ART_TIME_H); 2158 2158 hh_ts = ((u64)hh_ts_hi << 32) | hh_ts_lo; 2159 - *system = convert_art_ns_to_tsc(hh_ts); 2159 + system->cycles = hh_ts; 2160 + system->cs_id = CSID_X86_ART; 2160 2161 /* Read Device source clock time */ 2161 2162 hh_ts_lo = rd32(hw, GLTSYN_HHTIME_L(tmr_idx)); 2162 2163 hh_ts_hi = rd32(hw, GLTSYN_HHTIME_H(tmr_idx));
+5 -1
drivers/net/ethernet/intel/igc/igc_ptp.c
··· 938 938 static struct system_counterval_t igc_device_tstamp_to_system(u64 tstamp) 939 939 { 940 940 #if IS_ENABLED(CONFIG_X86_TSC) && !defined(CONFIG_UML) 941 - return convert_art_ns_to_tsc(tstamp); 941 + return (struct system_counterval_t) { 942 + .cs_id = CSID_X86_ART, 943 + .cycles = tstamp, 944 + .use_nsecs = true, 945 + }; 942 946 #else 943 947 return (struct system_counterval_t) { }; 944 948 #endif
+2 -1
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
··· 390 390 *device = ns_to_ktime(ptp_time); 391 391 read_unlock_irqrestore(&priv->ptp_lock, flags); 392 392 get_arttime(priv->mii, intel_priv->mdio_adhoc_addr, &art_time); 393 - *system = convert_art_to_tsc(art_time); 393 + system->cycles = art_time; 394 394 } 395 395 396 396 system->cycles *= intel_priv->crossts_adj; 397 + system->cs_id = CSID_X86_ART; 397 398 priv->plat->flags &= ~STMMAC_FLAG_INT_SNAPSHOT_EN; 398 399 399 400 return 0;
+27
include/linux/clocksource.h
··· 21 21 #include <asm/div64.h> 22 22 #include <asm/io.h> 23 23 24 + struct clocksource_base; 24 25 struct clocksource; 25 26 struct module; 26 27 ··· 51 50 * multiplication 52 51 * @name: Pointer to clocksource name 53 52 * @list: List head for registration (internal) 53 + * @freq_khz: Clocksource frequency in khz. 54 54 * @rating: Rating value for selection (higher is better) 55 55 * To avoid rating inflation the following 56 56 * list should give you a guide as to how ··· 72 70 * validate the clocksource from which the snapshot was 73 71 * taken. 74 72 * @flags: Flags describing special properties 73 + * @base: Hardware abstraction for clock on which a clocksource 74 + * is based 75 75 * @enable: Optional function to enable the clocksource 76 76 * @disable: Optional function to disable the clocksource 77 77 * @suspend: Optional suspend function for the clocksource ··· 111 107 u64 max_cycles; 112 108 const char *name; 113 109 struct list_head list; 110 + u32 freq_khz; 114 111 int rating; 115 112 enum clocksource_ids id; 116 113 enum vdso_clock_mode vdso_clock_mode; 117 114 unsigned long flags; 115 + struct clocksource_base *base; 118 116 119 117 int (*enable)(struct clocksource *cs); 120 118 void (*disable)(struct clocksource *cs); ··· 311 305 } 312 306 313 307 void clocksource_verify_percpu(struct clocksource *cs); 308 + 309 + /** 310 + * struct clocksource_base - hardware abstraction for clock on which a clocksource 311 + * is based 312 + * @id: Defaults to CSID_GENERIC. The id value is used for conversion 313 + * functions which require that the current clocksource is based 314 + * on a clocksource_base with a particular ID in certain snapshot 315 + * functions to allow callers to validate the clocksource from 316 + * which the snapshot was taken. 317 + * @freq_khz: Nominal frequency of the base clock in kHz 318 + * @offset: Offset between the base clock and the clocksource 319 + * @numerator: Numerator of the clock ratio between base clock and the clocksource 320 + * @denominator: Denominator of the clock ratio between base clock and the clocksource 321 + */ 322 + struct clocksource_base { 323 + enum clocksource_ids id; 324 + u32 freq_khz; 325 + u64 offset; 326 + u32 numerator; 327 + u32 denominator; 328 + }; 314 329 315 330 #endif /* _LINUX_CLOCKSOURCE_H */
+1
include/linux/clocksource_ids.h
··· 9 9 CSID_X86_TSC_EARLY, 10 10 CSID_X86_TSC, 11 11 CSID_X86_KVM_CLK, 12 + CSID_X86_ART, 12 13 CSID_MAX, 13 14 }; 14 15
+1
include/linux/cpuhotplug.h
··· 171 171 CPUHP_AP_ARMADA_TIMER_STARTING, 172 172 CPUHP_AP_MIPS_GIC_TIMER_STARTING, 173 173 CPUHP_AP_ARC_TIMER_STARTING, 174 + CPUHP_AP_REALTEK_TIMER_STARTING, 174 175 CPUHP_AP_RISCV_TIMER_STARTING, 175 176 CPUHP_AP_CLINT_TIMER_STARTING, 176 177 CPUHP_AP_CSKY_TIMER_STARTING,
-1
include/linux/tick.h
··· 139 139 extern bool tick_nohz_idle_got_tick(void); 140 140 extern ktime_t tick_nohz_get_next_hrtimer(void); 141 141 extern ktime_t tick_nohz_get_sleep_length(ktime_t *delta_next); 142 - extern unsigned long tick_nohz_get_idle_calls(void); 143 142 extern unsigned long tick_nohz_get_idle_calls_cpu(int cpu); 144 143 extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time); 145 144 extern u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time);
+6
include/linux/timekeeping.h
··· 310 310 * timekeeping code to verify comparability of two cycle values. 311 311 * The default ID, CSID_GENERIC, does not identify a specific 312 312 * clocksource. 313 + * @use_nsecs: @cycles is in nanoseconds. 313 314 */ 314 315 struct system_counterval_t { 315 316 u64 cycles; 316 317 enum clocksource_ids cs_id; 318 + bool use_nsecs; 317 319 }; 320 + 321 + extern bool ktime_real_to_base_clock(ktime_t treal, 322 + enum clocksource_ids base_id, u64 *cycles); 323 + extern bool timekeeping_clocksource_has_base(enum clocksource_ids id); 318 324 319 325 /* 320 326 * Get cross timestamp between system clock and device clock
+4
include/vdso/datapage.h
··· 77 77 * vdso_data will be accessed by 64 bit and compat code at the same time 78 78 * so we should be careful before modifying this structure. 79 79 * 80 + * The ordering of the struct members is optimized to have fast access to the 81 + * often required struct members which are related to CLOCK_REALTIME and 82 + * CLOCK_MONOTONIC. This information is stored in the first cache lines. 83 + * 80 84 * @basetime is used to store the base time for the system wide time getter 81 85 * VVAR page. 82 86 *
+1
kernel/time/clocksource-wdtest.c
··· 22 22 #include "tick-internal.h" 23 23 24 24 MODULE_LICENSE("GPL"); 25 + MODULE_DESCRIPTION("Clocksource watchdog unit test"); 25 26 MODULE_AUTHOR("Paul E. McKenney <paulmck@kernel.org>"); 26 27 27 28 static int holdoff = IS_BUILTIN(CONFIG_TEST_CLOCKSOURCE_WATCHDOG) ? 10 : 0;
+1
kernel/time/test_udelay.c
··· 155 155 156 156 module_exit(udelay_test_exit); 157 157 158 + MODULE_DESCRIPTION("udelay test module"); 158 159 MODULE_AUTHOR("David Riley <davidriley@chromium.org>"); 159 160 MODULE_LICENSE("GPL");
+23
kernel/time/tick-broadcast.c
··· 1141 1141 #ifdef CONFIG_HOTPLUG_CPU 1142 1142 void hotplug_cpu__broadcast_tick_pull(int deadcpu) 1143 1143 { 1144 + struct tick_device *td = this_cpu_ptr(&tick_cpu_device); 1144 1145 struct clock_event_device *bc; 1145 1146 unsigned long flags; 1146 1147 ··· 1149 1148 bc = tick_broadcast_device.evtdev; 1150 1149 1151 1150 if (bc && broadcast_needs_cpu(bc, deadcpu)) { 1151 + /* 1152 + * If the broadcast force bit of the current CPU is set, 1153 + * then the current CPU has not yet reprogrammed the local 1154 + * timer device to avoid a ping-pong race. See 1155 + * ___tick_broadcast_oneshot_control(). 1156 + * 1157 + * If the broadcast device is hrtimer based then 1158 + * programming the broadcast event below does not have any 1159 + * effect because the local clockevent device is not 1160 + * running and not programmed because the broadcast event 1161 + * is not earlier than the pending event of the local clock 1162 + * event device. As a consequence all CPUs waiting for a 1163 + * broadcast event are stuck forever. 1164 + * 1165 + * Detect this condition and reprogram the cpu local timer 1166 + * device to avoid the starvation. 1167 + */ 1168 + if (tick_check_broadcast_expired()) { 1169 + cpumask_clear_cpu(smp_processor_id(), tick_broadcast_force_mask); 1170 + tick_program_event(td->evtdev->next_event, 1); 1171 + } 1172 + 1152 1173 /* This moves the broadcast assignment to this CPU: */ 1153 1174 clockevents_program_event(bc, bc->next_event, 1); 1154 1175 }
+4 -18
kernel/time/tick-sched.c
··· 1026 1026 if (expires == KTIME_MAX || ts->next_tick == hrtimer_get_expires(&ts->sched_timer)) 1027 1027 return; 1028 1028 1029 - WARN_ON_ONCE(1); 1030 - printk_once("basemono: %llu ts->next_tick: %llu dev->next_event: %llu timer->active: %d timer->expires: %llu\n", 1031 - basemono, ts->next_tick, dev->next_event, 1032 - hrtimer_active(&ts->sched_timer), hrtimer_get_expires(&ts->sched_timer)); 1029 + WARN_ONCE(1, "basemono: %llu ts->next_tick: %llu dev->next_event: %llu " 1030 + "timer->active: %d timer->expires: %llu\n", basemono, ts->next_tick, 1031 + dev->next_event, hrtimer_active(&ts->sched_timer), 1032 + hrtimer_get_expires(&ts->sched_timer)); 1033 1033 } 1034 1034 1035 1035 /* ··· 1381 1381 unsigned long tick_nohz_get_idle_calls_cpu(int cpu) 1382 1382 { 1383 1383 struct tick_sched *ts = tick_get_tick_sched(cpu); 1384 - 1385 - return ts->idle_calls; 1386 - } 1387 - 1388 - /** 1389 - * tick_nohz_get_idle_calls - return the current idle calls counter value 1390 - * 1391 - * Called from the schedutil frequency scaling governor in scheduler context. 1392 - * 1393 - * Return: the current idle calls counter value for the current CPU 1394 - */ 1395 - unsigned long tick_nohz_get_idle_calls(void) 1396 - { 1397 - struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched); 1398 1384 1399 1385 return ts->idle_calls; 1400 1386 }
+1
kernel/time/time_test.c
··· 96 96 }; 97 97 98 98 kunit_test_suite(time_test_suite); 99 + MODULE_DESCRIPTION("time unit test suite"); 99 100 MODULE_LICENSE("GPL");
+130 -1
kernel/time/timekeeping.c
··· 1195 1195 return false; 1196 1196 } 1197 1197 1198 + static bool convert_clock(u64 *val, u32 numerator, u32 denominator) 1199 + { 1200 + u64 rem, res; 1201 + 1202 + if (!numerator || !denominator) 1203 + return false; 1204 + 1205 + res = div64_u64_rem(*val, denominator, &rem) * numerator; 1206 + *val = res + div_u64(rem * numerator, denominator); 1207 + return true; 1208 + } 1209 + 1210 + static bool convert_base_to_cs(struct system_counterval_t *scv) 1211 + { 1212 + struct clocksource *cs = tk_core.timekeeper.tkr_mono.clock; 1213 + struct clocksource_base *base; 1214 + u32 num, den; 1215 + 1216 + /* The timestamp was taken from the time keeper clock source */ 1217 + if (cs->id == scv->cs_id) 1218 + return true; 1219 + 1220 + /* 1221 + * Check whether cs_id matches the base clock. Prevent the compiler from 1222 + * re-evaluating @base as the clocksource might change concurrently. 1223 + */ 1224 + base = READ_ONCE(cs->base); 1225 + if (!base || base->id != scv->cs_id) 1226 + return false; 1227 + 1228 + num = scv->use_nsecs ? cs->freq_khz : base->numerator; 1229 + den = scv->use_nsecs ? USEC_PER_SEC : base->denominator; 1230 + 1231 + if (!convert_clock(&scv->cycles, num, den)) 1232 + return false; 1233 + 1234 + scv->cycles += base->offset; 1235 + return true; 1236 + } 1237 + 1238 + static bool convert_cs_to_base(u64 *cycles, enum clocksource_ids base_id) 1239 + { 1240 + struct clocksource *cs = tk_core.timekeeper.tkr_mono.clock; 1241 + struct clocksource_base *base; 1242 + 1243 + /* 1244 + * Check whether base_id matches the base clock. Prevent the compiler from 1245 + * re-evaluating @base as the clocksource might change concurrently. 1246 + */ 1247 + base = READ_ONCE(cs->base); 1248 + if (!base || base->id != base_id) 1249 + return false; 1250 + 1251 + *cycles -= base->offset; 1252 + if (!convert_clock(cycles, base->denominator, base->numerator)) 1253 + return false; 1254 + return true; 1255 + } 1256 + 1257 + static bool convert_ns_to_cs(u64 *delta) 1258 + { 1259 + struct tk_read_base *tkr = &tk_core.timekeeper.tkr_mono; 1260 + 1261 + if (BITS_TO_BYTES(fls64(*delta) + tkr->shift) >= sizeof(*delta)) 1262 + return false; 1263 + 1264 + *delta = div_u64((*delta << tkr->shift) - tkr->xtime_nsec, tkr->mult); 1265 + return true; 1266 + } 1267 + 1268 + /** 1269 + * ktime_real_to_base_clock() - Convert CLOCK_REALTIME timestamp to a base clock timestamp 1270 + * @treal: CLOCK_REALTIME timestamp to convert 1271 + * @base_id: base clocksource id 1272 + * @cycles: pointer to store the converted base clock timestamp 1273 + * 1274 + * Converts a supplied, future realtime clock value to the corresponding base clock value. 1275 + * 1276 + * Return: true if the conversion is successful, false otherwise. 1277 + */ 1278 + bool ktime_real_to_base_clock(ktime_t treal, enum clocksource_ids base_id, u64 *cycles) 1279 + { 1280 + struct timekeeper *tk = &tk_core.timekeeper; 1281 + unsigned int seq; 1282 + u64 delta; 1283 + 1284 + do { 1285 + seq = read_seqcount_begin(&tk_core.seq); 1286 + if ((u64)treal < tk->tkr_mono.base_real) 1287 + return false; 1288 + delta = (u64)treal - tk->tkr_mono.base_real; 1289 + if (!convert_ns_to_cs(&delta)) 1290 + return false; 1291 + *cycles = tk->tkr_mono.cycle_last + delta; 1292 + if (!convert_cs_to_base(cycles, base_id)) 1293 + return false; 1294 + } while (read_seqcount_retry(&tk_core.seq, seq)); 1295 + 1296 + return true; 1297 + } 1298 + EXPORT_SYMBOL_GPL(ktime_real_to_base_clock); 1299 + 1198 1300 /** 1199 1301 * get_device_system_crosststamp - Synchronously capture system/device timestamp 1200 1302 * @get_time_fn: Callback to get simultaneous device time and ··· 1343 1241 * installed timekeeper clocksource 1344 1242 */ 1345 1243 if (system_counterval.cs_id == CSID_GENERIC || 1346 - tk->tkr_mono.clock->id != system_counterval.cs_id) 1244 + !convert_base_to_cs(&system_counterval)) 1347 1245 return -ENODEV; 1348 1246 cycles = system_counterval.cycles; 1349 1247 ··· 1407 1305 return 0; 1408 1306 } 1409 1307 EXPORT_SYMBOL_GPL(get_device_system_crosststamp); 1308 + 1309 + /** 1310 + * timekeeping_clocksource_has_base - Check whether the current clocksource 1311 + * is based on given a base clock 1312 + * @id: base clocksource ID 1313 + * 1314 + * Note: The return value is a snapshot which can become invalid right 1315 + * after the function returns. 1316 + * 1317 + * Return: true if the timekeeper clocksource has a base clock with @id, 1318 + * false otherwise 1319 + */ 1320 + bool timekeeping_clocksource_has_base(enum clocksource_ids id) 1321 + { 1322 + /* 1323 + * This is a snapshot, so no point in using the sequence 1324 + * count. Just prevent the compiler from re-evaluating @base as the 1325 + * clocksource might change concurrently. 1326 + */ 1327 + struct clocksource_base *base = READ_ONCE(tk_core.timekeeper.tkr_mono.clock->base); 1328 + 1329 + return base ? base->id == id : false; 1330 + } 1331 + EXPORT_SYMBOL_GPL(timekeeping_clocksource_has_base); 1410 1332 1411 1333 /** 1412 1334 * do_settimeofday64 - Sets the time of day. ··· 2547 2421 2548 2422 /** 2549 2423 * do_adjtimex() - Accessor function to NTP __do_adjtimex function 2424 + * @txc: Pointer to kernel_timex structure containing NTP parameters 2550 2425 */ 2551 2426 int do_adjtimex(struct __kernel_timex *txc) 2552 2427 { ··· 2616 2489 #ifdef CONFIG_NTP_PPS 2617 2490 /** 2618 2491 * hardpps() - Accessor function to NTP __hardpps function 2492 + * @phase_ts: Pointer to timespec64 structure representing phase timestamp 2493 + * @raw_ts: Pointer to timespec64 structure representing raw timestamp 2619 2494 */ 2620 2495 void hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts) 2621 2496 {
+10 -10
lib/vdso/gettimeofday.c
··· 140 140 141 141 do { 142 142 /* 143 - * Open coded to handle VDSO_CLOCKMODE_TIMENS. Time namespace 144 - * enabled tasks have a special VVAR page installed which 145 - * has vd->seq set to 1 and vd->clock_mode set to 146 - * VDSO_CLOCKMODE_TIMENS. For non time namespace affected tasks 147 - * this does not affect performance because if vd->seq is 148 - * odd, i.e. a concurrent update is in progress the extra 149 - * check for vd->clock_mode is just a few extra 150 - * instructions while spin waiting for vd->seq to become 143 + * Open coded function vdso_read_begin() to handle 144 + * VDSO_CLOCKMODE_TIMENS. Time namespace enabled tasks have a 145 + * special VVAR page installed which has vd->seq set to 1 and 146 + * vd->clock_mode set to VDSO_CLOCKMODE_TIMENS. For non time 147 + * namespace affected tasks this does not affect performance 148 + * because if vd->seq is odd, i.e. a concurrent update is in 149 + * progress the extra check for vd->clock_mode is just a few 150 + * extra instructions while spin waiting for vd->seq to become 151 151 * even again. 152 152 */ 153 153 while (unlikely((seq = READ_ONCE(vd->seq)) & 1)) { ··· 223 223 224 224 do { 225 225 /* 226 - * Open coded to handle VDSO_CLOCK_TIMENS. See comment in 227 - * do_hres(). 226 + * Open coded function vdso_read_begin() to handle 227 + * VDSO_CLOCK_TIMENS. See comment in do_hres(). 228 228 */ 229 229 while ((seq = READ_ONCE(vd->seq)) & 1) { 230 230 if (IS_ENABLED(CONFIG_TIME_NS) &&
+2 -1
sound/pci/hda/hda_controller.c
··· 463 463 *device = ktime_add_ns(*device, (wallclk_cycles * NSEC_PER_SEC) / 464 464 ((HDA_MAX_CYCLE_VALUE + 1) * runtime->rate)); 465 465 466 - *system = convert_art_to_tsc(tsc_counter); 466 + system->cycles = tsc_counter; 467 + system->cs_id = CSID_X86_ART; 467 468 468 469 return 0; 469 470 }