diff options
-rw-r--r-- | Documentation/devicetree/bindings/timer/nxp,tpm-timer.txt | 28 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/timer/renesas,cmt.txt | 73 | ||||
-rw-r--r-- | drivers/clocksource/Kconfig | 8 | ||||
-rw-r--r-- | drivers/clocksource/Makefile | 1 | ||||
-rw-r--r-- | drivers/clocksource/bcm2835_timer.c | 1 | ||||
-rw-r--r-- | drivers/clocksource/tango_xtal.c | 6 | ||||
-rw-r--r-- | drivers/clocksource/timer-imx-tpm.c | 239 | ||||
-rw-r--r-- | drivers/clocksource/timer-of.c | 11 | ||||
-rw-r--r-- | drivers/clocksource/timer-probe.c | 3 | ||||
-rw-r--r-- | drivers/clocksource/timer-stm32.c | 8 | ||||
-rw-r--r-- | kernel/time/alarmtimer.c | 17 | ||||
-rw-r--r-- | kernel/time/posix-cpu-timers.c | 14 | ||||
-rw-r--r-- | kernel/time/timekeeping.c | 2 | ||||
-rw-r--r-- | tools/testing/selftests/timers/freq-step.c | 8 | ||||
-rw-r--r-- | tools/testing/selftests/timers/set-timer-lat.c | 103 |
15 files changed, 439 insertions, 83 deletions
diff --git a/Documentation/devicetree/bindings/timer/nxp,tpm-timer.txt b/Documentation/devicetree/bindings/timer/nxp,tpm-timer.txt new file mode 100644 index 000000000000..b4aa7ddb5b13 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/nxp,tpm-timer.txt | |||
@@ -0,0 +1,28 @@ | |||
1 | NXP Low Power Timer/Pulse Width Modulation Module (TPM) | ||
2 | |||
3 | The Timer/PWM Module (TPM) supports input capture, output compare, | ||
4 | and the generation of PWM signals to control electric motor and power | ||
5 | management applications. The counter, compare and capture registers | ||
6 | are clocked by an asynchronous clock that can remain enabled in low | ||
7 | power modes. TPM can support global counter bus where one TPM drives | ||
8 | the counter bus for the others, provided bit width is the same. | ||
9 | |||
10 | Required properties: | ||
11 | |||
12 | - compatible : should be "fsl,imx7ulp-tpm" | ||
13 | - reg : Specifies base physical address and size of the register sets | ||
14 | for the clock event device and clock source device. | ||
15 | - interrupts : Should be the clock event device interrupt. | ||
16 | - clocks : The clocks provided by the SoC to drive the timer, must contain | ||
17 | an entry for each entry in clock-names. | ||
18 | - clock-names : Must include the following entries: "igp" and "per". | ||
19 | |||
20 | Example: | ||
21 | tpm5: tpm@40260000 { | ||
22 | compatible = "fsl,imx7ulp-tpm"; | ||
23 | reg = <0x40260000 0x1000>; | ||
24 | interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>; | ||
25 | clocks = <&clks IMX7ULP_CLK_NIC1_BUS_DIV>, | ||
26 | <&clks IMX7ULP_CLK_LPTPM5>; | ||
27 | clock-names = "ipg", "per"; | ||
28 | }; | ||
diff --git a/Documentation/devicetree/bindings/timer/renesas,cmt.txt b/Documentation/devicetree/bindings/timer/renesas,cmt.txt index 1a05c1b243c1..6ca6b9e582a0 100644 --- a/Documentation/devicetree/bindings/timer/renesas,cmt.txt +++ b/Documentation/devicetree/bindings/timer/renesas,cmt.txt | |||
@@ -12,46 +12,29 @@ datasheets. | |||
12 | Required Properties: | 12 | Required Properties: |
13 | 13 | ||
14 | - compatible: must contain one or more of the following: | 14 | - compatible: must contain one or more of the following: |
15 | - "renesas,cmt-32-r8a7740" for the r8a7740 32-bit CMT | ||
16 | (CMT0) | ||
17 | - "renesas,cmt-32-sh7372" for the sh7372 32-bit CMT | ||
18 | (CMT0) | ||
19 | - "renesas,cmt-32-sh73a0" for the sh73a0 32-bit CMT | ||
20 | (CMT0) | ||
21 | - "renesas,cmt-32" for all 32-bit CMT without fast clock support | ||
22 | (CMT0 on sh7372, sh73a0 and r8a7740) | ||
23 | This is a fallback for the above renesas,cmt-32-* entries. | ||
24 | |||
25 | - "renesas,cmt-32-fast-r8a7740" for the r8a7740 32-bit CMT with fast | ||
26 | clock support (CMT[234]) | ||
27 | - "renesas,cmt-32-fast-sh7372" for the sh7372 32-bit CMT with fast | ||
28 | clock support (CMT[234]) | ||
29 | - "renesas,cmt-32-fast-sh73a0" for the sh73A0 32-bit CMT with fast | ||
30 | clock support (CMT[234]) | ||
31 | - "renesas,cmt-32-fast" for all 32-bit CMT with fast clock support | ||
32 | (CMT[234] on sh7372, sh73a0 and r8a7740) | ||
33 | This is a fallback for the above renesas,cmt-32-fast-* entries. | ||
34 | |||
35 | - "renesas,cmt-48-sh7372" for the sh7372 48-bit CMT | ||
36 | (CMT1) | ||
37 | - "renesas,cmt-48-sh73a0" for the sh73A0 48-bit CMT | 15 | - "renesas,cmt-48-sh73a0" for the sh73A0 48-bit CMT |
38 | (CMT1) | 16 | (CMT1) |
39 | - "renesas,cmt-48-r8a7740" for the r8a7740 48-bit CMT | 17 | - "renesas,cmt-48-r8a7740" for the r8a7740 48-bit CMT |
40 | (CMT1) | 18 | (CMT1) |
41 | - "renesas,cmt-48" for all non-second generation 48-bit CMT | 19 | - "renesas,cmt-48" for all non-second generation 48-bit CMT |
42 | (CMT1 on sh7372, sh73a0 and r8a7740) | 20 | (CMT1 on sh73a0 and r8a7740) |
43 | This is a fallback for the above renesas,cmt-48-* entries. | 21 | This is a fallback for the above renesas,cmt-48-* entries. |
44 | 22 | ||
45 | - "renesas,cmt-48-r8a73a4" for the r8a73a4 48-bit CMT | 23 | - "renesas,cmt0-r8a73a4" for the 32-bit CMT0 device included in r8a73a4. |
46 | (CMT[01]) | 24 | - "renesas,cmt1-r8a73a4" for the 48-bit CMT1 device included in r8a73a4. |
47 | - "renesas,cmt-48-r8a7790" for the r8a7790 48-bit CMT | 25 | - "renesas,cmt0-r8a7790" for the 32-bit CMT0 device included in r8a7790. |
48 | (CMT[01]) | 26 | - "renesas,cmt1-r8a7790" for the 48-bit CMT1 device included in r8a7790. |
49 | - "renesas,cmt-48-r8a7791" for the r8a7791 48-bit CMT | 27 | - "renesas,cmt0-r8a7791" for the 32-bit CMT0 device included in r8a7791. |
50 | (CMT[01]) | 28 | - "renesas,cmt1-r8a7791" for the 48-bit CMT1 device included in r8a7791. |
51 | - "renesas,cmt-48-gen2" for all second generation 48-bit CMT | 29 | - "renesas,cmt0-r8a7793" for the 32-bit CMT0 device included in r8a7793. |
52 | (CMT[01] on r8a73a4, r8a7790 and r8a7791) | 30 | - "renesas,cmt1-r8a7793" for the 48-bit CMT1 device included in r8a7793. |
53 | This is a fallback for the renesas,cmt-48-r8a73a4, | 31 | - "renesas,cmt0-r8a7794" for the 32-bit CMT0 device included in r8a7794. |
54 | renesas,cmt-48-r8a7790 and renesas,cmt-48-r8a7791 entries. | 32 | - "renesas,cmt1-r8a7794" for the 48-bit CMT1 device included in r8a7794. |
33 | |||
34 | - "renesas,rcar-gen2-cmt0" for 32-bit CMT0 devices included in R-Car Gen2. | ||
35 | - "renesas,rcar-gen2-cmt1" for 48-bit CMT1 devices included in R-Car Gen2. | ||
36 | These are fallbacks for r8a73a4 and all the R-Car Gen2 | ||
37 | entries listed above. | ||
55 | 38 | ||
56 | - reg: base address and length of the registers block for the timer module. | 39 | - reg: base address and length of the registers block for the timer module. |
57 | - interrupts: interrupt-specifier for the timer, one per channel. | 40 | - interrupts: interrupt-specifier for the timer, one per channel. |
@@ -59,21 +42,29 @@ Required Properties: | |||
59 | in clock-names. | 42 | in clock-names. |
60 | - clock-names: must contain "fck" for the functional clock. | 43 | - clock-names: must contain "fck" for the functional clock. |
61 | 44 | ||
62 | - renesas,channels-mask: bitmask of the available channels. | ||
63 | 45 | ||
64 | 46 | Example: R8A7790 (R-Car H2) CMT0 and CMT1 nodes | |
65 | Example: R8A7790 (R-Car H2) CMT0 node | ||
66 | |||
67 | CMT0 on R8A7790 implements hardware channels 5 and 6 only and names | ||
68 | them channels 0 and 1 in the documentation. | ||
69 | 47 | ||
70 | cmt0: timer@ffca0000 { | 48 | cmt0: timer@ffca0000 { |
71 | compatible = "renesas,cmt-48-r8a7790", "renesas,cmt-48-gen2"; | 49 | compatible = "renesas,cmt0-r8a7790", "renesas,rcar-gen2-cmt0"; |
72 | reg = <0 0xffca0000 0 0x1004>; | 50 | reg = <0 0xffca0000 0 0x1004>; |
73 | interrupts = <0 142 IRQ_TYPE_LEVEL_HIGH>, | 51 | interrupts = <0 142 IRQ_TYPE_LEVEL_HIGH>, |
74 | <0 142 IRQ_TYPE_LEVEL_HIGH>; | 52 | <0 142 IRQ_TYPE_LEVEL_HIGH>; |
75 | clocks = <&mstp1_clks R8A7790_CLK_CMT0>; | 53 | clocks = <&mstp1_clks R8A7790_CLK_CMT0>; |
76 | clock-names = "fck"; | 54 | clock-names = "fck"; |
55 | }; | ||
77 | 56 | ||
78 | renesas,channels-mask = <0x60>; | 57 | cmt1: timer@e6130000 { |
58 | compatible = "renesas,cmt1-r8a7790", "renesas,rcar-gen2-cmt1"; | ||
59 | reg = <0 0xe6130000 0 0x1004>; | ||
60 | interrupts = <0 120 IRQ_TYPE_LEVEL_HIGH>, | ||
61 | <0 121 IRQ_TYPE_LEVEL_HIGH>, | ||
62 | <0 122 IRQ_TYPE_LEVEL_HIGH>, | ||
63 | <0 123 IRQ_TYPE_LEVEL_HIGH>, | ||
64 | <0 124 IRQ_TYPE_LEVEL_HIGH>, | ||
65 | <0 125 IRQ_TYPE_LEVEL_HIGH>, | ||
66 | <0 126 IRQ_TYPE_LEVEL_HIGH>, | ||
67 | <0 127 IRQ_TYPE_LEVEL_HIGH>; | ||
68 | clocks = <&mstp3_clks R8A7790_CLK_CMT1>; | ||
69 | clock-names = "fck"; | ||
79 | }; | 70 | }; |
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 54a67f8a28eb..cc6062049170 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig | |||
@@ -598,6 +598,14 @@ config CLKSRC_IMX_GPT | |||
598 | depends on ARM && CLKDEV_LOOKUP | 598 | depends on ARM && CLKDEV_LOOKUP |
599 | select CLKSRC_MMIO | 599 | select CLKSRC_MMIO |
600 | 600 | ||
601 | config CLKSRC_IMX_TPM | ||
602 | bool "Clocksource using i.MX TPM" if COMPILE_TEST | ||
603 | depends on ARM && CLKDEV_LOOKUP && GENERIC_CLOCKEVENTS | ||
604 | select CLKSRC_MMIO | ||
605 | help | ||
606 | Enable this option to use IMX Timer/PWM Module (TPM) timer as | ||
607 | clocksource. | ||
608 | |||
601 | config CLKSRC_ST_LPC | 609 | config CLKSRC_ST_LPC |
602 | bool "Low power clocksource found in the LPC" if COMPILE_TEST | 610 | bool "Low power clocksource found in the LPC" if COMPILE_TEST |
603 | select TIMER_OF if OF | 611 | select TIMER_OF if OF |
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 6df949402dfc..dbc1ad14515e 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile | |||
@@ -67,6 +67,7 @@ obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o | |||
67 | obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o | 67 | obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o |
68 | obj-$(CONFIG_CLKSRC_TANGO_XTAL) += tango_xtal.o | 68 | obj-$(CONFIG_CLKSRC_TANGO_XTAL) += tango_xtal.o |
69 | obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o | 69 | obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o |
70 | obj-$(CONFIG_CLKSRC_IMX_TPM) += timer-imx-tpm.o | ||
70 | obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o | 71 | obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o |
71 | obj-$(CONFIG_H8300_TMR8) += h8300_timer8.o | 72 | obj-$(CONFIG_H8300_TMR8) += h8300_timer8.o |
72 | obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o | 73 | obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o |
diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c index 82828d3a4739..39e489a96ad7 100644 --- a/drivers/clocksource/bcm2835_timer.c +++ b/drivers/clocksource/bcm2835_timer.c | |||
@@ -114,7 +114,6 @@ static int __init bcm2835_timer_init(struct device_node *node) | |||
114 | 114 | ||
115 | timer = kzalloc(sizeof(*timer), GFP_KERNEL); | 115 | timer = kzalloc(sizeof(*timer), GFP_KERNEL); |
116 | if (!timer) { | 116 | if (!timer) { |
117 | pr_err("Can't allocate timer struct\n"); | ||
118 | ret = -ENOMEM; | 117 | ret = -ENOMEM; |
119 | goto err_iounmap; | 118 | goto err_iounmap; |
120 | } | 119 | } |
diff --git a/drivers/clocksource/tango_xtal.c b/drivers/clocksource/tango_xtal.c index c4e1c2e6046f..6a8d9838ce33 100644 --- a/drivers/clocksource/tango_xtal.c +++ b/drivers/clocksource/tango_xtal.c | |||
@@ -26,13 +26,13 @@ static int __init tango_clocksource_init(struct device_node *np) | |||
26 | 26 | ||
27 | xtal_in_cnt = of_iomap(np, 0); | 27 | xtal_in_cnt = of_iomap(np, 0); |
28 | if (xtal_in_cnt == NULL) { | 28 | if (xtal_in_cnt == NULL) { |
29 | pr_err("%s: invalid address\n", np->full_name); | 29 | pr_err("%pOF: invalid address\n", np); |
30 | return -ENXIO; | 30 | return -ENXIO; |
31 | } | 31 | } |
32 | 32 | ||
33 | clk = of_clk_get(np, 0); | 33 | clk = of_clk_get(np, 0); |
34 | if (IS_ERR(clk)) { | 34 | if (IS_ERR(clk)) { |
35 | pr_err("%s: invalid clock\n", np->full_name); | 35 | pr_err("%pOF: invalid clock\n", np); |
36 | return PTR_ERR(clk); | 36 | return PTR_ERR(clk); |
37 | } | 37 | } |
38 | 38 | ||
@@ -43,7 +43,7 @@ static int __init tango_clocksource_init(struct device_node *np) | |||
43 | ret = clocksource_mmio_init(xtal_in_cnt, "tango-xtal", xtal_freq, 350, | 43 | ret = clocksource_mmio_init(xtal_in_cnt, "tango-xtal", xtal_freq, 350, |
44 | 32, clocksource_mmio_readl_up); | 44 | 32, clocksource_mmio_readl_up); |
45 | if (ret) { | 45 | if (ret) { |
46 | pr_err("%s: registration failed\n", np->full_name); | 46 | pr_err("%pOF: registration failed\n", np); |
47 | return ret; | 47 | return ret; |
48 | } | 48 | } |
49 | 49 | ||
diff --git a/drivers/clocksource/timer-imx-tpm.c b/drivers/clocksource/timer-imx-tpm.c new file mode 100644 index 000000000000..21bffdcb2f20 --- /dev/null +++ b/drivers/clocksource/timer-imx-tpm.c | |||
@@ -0,0 +1,239 @@ | |||
1 | /* | ||
2 | * Copyright 2016 Freescale Semiconductor, Inc. | ||
3 | * Copyright 2017 NXP | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version 2 | ||
8 | * of the License, or (at your option) any later version. | ||
9 | */ | ||
10 | |||
11 | #include <linux/clk.h> | ||
12 | #include <linux/clockchips.h> | ||
13 | #include <linux/clocksource.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/of_address.h> | ||
17 | #include <linux/of_irq.h> | ||
18 | #include <linux/sched_clock.h> | ||
19 | |||
20 | #define TPM_SC 0x10 | ||
21 | #define TPM_SC_CMOD_INC_PER_CNT (0x1 << 3) | ||
22 | #define TPM_SC_CMOD_DIV_DEFAULT 0x3 | ||
23 | #define TPM_CNT 0x14 | ||
24 | #define TPM_MOD 0x18 | ||
25 | #define TPM_STATUS 0x1c | ||
26 | #define TPM_STATUS_CH0F BIT(0) | ||
27 | #define TPM_C0SC 0x20 | ||
28 | #define TPM_C0SC_CHIE BIT(6) | ||
29 | #define TPM_C0SC_MODE_SHIFT 2 | ||
30 | #define TPM_C0SC_MODE_MASK 0x3c | ||
31 | #define TPM_C0SC_MODE_SW_COMPARE 0x4 | ||
32 | #define TPM_C0V 0x24 | ||
33 | |||
34 | static void __iomem *timer_base; | ||
35 | static struct clock_event_device clockevent_tpm; | ||
36 | |||
37 | static inline void tpm_timer_disable(void) | ||
38 | { | ||
39 | unsigned int val; | ||
40 | |||
41 | /* channel disable */ | ||
42 | val = readl(timer_base + TPM_C0SC); | ||
43 | val &= ~(TPM_C0SC_MODE_MASK | TPM_C0SC_CHIE); | ||
44 | writel(val, timer_base + TPM_C0SC); | ||
45 | } | ||
46 | |||
47 | static inline void tpm_timer_enable(void) | ||
48 | { | ||
49 | unsigned int val; | ||
50 | |||
51 | /* channel enabled in sw compare mode */ | ||
52 | val = readl(timer_base + TPM_C0SC); | ||
53 | val |= (TPM_C0SC_MODE_SW_COMPARE << TPM_C0SC_MODE_SHIFT) | | ||
54 | TPM_C0SC_CHIE; | ||
55 | writel(val, timer_base + TPM_C0SC); | ||
56 | } | ||
57 | |||
58 | static inline void tpm_irq_acknowledge(void) | ||
59 | { | ||
60 | writel(TPM_STATUS_CH0F, timer_base + TPM_STATUS); | ||
61 | } | ||
62 | |||
63 | static struct delay_timer tpm_delay_timer; | ||
64 | |||
65 | static inline unsigned long tpm_read_counter(void) | ||
66 | { | ||
67 | return readl(timer_base + TPM_CNT); | ||
68 | } | ||
69 | |||
70 | static unsigned long tpm_read_current_timer(void) | ||
71 | { | ||
72 | return tpm_read_counter(); | ||
73 | } | ||
74 | |||
75 | static u64 notrace tpm_read_sched_clock(void) | ||
76 | { | ||
77 | return tpm_read_counter(); | ||
78 | } | ||
79 | |||
80 | static int __init tpm_clocksource_init(unsigned long rate) | ||
81 | { | ||
82 | tpm_delay_timer.read_current_timer = &tpm_read_current_timer; | ||
83 | tpm_delay_timer.freq = rate; | ||
84 | register_current_timer_delay(&tpm_delay_timer); | ||
85 | |||
86 | sched_clock_register(tpm_read_sched_clock, 32, rate); | ||
87 | |||
88 | return clocksource_mmio_init(timer_base + TPM_CNT, "imx-tpm", | ||
89 | rate, 200, 32, clocksource_mmio_readl_up); | ||
90 | } | ||
91 | |||
92 | static int tpm_set_next_event(unsigned long delta, | ||
93 | struct clock_event_device *evt) | ||
94 | { | ||
95 | unsigned long next, now; | ||
96 | |||
97 | next = tpm_read_counter(); | ||
98 | next += delta; | ||
99 | writel(next, timer_base + TPM_C0V); | ||
100 | now = tpm_read_counter(); | ||
101 | |||
102 | /* | ||
103 | * NOTE: We observed in a very small probability, the bus fabric | ||
104 | * contention between GPU and A7 may results a few cycles delay | ||
105 | * of writing CNT registers which may cause the min_delta event got | ||
106 | * missed, so we need add a ETIME check here in case it happened. | ||
107 | */ | ||
108 | return (int)((next - now) <= 0) ? -ETIME : 0; | ||
109 | } | ||
110 | |||
111 | static int tpm_set_state_oneshot(struct clock_event_device *evt) | ||
112 | { | ||
113 | tpm_timer_enable(); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int tpm_set_state_shutdown(struct clock_event_device *evt) | ||
119 | { | ||
120 | tpm_timer_disable(); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static irqreturn_t tpm_timer_interrupt(int irq, void *dev_id) | ||
126 | { | ||
127 | struct clock_event_device *evt = dev_id; | ||
128 | |||
129 | tpm_irq_acknowledge(); | ||
130 | |||
131 | evt->event_handler(evt); | ||
132 | |||
133 | return IRQ_HANDLED; | ||
134 | } | ||
135 | |||
136 | static struct clock_event_device clockevent_tpm = { | ||
137 | .name = "i.MX7ULP TPM Timer", | ||
138 | .features = CLOCK_EVT_FEAT_ONESHOT, | ||
139 | .set_state_oneshot = tpm_set_state_oneshot, | ||
140 | .set_next_event = tpm_set_next_event, | ||
141 | .set_state_shutdown = tpm_set_state_shutdown, | ||
142 | .rating = 200, | ||
143 | }; | ||
144 | |||
145 | static int __init tpm_clockevent_init(unsigned long rate, int irq) | ||
146 | { | ||
147 | int ret; | ||
148 | |||
149 | ret = request_irq(irq, tpm_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, | ||
150 | "i.MX7ULP TPM Timer", &clockevent_tpm); | ||
151 | |||
152 | clockevent_tpm.cpumask = cpumask_of(0); | ||
153 | clockevent_tpm.irq = irq; | ||
154 | clockevents_config_and_register(&clockevent_tpm, | ||
155 | rate, 300, 0xfffffffe); | ||
156 | |||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | static int __init tpm_timer_init(struct device_node *np) | ||
161 | { | ||
162 | struct clk *ipg, *per; | ||
163 | int irq, ret; | ||
164 | u32 rate; | ||
165 | |||
166 | timer_base = of_iomap(np, 0); | ||
167 | if (!timer_base) { | ||
168 | pr_err("tpm: failed to get base address\n"); | ||
169 | return -ENXIO; | ||
170 | } | ||
171 | |||
172 | irq = irq_of_parse_and_map(np, 0); | ||
173 | if (!irq) { | ||
174 | pr_err("tpm: failed to get irq\n"); | ||
175 | ret = -ENOENT; | ||
176 | goto err_iomap; | ||
177 | } | ||
178 | |||
179 | ipg = of_clk_get_by_name(np, "ipg"); | ||
180 | per = of_clk_get_by_name(np, "per"); | ||
181 | if (IS_ERR(ipg) || IS_ERR(per)) { | ||
182 | pr_err("tpm: failed to get igp or per clk\n"); | ||
183 | ret = -ENODEV; | ||
184 | goto err_clk_get; | ||
185 | } | ||
186 | |||
187 | /* enable clk before accessing registers */ | ||
188 | ret = clk_prepare_enable(ipg); | ||
189 | if (ret) { | ||
190 | pr_err("tpm: ipg clock enable failed (%d)\n", ret); | ||
191 | goto err_clk_get; | ||
192 | } | ||
193 | |||
194 | ret = clk_prepare_enable(per); | ||
195 | if (ret) { | ||
196 | pr_err("tpm: per clock enable failed (%d)\n", ret); | ||
197 | goto err_per_clk_enable; | ||
198 | } | ||
199 | |||
200 | /* | ||
201 | * Initialize tpm module to a known state | ||
202 | * 1) Counter disabled | ||
203 | * 2) TPM counter operates in up counting mode | ||
204 | * 3) Timer Overflow Interrupt disabled | ||
205 | * 4) Channel0 disabled | ||
206 | * 5) DMA transfers disabled | ||
207 | */ | ||
208 | writel(0, timer_base + TPM_SC); | ||
209 | writel(0, timer_base + TPM_CNT); | ||
210 | writel(0, timer_base + TPM_C0SC); | ||
211 | |||
212 | /* increase per cnt, div 8 by default */ | ||
213 | writel(TPM_SC_CMOD_INC_PER_CNT | TPM_SC_CMOD_DIV_DEFAULT, | ||
214 | timer_base + TPM_SC); | ||
215 | |||
216 | /* set MOD register to maximum for free running mode */ | ||
217 | writel(0xffffffff, timer_base + TPM_MOD); | ||
218 | |||
219 | rate = clk_get_rate(per) >> 3; | ||
220 | ret = tpm_clocksource_init(rate); | ||
221 | if (ret) | ||
222 | goto err_per_clk_enable; | ||
223 | |||
224 | ret = tpm_clockevent_init(rate, irq); | ||
225 | if (ret) | ||
226 | goto err_per_clk_enable; | ||
227 | |||
228 | return 0; | ||
229 | |||
230 | err_per_clk_enable: | ||
231 | clk_disable_unprepare(ipg); | ||
232 | err_clk_get: | ||
233 | clk_put(per); | ||
234 | clk_put(ipg); | ||
235 | err_iomap: | ||
236 | iounmap(timer_base); | ||
237 | return ret; | ||
238 | } | ||
239 | TIMER_OF_DECLARE(imx7ulp, "fsl,imx7ulp-tpm", tpm_timer_init); | ||
diff --git a/drivers/clocksource/timer-of.c b/drivers/clocksource/timer-of.c index 4d7aef9d9c15..c79122d8e10d 100644 --- a/drivers/clocksource/timer-of.c +++ b/drivers/clocksource/timer-of.c | |||
@@ -52,7 +52,7 @@ static __init int timer_irq_init(struct device_node *np, | |||
52 | of_irq->irq = irq_of_parse_and_map(np, of_irq->index); | 52 | of_irq->irq = irq_of_parse_and_map(np, of_irq->index); |
53 | } | 53 | } |
54 | if (!of_irq->irq) { | 54 | if (!of_irq->irq) { |
55 | pr_err("Failed to map interrupt for %s\n", np->full_name); | 55 | pr_err("Failed to map interrupt for %pOF\n", np); |
56 | return -EINVAL; | 56 | return -EINVAL; |
57 | } | 57 | } |
58 | 58 | ||
@@ -63,8 +63,7 @@ static __init int timer_irq_init(struct device_node *np, | |||
63 | of_irq->flags ? of_irq->flags : IRQF_TIMER, | 63 | of_irq->flags ? of_irq->flags : IRQF_TIMER, |
64 | np->full_name, clkevt); | 64 | np->full_name, clkevt); |
65 | if (ret) { | 65 | if (ret) { |
66 | pr_err("Failed to request irq %d for %s\n", of_irq->irq, | 66 | pr_err("Failed to request irq %d for %pOF\n", of_irq->irq, np); |
67 | np->full_name); | ||
68 | return ret; | 67 | return ret; |
69 | } | 68 | } |
70 | 69 | ||
@@ -88,20 +87,20 @@ static __init int timer_clk_init(struct device_node *np, | |||
88 | of_clk->clk = of_clk->name ? of_clk_get_by_name(np, of_clk->name) : | 87 | of_clk->clk = of_clk->name ? of_clk_get_by_name(np, of_clk->name) : |
89 | of_clk_get(np, of_clk->index); | 88 | of_clk_get(np, of_clk->index); |
90 | if (IS_ERR(of_clk->clk)) { | 89 | if (IS_ERR(of_clk->clk)) { |
91 | pr_err("Failed to get clock for %s\n", np->full_name); | 90 | pr_err("Failed to get clock for %pOF\n", np); |
92 | return PTR_ERR(of_clk->clk); | 91 | return PTR_ERR(of_clk->clk); |
93 | } | 92 | } |
94 | 93 | ||
95 | ret = clk_prepare_enable(of_clk->clk); | 94 | ret = clk_prepare_enable(of_clk->clk); |
96 | if (ret) { | 95 | if (ret) { |
97 | pr_err("Failed for enable clock for %s\n", np->full_name); | 96 | pr_err("Failed for enable clock for %pOF\n", np); |
98 | goto out_clk_put; | 97 | goto out_clk_put; |
99 | } | 98 | } |
100 | 99 | ||
101 | of_clk->rate = clk_get_rate(of_clk->clk); | 100 | of_clk->rate = clk_get_rate(of_clk->clk); |
102 | if (!of_clk->rate) { | 101 | if (!of_clk->rate) { |
103 | ret = -EINVAL; | 102 | ret = -EINVAL; |
104 | pr_err("Failed to get clock rate for %s\n", np->full_name); | 103 | pr_err("Failed to get clock rate for %pOF\n", np); |
105 | goto out_clk_disable; | 104 | goto out_clk_disable; |
106 | } | 105 | } |
107 | 106 | ||
diff --git a/drivers/clocksource/timer-probe.c b/drivers/clocksource/timer-probe.c index da81e5de74fe..028075720334 100644 --- a/drivers/clocksource/timer-probe.c +++ b/drivers/clocksource/timer-probe.c | |||
@@ -40,8 +40,7 @@ void __init timer_probe(void) | |||
40 | 40 | ||
41 | ret = init_func_ret(np); | 41 | ret = init_func_ret(np); |
42 | if (ret) { | 42 | if (ret) { |
43 | pr_err("Failed to initialize '%s': %d\n", | 43 | pr_err("Failed to initialize '%pOF': %d\n", np, ret); |
44 | of_node_full_name(np), ret); | ||
45 | continue; | 44 | continue; |
46 | } | 45 | } |
47 | 46 | ||
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c index 174d1243ea93..8f2423789ba9 100644 --- a/drivers/clocksource/timer-stm32.c +++ b/drivers/clocksource/timer-stm32.c | |||
@@ -138,7 +138,7 @@ static int __init stm32_clockevent_init(struct device_node *np) | |||
138 | irq = irq_of_parse_and_map(np, 0); | 138 | irq = irq_of_parse_and_map(np, 0); |
139 | if (!irq) { | 139 | if (!irq) { |
140 | ret = -EINVAL; | 140 | ret = -EINVAL; |
141 | pr_err("%s: failed to get irq.\n", np->full_name); | 141 | pr_err("%pOF: failed to get irq.\n", np); |
142 | goto err_get_irq; | 142 | goto err_get_irq; |
143 | } | 143 | } |
144 | 144 | ||
@@ -168,12 +168,12 @@ static int __init stm32_clockevent_init(struct device_node *np) | |||
168 | ret = request_irq(irq, stm32_clock_event_handler, IRQF_TIMER, | 168 | ret = request_irq(irq, stm32_clock_event_handler, IRQF_TIMER, |
169 | "stm32 clockevent", data); | 169 | "stm32 clockevent", data); |
170 | if (ret) { | 170 | if (ret) { |
171 | pr_err("%s: failed to request irq.\n", np->full_name); | 171 | pr_err("%pOF: failed to request irq.\n", np); |
172 | goto err_get_irq; | 172 | goto err_get_irq; |
173 | } | 173 | } |
174 | 174 | ||
175 | pr_info("%s: STM32 clockevent driver initialized (%d bits)\n", | 175 | pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n", |
176 | np->full_name, bits); | 176 | np, bits); |
177 | 177 | ||
178 | return ret; | 178 | return ret; |
179 | 179 | ||
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 0b8ff7d257ea..ec09ce9a6012 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
29 | #include <linux/freezer.h> | 29 | #include <linux/freezer.h> |
30 | #include <linux/compat.h> | 30 | #include <linux/compat.h> |
31 | #include <linux/module.h> | ||
31 | 32 | ||
32 | #include "posix-timers.h" | 33 | #include "posix-timers.h" |
33 | 34 | ||
@@ -56,9 +57,9 @@ static ktime_t freezer_delta; | |||
56 | static DEFINE_SPINLOCK(freezer_delta_lock); | 57 | static DEFINE_SPINLOCK(freezer_delta_lock); |
57 | #endif | 58 | #endif |
58 | 59 | ||
60 | #ifdef CONFIG_RTC_CLASS | ||
59 | static struct wakeup_source *ws; | 61 | static struct wakeup_source *ws; |
60 | 62 | ||
61 | #ifdef CONFIG_RTC_CLASS | ||
62 | /* rtc timer and device for setting alarm wakeups at suspend */ | 63 | /* rtc timer and device for setting alarm wakeups at suspend */ |
63 | static struct rtc_timer rtctimer; | 64 | static struct rtc_timer rtctimer; |
64 | static struct rtc_device *rtcdev; | 65 | static struct rtc_device *rtcdev; |
@@ -89,6 +90,7 @@ static int alarmtimer_rtc_add_device(struct device *dev, | |||
89 | { | 90 | { |
90 | unsigned long flags; | 91 | unsigned long flags; |
91 | struct rtc_device *rtc = to_rtc_device(dev); | 92 | struct rtc_device *rtc = to_rtc_device(dev); |
93 | struct wakeup_source *__ws; | ||
92 | 94 | ||
93 | if (rtcdev) | 95 | if (rtcdev) |
94 | return -EBUSY; | 96 | return -EBUSY; |
@@ -98,13 +100,25 @@ static int alarmtimer_rtc_add_device(struct device *dev, | |||
98 | if (!device_may_wakeup(rtc->dev.parent)) | 100 | if (!device_may_wakeup(rtc->dev.parent)) |
99 | return -1; | 101 | return -1; |
100 | 102 | ||
103 | __ws = wakeup_source_register("alarmtimer"); | ||
104 | |||
101 | spin_lock_irqsave(&rtcdev_lock, flags); | 105 | spin_lock_irqsave(&rtcdev_lock, flags); |
102 | if (!rtcdev) { | 106 | if (!rtcdev) { |
107 | if (!try_module_get(rtc->owner)) { | ||
108 | spin_unlock_irqrestore(&rtcdev_lock, flags); | ||
109 | return -1; | ||
110 | } | ||
111 | |||
103 | rtcdev = rtc; | 112 | rtcdev = rtc; |
104 | /* hold a reference so it doesn't go away */ | 113 | /* hold a reference so it doesn't go away */ |
105 | get_device(dev); | 114 | get_device(dev); |
115 | ws = __ws; | ||
116 | __ws = NULL; | ||
106 | } | 117 | } |
107 | spin_unlock_irqrestore(&rtcdev_lock, flags); | 118 | spin_unlock_irqrestore(&rtcdev_lock, flags); |
119 | |||
120 | wakeup_source_unregister(__ws); | ||
121 | |||
108 | return 0; | 122 | return 0; |
109 | } | 123 | } |
110 | 124 | ||
@@ -860,7 +874,6 @@ static int __init alarmtimer_init(void) | |||
860 | error = PTR_ERR(pdev); | 874 | error = PTR_ERR(pdev); |
861 | goto out_drv; | 875 | goto out_drv; |
862 | } | 876 | } |
863 | ws = wakeup_source_register("alarmtimer"); | ||
864 | return 0; | 877 | return 0; |
865 | 878 | ||
866 | out_drv: | 879 | out_drv: |
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index a3bd5dbe0dc4..8585ad6e472a 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c | |||
@@ -799,7 +799,6 @@ static void check_thread_timers(struct task_struct *tsk, | |||
799 | struct list_head *firing) | 799 | struct list_head *firing) |
800 | { | 800 | { |
801 | struct list_head *timers = tsk->cpu_timers; | 801 | struct list_head *timers = tsk->cpu_timers; |
802 | struct signal_struct *const sig = tsk->signal; | ||
803 | struct task_cputime *tsk_expires = &tsk->cputime_expires; | 802 | struct task_cputime *tsk_expires = &tsk->cputime_expires; |
804 | u64 expires; | 803 | u64 expires; |
805 | unsigned long soft; | 804 | unsigned long soft; |
@@ -823,10 +822,9 @@ static void check_thread_timers(struct task_struct *tsk, | |||
823 | /* | 822 | /* |
824 | * Check for the special case thread timers. | 823 | * Check for the special case thread timers. |
825 | */ | 824 | */ |
826 | soft = READ_ONCE(sig->rlim[RLIMIT_RTTIME].rlim_cur); | 825 | soft = task_rlimit(tsk, RLIMIT_RTTIME); |
827 | if (soft != RLIM_INFINITY) { | 826 | if (soft != RLIM_INFINITY) { |
828 | unsigned long hard = | 827 | unsigned long hard = task_rlimit_max(tsk, RLIMIT_RTTIME); |
829 | READ_ONCE(sig->rlim[RLIMIT_RTTIME].rlim_max); | ||
830 | 828 | ||
831 | if (hard != RLIM_INFINITY && | 829 | if (hard != RLIM_INFINITY && |
832 | tsk->rt.timeout > DIV_ROUND_UP(hard, USEC_PER_SEC/HZ)) { | 830 | tsk->rt.timeout > DIV_ROUND_UP(hard, USEC_PER_SEC/HZ)) { |
@@ -847,7 +845,8 @@ static void check_thread_timers(struct task_struct *tsk, | |||
847 | */ | 845 | */ |
848 | if (soft < hard) { | 846 | if (soft < hard) { |
849 | soft += USEC_PER_SEC; | 847 | soft += USEC_PER_SEC; |
850 | sig->rlim[RLIMIT_RTTIME].rlim_cur = soft; | 848 | tsk->signal->rlim[RLIMIT_RTTIME].rlim_cur = |
849 | soft; | ||
851 | } | 850 | } |
852 | if (print_fatal_signals) { | 851 | if (print_fatal_signals) { |
853 | pr_info("RT Watchdog Timeout (soft): %s[%d]\n", | 852 | pr_info("RT Watchdog Timeout (soft): %s[%d]\n", |
@@ -938,11 +937,10 @@ static void check_process_timers(struct task_struct *tsk, | |||
938 | SIGPROF); | 937 | SIGPROF); |
939 | check_cpu_itimer(tsk, &sig->it[CPUCLOCK_VIRT], &virt_expires, utime, | 938 | check_cpu_itimer(tsk, &sig->it[CPUCLOCK_VIRT], &virt_expires, utime, |
940 | SIGVTALRM); | 939 | SIGVTALRM); |
941 | soft = READ_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur); | 940 | soft = task_rlimit(tsk, RLIMIT_CPU); |
942 | if (soft != RLIM_INFINITY) { | 941 | if (soft != RLIM_INFINITY) { |
943 | unsigned long psecs = div_u64(ptime, NSEC_PER_SEC); | 942 | unsigned long psecs = div_u64(ptime, NSEC_PER_SEC); |
944 | unsigned long hard = | 943 | unsigned long hard = task_rlimit_max(tsk, RLIMIT_CPU); |
945 | READ_ONCE(sig->rlim[RLIMIT_CPU].rlim_max); | ||
946 | u64 x; | 944 | u64 x; |
947 | if (psecs >= hard) { | 945 | if (psecs >= hard) { |
948 | /* | 946 | /* |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 7e7e61c00d61..8ea4fb315719 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -2064,7 +2064,7 @@ void update_wall_time(void) | |||
2064 | goto out; | 2064 | goto out; |
2065 | 2065 | ||
2066 | /* Do some additional sanity checking */ | 2066 | /* Do some additional sanity checking */ |
2067 | timekeeping_check_update(real_tk, offset); | 2067 | timekeeping_check_update(tk, offset); |
2068 | 2068 | ||
2069 | /* | 2069 | /* |
2070 | * With NO_HZ we may have to accumulate many cycle_intervals | 2070 | * With NO_HZ we may have to accumulate many cycle_intervals |
diff --git a/tools/testing/selftests/timers/freq-step.c b/tools/testing/selftests/timers/freq-step.c index 22312eb4c941..14a2b77fd012 100644 --- a/tools/testing/selftests/timers/freq-step.c +++ b/tools/testing/selftests/timers/freq-step.c | |||
@@ -33,6 +33,10 @@ | |||
33 | #define MAX_FREQ_ERROR 10e-6 | 33 | #define MAX_FREQ_ERROR 10e-6 |
34 | #define MAX_STDDEV 1000e-9 | 34 | #define MAX_STDDEV 1000e-9 |
35 | 35 | ||
36 | #ifndef ADJ_SETOFFSET | ||
37 | #define ADJ_SETOFFSET 0x0100 | ||
38 | #endif | ||
39 | |||
36 | struct sample { | 40 | struct sample { |
37 | double offset; | 41 | double offset; |
38 | double time; | 42 | double time; |
@@ -261,7 +265,7 @@ int main(int argc, char **argv) | |||
261 | set_frequency(0.0); | 265 | set_frequency(0.0); |
262 | 266 | ||
263 | if (fails) | 267 | if (fails) |
264 | ksft_exit_fail(); | 268 | return ksft_exit_fail(); |
265 | 269 | ||
266 | ksft_exit_pass(); | 270 | return ksft_exit_pass(); |
267 | } | 271 | } |
diff --git a/tools/testing/selftests/timers/set-timer-lat.c b/tools/testing/selftests/timers/set-timer-lat.c index 4fc98c5b0899..15434da23b04 100644 --- a/tools/testing/selftests/timers/set-timer-lat.c +++ b/tools/testing/selftests/timers/set-timer-lat.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | 22 | ||
23 | #include <errno.h> | ||
23 | #include <stdio.h> | 24 | #include <stdio.h> |
24 | #include <unistd.h> | 25 | #include <unistd.h> |
25 | #include <time.h> | 26 | #include <time.h> |
@@ -63,6 +64,7 @@ int alarmcount; | |||
63 | int clock_id; | 64 | int clock_id; |
64 | struct timespec start_time; | 65 | struct timespec start_time; |
65 | long long max_latency_ns; | 66 | long long max_latency_ns; |
67 | int timer_fired_early; | ||
66 | 68 | ||
67 | char *clockstring(int clockid) | 69 | char *clockstring(int clockid) |
68 | { | 70 | { |
@@ -115,16 +117,23 @@ void sigalarm(int signo) | |||
115 | delta_ns -= NSEC_PER_SEC * TIMER_SECS * alarmcount; | 117 | delta_ns -= NSEC_PER_SEC * TIMER_SECS * alarmcount; |
116 | 118 | ||
117 | if (delta_ns < 0) | 119 | if (delta_ns < 0) |
118 | printf("%s timer fired early: FAIL\n", clockstring(clock_id)); | 120 | timer_fired_early = 1; |
119 | 121 | ||
120 | if (delta_ns > max_latency_ns) | 122 | if (delta_ns > max_latency_ns) |
121 | max_latency_ns = delta_ns; | 123 | max_latency_ns = delta_ns; |
122 | } | 124 | } |
123 | 125 | ||
124 | int do_timer(int clock_id, int flags) | 126 | void describe_timer(int flags, int interval) |
127 | { | ||
128 | printf("%-22s %s %s ", | ||
129 | clockstring(clock_id), | ||
130 | flags ? "ABSTIME":"RELTIME", | ||
131 | interval ? "PERIODIC":"ONE-SHOT"); | ||
132 | } | ||
133 | |||
134 | int setup_timer(int clock_id, int flags, int interval, timer_t *tm1) | ||
125 | { | 135 | { |
126 | struct sigevent se; | 136 | struct sigevent se; |
127 | timer_t tm1; | ||
128 | struct itimerspec its1, its2; | 137 | struct itimerspec its1, its2; |
129 | int err; | 138 | int err; |
130 | 139 | ||
@@ -136,8 +145,9 @@ int do_timer(int clock_id, int flags) | |||
136 | 145 | ||
137 | max_latency_ns = 0; | 146 | max_latency_ns = 0; |
138 | alarmcount = 0; | 147 | alarmcount = 0; |
148 | timer_fired_early = 0; | ||
139 | 149 | ||
140 | err = timer_create(clock_id, &se, &tm1); | 150 | err = timer_create(clock_id, &se, tm1); |
141 | if (err) { | 151 | if (err) { |
142 | if ((clock_id == CLOCK_REALTIME_ALARM) || | 152 | if ((clock_id == CLOCK_REALTIME_ALARM) || |
143 | (clock_id == CLOCK_BOOTTIME_ALARM)) { | 153 | (clock_id == CLOCK_BOOTTIME_ALARM)) { |
@@ -158,32 +168,97 @@ int do_timer(int clock_id, int flags) | |||
158 | its1.it_value.tv_sec = TIMER_SECS; | 168 | its1.it_value.tv_sec = TIMER_SECS; |
159 | its1.it_value.tv_nsec = 0; | 169 | its1.it_value.tv_nsec = 0; |
160 | } | 170 | } |
161 | its1.it_interval.tv_sec = TIMER_SECS; | 171 | its1.it_interval.tv_sec = interval; |
162 | its1.it_interval.tv_nsec = 0; | 172 | its1.it_interval.tv_nsec = 0; |
163 | 173 | ||
164 | err = timer_settime(tm1, flags, &its1, &its2); | 174 | err = timer_settime(*tm1, flags, &its1, &its2); |
165 | if (err) { | 175 | if (err) { |
166 | printf("%s - timer_settime() failed\n", clockstring(clock_id)); | 176 | printf("%s - timer_settime() failed\n", clockstring(clock_id)); |
167 | return -1; | 177 | return -1; |
168 | } | 178 | } |
169 | 179 | ||
170 | while (alarmcount < 5) | 180 | return 0; |
171 | sleep(1); | 181 | } |
172 | 182 | ||
173 | printf("%-22s %s max latency: %10lld ns : ", | 183 | int check_timer_latency(int flags, int interval) |
174 | clockstring(clock_id), | 184 | { |
175 | flags ? "ABSTIME":"RELTIME", | 185 | int err = 0; |
176 | max_latency_ns); | 186 | |
187 | describe_timer(flags, interval); | ||
188 | printf("timer fired early: %7d : ", timer_fired_early); | ||
189 | if (!timer_fired_early) { | ||
190 | printf("[OK]\n"); | ||
191 | } else { | ||
192 | printf("[FAILED]\n"); | ||
193 | err = -1; | ||
194 | } | ||
195 | |||
196 | describe_timer(flags, interval); | ||
197 | printf("max latency: %10lld ns : ", max_latency_ns); | ||
177 | 198 | ||
178 | timer_delete(tm1); | ||
179 | if (max_latency_ns < UNRESONABLE_LATENCY) { | 199 | if (max_latency_ns < UNRESONABLE_LATENCY) { |
180 | printf("[OK]\n"); | 200 | printf("[OK]\n"); |
201 | } else { | ||
202 | printf("[FAILED]\n"); | ||
203 | err = -1; | ||
204 | } | ||
205 | return err; | ||
206 | } | ||
207 | |||
208 | int check_alarmcount(int flags, int interval) | ||
209 | { | ||
210 | describe_timer(flags, interval); | ||
211 | printf("count: %19d : ", alarmcount); | ||
212 | if (alarmcount == 1) { | ||
213 | printf("[OK]\n"); | ||
181 | return 0; | 214 | return 0; |
182 | } | 215 | } |
183 | printf("[FAILED]\n"); | 216 | printf("[FAILED]\n"); |
184 | return -1; | 217 | return -1; |
185 | } | 218 | } |
186 | 219 | ||
220 | int do_timer(int clock_id, int flags) | ||
221 | { | ||
222 | timer_t tm1; | ||
223 | const int interval = TIMER_SECS; | ||
224 | int err; | ||
225 | |||
226 | err = setup_timer(clock_id, flags, interval, &tm1); | ||
227 | if (err) | ||
228 | return err; | ||
229 | |||
230 | while (alarmcount < 5) | ||
231 | sleep(1); | ||
232 | |||
233 | timer_delete(tm1); | ||
234 | return check_timer_latency(flags, interval); | ||
235 | } | ||
236 | |||
237 | int do_timer_oneshot(int clock_id, int flags) | ||
238 | { | ||
239 | timer_t tm1; | ||
240 | const int interval = 0; | ||
241 | struct timeval timeout; | ||
242 | fd_set fds; | ||
243 | int err; | ||
244 | |||
245 | err = setup_timer(clock_id, flags, interval, &tm1); | ||
246 | if (err) | ||
247 | return err; | ||
248 | |||
249 | memset(&timeout, 0, sizeof(timeout)); | ||
250 | timeout.tv_sec = 5; | ||
251 | FD_ZERO(&fds); | ||
252 | do { | ||
253 | err = select(FD_SETSIZE, &fds, NULL, NULL, &timeout); | ||
254 | } while (err == -1 && errno == EINTR); | ||
255 | |||
256 | timer_delete(tm1); | ||
257 | err = check_timer_latency(flags, interval); | ||
258 | err |= check_alarmcount(flags, interval); | ||
259 | return err; | ||
260 | } | ||
261 | |||
187 | int main(void) | 262 | int main(void) |
188 | { | 263 | { |
189 | struct sigaction act; | 264 | struct sigaction act; |
@@ -209,6 +284,8 @@ int main(void) | |||
209 | 284 | ||
210 | ret |= do_timer(clock_id, TIMER_ABSTIME); | 285 | ret |= do_timer(clock_id, TIMER_ABSTIME); |
211 | ret |= do_timer(clock_id, 0); | 286 | ret |= do_timer(clock_id, 0); |
287 | ret |= do_timer_oneshot(clock_id, TIMER_ABSTIME); | ||
288 | ret |= do_timer_oneshot(clock_id, 0); | ||
212 | } | 289 | } |
213 | if (ret) | 290 | if (ret) |
214 | return ksft_exit_fail(); | 291 | return ksft_exit_fail(); |