When I created the patch removing CONFIG_ARCH_GETTIMEOFFSET,
I also had a look at CONFIG_GENERIC_CLOCKEVENTS, which is
selected by most, but not all, platforms today, each of the
ones that lack it doing the timer tick slightly differently.
The cleanups here make the old platforms a bit more
consistent, in multiple ways:
- rather than selecting GENERIC_CLOCKEVENTS on modern
platforms, select LEGACY_TIMER_TICK on the old ones.
- Hide some more of the internal implementation and only
provide a single common entry point for the timer tick,
which also makes the behavior more consistent.
- Remove the m68k and arm specific infrastructure pieces
and call the common helper directly from each timer
interrupt function.
I tested the series on m68k with the qemu q800 target
platform, both with the legacy_timer_tick() implementation
and after converting that to a periodic clockevent driver.
Arnd
Arnd Bergmann (13):
timekeeping: add CONFIG_LEGACY_TIMER_TICK
ia64: convert to legacy_timer_tick
ARM: rpc: use legacy_timer_tick
parisc: use legacy_timer_tick
m68k: coldfire: use legacy_timer_tick()
m68k: split heartbeat out of timer function
m68k: sun3/sun3c: use legacy_timer_tick
m68k: m68328: use legacy_timer_tick()
m68k: change remaining timers to legacy_timer_tick
m68k: remove timer_interrupt() function
timekeeping: remove xtime_update
timekeeping: default GENERIC_CLOCKEVENTS to enabled
[RFC] m68k: mac: convert to generic clockevent
.../time/clockevents/arch-support.txt | 8 ++--
arch/alpha/Kconfig | 1 -
arch/arc/Kconfig | 1 -
arch/arm/Kconfig | 13 +-----
arch/arm/include/asm/mach/time.h | 2 -
arch/arm/kernel/time.c | 14 ------
arch/arm/mach-rpc/time.c | 2 +-
arch/arm64/Kconfig | 1 -
arch/arm64/Kconfig.platforms | 1 -
arch/c6x/Kconfig | 1 -
arch/csky/Kconfig | 1 -
arch/h8300/Kconfig | 1 -
arch/hexagon/Kconfig | 1 -
arch/ia64/Kconfig | 1 +
arch/ia64/kernel/time.c | 36 ++++++---------
arch/m68k/68000/timers.c | 7 ++-
arch/m68k/Kconfig.cpu | 34 +++++++++++---
arch/m68k/Kconfig.machine | 15 +++++++
arch/m68k/amiga/config.c | 11 +++--
arch/m68k/apollo/config.c | 11 +++--
arch/m68k/atari/config.c | 2 +-
arch/m68k/atari/time.c | 9 ++--
arch/m68k/bvme6000/config.c | 9 ++--
arch/m68k/coldfire/Makefile | 32 ++++++++------
arch/m68k/coldfire/pit.c | 2 +-
arch/m68k/coldfire/sltimers.c | 8 ++--
arch/m68k/coldfire/timers.c | 8 ++--
arch/m68k/hp300/time.c | 8 ++--
arch/m68k/hp300/time.h | 2 +-
arch/m68k/include/asm/machdep.h | 12 +++--
arch/m68k/kernel/setup_mm.c | 2 +-
arch/m68k/kernel/setup_no.c | 2 +-
arch/m68k/kernel/time.c | 18 ++------
arch/m68k/mac/config.c | 6 +--
arch/m68k/mac/via.c | 44 +++++++++++++++----
arch/m68k/mvme147/config.c | 9 ++--
arch/m68k/mvme16x/config.c | 9 ++--
arch/m68k/q40/config.c | 2 +-
arch/m68k/q40/q40ints.c | 10 ++---
arch/m68k/sun3/config.c | 4 +-
arch/m68k/sun3/sun3ints.c | 3 +-
arch/m68k/sun3x/time.c | 5 +--
arch/m68k/sun3x/time.h | 2 +-
arch/microblaze/Kconfig | 1 -
arch/mips/Kconfig | 1 -
arch/nds32/Kconfig | 1 -
arch/nios2/Kconfig | 1 -
arch/openrisc/Kconfig | 1 -
arch/parisc/Kconfig | 2 +-
arch/parisc/kernel/time.c | 9 ++--
arch/powerpc/Kconfig | 1 -
arch/riscv/Kconfig | 1 -
arch/s390/Kconfig | 1 -
arch/sh/Kconfig | 1 -
arch/sparc/Kconfig | 1 -
arch/um/Kconfig | 1 -
arch/x86/Kconfig | 1 -
arch/xtensa/Kconfig | 1 -
include/linux/timekeeping.h | 5 +--
kernel/time/Kconfig | 9 +++-
kernel/time/Makefile | 1 +
kernel/time/tick-legacy.c | 37 ++++++++++++++++
kernel/time/timekeeping.c | 16 -------
kernel/time/timekeeping.h | 1 +
64 files changed, 242 insertions(+), 221 deletions(-)
create mode 100644 kernel/time/tick-legacy.c
Cc: Russell King <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Fenghua Yu <[email protected]>
Cc: Greg Ungerer <[email protected]>
Cc: Geert Uytterhoeven <[email protected]>
Cc: Finn Thain <[email protected]>
Cc: Philip Blundell <[email protected]>
Cc: Joshua Thompson <[email protected]>
Cc: Sam Creasey <[email protected]>
Cc: "James E.J. Bottomley" <[email protected]>
Cc: Helge Deller <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Daniel Lezcano <[email protected]>
Cc: John Stultz <[email protected]>
Cc: Stephen Boyd <[email protected]>
Cc: Linus Walleij <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
--
2.27.0
A couple of machines share the m68328 timer code that
is based on calling timer_interrupt(). Change these
to the new and slightly more generic legacy_timer_tick()
helper.
Signed-off-by: Arnd Bergmann <[email protected]>
---
arch/m68k/68000/timers.c | 5 ++---
arch/m68k/Kconfig.machine | 4 ++++
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/arch/m68k/68000/timers.c b/arch/m68k/68000/timers.c
index e8dfdd2556a5..3aa006f8e7ea 100644
--- a/arch/m68k/68000/timers.c
+++ b/arch/m68k/68000/timers.c
@@ -52,7 +52,6 @@
#endif
static u32 m68328_tick_cnt;
-static irq_handler_t timer_interrupt;
/***************************************************************************/
@@ -62,7 +61,8 @@ static irqreturn_t hw_tick(int irq, void *dummy)
TSTAT &= 0;
m68328_tick_cnt += TICKS_PER_JIFFY;
- return timer_interrupt(irq, dummy);
+ legacy_timer_tick(1);
+ return IRQ_HANDLED;
}
/***************************************************************************/
@@ -113,7 +113,6 @@ void hw_timer_init(irq_handler_t handler)
/* Enable timer 1 */
TCTL |= TCTL_TEN;
clocksource_register_hz(&m68328_clk, TICKS_PER_JIFFY*HZ);
- timer_interrupt = handler;
}
/***************************************************************************/
diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine
index e3c835440d9a..0ff9338b958e 100644
--- a/arch/m68k/Kconfig.machine
+++ b/arch/m68k/Kconfig.machine
@@ -146,6 +146,7 @@ config PILOT
config PILOT3
bool "Pilot 1000/5000, PalmPilot Personal/Pro, or PalmIII support"
depends on M68328
+ select LEGACY_TIMER_TICK
select PILOT
help
Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII.
@@ -159,18 +160,21 @@ config XCOPILOT_BUGS
config UCSIMM
bool "uCsimm module support"
depends on M68EZ328
+ select LEGACY_TIMER_TICK
help
Support for the Arcturus Networks uCsimm module.
config UCDIMM
bool "uDsimm module support"
depends on M68VZ328
+ select LEGACY_TIMER_TICK
help
Support for the Arcturus Networks uDsimm module.
config DRAGEN2
bool "DragenEngine II board support"
depends on M68VZ328
+ select LEGACY_TIMER_TICK
help
Support for the DragenEngine II board.
--
2.27.0
This gets passed to a number of init functions, but is
ignored everywhere, so remove the function and change the
mach_sched_init callback to take no arguments.
Signed-off-by: Arnd Bergmann <[email protected]>
---
arch/m68k/68000/timers.c | 2 +-
arch/m68k/amiga/config.c | 4 ++--
arch/m68k/apollo/config.c | 4 ++--
arch/m68k/atari/config.c | 2 +-
arch/m68k/atari/time.c | 2 +-
arch/m68k/bvme6000/config.c | 4 ++--
arch/m68k/coldfire/pit.c | 2 +-
arch/m68k/coldfire/sltimers.c | 2 +-
arch/m68k/coldfire/timers.c | 2 +-
arch/m68k/hp300/time.c | 2 +-
arch/m68k/hp300/time.h | 2 +-
arch/m68k/include/asm/machdep.h | 5 ++---
arch/m68k/kernel/setup_mm.c | 2 +-
arch/m68k/kernel/setup_no.c | 2 +-
arch/m68k/kernel/time.c | 15 +--------------
arch/m68k/mac/config.c | 6 +++---
arch/m68k/mac/via.c | 2 +-
arch/m68k/mvme147/config.c | 4 ++--
arch/m68k/mvme16x/config.c | 4 ++--
arch/m68k/q40/config.c | 2 +-
arch/m68k/q40/q40ints.c | 2 +-
arch/m68k/sun3/config.c | 4 ++--
arch/m68k/sun3x/time.c | 2 +-
arch/m68k/sun3x/time.h | 2 +-
24 files changed, 33 insertions(+), 47 deletions(-)
diff --git a/arch/m68k/68000/timers.c b/arch/m68k/68000/timers.c
index 3aa006f8e7ea..0d0417cebc7f 100644
--- a/arch/m68k/68000/timers.c
+++ b/arch/m68k/68000/timers.c
@@ -91,7 +91,7 @@ static struct clocksource m68328_clk = {
/***************************************************************************/
-void hw_timer_init(irq_handler_t handler)
+void hw_timer_init(void)
{
int ret;
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 91dc87b86411..50e9a2c6523e 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -92,7 +92,7 @@ static char *amiga_models[] __initdata = {
static char amiga_model_name[13] = "Amiga ";
-static void amiga_sched_init(irq_handler_t handler);
+static void amiga_sched_init(void);
static void amiga_get_model(char *model);
static void amiga_get_hardware_list(struct seq_file *m);
extern void amiga_mksound(unsigned int count, unsigned int ticks);
@@ -483,7 +483,7 @@ static irqreturn_t ciab_timer_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void __init amiga_sched_init(irq_handler_t timer_routine)
+static void __init amiga_sched_init(void)
{
static struct resource sched_res = {
.name = "timer", .start = 0x00bfd400, .end = 0x00bfd5ff,
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
index 17d59fa6b25b..36c2cd97f228 100644
--- a/arch/m68k/apollo/config.c
+++ b/arch/m68k/apollo/config.c
@@ -26,7 +26,7 @@ u_long cpuctrl_physaddr;
u_long timer_physaddr;
u_long apollo_model;
-extern void dn_sched_init(irq_handler_t handler);
+extern void dn_sched_init(void);
extern void dn_init_IRQ(void);
extern int dn_dummy_hwclk(int, struct rtc_time *);
extern void dn_dummy_reset(void);
@@ -179,7 +179,7 @@ irqreturn_t dn_timer_int(int irq, void *dev_id)
return IRQ_HANDLED;
}
-void dn_sched_init(irq_handler_t timer_routine)
+void dn_sched_init(void)
{
/* program timer 1 */
*(volatile unsigned char *)(apollo_timer + 3) = 0x01;
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index 7ec3161e8517..50fda4bea521 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -77,7 +77,7 @@ static void atari_heartbeat(int on);
#endif
/* atari specific timer functions (in time.c) */
-extern void atari_sched_init(irq_handler_t);
+extern void atari_sched_init(void);
extern int atari_mste_hwclk (int, struct rtc_time *);
extern int atari_tt_hwclk (int, struct rtc_time *);
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index 36d811ae09ee..1068670cb741 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -56,7 +56,7 @@ static irqreturn_t mfp_timer_c_handler(int irq, void *dev_id)
}
void __init
-atari_sched_init(irq_handler_t timer_routine)
+atari_sched_init(void)
{
/* set Timer C data Register */
st_mfp.tim_dt_c = INT_TICKS;
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index d3f5963021d3..b37f8ce034e7 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -38,7 +38,7 @@
#include <asm/bvme6000hw.h>
static void bvme6000_get_model(char *model);
-extern void bvme6000_sched_init(irq_handler_t handler);
+extern void bvme6000_sched_init(void);
extern int bvme6000_hwclk (int, struct rtc_time *);
extern void bvme6000_reset (void);
void bvme6000_set_vectors (void);
@@ -189,7 +189,7 @@ static irqreturn_t bvme6000_timer_int (int irq, void *dev_id)
* so divide by 8 to get the microsecond result.
*/
-void bvme6000_sched_init (irq_handler_t timer_routine)
+void bvme6000_sched_init (void)
{
volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
unsigned char msr = rtc->msr & 0xc0;
diff --git a/arch/m68k/coldfire/pit.c b/arch/m68k/coldfire/pit.c
index fd1d9c915daa..855d0af47097 100644
--- a/arch/m68k/coldfire/pit.c
+++ b/arch/m68k/coldfire/pit.c
@@ -136,7 +136,7 @@ static struct clocksource pit_clk = {
/***************************************************************************/
-void hw_timer_init(irq_handler_t handler)
+void hw_timer_init(void)
{
int ret;
diff --git a/arch/m68k/coldfire/sltimers.c b/arch/m68k/coldfire/sltimers.c
index 25a1319f3cb8..f9d572ee63db 100644
--- a/arch/m68k/coldfire/sltimers.c
+++ b/arch/m68k/coldfire/sltimers.c
@@ -118,7 +118,7 @@ static struct clocksource mcfslt_clk = {
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
-void hw_timer_init(irq_handler_t handler)
+void hw_timer_init(void)
{
int r;
diff --git a/arch/m68k/coldfire/timers.c b/arch/m68k/coldfire/timers.c
index 24b5e2d1b00b..05a42d8e0a59 100644
--- a/arch/m68k/coldfire/timers.c
+++ b/arch/m68k/coldfire/timers.c
@@ -107,7 +107,7 @@ static struct clocksource mcftmr_clk = {
/***************************************************************************/
-void hw_timer_init(irq_handler_t handler)
+void hw_timer_init(void)
{
int r;
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
index 011fc2e5a68a..1d1b7b3b5dd4 100644
--- a/arch/m68k/hp300/time.c
+++ b/arch/m68k/hp300/time.c
@@ -98,7 +98,7 @@ static u64 hp300_read_clk(struct clocksource *cs)
return ticks;
}
-void __init hp300_sched_init(irq_handler_t vector)
+void __init hp300_sched_init(void)
{
out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */
out_8(CLOCKBASE + CLKCR1, 0x1); /* reset */
diff --git a/arch/m68k/hp300/time.h b/arch/m68k/hp300/time.h
index 1d77b55cc72a..040a098b7db1 100644
--- a/arch/m68k/hp300/time.h
+++ b/arch/m68k/hp300/time.h
@@ -1 +1 @@
-extern void hp300_sched_init(irq_handler_t vector);
+extern void hp300_sched_init(void);
diff --git a/arch/m68k/include/asm/machdep.h b/arch/m68k/include/asm/machdep.h
index e62a39d01ae4..7181ed43ba22 100644
--- a/arch/m68k/include/asm/machdep.h
+++ b/arch/m68k/include/asm/machdep.h
@@ -12,7 +12,7 @@ struct rtc_time;
struct rtc_pll_info;
struct buffer_head;
-extern void (*mach_sched_init) (irq_handler_t handler);
+extern void (*mach_sched_init) (void);
/* machine dependent irq functions */
extern void (*mach_init_IRQ) (void);
extern void (*mach_get_model) (char *model);
@@ -33,8 +33,7 @@ extern void (*mach_l2_flush) (int);
extern void (*mach_beep) (unsigned int, unsigned int);
/* Hardware clock functions */
-extern void hw_timer_init(irq_handler_t handler);
-extern unsigned long hw_timer_offset(void);
+extern void hw_timer_init(void);
#ifdef CONFIG_HEARTBEAT
extern void timer_heartbeat(void);
#else
diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c
index ab8aa7be260f..0628733bfb88 100644
--- a/arch/m68k/kernel/setup_mm.c
+++ b/arch/m68k/kernel/setup_mm.c
@@ -82,7 +82,7 @@ static struct m68k_mem_info m68k_ramdisk __initdata;
static char m68k_command_line[CL_SIZE] __initdata;
-void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL;
+void (*mach_sched_init) (void) __initdata = NULL;
/* machine dependent irq functions */
void (*mach_init_IRQ) (void) __initdata = NULL;
void (*mach_get_model) (char *model);
diff --git a/arch/m68k/kernel/setup_no.c b/arch/m68k/kernel/setup_no.c
index f66f4b1d062e..e377b4219528 100644
--- a/arch/m68k/kernel/setup_no.c
+++ b/arch/m68k/kernel/setup_no.c
@@ -49,7 +49,7 @@ EXPORT_SYMBOL(memory_end);
char __initdata command_line[COMMAND_LINE_SIZE];
/* machine dependent timer functions */
-void (*mach_sched_init)(irq_handler_t handler) __initdata = NULL;
+void (*mach_sched_init)(void) __initdata = NULL;
int (*mach_hwclk) (int, struct rtc_time*);
/* machine dependent reboot functions */
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index c05cec21b05f..340ffeea0a9d 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -35,19 +35,6 @@
unsigned long (*mach_random_get_entropy)(void);
EXPORT_SYMBOL_GPL(mach_random_get_entropy);
-
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "xtime_update()" routine every clocktick
- */
-static irqreturn_t timer_interrupt(int irq, void *dummy)
-{
- xtime_update(1);
- update_process_times(user_mode(get_irq_regs()));
- profile_tick(CPU_PROFILING);
- return IRQ_HANDLED;
-}
-
#ifdef CONFIG_HEARTBEAT
void timer_heartbeat(void)
{
@@ -157,5 +144,5 @@ module_init(rtc_init);
void __init time_init(void)
{
- mach_sched_init(timer_interrupt);
+ mach_sched_init();
}
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 0ac53d87493c..0dbe0fedd826 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -58,7 +58,7 @@ extern int mac_hwclk(int, struct rtc_time *);
extern void iop_preinit(void);
extern void iop_init(void);
extern void via_init(void);
-extern void via_init_clock(irq_handler_t func);
+extern void via_init_clock(void);
extern void oss_init(void);
extern void psc_init(void);
extern void baboon_init(void);
@@ -69,9 +69,9 @@ static void mac_get_model(char *str);
static void mac_identify(void);
static void mac_report_hardware(void);
-static void __init mac_sched_init(irq_handler_t vector)
+static void __init mac_sched_init(void)
{
- via_init_clock(vector);
+ via_init_clock();
}
/*
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index ba444e1774b8..8ad734e3c934 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -609,7 +609,7 @@ static irqreturn_t via_timer_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
-void __init via_init_clock(irq_handler_t timer_routine)
+void __init via_init_clock(void)
{
if (request_irq(IRQ_MAC_TIMER_1, via_timer_handler, IRQF_TIMER, "timer",
NULL)) {
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index 5dabbc915b8d..4fc43b5d7545 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -37,7 +37,7 @@
static void mvme147_get_model(char *model);
-extern void mvme147_sched_init(irq_handler_t handler);
+extern void mvme147_sched_init(void);
extern int mvme147_hwclk (int, struct rtc_time *);
extern void mvme147_reset (void);
@@ -125,7 +125,7 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
}
-void mvme147_sched_init (irq_handler_t timer_routine)
+void mvme147_sched_init (void)
{
if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQF_TIMER,
"timer 1", NULL))
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index ae9bb7fda161..18e158887ec9 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -43,7 +43,7 @@ extern t_bdid mvme_bdid;
static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE;
static void mvme16x_get_model(char *model);
-extern void mvme16x_sched_init(irq_handler_t handler);
+extern void mvme16x_sched_init(void);
extern int mvme16x_hwclk (int, struct rtc_time *);
extern void mvme16x_reset (void);
@@ -384,7 +384,7 @@ static irqreturn_t mvme16x_timer_int (int irq, void *dev_id)
return IRQ_HANDLED;
}
-void mvme16x_sched_init (irq_handler_t timer_routine)
+void mvme16x_sched_init(void)
{
uint16_t brdno = be16_to_cpu(mvme_bdid.brdno);
int irq;
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 4627de3c0603..55f76f0fa29b 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -37,7 +37,7 @@
extern void q40_init_IRQ(void);
static void q40_get_model(char *model);
-extern void q40_sched_init(irq_handler_t handler);
+extern void q40_sched_init(void);
static int q40_hwclk(int, struct rtc_time *);
static unsigned int q40_get_ss(void);
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
index 4c6c409053fd..6886a5d0007b 100644
--- a/arch/m68k/q40/q40ints.c
+++ b/arch/m68k/q40/q40ints.c
@@ -149,7 +149,7 @@ static irqreturn_t q40_timer_int(int irq, void *dev_id)
return IRQ_HANDLED;
}
-void q40_sched_init (irq_handler_t timer_routine)
+void q40_sched_init (void)
{
int timer_irq;
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index 7204c0ea0dc7..f7dd47232b6c 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -36,7 +36,7 @@
char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
-static void sun3_sched_init(irq_handler_t handler);
+static void sun3_sched_init(void);
extern void sun3_get_model (char* model);
extern int sun3_hwclk(int set, struct rtc_time *t);
@@ -151,7 +151,7 @@ void __init config_sun3(void)
sun3_bootmem_alloc(memory_start, memory_end);
}
-static void __init sun3_sched_init(irq_handler_t timer_routine)
+static void __init sun3_sched_init(void)
{
sun3_disable_interrupts();
intersil_clock->cmd_reg=(INTERSIL_RUN|INTERSIL_INT_DISABLE|INTERSIL_24H_MODE);
diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c
index f6e25fdc008c..a2c97821faf2 100644
--- a/arch/m68k/sun3x/time.c
+++ b/arch/m68k/sun3x/time.c
@@ -90,7 +90,7 @@ static irqreturn_t sun3x_timer_tick(int irq, void *dev_id)
}
#endif
-void __init sun3x_sched_init(irq_handler_t vector)
+void __init sun3x_sched_init(void)
{
sun3_disable_interrupts();
diff --git a/arch/m68k/sun3x/time.h b/arch/m68k/sun3x/time.h
index 86ce78bb3c28..7cfff22e4986 100644
--- a/arch/m68k/sun3x/time.h
+++ b/arch/m68k/sun3x/time.h
@@ -3,7 +3,7 @@
#define SUN3X_TIME_H
extern int sun3x_hwclk(int set, struct rtc_time *t);
-void sun3x_sched_init(irq_handler_t vector);
+void sun3x_sched_init(void);
struct mostek_dt {
volatile unsigned char csr;
--
2.27.0
All platforms that currently do not use generic clockevents roughly call
the same set of functions in their timer interrupts: xtime_update(),
update_process_times() and profile_tick(), sometimes in a different
sequence.
Add a helper function that performs all three of them, to make the
callers more uniform and simplify the interface.
Signed-off-by: Arnd Bergmann <[email protected]>
---
include/linux/timekeeping.h | 1 +
kernel/time/Kconfig | 7 +++++++
kernel/time/Makefile | 1 +
kernel/time/tick-legacy.c | 19 +++++++++++++++++++
4 files changed, 28 insertions(+)
create mode 100644 kernel/time/tick-legacy.c
diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h
index 7f7e4a3f4394..3670cb1670ff 100644
--- a/include/linux/timekeeping.h
+++ b/include/linux/timekeeping.h
@@ -12,6 +12,7 @@ extern int timekeeping_suspended;
/* Architecture timer tick functions: */
extern void update_process_times(int user);
extern void xtime_update(unsigned long ticks);
+extern void legacy_timer_tick(unsigned long ticks);
/*
* Get and set timeofday
diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig
index a09b1d61df6a..f2b0cfeade47 100644
--- a/kernel/time/Kconfig
+++ b/kernel/time/Kconfig
@@ -61,6 +61,13 @@ config POSIX_CPU_TIMERS_TASK_WORK
bool
default y if POSIX_TIMERS && HAVE_POSIX_CPU_TIMERS_TASK_WORK
+config LEGACY_TIMER_TICK
+ bool
+ help
+ The legacy timer tick helper is used by platforms that
+ lack support for the generic clockevent framework.
+ New platforms should use generic clockevents instead.
+
if GENERIC_CLOCKEVENTS
menu "Timers subsystem"
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
index c8f00168afe8..1fb1c1ef6a19 100644
--- a/kernel/time/Makefile
+++ b/kernel/time/Makefile
@@ -16,6 +16,7 @@ ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y)
endif
obj-$(CONFIG_GENERIC_SCHED_CLOCK) += sched_clock.o
obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o tick-sched.o
+obj-$(CONFIG_LEGACY_TIMER_TICK) += tick-legacy.o
obj-$(CONFIG_HAVE_GENERIC_VDSO) += vsyscall.o
obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o
obj-$(CONFIG_TEST_UDELAY) += test_udelay.o
diff --git a/kernel/time/tick-legacy.c b/kernel/time/tick-legacy.c
new file mode 100644
index 000000000000..73c5a0af4743
--- /dev/null
+++ b/kernel/time/tick-legacy.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Timer tick function for architectures that lack generic clockevents,
+ * consolidated here from m68k/ia64/parisc/arm.
+ */
+
+#include <linux/irq.h>
+#include <linux/profile.h>
+#include <linux/timekeeper_internal.h>
+
+#include "tick-internal.h"
+
+void legacy_timer_tick(unsigned long ticks)
+{
+ if (ticks)
+ xtime_update(ticks);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
+}
--
2.27.0
Replace the indirect function calls in the timer code
with direct calls to the newly added legacy_timer_tick()
helper for those that have not yet been converted to
generic clockevents.
This makes the timer code a little more self-contained.
Signed-off-by: Arnd Bergmann <[email protected]>
---
arch/m68k/Kconfig.cpu | 35 +++++++++++++++++++++++++++++------
arch/m68k/coldfire/Makefile | 32 ++++++++++++++++++--------------
arch/m68k/coldfire/sltimers.c | 6 ++----
arch/m68k/coldfire/timers.c | 6 ++----
4 files changed, 51 insertions(+), 28 deletions(-)
diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu
index 694c4fca9f5d..322a35ef14c6 100644
--- a/arch/m68k/Kconfig.cpu
+++ b/arch/m68k/Kconfig.cpu
@@ -137,6 +137,7 @@ config M5206
bool "MCF5206"
depends on !MMU
select COLDFIRE_SW_A7
+ select COLDFIRE_TIMERS
select HAVE_MBAR
select CPU_NO_EFFICIENT_FFS
help
@@ -146,6 +147,7 @@ config M5206e
bool "MCF5206e"
depends on !MMU
select COLDFIRE_SW_A7
+ select COLDFIRE_TIMERS
select HAVE_MBAR
select CPU_NO_EFFICIENT_FFS
help
@@ -154,7 +156,7 @@ config M5206e
config M520x
bool "MCF520x"
depends on !MMU
- select GENERIC_CLOCKEVENTS
+ select COLDFIRE_PIT_TIMER
select HAVE_CACHE_SPLIT
help
Freescale Coldfire 5207/5208 processor support.
@@ -162,7 +164,7 @@ config M520x
config M523x
bool "MCF523x"
depends on !MMU
- select GENERIC_CLOCKEVENTS
+ select COLDFIRE_PIT_TIMER
select HAVE_CACHE_SPLIT
select HAVE_IPSBAR
help
@@ -172,6 +174,7 @@ config M5249
bool "MCF5249"
depends on !MMU
select COLDFIRE_SW_A7
+ select COLDFIRE_TIMERS
select HAVE_MBAR
select CPU_NO_EFFICIENT_FFS
help
@@ -181,6 +184,7 @@ config M525x
bool "MCF525x"
depends on !MMU
select COLDFIRE_SW_A7
+ select COLDFIRE_TIMERS
select HAVE_MBAR
select CPU_NO_EFFICIENT_FFS
help
@@ -189,10 +193,10 @@ config M525x
config M5271
bool "MCF5271"
depends on !MMU
+ select COLDFIRE_PIT_TIMER
select M527x
select HAVE_CACHE_SPLIT
select HAVE_IPSBAR
- select GENERIC_CLOCKEVENTS
help
Freescale (Motorola) ColdFire 5270/5271 processor support.
@@ -200,6 +204,7 @@ config M5272
bool "MCF5272"
depends on !MMU
select COLDFIRE_SW_A7
+ select COLDFIRE_TIMERS
select HAVE_MBAR
select CPU_NO_EFFICIENT_FFS
help
@@ -208,17 +213,17 @@ config M5272
config M5275
bool "MCF5275"
depends on !MMU
+ select COLDFIRE_PIT_TIMER
select M527x
select HAVE_CACHE_SPLIT
select HAVE_IPSBAR
- select GENERIC_CLOCKEVENTS
help
Freescale (Motorola) ColdFire 5274/5275 processor support.
config M528x
bool "MCF528x"
depends on !MMU
- select GENERIC_CLOCKEVENTS
+ select COLDFIRE_PIT_TIMER
select HAVE_CACHE_SPLIT
select HAVE_IPSBAR
help
@@ -227,6 +232,7 @@ config M528x
config M5307
bool "MCF5307"
depends on !MMU
+ select COLDFIRE_TIMERS
select COLDFIRE_SW_A7
select HAVE_CACHE_CB
select HAVE_MBAR
@@ -237,6 +243,7 @@ config M5307
config M532x
bool "MCF532x"
depends on !MMU
+ select COLDFIRE_TIMERS
select M53xx
select HAVE_CACHE_CB
help
@@ -245,6 +252,7 @@ config M532x
config M537x
bool "MCF537x"
depends on !MMU
+ select COLDFIRE_TIMERS
select M53xx
select HAVE_CACHE_CB
help
@@ -254,6 +262,7 @@ config M5407
bool "MCF5407"
depends on !MMU
select COLDFIRE_SW_A7
+ select COLDFIRE_TIMERS
select HAVE_CACHE_CB
select HAVE_MBAR
select CPU_NO_EFFICIENT_FFS
@@ -263,6 +272,7 @@ config M5407
config M547x
bool "MCF547x"
select M54xx
+ select COLDFIRE_SLTIMERS
select MMU_COLDFIRE if MMU
select FPU if MMU
select HAVE_CACHE_CB
@@ -273,6 +283,7 @@ config M547x
config M548x
bool "MCF548x"
+ select COLDFIRE_SLTIMERS
select MMU_COLDFIRE if MMU
select FPU if MMU
select M54xx
@@ -284,8 +295,8 @@ config M548x
config M5441x
bool "MCF5441x"
+ select COLDFIRE_PIT_TIMER
select MMU_COLDFIRE if MMU
- select GENERIC_CLOCKEVENTS
select HAVE_CACHE_CB
help
Freescale Coldfire 54410/54415/54416/54417/54418 processor support.
@@ -302,6 +313,18 @@ config M54xx
select HAVE_PCI
bool
+config COLDFIRE_PIT_TIMER
+ bool
+ select GENERIC_CLOCKEVENTS
+
+config COLDFIRE_TIMERS
+ bool
+ select LEGACY_TIMER_TICK
+
+config COLDFIRE_SLTIMERS
+ bool
+ select LEGACY_TIMER_TICK
+
endif # COLDFIRE
diff --git a/arch/m68k/coldfire/Makefile b/arch/m68k/coldfire/Makefile
index 573eabca1a3a..a3e18d73d8b8 100644
--- a/arch/m68k/coldfire/Makefile
+++ b/arch/m68k/coldfire/Makefile
@@ -16,20 +16,24 @@
asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
obj-$(CONFIG_COLDFIRE) += cache.o clk.o device.o dma.o entry.o vectors.o
-obj-$(CONFIG_M5206) += m5206.o timers.o intc.o reset.o
-obj-$(CONFIG_M5206e) += m5206.o timers.o intc.o reset.o
-obj-$(CONFIG_M520x) += m520x.o pit.o intc-simr.o reset.o
-obj-$(CONFIG_M523x) += m523x.o pit.o dma_timer.o intc-2.o reset.o
-obj-$(CONFIG_M5249) += m5249.o timers.o intc.o intc-5249.o reset.o
-obj-$(CONFIG_M525x) += m525x.o timers.o intc.o intc-525x.o reset.o
-obj-$(CONFIG_M527x) += m527x.o pit.o intc-2.o reset.o
-obj-$(CONFIG_M5272) += m5272.o intc-5272.o timers.o
-obj-$(CONFIG_M528x) += m528x.o pit.o intc-2.o reset.o
-obj-$(CONFIG_M5307) += m5307.o timers.o intc.o reset.o
-obj-$(CONFIG_M53xx) += m53xx.o timers.o intc-simr.o reset.o
-obj-$(CONFIG_M5407) += m5407.o timers.o intc.o reset.o
-obj-$(CONFIG_M54xx) += m54xx.o sltimers.o intc-2.o
-obj-$(CONFIG_M5441x) += m5441x.o pit.o intc-simr.o reset.o
+obj-$(CONFIG_M5206) += m5206.o intc.o reset.o
+obj-$(CONFIG_M5206e) += m5206.o intc.o reset.o
+obj-$(CONFIG_M520x) += m520x.o intc-simr.o reset.o
+obj-$(CONFIG_M523x) += m523x.o dma_timer.o intc-2.o reset.o
+obj-$(CONFIG_M5249) += m5249.o intc.o intc-5249.o reset.o
+obj-$(CONFIG_M525x) += m525x.o intc.o intc-525x.o reset.o
+obj-$(CONFIG_M527x) += m527x.o intc-2.o reset.o
+obj-$(CONFIG_M5272) += m5272.o intc-5272.o
+obj-$(CONFIG_M528x) += m528x.o intc-2.o reset.o
+obj-$(CONFIG_M5307) += m5307.o intc.o reset.o
+obj-$(CONFIG_M53xx) += m53xx.o intc-simr.o reset.o
+obj-$(CONFIG_M5407) += m5407.o intc.o reset.o
+obj-$(CONFIG_M54xx) += m54xx.o intc-2.o
+obj-$(CONFIG_M5441x) += m5441x.o intc-simr.o reset.o
+
+obj-$(CONFIG_COLDFIRE_PIT_TIMER) += pit.o
+obj-$(CONFIG_COLDFIRE_TIMERS) += timers.o
+obj-$(CONFIG_COLDFIRE_SLTIMERS) += sltimers.o
obj-$(CONFIG_NETtel) += nettel.o
obj-$(CONFIG_CLEOPATRA) += nettel.o
diff --git a/arch/m68k/coldfire/sltimers.c b/arch/m68k/coldfire/sltimers.c
index 5ab81c9c552d..25a1319f3cb8 100644
--- a/arch/m68k/coldfire/sltimers.c
+++ b/arch/m68k/coldfire/sltimers.c
@@ -83,14 +83,13 @@ void mcfslt_profile_init(void)
static u32 mcfslt_cycles_per_jiffy;
static u32 mcfslt_cnt;
-static irq_handler_t timer_interrupt;
-
static irqreturn_t mcfslt_tick(int irq, void *dummy)
{
/* Reset Slice Timer 0 */
__raw_writel(MCFSLT_SSR_BE | MCFSLT_SSR_TE, TA(MCFSLT_SSR));
mcfslt_cnt += mcfslt_cycles_per_jiffy;
- return timer_interrupt(irq, dummy);
+ legacy_timer_tick(1);
+ return IRQ_HANDLED;
}
static u64 mcfslt_read_clk(struct clocksource *cs)
@@ -136,7 +135,6 @@ void hw_timer_init(irq_handler_t handler)
/* initialize mcfslt_cnt knowing that slice timers count down */
mcfslt_cnt = mcfslt_cycles_per_jiffy;
- timer_interrupt = handler;
r = request_irq(MCF_IRQ_TIMER, mcfslt_tick, IRQF_TIMER, "timer", NULL);
if (r) {
pr_err("Failed to request irq %d (timer): %pe\n", MCF_IRQ_TIMER,
diff --git a/arch/m68k/coldfire/timers.c b/arch/m68k/coldfire/timers.c
index b8301fddf901..24b5e2d1b00b 100644
--- a/arch/m68k/coldfire/timers.c
+++ b/arch/m68k/coldfire/timers.c
@@ -48,8 +48,6 @@ void coldfire_profile_init(void);
static u32 mcftmr_cycles_per_jiffy;
static u32 mcftmr_cnt;
-static irq_handler_t timer_interrupt;
-
/***************************************************************************/
static void init_timer_irq(void)
@@ -77,7 +75,8 @@ static irqreturn_t mcftmr_tick(int irq, void *dummy)
__raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, TA(MCFTIMER_TER));
mcftmr_cnt += mcftmr_cycles_per_jiffy;
- return timer_interrupt(irq, dummy);
+ legacy_timer_tick(1);
+ return IRQ_HANDLED;
}
/***************************************************************************/
@@ -126,7 +125,6 @@ void hw_timer_init(irq_handler_t handler)
clocksource_register_hz(&mcftmr_clk, FREQ);
- timer_interrupt = handler;
init_timer_irq();
r = request_irq(MCF_IRQ_TIMER, mcftmr_tick, IRQF_TIMER, "timer", NULL);
if (r) {
--
2.27.0
parisc has selected CONFIG_GENERIC_CLOCKEVENTS since commit 43b1f6abd590
("parisc: Switch to generic sched_clock implementation"), but does not
appear to actually be using it, and instead calls the low-level
timekeeping functions directly.
Remove the GENERIC_CLOCKEVENTS select again, and instead convert to
the newly added legacy_timer_tick() helper.
Signed-off-by: Arnd Bergmann <[email protected]>
---
Documentation/features/time/clockevents/arch-support.txt | 2 +-
arch/parisc/Kconfig | 2 +-
arch/parisc/kernel/time.c | 9 +++------
3 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/Documentation/features/time/clockevents/arch-support.txt b/Documentation/features/time/clockevents/arch-support.txt
index 8287b6aa522e..61a5c9d68c15 100644
--- a/Documentation/features/time/clockevents/arch-support.txt
+++ b/Documentation/features/time/clockevents/arch-support.txt
@@ -21,7 +21,7 @@
| nds32: | ok |
| nios2: | ok |
| openrisc: | ok |
- | parisc: | ok |
+ | parisc: | TODO |
| powerpc: | ok |
| riscv: | ok |
| s390: | ok |
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index b234e8154cbd..78b17621ee4a 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -52,7 +52,7 @@ config PARISC
select HAVE_REGS_AND_STACK_ACCESS_API
select GENERIC_SCHED_CLOCK
select HAVE_UNSTABLE_SCHED_CLOCK if SMP
- select GENERIC_CLOCKEVENTS
+ select LEGACY_TIMER_TICK
select CPU_NO_EFFICIENT_FFS
select NEED_DMA_MAP_STATE
select NEED_SG_DMA_LENGTH
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 04508158815c..889aaaa555ea 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -70,8 +70,6 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
/* gcc can optimize for "read-only" case with a local clocktick */
unsigned long cpt = clocktick;
- profile_tick(CPU_PROFILING);
-
/* Initialize next_tick to the old expected tick time. */
next_tick = cpuinfo->it_value;
@@ -86,10 +84,9 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
cpuinfo->it_value = next_tick;
/* Go do system house keeping. */
- if (cpu == 0)
- xtime_update(ticks_elapsed);
-
- update_process_times(user_mode(get_irq_regs()));
+ if (cpu != 0)
+ ticks_elapsed = 0;
+ legacy_timer_tick(ticks_elapsed);
/* Skip clockticks on purpose if we know we would miss those.
* The new CR16 must be "later" than current CR16 otherwise
--
2.27.0
rpc is the only user of the timer_tick() function now, and can
just call the newly added generic version instead.
Signed-off-by: Arnd Bergmann <[email protected]>
---
arch/arm/Kconfig | 1 +
arch/arm/include/asm/mach/time.h | 2 --
arch/arm/kernel/time.c | 14 --------------
arch/arm/mach-rpc/time.c | 2 +-
4 files changed, 2 insertions(+), 17 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index fe2f17eb2b50..13af8d7a6c17 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -467,6 +467,7 @@ config ARCH_RPC
select HAVE_IDE
select HAVE_PATA_PLATFORM
select ISA_DMA_API
+ select LEGACY_TIMER_TICK
select NEED_MACH_IO_H
select NEED_MACH_MEMORY_H
select NO_IOPORT_MAP
diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h
index d75d39280db7..5f522916ec99 100644
--- a/arch/arm/include/asm/mach/time.h
+++ b/arch/arm/include/asm/mach/time.h
@@ -7,8 +7,6 @@
#ifndef __ASM_ARM_MACH_TIME_H
#define __ASM_ARM_MACH_TIME_H
-extern void timer_tick(void);
-
typedef void (*clock_access_fn)(struct timespec64 *);
extern int register_persistent_clock(clock_access_fn read_persistent);
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 09b149b09c43..b3836c94dc74 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -60,20 +60,6 @@ unsigned long profile_pc(struct pt_regs *regs)
EXPORT_SYMBOL(profile_pc);
#endif
-#ifndef CONFIG_GENERIC_CLOCKEVENTS
-/*
- * Kernel system timer support.
- */
-void timer_tick(void)
-{
- profile_tick(CPU_PROFILING);
- xtime_update(1);
-#ifndef CONFIG_SMP
- update_process_times(user_mode(get_irq_regs()));
-#endif
-}
-#endif
-
static void dummy_clock_access(struct timespec64 *ts)
{
ts->tv_sec = 0;
diff --git a/arch/arm/mach-rpc/time.c b/arch/arm/mach-rpc/time.c
index da85cac761ba..9f8edcfe9357 100644
--- a/arch/arm/mach-rpc/time.c
+++ b/arch/arm/mach-rpc/time.c
@@ -81,7 +81,7 @@ static irqreturn_t
ioc_timer_interrupt(int irq, void *dev_id)
{
ioc_time += RPC_LATCH;
- timer_tick();
+ legacy_timer_tick(1);
return IRQ_HANDLED;
}
--
2.27.0
These two are different from all other machines:
* sun3 does not call timer_routine() but open-codes it
except for the profile_tick() call that appears to
be unintentionally missing.
* sun3x has a commented-out timer irq handler but no
functional timer tick I could find.
Change both to calling the new legacy_timer_tick here,
which includes the call to profile_tick() but does not
fix sun3x as that is still commented out.
Signed-off-by: Arnd Bergmann <[email protected]>
---
arch/m68k/Kconfig.machine | 2 ++
arch/m68k/sun3/sun3ints.c | 3 +--
arch/m68k/sun3x/time.c | 3 +--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine
index 17e8c3a292d7..e3c835440d9a 100644
--- a/arch/m68k/Kconfig.machine
+++ b/arch/m68k/Kconfig.machine
@@ -99,6 +99,7 @@ config HP300
config SUN3X
bool "Sun3x support"
depends on MMU
+ select LEGACY_TIMER_TICK
select MMU_MOTOROLA if MMU
select M68030
help
@@ -126,6 +127,7 @@ config SUN3
depends on MMU
depends on !MMU_MOTOROLA
select MMU_SUN3 if MMU
+ select LEGACY_TIMER_TICK
select NO_DMA
select M68020
help
diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c
index a5824abb4a39..41ae422119d3 100644
--- a/arch/m68k/sun3/sun3ints.c
+++ b/arch/m68k/sun3/sun3ints.c
@@ -73,8 +73,7 @@ static irqreturn_t sun3_int5(int irq, void *dev_id)
#ifdef CONFIG_SUN3
intersil_clear();
#endif
- xtime_update(1);
- update_process_times(user_mode(get_irq_regs()));
+ legacy_timer_tick(1);
cnt = kstat_irqs_cpu(irq, 0);
if (!(cnt % 20))
sun3_leds(led_pattern[cnt % 160 / 20]);
diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c
index 9163294b0fb6..f6e25fdc008c 100644
--- a/arch/m68k/sun3x/time.c
+++ b/arch/m68k/sun3x/time.c
@@ -77,14 +77,13 @@ int sun3x_hwclk(int set, struct rtc_time *t)
#if 0
static irqreturn_t sun3x_timer_tick(int irq, void *dev_id)
{
- irq_handler_t timer_routine = dev_id;
unsigned long flags;
local_irq_save(flags);
/* Clear the pending interrupt - pulse the enable line low */
disable_irq(5);
enable_irq(5);
- timer_routine(0, NULL);
+ legacy_timer_tick(1);
local_irq_restore(flags);
return IRQ_HANDLED;
--
2.27.0
The heartbeat functionality is mostly separate from the
actual timer interrupt handling, and it is only used on
five platforms.
Split it out into a separate function and call that directly
from the timer irq on those platforms.
Signed-off-by: Arnd Bergmann <[email protected]>
---
arch/m68k/amiga/config.c | 1 +
arch/m68k/apollo/config.c | 1 +
arch/m68k/atari/time.c | 2 ++
arch/m68k/hp300/time.c | 1 +
arch/m68k/include/asm/machdep.h | 7 +++++++
arch/m68k/kernel/time.c | 7 +++++--
arch/m68k/q40/q40ints.c | 2 ++
7 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index bee9f240f35d..29f92333119e 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -480,6 +480,7 @@ static irqreturn_t ciab_timer_handler(int irq, void *dev_id)
clk_total += jiffy_ticks;
clk_offset = 0;
timer_routine(0, NULL);
+ timer_heartbeat();
return IRQ_HANDLED;
}
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
index 762da5d7a415..30915f1a8760 100644
--- a/arch/m68k/apollo/config.c
+++ b/arch/m68k/apollo/config.c
@@ -173,6 +173,7 @@ irqreturn_t dn_timer_int(int irq, void *dev_id)
volatile unsigned char x;
timer_handler(irq, dev_id);
+ timer_heartbeat();
x = *(volatile unsigned char *)(apollo_timer + 3);
x = *(volatile unsigned char *)(apollo_timer + 5);
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index ce923a523695..ce4a5961ca93 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -21,6 +21,7 @@
#include <linux/export.h>
#include <asm/atariints.h>
+#include <asm/machdep.h>
DEFINE_SPINLOCK(rtc_lock);
EXPORT_SYMBOL_GPL(rtc_lock);
@@ -49,6 +50,7 @@ static irqreturn_t mfp_timer_c_handler(int irq, void *dev_id)
} while (last_timer_count == 1);
clk_total += INT_TICKS;
timer_routine(0, NULL);
+ timer_heartbeat();
local_irq_restore(flags);
return IRQ_HANDLED;
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
index bfee13e1d0fe..e3cd938de0f9 100644
--- a/arch/m68k/hp300/time.c
+++ b/arch/m68k/hp300/time.c
@@ -65,6 +65,7 @@ static irqreturn_t hp300_tick(int irq, void *dev_id)
clk_total += INTVAL;
clk_offset = 0;
timer_routine(0, NULL);
+ timer_heartbeat();
local_irq_restore(flags);
/* Turn off the network and SCSI leds */
diff --git a/arch/m68k/include/asm/machdep.h b/arch/m68k/include/asm/machdep.h
index 49bd3266b4b1..e62a39d01ae4 100644
--- a/arch/m68k/include/asm/machdep.h
+++ b/arch/m68k/include/asm/machdep.h
@@ -35,6 +35,13 @@ extern void (*mach_beep) (unsigned int, unsigned int);
/* Hardware clock functions */
extern void hw_timer_init(irq_handler_t handler);
extern unsigned long hw_timer_offset(void);
+#ifdef CONFIG_HEARTBEAT
+extern void timer_heartbeat(void);
+#else
+static inline void timer_heartbeat(void)
+{
+}
+#endif
extern void config_BSP(char *command, int len);
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index c2697a4d4ddd..c05cec21b05f 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -45,8 +45,12 @@ static irqreturn_t timer_interrupt(int irq, void *dummy)
xtime_update(1);
update_process_times(user_mode(get_irq_regs()));
profile_tick(CPU_PROFILING);
+ return IRQ_HANDLED;
+}
#ifdef CONFIG_HEARTBEAT
+void timer_heartbeat(void)
+{
/* use power LED as a heartbeat instead -- much more useful
for debugging -- based on the version for PReP by Cort */
/* acts like an actual heart beat -- ie thump-thump-pause... */
@@ -68,9 +72,8 @@ static irqreturn_t timer_interrupt(int irq, void *dummy)
dist = period / 4;
}
}
-#endif /* CONFIG_HEARTBEAT */
- return IRQ_HANDLED;
}
+#endif /* CONFIG_HEARTBEAT */
#ifdef CONFIG_M68KCLASSIC
#if !IS_BUILTIN(CONFIG_RTC_DRV_GENERIC)
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
index 1c696906c159..b01b545a2db0 100644
--- a/arch/m68k/q40/q40ints.c
+++ b/arch/m68k/q40/q40ints.c
@@ -17,6 +17,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <asm/machdep.h>
#include <asm/ptrace.h>
#include <asm/traps.h>
@@ -144,6 +145,7 @@ static irqreturn_t q40_timer_int(int irq, void *dev_id)
local_irq_save(flags);
timer_routine(0, NULL);
+ timer_heartbeat();
local_irq_restore(flags);
}
return IRQ_HANDLED;
--
2.27.0
There are no more users of xtime_update aside from legacy_timer_tick(),
so fold it into that function and remove the declaration.
update_process_times() is now only called inside of the kernel/time/
code, so the declaration can be moved there.
Signed-off-by: Arnd Bergmann <[email protected]>
---
include/linux/timekeeping.h | 4 +---
kernel/time/tick-legacy.c | 22 ++++++++++++++++++++--
kernel/time/timekeeping.c | 16 ----------------
kernel/time/timekeeping.h | 1 +
4 files changed, 22 insertions(+), 21 deletions(-)
diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h
index 3670cb1670ff..a8bef0ffcbdd 100644
--- a/include/linux/timekeeping.h
+++ b/include/linux/timekeeping.h
@@ -9,9 +9,7 @@
void timekeeping_init(void);
extern int timekeeping_suspended;
-/* Architecture timer tick functions: */
-extern void update_process_times(int user);
-extern void xtime_update(unsigned long ticks);
+/* Architecture timer tick functions */
extern void legacy_timer_tick(unsigned long ticks);
/*
diff --git a/kernel/time/tick-legacy.c b/kernel/time/tick-legacy.c
index 73c5a0af4743..af225b32f5b3 100644
--- a/kernel/time/tick-legacy.c
+++ b/kernel/time/tick-legacy.c
@@ -10,10 +10,28 @@
#include "tick-internal.h"
+/**
+ * legacy_timer_tick() - advances the timekeeping infrastructure
+ * @ticks: number of ticks, that have elapsed since the last call.
+ *
+ * This is used by platforms that have not been converted to
+ * generic clockevents.
+ *
+ * If 'ticks' is zero, the CPU is not handling timekeeping, so
+ * only perform process accounting and profiling.
+ *
+ * Must be called with interrupts disabled.
+ */
void legacy_timer_tick(unsigned long ticks)
{
- if (ticks)
- xtime_update(ticks);
+ if (ticks) {
+ raw_spin_lock(&jiffies_lock);
+ write_seqcount_begin(&jiffies_seq);
+ do_timer(ticks);
+ write_seqcount_end(&jiffies_seq);
+ raw_spin_unlock(&jiffies_lock);
+ update_wall_time();
+ }
update_process_times(user_mode(get_irq_regs()));
profile_tick(CPU_PROFILING);
}
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 6858a31364b6..2c7814411f83 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2461,19 +2461,3 @@ void hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts)
}
EXPORT_SYMBOL(hardpps);
#endif /* CONFIG_NTP_PPS */
-
-/**
- * xtime_update() - advances the timekeeping infrastructure
- * @ticks: number of ticks, that have elapsed since the last call.
- *
- * Must be called with interrupts disabled.
- */
-void xtime_update(unsigned long ticks)
-{
- raw_spin_lock(&jiffies_lock);
- write_seqcount_begin(&jiffies_seq);
- do_timer(ticks);
- write_seqcount_end(&jiffies_seq);
- raw_spin_unlock(&jiffies_lock);
- update_wall_time();
-}
diff --git a/kernel/time/timekeeping.h b/kernel/time/timekeeping.h
index 099737f6f10c..d94b69c5b869 100644
--- a/kernel/time/timekeeping.h
+++ b/kernel/time/timekeeping.h
@@ -22,6 +22,7 @@ static inline int sched_clock_suspend(void) { return 0; }
static inline void sched_clock_resume(void) { }
#endif
+extern void update_process_times(int user);
extern void do_timer(unsigned long ticks);
extern void update_wall_time(void);
--
2.27.0
On Fri, Oct 9, 2020 at 2:53 PM Greg Ungerer <[email protected]> wrote:
>
> Hi Arnd,
>
> On 9/10/20 1:46 am, Arnd Bergmann wrote:
> > Replace the indirect function calls in the timer code
> > with direct calls to the newly added legacy_timer_tick()
> > helper for those that have not yet been converted to
> > generic clockevents.
> >
> > This makes the timer code a little more self-contained.
> >
> > Signed-off-by: Arnd Bergmann <[email protected]>
>
> I tested this series on a couple of different ColdFire parts
> (5208 and 5475) and under QEMU emulating the 5208. All checked
> out good, all worked as expected. So for the ColdFire changes:
>
> Tested-by: Greg Ungerer <[email protected]>
Awesome, thanks for testing!
Arnd
Hi Arnd,
On 9/10/20 1:46 am, Arnd Bergmann wrote:
> Replace the indirect function calls in the timer code
> with direct calls to the newly added legacy_timer_tick()
> helper for those that have not yet been converted to
> generic clockevents.
>
> This makes the timer code a little more self-contained.
>
> Signed-off-by: Arnd Bergmann <[email protected]>
I tested this series on a couple of different ColdFire parts
(5208 and 5475) and under QEMU emulating the 5208. All checked
out good, all worked as expected. So for the ColdFire changes:
Tested-by: Greg Ungerer <[email protected]>
Regards
Greg
> ---
> arch/m68k/Kconfig.cpu | 35 +++++++++++++++++++++++++++++------
> arch/m68k/coldfire/Makefile | 32 ++++++++++++++++++--------------
> arch/m68k/coldfire/sltimers.c | 6 ++----
> arch/m68k/coldfire/timers.c | 6 ++----
> 4 files changed, 51 insertions(+), 28 deletions(-)
>
> diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu
> index 694c4fca9f5d..322a35ef14c6 100644
> --- a/arch/m68k/Kconfig.cpu
> +++ b/arch/m68k/Kconfig.cpu
> @@ -137,6 +137,7 @@ config M5206
> bool "MCF5206"
> depends on !MMU
> select COLDFIRE_SW_A7
> + select COLDFIRE_TIMERS
> select HAVE_MBAR
> select CPU_NO_EFFICIENT_FFS
> help
> @@ -146,6 +147,7 @@ config M5206e
> bool "MCF5206e"
> depends on !MMU
> select COLDFIRE_SW_A7
> + select COLDFIRE_TIMERS
> select HAVE_MBAR
> select CPU_NO_EFFICIENT_FFS
> help
> @@ -154,7 +156,7 @@ config M5206e
> config M520x
> bool "MCF520x"
> depends on !MMU
> - select GENERIC_CLOCKEVENTS
> + select COLDFIRE_PIT_TIMER
> select HAVE_CACHE_SPLIT
> help
> Freescale Coldfire 5207/5208 processor support.
> @@ -162,7 +164,7 @@ config M520x
> config M523x
> bool "MCF523x"
> depends on !MMU
> - select GENERIC_CLOCKEVENTS
> + select COLDFIRE_PIT_TIMER
> select HAVE_CACHE_SPLIT
> select HAVE_IPSBAR
> help
> @@ -172,6 +174,7 @@ config M5249
> bool "MCF5249"
> depends on !MMU
> select COLDFIRE_SW_A7
> + select COLDFIRE_TIMERS
> select HAVE_MBAR
> select CPU_NO_EFFICIENT_FFS
> help
> @@ -181,6 +184,7 @@ config M525x
> bool "MCF525x"
> depends on !MMU
> select COLDFIRE_SW_A7
> + select COLDFIRE_TIMERS
> select HAVE_MBAR
> select CPU_NO_EFFICIENT_FFS
> help
> @@ -189,10 +193,10 @@ config M525x
> config M5271
> bool "MCF5271"
> depends on !MMU
> + select COLDFIRE_PIT_TIMER
> select M527x
> select HAVE_CACHE_SPLIT
> select HAVE_IPSBAR
> - select GENERIC_CLOCKEVENTS
> help
> Freescale (Motorola) ColdFire 5270/5271 processor support.
>
> @@ -200,6 +204,7 @@ config M5272
> bool "MCF5272"
> depends on !MMU
> select COLDFIRE_SW_A7
> + select COLDFIRE_TIMERS
> select HAVE_MBAR
> select CPU_NO_EFFICIENT_FFS
> help
> @@ -208,17 +213,17 @@ config M5272
> config M5275
> bool "MCF5275"
> depends on !MMU
> + select COLDFIRE_PIT_TIMER
> select M527x
> select HAVE_CACHE_SPLIT
> select HAVE_IPSBAR
> - select GENERIC_CLOCKEVENTS
> help
> Freescale (Motorola) ColdFire 5274/5275 processor support.
>
> config M528x
> bool "MCF528x"
> depends on !MMU
> - select GENERIC_CLOCKEVENTS
> + select COLDFIRE_PIT_TIMER
> select HAVE_CACHE_SPLIT
> select HAVE_IPSBAR
> help
> @@ -227,6 +232,7 @@ config M528x
> config M5307
> bool "MCF5307"
> depends on !MMU
> + select COLDFIRE_TIMERS
> select COLDFIRE_SW_A7
> select HAVE_CACHE_CB
> select HAVE_MBAR
> @@ -237,6 +243,7 @@ config M5307
> config M532x
> bool "MCF532x"
> depends on !MMU
> + select COLDFIRE_TIMERS
> select M53xx
> select HAVE_CACHE_CB
> help
> @@ -245,6 +252,7 @@ config M532x
> config M537x
> bool "MCF537x"
> depends on !MMU
> + select COLDFIRE_TIMERS
> select M53xx
> select HAVE_CACHE_CB
> help
> @@ -254,6 +262,7 @@ config M5407
> bool "MCF5407"
> depends on !MMU
> select COLDFIRE_SW_A7
> + select COLDFIRE_TIMERS
> select HAVE_CACHE_CB
> select HAVE_MBAR
> select CPU_NO_EFFICIENT_FFS
> @@ -263,6 +272,7 @@ config M5407
> config M547x
> bool "MCF547x"
> select M54xx
> + select COLDFIRE_SLTIMERS
> select MMU_COLDFIRE if MMU
> select FPU if MMU
> select HAVE_CACHE_CB
> @@ -273,6 +283,7 @@ config M547x
>
> config M548x
> bool "MCF548x"
> + select COLDFIRE_SLTIMERS
> select MMU_COLDFIRE if MMU
> select FPU if MMU
> select M54xx
> @@ -284,8 +295,8 @@ config M548x
>
> config M5441x
> bool "MCF5441x"
> + select COLDFIRE_PIT_TIMER
> select MMU_COLDFIRE if MMU
> - select GENERIC_CLOCKEVENTS
> select HAVE_CACHE_CB
> help
> Freescale Coldfire 54410/54415/54416/54417/54418 processor support.
> @@ -302,6 +313,18 @@ config M54xx
> select HAVE_PCI
> bool
>
> +config COLDFIRE_PIT_TIMER
> + bool
> + select GENERIC_CLOCKEVENTS
> +
> +config COLDFIRE_TIMERS
> + bool
> + select LEGACY_TIMER_TICK
> +
> +config COLDFIRE_SLTIMERS
> + bool
> + select LEGACY_TIMER_TICK
> +
> endif # COLDFIRE
>
>
> diff --git a/arch/m68k/coldfire/Makefile b/arch/m68k/coldfire/Makefile
> index 573eabca1a3a..a3e18d73d8b8 100644
> --- a/arch/m68k/coldfire/Makefile
> +++ b/arch/m68k/coldfire/Makefile
> @@ -16,20 +16,24 @@
> asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
>
> obj-$(CONFIG_COLDFIRE) += cache.o clk.o device.o dma.o entry.o vectors.o
> -obj-$(CONFIG_M5206) += m5206.o timers.o intc.o reset.o
> -obj-$(CONFIG_M5206e) += m5206.o timers.o intc.o reset.o
> -obj-$(CONFIG_M520x) += m520x.o pit.o intc-simr.o reset.o
> -obj-$(CONFIG_M523x) += m523x.o pit.o dma_timer.o intc-2.o reset.o
> -obj-$(CONFIG_M5249) += m5249.o timers.o intc.o intc-5249.o reset.o
> -obj-$(CONFIG_M525x) += m525x.o timers.o intc.o intc-525x.o reset.o
> -obj-$(CONFIG_M527x) += m527x.o pit.o intc-2.o reset.o
> -obj-$(CONFIG_M5272) += m5272.o intc-5272.o timers.o
> -obj-$(CONFIG_M528x) += m528x.o pit.o intc-2.o reset.o
> -obj-$(CONFIG_M5307) += m5307.o timers.o intc.o reset.o
> -obj-$(CONFIG_M53xx) += m53xx.o timers.o intc-simr.o reset.o
> -obj-$(CONFIG_M5407) += m5407.o timers.o intc.o reset.o
> -obj-$(CONFIG_M54xx) += m54xx.o sltimers.o intc-2.o
> -obj-$(CONFIG_M5441x) += m5441x.o pit.o intc-simr.o reset.o
> +obj-$(CONFIG_M5206) += m5206.o intc.o reset.o
> +obj-$(CONFIG_M5206e) += m5206.o intc.o reset.o
> +obj-$(CONFIG_M520x) += m520x.o intc-simr.o reset.o
> +obj-$(CONFIG_M523x) += m523x.o dma_timer.o intc-2.o reset.o
> +obj-$(CONFIG_M5249) += m5249.o intc.o intc-5249.o reset.o
> +obj-$(CONFIG_M525x) += m525x.o intc.o intc-525x.o reset.o
> +obj-$(CONFIG_M527x) += m527x.o intc-2.o reset.o
> +obj-$(CONFIG_M5272) += m5272.o intc-5272.o
> +obj-$(CONFIG_M528x) += m528x.o intc-2.o reset.o
> +obj-$(CONFIG_M5307) += m5307.o intc.o reset.o
> +obj-$(CONFIG_M53xx) += m53xx.o intc-simr.o reset.o
> +obj-$(CONFIG_M5407) += m5407.o intc.o reset.o
> +obj-$(CONFIG_M54xx) += m54xx.o intc-2.o
> +obj-$(CONFIG_M5441x) += m5441x.o intc-simr.o reset.o
> +
> +obj-$(CONFIG_COLDFIRE_PIT_TIMER) += pit.o
> +obj-$(CONFIG_COLDFIRE_TIMERS) += timers.o
> +obj-$(CONFIG_COLDFIRE_SLTIMERS) += sltimers.o
>
> obj-$(CONFIG_NETtel) += nettel.o
> obj-$(CONFIG_CLEOPATRA) += nettel.o
> diff --git a/arch/m68k/coldfire/sltimers.c b/arch/m68k/coldfire/sltimers.c
> index 5ab81c9c552d..25a1319f3cb8 100644
> --- a/arch/m68k/coldfire/sltimers.c
> +++ b/arch/m68k/coldfire/sltimers.c
> @@ -83,14 +83,13 @@ void mcfslt_profile_init(void)
> static u32 mcfslt_cycles_per_jiffy;
> static u32 mcfslt_cnt;
>
> -static irq_handler_t timer_interrupt;
> -
> static irqreturn_t mcfslt_tick(int irq, void *dummy)
> {
> /* Reset Slice Timer 0 */
> __raw_writel(MCFSLT_SSR_BE | MCFSLT_SSR_TE, TA(MCFSLT_SSR));
> mcfslt_cnt += mcfslt_cycles_per_jiffy;
> - return timer_interrupt(irq, dummy);
> + legacy_timer_tick(1);
> + return IRQ_HANDLED;
> }
>
> static u64 mcfslt_read_clk(struct clocksource *cs)
> @@ -136,7 +135,6 @@ void hw_timer_init(irq_handler_t handler)
> /* initialize mcfslt_cnt knowing that slice timers count down */
> mcfslt_cnt = mcfslt_cycles_per_jiffy;
>
> - timer_interrupt = handler;
> r = request_irq(MCF_IRQ_TIMER, mcfslt_tick, IRQF_TIMER, "timer", NULL);
> if (r) {
> pr_err("Failed to request irq %d (timer): %pe\n", MCF_IRQ_TIMER,
> diff --git a/arch/m68k/coldfire/timers.c b/arch/m68k/coldfire/timers.c
> index b8301fddf901..24b5e2d1b00b 100644
> --- a/arch/m68k/coldfire/timers.c
> +++ b/arch/m68k/coldfire/timers.c
> @@ -48,8 +48,6 @@ void coldfire_profile_init(void);
> static u32 mcftmr_cycles_per_jiffy;
> static u32 mcftmr_cnt;
>
> -static irq_handler_t timer_interrupt;
> -
> /***************************************************************************/
>
> static void init_timer_irq(void)
> @@ -77,7 +75,8 @@ static irqreturn_t mcftmr_tick(int irq, void *dummy)
> __raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, TA(MCFTIMER_TER));
>
> mcftmr_cnt += mcftmr_cycles_per_jiffy;
> - return timer_interrupt(irq, dummy);
> + legacy_timer_tick(1);
> + return IRQ_HANDLED;
> }
>
> /***************************************************************************/
> @@ -126,7 +125,6 @@ void hw_timer_init(irq_handler_t handler)
>
> clocksource_register_hz(&mcftmr_clk, FREQ);
>
> - timer_interrupt = handler;
> init_timer_irq();
> r = request_irq(MCF_IRQ_TIMER, mcftmr_tick, IRQF_TIMER, "timer", NULL);
> if (r) {
>
Hi Arnd,
On Thu, 8 Oct 2020, Arnd Bergmann wrote:
> All platforms that currently do not use generic clockevents roughly call
> the same set of functions in their timer interrupts: xtime_update(),
> update_process_times() and profile_tick(), sometimes in a different
> sequence.
>
> Add a helper function that performs all three of them, to make the
> callers more uniform and simplify the interface.
>
> Signed-off-by: Arnd Bergmann <[email protected]>
> ---
> include/linux/timekeeping.h | 1 +
> kernel/time/Kconfig | 7 +++++++
> kernel/time/Makefile | 1 +
> kernel/time/tick-legacy.c | 19 +++++++++++++++++++
> 4 files changed, 28 insertions(+)
> create mode 100644 kernel/time/tick-legacy.c
>
> diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h
> index 7f7e4a3f4394..3670cb1670ff 100644
> --- a/include/linux/timekeeping.h
> +++ b/include/linux/timekeeping.h
> @@ -12,6 +12,7 @@ extern int timekeeping_suspended;
> /* Architecture timer tick functions: */
> extern void update_process_times(int user);
> extern void xtime_update(unsigned long ticks);
> +extern void legacy_timer_tick(unsigned long ticks);
>
> /*
> * Get and set timeofday
> diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig
> index a09b1d61df6a..f2b0cfeade47 100644
> --- a/kernel/time/Kconfig
> +++ b/kernel/time/Kconfig
> @@ -61,6 +61,13 @@ config POSIX_CPU_TIMERS_TASK_WORK
> bool
> default y if POSIX_TIMERS && HAVE_POSIX_CPU_TIMERS_TASK_WORK
>
> +config LEGACY_TIMER_TICK
> + bool
> + help
> + The legacy timer tick helper is used by platforms that
> + lack support for the generic clockevent framework.
> + New platforms should use generic clockevents instead.
> +
> if GENERIC_CLOCKEVENTS
> menu "Timers subsystem"
>
> diff --git a/kernel/time/Makefile b/kernel/time/Makefile
> index c8f00168afe8..1fb1c1ef6a19 100644
> --- a/kernel/time/Makefile
> +++ b/kernel/time/Makefile
> @@ -16,6 +16,7 @@ ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y)
> endif
> obj-$(CONFIG_GENERIC_SCHED_CLOCK) += sched_clock.o
> obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o tick-sched.o
> +obj-$(CONFIG_LEGACY_TIMER_TICK) += tick-legacy.o
> obj-$(CONFIG_HAVE_GENERIC_VDSO) += vsyscall.o
> obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o
> obj-$(CONFIG_TEST_UDELAY) += test_udelay.o
> diff --git a/kernel/time/tick-legacy.c b/kernel/time/tick-legacy.c
> new file mode 100644
> index 000000000000..73c5a0af4743
> --- /dev/null
> +++ b/kernel/time/tick-legacy.c
> @@ -0,0 +1,19 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Timer tick function for architectures that lack generic clockevents,
> + * consolidated here from m68k/ia64/parisc/arm.
> + */
> +
> +#include <linux/irq.h>
> +#include <linux/profile.h>
> +#include <linux/timekeeper_internal.h>
> +
> +#include "tick-internal.h"
> +
> +void legacy_timer_tick(unsigned long ticks)
> +{
> + if (ticks)
> + xtime_update(ticks);
> + update_process_times(user_mode(get_irq_regs()));
> + profile_tick(CPU_PROFILING);
> +}
>
It's good to see this code refactored in this way because, as well as
de-duplication, it reveals the logic that's common to the relevant
platforms and may shed some light on the need for that logic.
Yet it's not clear to me that the clockevents framework is able to replace
that logic on all of the affected hardware. I suppose it remains to be
seen.
I hate to quibble about naming, but you seem to be using "legacy" here to
mean "deprecated" (?) Is it a good idea to prepend such adjectives to
symbol names?
IMO, the term "legacy" is redundant in this context. That term covers a
large portion of kernel code, a large number of hardware features in
current silicon, a large portion of the userspace ABI, a large number of
production Linux systems, probably all "Unix" systems, etc.
As a corollary, cutting edge ("non-legacy") code is often kept out of open
source projects by the owners of the intellectual property rights.
On Sat, Oct 10, 2020 at 12:18 AM Finn Thain <[email protected]> wrote:
> On Thu, 8 Oct 2020, Arnd Bergmann wrote:
>
> It's good to see this code refactored in this way because, as well as
> de-duplication, it reveals the logic that's common to the relevant
> platforms and may shed some light on the need for that logic.
>
> Yet it's not clear to me that the clockevents framework is able to replace
> that logic on all of the affected hardware. I suppose it remains to be
> seen.
I suspect that the change I did for one platform in patch 13/13 could be
duplicated for all 16 platforms, adding lots of trivial clockevent drivers that
only support periodic ticks, but any platform that can instead support
oneshot timers should probably do that, or it won't provide any better
behavior.
What do others think we should do here?
> As a corollary, cutting edge ("non-legacy") code is often kept out of open
> source projects by the owners of the intellectual property rights.
I'm happy to change the name in any way if you have a suggestion
that the clock event maintainers (Daniel and Thomas) like.
Arnd
On Thu, Oct 8, 2020 at 5:47 PM Arnd Bergmann <[email protected]> wrote:
> All platforms that currently do not use generic clockevents roughly call
> the same set of functions in their timer interrupts: xtime_update(),
> update_process_times() and profile_tick(), sometimes in a different
> sequence.
>
> Add a helper function that performs all three of them, to make the
> callers more uniform and simplify the interface.
>
> Signed-off-by: Arnd Bergmann <[email protected]>
Reviewed-by: Geert Uytterhoeven <[email protected]>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
On Thu, Oct 8, 2020 at 5:48 PM Arnd Bergmann <[email protected]> wrote:
> The heartbeat functionality is mostly separate from the
> actual timer interrupt handling, and it is only used on
> five platforms.
>
> Split it out into a separate function and call that directly
> from the timer irq on those platforms.
>
> Signed-off-by: Arnd Bergmann <[email protected]>
Reviewed-by: Geert Uytterhoeven <[email protected]>
Acked-by: Geert Uytterhoeven <[email protected]>
And finally (for Amiga):
Tested-by: Geert Uytterhoeven <[email protected]>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Hi Arnd,
On Thu, Oct 8, 2020 at 5:48 PM Arnd Bergmann <[email protected]> wrote:
> This gets passed to a number of init functions, but is
> ignored everywhere, so remove the function and change the
> mach_sched_init callback to take no arguments.
>
> Signed-off-by: Arnd Bergmann <[email protected]>
Reviewed-by: Geert Uytterhoeven <[email protected]>
Acked-by: Geert Uytterhoeven <[email protected]>
And finally (for Amiga and Atari/ARAnyM):
Tested-by: Geert Uytterhoeven <[email protected]>
> --- a/arch/m68k/include/asm/machdep.h
> +++ b/arch/m68k/include/asm/machdep.h
> @@ -33,8 +33,7 @@ extern void (*mach_l2_flush) (int);
> extern void (*mach_beep) (unsigned int, unsigned int);
>
> /* Hardware clock functions */
> -extern void hw_timer_init(irq_handler_t handler);
> -extern unsigned long hw_timer_offset(void);
Yeah, this never-used prototype, which entered through the nommu merge,
can go. But that's not really related to this patch.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Hi Arnd,
On Thu, Oct 8, 2020 at 5:48 PM Arnd Bergmann <[email protected]> wrote:
> A couple of machines share the m68328 timer code that
> is based on calling timer_interrupt(). Change these
> to the new and slightly more generic legacy_timer_tick()
> helper.
>
> Signed-off-by: Arnd Bergmann <[email protected]>
Thanks for your patch!
> --- a/arch/m68k/Kconfig.machine
> +++ b/arch/m68k/Kconfig.machine
> @@ -146,6 +146,7 @@ config PILOT
> config PILOT3
> bool "Pilot 1000/5000, PalmPilot Personal/Pro, or PalmIII support"
> depends on M68328
> + select LEGACY_TIMER_TICK
> select PILOT
> help
> Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII.
> @@ -159,18 +160,21 @@ config XCOPILOT_BUGS
> config UCSIMM
> bool "uCsimm module support"
> depends on M68EZ328
> + select LEGACY_TIMER_TICK
> help
> Support for the Arcturus Networks uCsimm module.
>
> config UCDIMM
> bool "uDsimm module support"
> depends on M68VZ328
> + select LEGACY_TIMER_TICK
> help
> Support for the Arcturus Networks uDsimm module.
>
> config DRAGEN2
> bool "DragenEngine II board support"
> depends on M68VZ328
> + select LEGACY_TIMER_TICK
> help
> Support for the DragenEngine II board.
Given this feature is SoC-specific, not platform-specific, perhaps
it makes sense to move the selects to the M68{,EZ,VZ}328 symbols?
Regardless:
Reviewed-by: Geert Uytterhoeven <[email protected]>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
On Thu, Oct 8, 2020 at 5:48 PM Arnd Bergmann <[email protected]> wrote:
> These two are different from all other machines:
>
> * sun3 does not call timer_routine() but open-codes it
> except for the profile_tick() call that appears to
> be unintentionally missing.
>
> * sun3x has a commented-out timer irq handler but no
> functional timer tick I could find.
>
> Change both to calling the new legacy_timer_tick here,
> which includes the call to profile_tick() but does not
> fix sun3x as that is still commented out.
>
> Signed-off-by: Arnd Bergmann <[email protected]>
Reviewed-by: Geert Uytterhoeven <[email protected]>
Acked-by: Geert Uytterhoeven <[email protected]>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
On Mon, Oct 12, 2020 at 3:16 PM Geert Uytterhoeven <[email protected]> wrote:
> On Thu, Oct 8, 2020 at 5:48 PM Arnd Bergmann <[email protected]> wrote:
> > There are no more users of xtime_update aside from legacy_timer_tick(),
> > so fold it into that function and remove the declaration.
> >
> > update_process_times() is now only called inside of the kernel/time/
> > code, so the declaration can be moved there.
> >
> > Signed-off-by: Arnd Bergmann <[email protected]>
>
> Thanks for your patch!
>
> Reviewed-by: Geert Uytterhoeven <[email protected]>
>
> The comment about xtime_update() in arch/ia64/kernel/time.c needs
> an update.
I think the correct action for ia64 would be to make it a
proper clockevent driver with oneshot support, and remove
the rest of this logic.
I could try to rewrite the comment, but I tried not to touch that
part since I don't understand the logic behind it. Maybe the
ia64 maintainers can comment here why it even tries to skip
a timer tick. Is there a danger of ending up with the timer irq
permanently disabled if the timer_interrupt() function returns
with the itm register in the past, or is this simply about not having
too many interrupts in a row?
> Does the comment about update_process_times() in
> arch/openrisc/kernel/time.c needs an update, too?
I think that one is still technically correct.
Arnd
Hi Arnd,
On Thu, Oct 8, 2020 at 5:48 PM Arnd Bergmann <[email protected]> wrote:
> There are no more users of xtime_update aside from legacy_timer_tick(),
> so fold it into that function and remove the declaration.
>
> update_process_times() is now only called inside of the kernel/time/
> code, so the declaration can be moved there.
>
> Signed-off-by: Arnd Bergmann <[email protected]>
Thanks for your patch!
Reviewed-by: Geert Uytterhoeven <[email protected]>
The comment about xtime_update() in arch/ia64/kernel/time.c needs
an update.
Does the comment about update_process_times() in
arch/openrisc/kernel/time.c needs an update, too?
For Amiga and Atari/ARAnyM:
Tested-by: Geert Uytterhoeven <[email protected]>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
On Mon, Oct 12, 2020 at 3:15 PM Geert Uytterhoeven <[email protected]> wrote:
>
> Given this feature is SoC-specific, not platform-specific, perhaps
> it makes sense to move the selects to the M68{,EZ,VZ}328 symbols?
>
> Regardless:
> Reviewed-by: Geert Uytterhoeven <[email protected]>
Ok, folded in the change blow, using one less line. I couldn't figure
out whether
it should just be part of the CONFIG_M68000 instead, which doesn't appear
to have any machine support by itself. The dragonball CPU configuration
looks really odd, because you have to build exactly one of M68{,EZ,VZ}328
into the kernel to get a successful compilation, while Kconfig allows
many other combinations.
Arnd
diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu
index 322a35ef14c6..648054d4f860 100644
--- a/arch/m68k/Kconfig.cpu
+++ b/arch/m68k/Kconfig.cpu
@@ -104,6 +104,7 @@ config M68060
config M68328
bool "MC68328"
depends on !MMU
+ select LEGACY_TIMER_TICK
select M68000
help
Motorola 68328 processor support.
@@ -111,6 +112,7 @@ config M68328
config M68EZ328
bool "MC68EZ328"
depends on !MMU
+ select LEGACY_TIMER_TICK
select M68000
help
Motorola 68EX328 processor support.
@@ -118,6 +120,7 @@ config M68EZ328
config M68VZ328
bool "MC68VZ328"
depends on !MMU
+ select LEGACY_TIMER_TICK
select M68000
help
Motorola 68VZ328 processor support.
diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine
index 0ff9338b958e..e3c835440d9a 100644
--- a/arch/m68k/Kconfig.machine
+++ b/arch/m68k/Kconfig.machine
@@ -146,7 +146,6 @@ config PILOT
config PILOT3
bool "Pilot 1000/5000, PalmPilot Personal/Pro, or PalmIII support"
depends on M68328
- select LEGACY_TIMER_TICK
select PILOT
help
Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII.
@@ -160,21 +159,18 @@ config XCOPILOT_BUGS
config UCSIMM
bool "uCsimm module support"
depends on M68EZ328
- select LEGACY_TIMER_TICK
help
Support for the Arcturus Networks uCsimm module.
config UCDIMM
bool "uDsimm module support"
depends on M68VZ328
- select LEGACY_TIMER_TICK
help
Support for the Arcturus Networks uDsimm module.
config DRAGEN2
bool "DragenEngine II board support"
depends on M68VZ328
- select LEGACY_TIMER_TICK
help
Support for the DragenEngine II board.
Hi Arnd,
On Mon, Oct 12, 2020 at 5:31 PM Arnd Bergmann <[email protected]> wrote:
> On Mon, Oct 12, 2020 at 3:15 PM Geert Uytterhoeven <[email protected]> wrote:
> > Given this feature is SoC-specific, not platform-specific, perhaps
> > it makes sense to move the selects to the M68{,EZ,VZ}328 symbols?
> >
> > Regardless:
> > Reviewed-by: Geert Uytterhoeven <[email protected]>
>
> Ok, folded in the change blow, using one less line. I couldn't figure
Thanks, looks good.
> out whether
> it should just be part of the CONFIG_M68000 instead, which doesn't appear
It must definitely not be selected by CONFIG_M68000, as the plain MC68000
is a CPU, not an SoC, and does not have the timer.
> to have any machine support by itself. The dragonball CPU configuration
> looks really odd, because you have to build exactly one of M68{,EZ,VZ}328
> into the kernel to get a successful compilation, while Kconfig allows
> many other combinations.
While CONFIG_M68000 could be used for a "pure" MC68000-based machine,
I believe we don't support any yet.
M68{,EZ,VZ}328 select M68000 as they are SoCs containing a 68000
CPU core.
Other m68k SoCs have a CPU32 core, which is a simplified 68020 CPU core
(hmm, what happened to 68360 support? Oh, removed in 2016, so nothing
selects CPU32 anymore).
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
On Mon, Oct 12 2020 at 15:37, Arnd Bergmann wrote:
> On Mon, Oct 12, 2020 at 3:16 PM Geert Uytterhoeven <[email protected]> wrote:
>> On Thu, Oct 8, 2020 at 5:48 PM Arnd Bergmann <[email protected]> wrote:
>> The comment about xtime_update() in arch/ia64/kernel/time.c needs
>> an update.
>
> I think the correct action for ia64 would be to make it a
> proper clockevent driver with oneshot support, and remove
> the rest of this logic.
Correct action would be to remove all of arch/ia64 :)
> I could try to rewrite the comment, but I tried not to touch that
> part since I don't understand the logic behind it. Maybe the
> ia64 maintainers can comment here why it even tries to skip
> a timer tick. Is there a danger of ending up with the timer irq
> permanently disabled if the timer_interrupt() function returns
> with the itm register in the past, or is this simply about not having
> too many interrupts in a row?
There was a comment in the initial ia64 code:
* There is a race condition here: to be on the "safe"
* side, we process timer ticks until itm.next is
* ahead of the itc by at least half the timer
* interval. This should give us enough time to set
* the new itm value without losing a timer tick.
The ITM (Interval Timer Match) register is raising an interrupt when the
ITM value matches the ITC (Interval Timer Counter) register. If the new
counter is already past the match then the timer interrupt will happen
once ITC wrapped around and reaches the match value again. Might take
ages for a 64bit counter to do that. :)
IIRC, PXA had the same problem and HPET definitely has it as well. Seems
Intel patented the concept of broken timers, but at least they listened
when they proposed to implement the TSC deadline timer on x86 in the
exact same way.
See hpet_clkevt_set_next_event() for the gory details how to handle that
correctly.
Thanks,
tglx
On Thu, Oct 8, 2020 at 5:47 PM Arnd Bergmann <[email protected]> wrote:
> When I created the patch removing CONFIG_ARCH_GETTIMEOFFSET,
> I also had a look at CONFIG_GENERIC_CLOCKEVENTS, which is
> selected by most, but not all, platforms today, each of the
> ones that lack it doing the timer tick slightly differently.
>
> The cleanups here make the old platforms a bit more
> consistent, in multiple ways:
>
> - rather than selecting GENERIC_CLOCKEVENTS on modern
> platforms, select LEGACY_TIMER_TICK on the old ones.
>
> - Hide some more of the internal implementation and only
> provide a single common entry point for the timer tick,
> which also makes the behavior more consistent.
>
> - Remove the m68k and arm specific infrastructure pieces
> and call the common helper directly from each timer
> interrupt function.
>
> I tested the series on m68k with the qemu q800 target
> platform, both with the legacy_timer_tick() implementation
> and after converting that to a periodic clockevent driver.
I am a big fan of this patch series:
Reviewed-by: Linus Walleij <[email protected]>
Maybe the RFC patch can be kept in the sidelines but the
rest should be merged ASAP in my opinion, the kernel just
looks so much better after this.
Yours,
Linus Walleij