linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 01/14] m68k: Call timer_interrupt() with interrupts disabled
  2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
  2018-12-01  0:53 ` [PATCH v4 05/14] m68k: amiga: Convert to " Finn Thain
  2018-12-01  0:53 ` [PATCH v4 02/14] m68k: mac: Fix VIA timer counter accesses Finn Thain
@ 2018-12-01  0:53 ` Finn Thain
  2018-12-01  0:53 ` [PATCH v4 09/14] m68k: hp300: Handle timer counter overflow Finn Thain
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Finn Thain @ 2018-12-01  0:53 UTC (permalink / raw)
  To: Geert Uytterhoeven, Philip Blundell, Joshua Thompson, Sam Creasey
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

Some platforms execute their timer handler with the interrupt priority
level set below 6. That means the handler could be interrupted by another
driver and this could lead to re-entry of the timer core.

Avoid this by use of local_irq_save/restore for timer interrupt dispatch.
This provides mutual exclusion around the timer interrupt flag access
which is needed later in this series for the clocksource conversion.

Reported-by: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/alpine.DEB.2.21.1811131407120.2697@nanos.tec.linutronix.de
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
I've only checked 680x0 MMU platforms for this issue.

Changed since v2:
 - Don't waste an iteration of the for loop in cia_handler().
 - Remove q40_timer_routine for better consistency with other platforms.
 - Minor cleanup.
---
 arch/m68k/amiga/cia.c       |  9 +++++++++
 arch/m68k/atari/ataints.c   |  4 ++--
 arch/m68k/atari/time.c      | 15 ++++++++++++++-
 arch/m68k/bvme6000/config.c | 20 ++++++++++----------
 arch/m68k/hp300/time.c      | 10 ++++++++--
 arch/m68k/mac/via.c         | 17 +++++++++++++++++
 arch/m68k/mvme147/config.c  | 18 ++++++++++--------
 arch/m68k/mvme16x/config.c  | 21 +++++++++++----------
 arch/m68k/q40/q40ints.c     | 19 +++++++++++--------
 arch/m68k/sun3/sun3ints.c   |  3 +++
 arch/m68k/sun3x/time.c      | 16 ++++++++++------
 11 files changed, 105 insertions(+), 47 deletions(-)

diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c
index 2081b8cd5591..b9aee983e6f4 100644
--- a/arch/m68k/amiga/cia.c
+++ b/arch/m68k/amiga/cia.c
@@ -88,10 +88,19 @@ static irqreturn_t cia_handler(int irq, void *dev_id)
 	struct ciabase *base = dev_id;
 	int mach_irq;
 	unsigned char ints;
+	unsigned long flags;
 
+	/* Interrupts get disabled while the timer irq flag is cleared and
+	 * the timer interrupt serviced.
+	 */
 	mach_irq = base->cia_irq;
+	local_irq_save(flags);
 	ints = cia_set_irq(base, CIA_ICR_ALL);
 	amiga_custom.intreq = base->int_mask;
+	if (ints & 1)
+		generic_handle_irq(mach_irq);
+	local_irq_restore(flags);
+	mach_irq++, ints >>= 1;
 	for (; ints; mach_irq++, ints >>= 1) {
 		if (ints & 1)
 			generic_handle_irq(mach_irq);
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index 3d2b63bedf05..56f02ea2c248 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -142,7 +142,7 @@ struct mfptimerbase {
 	.name		= "MFP Timer D"
 };
 
-static irqreturn_t mfptimer_handler(int irq, void *dev_id)
+static irqreturn_t mfp_timer_d_handler(int irq, void *dev_id)
 {
 	struct mfptimerbase *base = dev_id;
 	int mach_irq;
@@ -344,7 +344,7 @@ void __init atari_init_IRQ(void)
 	st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 0xf0) | 0x6;
 
 	/* request timer D dispatch handler */
-	if (request_irq(IRQ_MFP_TIMD, mfptimer_handler, IRQF_SHARED,
+	if (request_irq(IRQ_MFP_TIMD, mfp_timer_d_handler, IRQF_SHARED,
 			stmfp_base.name, &stmfp_base))
 		pr_err("Couldn't register %s interrupt\n", stmfp_base.name);
 
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index 9cca64286464..fafa20f75ab9 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -24,6 +24,18 @@
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL_GPL(rtc_lock);
 
+static irqreturn_t mfp_timer_c_handler(int irq, void *dev_id)
+{
+	irq_handler_t timer_routine = dev_id;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	timer_routine(0, NULL);
+	local_irq_restore(flags);
+
+	return IRQ_HANDLED;
+}
+
 void __init
 atari_sched_init(irq_handler_t timer_routine)
 {
@@ -32,7 +44,8 @@ atari_sched_init(irq_handler_t timer_routine)
     /* start timer C, div = 1:100 */
     st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 15) | 0x60;
     /* install interrupt service routine for MFP Timer C */
-    if (request_irq(IRQ_MFP_TIMC, timer_routine, 0, "timer", timer_routine))
+    if (request_irq(IRQ_MFP_TIMC, mfp_timer_c_handler, 0, "timer",
+                    timer_routine))
 	pr_err("Couldn't register timer interrupt\n");
 }
 
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index 143ee9fa3893..0e5efed4da86 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -44,11 +44,6 @@ extern int bvme6000_hwclk (int, struct rtc_time *);
 extern void bvme6000_reset (void);
 void bvme6000_set_vectors (void);
 
-/* Save tick handler routine pointer, will point to xtime_update() in
- * kernel/timer/timekeeping.c, called via bvme6000_process_int() */
-
-static irq_handler_t tick_handler;
-
 
 int __init bvme6000_parse_bootinfo(const struct bi_record *bi)
 {
@@ -157,12 +152,18 @@ irqreturn_t bvme6000_abort_int (int irq, void *dev_id)
 
 static irqreturn_t bvme6000_timer_int (int irq, void *dev_id)
 {
+    irq_handler_t timer_routine = dev_id;
+    unsigned long flags;
     volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
-    unsigned char msr = rtc->msr & 0xc0;
+    unsigned char msr;
 
+    local_irq_save(flags);
+    msr = rtc->msr & 0xc0;
     rtc->msr = msr | 0x20;		/* Ack the interrupt */
+    timer_routine(0, NULL);
+    local_irq_restore(flags);
 
-    return tick_handler(irq, dev_id);
+    return IRQ_HANDLED;
 }
 
 /*
@@ -181,9 +182,8 @@ void bvme6000_sched_init (irq_handler_t timer_routine)
 
     rtc->msr = 0;	/* Ensure timer registers accessible */
 
-    tick_handler = timer_routine;
-    if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, 0,
-				"timer", bvme6000_timer_int))
+    if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, 0, "timer",
+                    timer_routine))
 	panic ("Couldn't register timer int");
 
     rtc->t1cr_omr = 0x04;	/* Mode 2, ext clk */
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
index 289d928a46cb..d30b03ea93a2 100644
--- a/arch/m68k/hp300/time.c
+++ b/arch/m68k/hp300/time.c
@@ -38,13 +38,19 @@
 
 static irqreturn_t hp300_tick(int irq, void *dev_id)
 {
+	irq_handler_t timer_routine = dev_id;
+	unsigned long flags;
 	unsigned long tmp;
-	irq_handler_t vector = dev_id;
+
+	local_irq_save(flags);
 	in_8(CLOCKBASE + CLKSR);
 	asm volatile ("movpw %1@(5),%0" : "=d" (tmp) : "a" (CLOCKBASE));
+	timer_routine(0, NULL);
+	local_irq_restore(flags);
+
 	/* Turn off the network and SCSI leds */
 	blinken_leds(0, 0xe0);
-	return vector(irq, NULL);
+	return IRQ_HANDLED;
 }
 
 u32 hp300_gettimeoffset(void)
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index e4facff0c1f3..f6df83ba2227 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -436,6 +436,8 @@ void via_nubus_irq_shutdown(int irq)
  * via6522.c :-), disable/pending masks added.
  */
 
+#define VIA_TIMER_1_INT BIT(6)
+
 void via1_irq(struct irq_desc *desc)
 {
 	int irq_num;
@@ -445,6 +447,21 @@ void via1_irq(struct irq_desc *desc)
 	if (!events)
 		return;
 
+	irq_num = IRQ_MAC_TIMER_1;
+	irq_bit = VIA_TIMER_1_INT;
+	if (events & irq_bit) {
+		unsigned long flags;
+
+		local_irq_save(flags);
+		via1[vIFR] = irq_bit;
+		generic_handle_irq(irq_num);
+		local_irq_restore(flags);
+
+		events &= ~irq_bit;
+		if (!events)
+			return;
+	}
+
 	irq_num = VIA1_SOURCE_BASE;
 	irq_bit = 1;
 	do {
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index adea549d240e..93c68d2b8e0e 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -45,11 +45,6 @@ extern void mvme147_reset (void);
 
 static int bcd2int (unsigned char b);
 
-/* Save tick handler routine pointer, will point to xtime_update() in
- * kernel/time/timekeeping.c, called via mvme147_process_int() */
-
-irq_handler_t tick_handler;
-
 
 int __init mvme147_parse_bootinfo(const struct bi_record *bi)
 {
@@ -104,16 +99,23 @@ void __init config_mvme147(void)
 
 static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
 {
+	irq_handler_t timer_routine = dev_id;
+	unsigned long flags;
+
+	local_irq_save(flags);
 	m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;
 	m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
-	return tick_handler(irq, dev_id);
+	timer_routine(0, NULL);
+	local_irq_restore(flags);
+
+	return IRQ_HANDLED;
 }
 
 
 void mvme147_sched_init (irq_handler_t timer_routine)
 {
-	tick_handler = timer_routine;
-	if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, 0, "timer 1", NULL))
+	if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, 0, "timer 1",
+			timer_routine))
 		pr_err("Couldn't register timer interrupt\n");
 
 	/* Init the clock with a value */
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index 6ee36a5b528d..5feb3ab484d0 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -50,11 +50,6 @@ extern void mvme16x_reset (void);
 
 int bcd2int (unsigned char b);
 
-/* Save tick handler routine pointer, will point to xtime_update() in
- * kernel/time/timekeeping.c, called via mvme16x_process_int() */
-
-static irq_handler_t tick_handler;
-
 
 unsigned short mvme16x_config;
 EXPORT_SYMBOL(mvme16x_config);
@@ -352,8 +347,15 @@ static irqreturn_t mvme16x_abort_int (int irq, void *dev_id)
 
 static irqreturn_t mvme16x_timer_int (int irq, void *dev_id)
 {
-    *(volatile unsigned char *)0xfff4201b |= 8;
-    return tick_handler(irq, dev_id);
+	irq_handler_t timer_routine = dev_id;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	*(volatile unsigned char *)0xfff4201b |= 8;
+	timer_routine(0, NULL);
+	local_irq_restore(flags);
+
+	return IRQ_HANDLED;
 }
 
 void mvme16x_sched_init (irq_handler_t timer_routine)
@@ -361,14 +363,13 @@ void mvme16x_sched_init (irq_handler_t timer_routine)
     uint16_t brdno = be16_to_cpu(mvme_bdid.brdno);
     int irq;
 
-    tick_handler = timer_routine;
     /* Using PCCchip2 or MC2 chip tick timer 1 */
     *(volatile unsigned long *)0xfff42008 = 0;
     *(volatile unsigned long *)0xfff42004 = 10000;	/* 10ms */
     *(volatile unsigned char *)0xfff42017 |= 3;
     *(volatile unsigned char *)0xfff4201b = 0x16;
-    if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, 0,
-				"timer", mvme16x_timer_int))
+    if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, 0, "timer",
+                    timer_routine))
 	panic ("Couldn't register timer int");
 
     if (brdno == 0x0162 || brdno == 0x172)
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
index 3e7603202977..1c696906c159 100644
--- a/arch/m68k/q40/q40ints.c
+++ b/arch/m68k/q40/q40ints.c
@@ -127,10 +127,10 @@ void q40_mksound(unsigned int hz, unsigned int ticks)
 	sound_ticks = ticks << 1;
 }
 
-static irq_handler_t q40_timer_routine;
-
-static irqreturn_t q40_timer_int (int irq, void * dev)
+static irqreturn_t q40_timer_int(int irq, void *dev_id)
 {
+	irq_handler_t timer_routine = dev_id;
+
 	ql_ticks = ql_ticks ? 0 : 1;
 	if (sound_ticks) {
 		unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL;
@@ -139,8 +139,13 @@ static irqreturn_t q40_timer_int (int irq, void * dev)
 		*DAC_RIGHT=sval;
 	}
 
-	if (!ql_ticks)
-		q40_timer_routine(irq, dev);
+	if (!ql_ticks) {
+		unsigned long flags;
+
+		local_irq_save(flags);
+		timer_routine(0, NULL);
+		local_irq_restore(flags);
+	}
 	return IRQ_HANDLED;
 }
 
@@ -148,11 +153,9 @@ void q40_sched_init (irq_handler_t timer_routine)
 {
 	int timer_irq;
 
-	q40_timer_routine = timer_routine;
 	timer_irq = Q40_IRQ_FRAME;
 
-	if (request_irq(timer_irq, q40_timer_int, 0,
-				"timer", q40_timer_int))
+	if (request_irq(timer_irq, q40_timer_int, 0, "timer", timer_routine))
 		panic("Couldn't register timer int");
 
 	master_outb(-1, FRAME_CLEAR_REG);
diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c
index 6bbca30c9188..a5824abb4a39 100644
--- a/arch/m68k/sun3/sun3ints.c
+++ b/arch/m68k/sun3/sun3ints.c
@@ -61,8 +61,10 @@ static irqreturn_t sun3_int7(int irq, void *dev_id)
 
 static irqreturn_t sun3_int5(int irq, void *dev_id)
 {
+	unsigned long flags;
 	unsigned int cnt;
 
+	local_irq_save(flags);
 #ifdef CONFIG_SUN3
 	intersil_clear();
 #endif
@@ -76,6 +78,7 @@ static irqreturn_t sun3_int5(int irq, void *dev_id)
 	cnt = kstat_irqs_cpu(irq, 0);
 	if (!(cnt % 20))
 		sun3_leds(led_pattern[cnt % 160 / 20]);
+	local_irq_restore(flags);
 	return IRQ_HANDLED;
 }
 
diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c
index 047e2bcee3d7..3c8a86d08508 100644
--- a/arch/m68k/sun3x/time.c
+++ b/arch/m68k/sun3x/time.c
@@ -80,15 +80,19 @@ u32 sun3x_gettimeoffset(void)
 }
 
 #if 0
-static void sun3x_timer_tick(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sun3x_timer_tick(int irq, void *dev_id)
 {
-    void (*vector)(int, void *, struct pt_regs *) = dev_id;
+	irq_handler_t timer_routine = dev_id;
+	unsigned long flags;
 
-    /* Clear the pending interrupt - pulse the enable line low */
-    disable_irq(5);
-    enable_irq(5);
+	local_irq_save(flags);
+	/* Clear the pending interrupt - pulse the enable line low */
+	disable_irq(5);
+	enable_irq(5);
+	timer_routine(0, NULL);
+	local_irq_restore(flags);
 
-    vector(irq, NULL, regs);
+	return IRQ_HANDLED;
 }
 #endif
 
-- 
2.18.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v4 09/14] m68k: hp300: Handle timer counter overflow
  2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
                   ` (2 preceding siblings ...)
  2018-12-01  0:53 ` [PATCH v4 01/14] m68k: Call timer_interrupt() with interrupts disabled Finn Thain
@ 2018-12-01  0:53 ` Finn Thain
  2018-12-01  0:53 ` [PATCH v4 03/14] m68k: apollo, q40, sun3, sun3x: Remove arch_gettimeoffset implementations Finn Thain
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Finn Thain @ 2018-12-01  0:53 UTC (permalink / raw)
  To: Geert Uytterhoeven, Philip Blundell
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

Because hp300_read_clk() never checks the timer interrupt flag it may
fail to notice that the timer has wrapped, allowing the clock to jump
backwards. This is not a new problem.

This is resolved by checking the interrupt flag and, if need be,
taking wrap-around into account. The interrupt handler clears the flag
when it eventually executes.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
TODO: find a spare counter for the clocksource, rather than hanging
it off the HZ timer.

Changed since v3:
 - Use clk_offset variable to track the offset when the irq check is skipped.
---
 arch/m68k/hp300/time.c | 46 +++++++++++++++++++++++++-----------------
 1 file changed, 27 insertions(+), 19 deletions(-)

diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
index 90982803a629..bfee13e1d0fe 100644
--- a/arch/m68k/hp300/time.c
+++ b/arch/m68k/hp300/time.c
@@ -30,7 +30,7 @@ static struct clocksource hp300_clk = {
 	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-static u32 clk_total;
+static u32 clk_total, clk_offset;
 
 /* Clock hardware definitions */
 
@@ -41,9 +41,12 @@ static u32 clk_total;
 #define	CLKCR3		CLKCR1
 #define	CLKSR		CLKCR2
 #define	CLKMSB1		0x5
+#define	CLKLSB1		0x7
 #define	CLKMSB2		0x9
 #define	CLKMSB3		0xD
 
+#define	CLKSR_INT1	BIT(0)
+
 /* This is for machines which generate the exact clock. */
 
 #define HP300_TIMER_CLOCK_FREQ 250000
@@ -60,6 +63,7 @@ static irqreturn_t hp300_tick(int irq, void *dev_id)
 	in_8(CLOCKBASE + CLKSR);
 	asm volatile ("movpw %1@(5),%0" : "=d" (tmp) : "a" (CLOCKBASE));
 	clk_total += INTVAL;
+	clk_offset = 0;
 	timer_routine(0, NULL);
 	local_irq_restore(flags);
 
@@ -70,24 +74,28 @@ static irqreturn_t hp300_tick(int irq, void *dev_id)
 
 static u64 hp300_read_clk(struct clocksource *cs)
 {
-  unsigned long flags;
-  unsigned char lsb, msb1, msb2;
-  u32 ticks;
-
-  local_irq_save(flags);
-  /* Read current timer 1 value */
-  msb1 = in_8(CLOCKBASE + 5);
-  lsb = in_8(CLOCKBASE + 7);
-  msb2 = in_8(CLOCKBASE + 5);
-  if (msb1 != msb2)
-    /* A carry happened while we were reading.  Read it again */
-    lsb = in_8(CLOCKBASE + 7);
-
-  ticks = INTVAL - ((msb2 << 8) | lsb);
-  ticks += clk_total;
-  local_irq_restore(flags);
-
-  return ticks;
+	unsigned long flags;
+	unsigned char lsb, msb, msb_new;
+	u32 ticks;
+
+	local_irq_save(flags);
+	/* Read current timer 1 value */
+	msb = in_8(CLOCKBASE + CLKMSB1);
+again:
+	if ((in_8(CLOCKBASE + CLKSR) & CLKSR_INT1) && msb > 0)
+		clk_offset = INTVAL;
+	lsb = in_8(CLOCKBASE + CLKLSB1);
+	msb_new = in_8(CLOCKBASE + CLKMSB1);
+	if (msb_new != msb) {
+		msb = msb_new;
+		goto again;
+	}
+
+	ticks = INTVAL - ((msb << 8) | lsb);
+	ticks += clk_offset + clk_total;
+	local_irq_restore(flags);
+
+	return ticks;
 }
 
 void __init hp300_sched_init(irq_handler_t vector)
-- 
2.18.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v4 06/14] m68k: atari: Convert to clocksource API
  2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
                   ` (11 preceding siblings ...)
  2018-12-01  0:53 ` [PATCH v4 08/14] m68k: hp300: Convert to clocksource API Finn Thain
@ 2018-12-01  0:53 ` Finn Thain
  2018-12-01  0:53 ` [PATCH v4 11/14] m68k: mvme147: " Finn Thain
  2019-03-05  6:13 ` [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt " Finn Thain
  14 siblings, 0 replies; 20+ messages in thread
From: Finn Thain @ 2018-12-01  0:53 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Normally the MFP timer C interrupt flag would be used to check for
timer counter wrap-around. Unfortunately, that flag gets cleared by the
MFP itself (due to automatic End-of-Interrupt mode). This means that
mfp_timer_c_handler() and atari_read_clk() must race when accounting
for counter wrap-around.

That problem is avoided by effectively stopping the clock when it might
otherwise jump backwards (due to interrupt latency). Note that this may
affect clock accuracy.

After the timer interrupt is asserted, wait for the counter to be
reloaded so that atari_read_clk() will not see the intermediate state
as that would cause the clock to jump backwards.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Tested-by: Michael Schmitz <schmitzmic@gmail.com>
---
TODO: find a spare counter for the clocksource, rather than hanging
it off the HZ timer.

Changed since v2:
 - Wait for timer reload after timer interrupt.
 - Add comment and improve code style for better clarity.

Changed since v1:
 - Moved clk_total access to within the irq lock.
 - Renamed mfp_timer_handler and mfptimer_handler.
 - Avoid accessing the timer interrupt flag in atari_read_clk(). To
get monotonicity, keep track of the previous timer counter value.
---
 arch/m68k/atari/time.c | 53 ++++++++++++++++++++++++++++--------------
 1 file changed, 36 insertions(+), 17 deletions(-)

diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index fafa20f75ab9..ce923a523695 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/rtc.h>
 #include <linux/bcd.h>
+#include <linux/clocksource.h>
 #include <linux/delay.h>
 #include <linux/export.h>
 
@@ -24,12 +25,29 @@
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL_GPL(rtc_lock);
 
+static u64 atari_read_clk(struct clocksource *cs);
+
+static struct clocksource atari_clk = {
+	.name   = "mfp",
+	.rating = 100,
+	.read   = atari_read_clk,
+	.mask   = CLOCKSOURCE_MASK(32),
+	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static u32 clk_total;
+static u8 last_timer_count;
+
 static irqreturn_t mfp_timer_c_handler(int irq, void *dev_id)
 {
 	irq_handler_t timer_routine = dev_id;
 	unsigned long flags;
 
 	local_irq_save(flags);
+	do {
+		last_timer_count = st_mfp.tim_dt_c;
+	} while (last_timer_count == 1);
+	clk_total += INT_TICKS;
 	timer_routine(0, NULL);
 	local_irq_restore(flags);
 
@@ -44,32 +62,33 @@ atari_sched_init(irq_handler_t timer_routine)
     /* start timer C, div = 1:100 */
     st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 15) | 0x60;
     /* install interrupt service routine for MFP Timer C */
-    if (request_irq(IRQ_MFP_TIMC, mfp_timer_c_handler, 0, "timer",
+    if (request_irq(IRQ_MFP_TIMC, mfp_timer_c_handler, IRQF_TIMER, "timer",
                     timer_routine))
 	pr_err("Couldn't register timer interrupt\n");
+
+    clocksource_register_hz(&atari_clk, INT_CLK);
 }
 
 /* ++andreas: gettimeoffset fixed to check for pending interrupt */
 
-#define TICK_SIZE 10000
-
-/* This is always executed with interrupts disabled.  */
-u32 atari_gettimeoffset(void)
+static u64 atari_read_clk(struct clocksource *cs)
 {
-  u32 ticks, offset = 0;
-
-  /* read MFP timer C current value */
-  ticks = st_mfp.tim_dt_c;
-  /* The probability of underflow is less than 2% */
-  if (ticks > INT_TICKS - INT_TICKS / 50)
-    /* Check for pending timer interrupt */
-    if (st_mfp.int_pn_b & (1 << 5))
-      offset = TICK_SIZE;
+	unsigned long flags;
+	u8 count;
+	u32 ticks;
 
-  ticks = INT_TICKS - ticks;
-  ticks = ticks * 10000L / INT_TICKS;
+	local_irq_save(flags);
+	/* Ensure that the count is monotonically decreasing, even though
+	 * the result may briefly stop changing after counter wrap-around.
+	 */
+	count = min(st_mfp.tim_dt_c, last_timer_count);
+	last_timer_count = count;
+
+	ticks = INT_TICKS - count;
+	ticks += clk_total;
+	local_irq_restore(flags);
 
-  return (ticks + offset) * 1000;
+	return ticks;
 }
 
 
-- 
2.18.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v4 11/14] m68k: mvme147: Convert to clocksource API
  2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
                   ` (12 preceding siblings ...)
  2018-12-01  0:53 ` [PATCH v4 06/14] m68k: atari: " Finn Thain
@ 2018-12-01  0:53 ` Finn Thain
  2019-03-05  6:13 ` [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt " Finn Thain
  14 siblings, 0 replies; 20+ messages in thread
From: Finn Thain @ 2018-12-01  0:53 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
Changed since v1:
 - Moved clk_total access to within the irq lock.
 - Use type u32 for tick counter.
---
 arch/m68k/include/asm/mvme147hw.h |  1 -
 arch/m68k/mvme147/config.c        | 36 +++++++++++++++++++++++++------
 2 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/arch/m68k/include/asm/mvme147hw.h b/arch/m68k/include/asm/mvme147hw.h
index 9c7ff67c5ffd..7c3dd513128e 100644
--- a/arch/m68k/include/asm/mvme147hw.h
+++ b/arch/m68k/include/asm/mvme147hw.h
@@ -66,7 +66,6 @@ struct pcc_regs {
 #define PCC_INT_ENAB		0x08
 
 #define PCC_TIMER_INT_CLR	0x80
-#define PCC_TIMER_PRELOAD	63936l
 
 #define PCC_LEVEL_ABORT		0x07
 #define PCC_LEVEL_SERIAL	0x04
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index 4ef4faa5ed8b..c44a254e8a8c 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
+#include <linux/clocksource.h>
 #include <linux/console.h>
 #include <linux/linkage.h>
 #include <linux/init.h>
@@ -92,6 +93,21 @@ void __init config_mvme147(void)
 		vme_brdtype = VME_TYPE_MVME147;
 }
 
+static u64 mvme147_read_clk(struct clocksource *cs);
+
+static struct clocksource mvme147_clk = {
+	.name   = "pcc",
+	.rating = 250,
+	.read   = mvme147_read_clk,
+	.mask   = CLOCKSOURCE_MASK(32),
+	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static u32 clk_total;
+
+#define PCC_TIMER_CLOCK_FREQ 160000
+#define PCC_TIMER_CYCLES     (PCC_TIMER_CLOCK_FREQ / HZ)
+#define PCC_TIMER_PRELOAD    (0x10000 - PCC_TIMER_CYCLES)
 
 /* Using pcc tick timer 1 */
 
@@ -103,6 +119,7 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
 	local_irq_save(flags);
 	m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;
 	m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
+	clk_total += PCC_TIMER_CYCLES;
 	timer_routine(0, NULL);
 	local_irq_restore(flags);
 
@@ -112,32 +129,39 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
 
 void mvme147_sched_init (irq_handler_t timer_routine)
 {
-	if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, 0, "timer 1",
-			timer_routine))
+	if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQF_TIMER,
+			"timer 1", timer_routine))
 		pr_err("Couldn't register timer interrupt\n");
 
 	/* Init the clock with a value */
-	/* our clock goes off every 6.25us */
+	/* The clock counter increments until 0xFFFF then reloads */
 	m147_pcc->t1_preload = PCC_TIMER_PRELOAD;
 	m147_pcc->t1_cntrl = 0x0;	/* clear timer */
 	m147_pcc->t1_cntrl = 0x3;	/* start timer */
 	m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;  /* clear pending ints */
 	m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
+
+	clocksource_register_hz(&mvme147_clk, PCC_TIMER_CLOCK_FREQ);
 }
 
-/* This is always executed with interrupts disabled.  */
 /* XXX There are race hazards in this code XXX */
-u32 mvme147_gettimeoffset(void)
+static u64 mvme147_read_clk(struct clocksource *cs)
 {
+	unsigned long flags;
 	volatile unsigned short *cp = (volatile unsigned short *)0xfffe1012;
 	unsigned short n;
+	u32 ticks;
 
+	local_irq_save(flags);
 	n = *cp;
 	while (n != *cp)
 		n = *cp;
 
 	n -= PCC_TIMER_PRELOAD;
-	return ((unsigned long)n * 25 / 4) * 1000;
+	ticks = clk_total + n;
+	local_irq_restore(flags);
+
+	return ticks;
 }
 
 static int bcd2int (unsigned char b)
-- 
2.18.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v4 10/14] m68k: mac: Convert to clocksource API
  2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
                   ` (6 preceding siblings ...)
  2018-12-01  0:53 ` [PATCH v4 13/14] m68k: mvme16x: Convert to clocksource API Finn Thain
@ 2018-12-01  0:53 ` Finn Thain
  2018-12-01  0:53 ` [PATCH v4 04/14] m68k: Drop ARCH_USES_GETTIMEOFFSET Finn Thain
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Finn Thain @ 2018-12-01  0:53 UTC (permalink / raw)
  To: Geert Uytterhoeven, Joshua Thompson
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Tested-by: Stan Johnson <userm57@yahoo.com>
---
Changed since v3:
 - Use clk_offset variable to track the offset when the irq check is skipped.

Changed since v2:
 - Drop 'clk_offset' variable.

Changed since v1:
 - Moved clk_total access to within the irq lock.
 - Use type u32 for tick counter.
---
 arch/m68k/mac/via.c | 45 ++++++++++++++++++++++++++++++++++++---------
 1 file changed, 36 insertions(+), 9 deletions(-)

diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 65aca12a8694..31cccc79cb7a 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -23,6 +23,7 @@
  *
  */
 
+#include <linux/clocksource.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -573,16 +574,39 @@ EXPORT_SYMBOL(via2_scsi_drq_pending);
 /* timer and clock source */
 
 #define VIA_CLOCK_FREQ     783360                /* VIA "phase 2" clock in Hz */
-#define VIA_TIMER_INTERVAL (1000000 / HZ)        /* microseconds per jiffy */
 #define VIA_TIMER_CYCLES   (VIA_CLOCK_FREQ / HZ) /* clock cycles per jiffy */
 
 #define VIA_TC             (VIA_TIMER_CYCLES - 2) /* including 0 and -1 */
 #define VIA_TC_LOW         (VIA_TC & 0xFF)
 #define VIA_TC_HIGH        (VIA_TC >> 8)
 
+static u64 mac_read_clk(struct clocksource *cs);
+
+static struct clocksource mac_clk = {
+	.name   = "via1",
+	.rating = 250,
+	.read   = mac_read_clk,
+	.mask   = CLOCKSOURCE_MASK(32),
+	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static u32 clk_total, clk_offset;
+
+static irqreturn_t via_timer_handler(int irq, void *dev_id)
+{
+	irq_handler_t timer_routine = dev_id;
+
+	clk_total += VIA_TIMER_CYCLES;
+	clk_offset = 0;
+	timer_routine(0, NULL);
+
+	return IRQ_HANDLED;
+}
+
 void __init via_init_clock(irq_handler_t timer_routine)
 {
-	if (request_irq(IRQ_MAC_TIMER_1, timer_routine, 0, "timer", NULL)) {
+	if (request_irq(IRQ_MAC_TIMER_1, via_timer_handler, IRQF_TIMER, "timer",
+			timer_routine)) {
 		pr_err("Couldn't register %s interrupt\n", "timer");
 		return;
 	}
@@ -592,13 +616,16 @@ void __init via_init_clock(irq_handler_t timer_routine)
 	via1[vT1CL] = VIA_TC_LOW;
 	via1[vT1CH] = VIA_TC_HIGH;
 	via1[vACR] |= 0x40;
+
+	clocksource_register_hz(&mac_clk, VIA_CLOCK_FREQ);
 }
 
-u32 mac_gettimeoffset(void)
+static u64 mac_read_clk(struct clocksource *cs)
 {
 	unsigned long flags;
 	u8 count_high;
-	u16 count, offset = 0;
+	u16 count;
+	u32 ticks;
 
 	/*
 	 * Timer counter wrap-around is detected with the timer interrupt flag
@@ -614,11 +641,11 @@ u32 mac_gettimeoffset(void)
 	if (count_high == 0xFF)
 		count_high = 0;
 	if (count_high > 0 && (via1[vIFR] & VIA_TIMER_1_INT))
-		offset = VIA_TIMER_CYCLES;
-	local_irq_restore(flags);
-
+		clk_offset = VIA_TIMER_CYCLES;
 	count = count_high << 8;
-	count = VIA_TIMER_CYCLES - count + offset;
+	ticks = VIA_TIMER_CYCLES - count;
+	ticks += clk_offset + clk_total;
+	local_irq_restore(flags);
 
-	return ((count * VIA_TIMER_INTERVAL) / VIA_TIMER_CYCLES) * 1000;
+	return ticks;
 }
-- 
2.18.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v4 14/14] m68k: mvme16x: Handle timer counter overflow
  2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
                   ` (9 preceding siblings ...)
  2018-12-01  0:53 ` [PATCH v4 07/14] m68k: bvme6000: Convert to clocksource API Finn Thain
@ 2018-12-01  0:53 ` Finn Thain
  2018-12-01  0:53 ` [PATCH v4 08/14] m68k: hp300: Convert to clocksource API Finn Thain
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Finn Thain @ 2018-12-01  0:53 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

Reading the timer counter races with timer overflow (and the
corresponding interrupt). This is resolved by reading the overflow
register and taking this value into account. The interrupt handler
must clear the overflow register when it eventually executes.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
TODO: find a spare counter for the clocksource, rather than hanging
it off the HZ timer.
---
 arch/m68k/mvme16x/config.c | 45 +++++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 13 deletions(-)

diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index 2c109ee2a1a5..9bc2da69f80c 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -115,11 +115,11 @@ static void __init mvme16x_init_IRQ (void)
 	m68k_setup_user_interrupt(VEC_USER, 192);
 }
 
-#define pcc2chip	((volatile u_char *)0xfff42000)
-#define PccSCCMICR	0x1d
-#define PccSCCTICR	0x1e
-#define PccSCCRICR	0x1f
-#define PccTPIACKR	0x25
+#define PCC2CHIP   (0xfff42000)
+#define PCCSCCMICR (PCC2CHIP + 0x1d)
+#define PCCSCCTICR (PCC2CHIP + 0x1e)
+#define PCCSCCRICR (PCC2CHIP + 0x1f)
+#define PCCTPIACKR (PCC2CHIP + 0x25)
 
 #ifdef CONFIG_EARLY_PRINTK
 
@@ -227,10 +227,10 @@ void mvme16x_cons_write(struct console *co, const char *str, unsigned count)
 	base_addr[CyIER] = CyTxMpty;
 
 	while (1) {
-		if (pcc2chip[PccSCCTICR] & 0x20)
+		if (in_8(PCCSCCTICR) & 0x20)
 		{
 			/* We have a Tx int. Acknowledge it */
-			sink = pcc2chip[PccTPIACKR];
+			sink = in_8(PCCTPIACKR);
 			if ((base_addr[CyLICR] >> 2) == port) {
 				if (i == count) {
 					/* Last char of string is now output */
@@ -359,13 +359,26 @@ static u32 clk_total;
 #define PCC_TIMER_CLOCK_FREQ 1000000
 #define PCC_TIMER_CYCLES     (PCC_TIMER_CLOCK_FREQ / HZ)
 
+#define PCCTCMP1             (PCC2CHIP + 0x04)
+#define PCCTCNT1             (PCC2CHIP + 0x08)
+#define PCCTOVR1             (PCC2CHIP + 0x17)
+#define PCCTIC1              (PCC2CHIP + 0x1b)
+
+#define PCCTOVR1_TIC_EN      0x01
+#define PCCTOVR1_COC_EN      0x02
+#define PCCTOVR1_OVR_CLR     0x04
+
+#define PCCTIC1_INT_CLR      0x08
+#define PCCTIC1_INT_EN       0x10
+
 static irqreturn_t mvme16x_timer_int (int irq, void *dev_id)
 {
 	irq_handler_t timer_routine = dev_id;
 	unsigned long flags;
 
 	local_irq_save(flags);
-	*(volatile unsigned char *)0xfff4201b |= 8;
+	out_8(PCCTIC1, in_8(PCCTIC1) | PCCTIC1_INT_CLR);
+	out_8(PCCTOVR1, PCCTOVR1_OVR_CLR);
 	clk_total += PCC_TIMER_CYCLES;
 	timer_routine(0, NULL);
 	local_irq_restore(flags);
@@ -379,10 +392,10 @@ void mvme16x_sched_init (irq_handler_t timer_routine)
     int irq;
 
     /* Using PCCchip2 or MC2 chip tick timer 1 */
-    *(volatile unsigned long *)0xfff42008 = 0;
-    *(volatile unsigned long *)0xfff42004 = PCC_TIMER_CYCLES;
-    *(volatile unsigned char *)0xfff42017 |= 3;
-    *(volatile unsigned char *)0xfff4201b = 0x16;
+    out_be32(PCCTCNT1, 0);
+    out_be32(PCCTCMP1, PCC_TIMER_CYCLES);
+    out_8(PCCTOVR1, in_8(PCCTOVR1) | PCCTOVR1_TIC_EN | PCCTOVR1_COC_EN);
+    out_8(PCCTIC1, PCCTIC1_INT_EN | 6);
     if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, IRQF_TIMER, "timer",
                     timer_routine))
 	panic ("Couldn't register timer int");
@@ -401,10 +414,16 @@ void mvme16x_sched_init (irq_handler_t timer_routine)
 static u64 mvme16x_read_clk(struct clocksource *cs)
 {
 	unsigned long flags;
+	u8 overflow, tmp;
 	u32 ticks;
 
 	local_irq_save(flags);
-	ticks = *(volatile u32 *)0xfff42008;
+	tmp = in_8(PCCTOVR1) >> 4;
+	ticks = in_be32(PCCTCNT1);
+	overflow = in_8(PCCTOVR1) >> 4;
+	if (overflow != tmp)
+		ticks = in_be32(PCCTCNT1);
+	ticks += overflow * PCC_TIMER_CYCLES;
 	ticks += clk_total;
 	local_irq_restore(flags);
 
-- 
2.18.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v4 02/14] m68k: mac: Fix VIA timer counter accesses
  2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
  2018-12-01  0:53 ` [PATCH v4 05/14] m68k: amiga: Convert to " Finn Thain
@ 2018-12-01  0:53 ` Finn Thain
  2018-12-01  0:53 ` [PATCH v4 01/14] m68k: Call timer_interrupt() with interrupts disabled Finn Thain
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Finn Thain @ 2018-12-01  0:53 UTC (permalink / raw)
  To: Geert Uytterhoeven, Joshua Thompson
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

This resolves some bugs that affect VIA timer counter accesses.
Avoid lost interrupts caused by reading the counter low byte register.
Make allowance for the fact that the counter will be decremented to
0xFFFF before being reloaded.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
Changed since v3:
 - Don't add offset until after the timer counter actually wraps.

Changed since v2:
 - Don't check for timer interrupt in mac_gettimeoffset() when the timer is
about to be reloaded.

Changed since v1:
 - Test the timer interrupt flag unconditionally.
 - Drop some extraneous clean up.
 - Don't try to recover from lost timer interrupts. Don't lose them
in the first place. That means giving up on the timer counter low byte.
The extra precision is probably not worth the extra complexity and
I couldn't make it work anyway.
---
 arch/m68k/mac/via.c | 102 +++++++++++++++++++++++---------------------
 1 file changed, 53 insertions(+), 49 deletions(-)

diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index f6df83ba2227..65aca12a8694 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -54,16 +54,6 @@ static __u8 rbv_clear;
 
 static int gIER,gIFR,gBufA,gBufB;
 
-/*
- * Timer defs.
- */
-
-#define TICK_SIZE		10000
-#define MAC_CLOCK_TICK		(783300/HZ)		/* ticks per HZ */
-#define MAC_CLOCK_LOW		(MAC_CLOCK_TICK&0xFF)
-#define MAC_CLOCK_HIGH		(MAC_CLOCK_TICK>>8)
-
-
 /*
  * On Macs with a genuine VIA chip there is no way to mask an individual slot
  * interrupt. This limitation also seems to apply to VIA clone logic cores in
@@ -267,22 +257,6 @@ void __init via_init(void)
 	}
 }
 
-/*
- * Start the 100 Hz clock
- */
-
-void __init via_init_clock(irq_handler_t func)
-{
-	via1[vACR] |= 0x40;
-	via1[vT1LL] = MAC_CLOCK_LOW;
-	via1[vT1LH] = MAC_CLOCK_HIGH;
-	via1[vT1CL] = MAC_CLOCK_LOW;
-	via1[vT1CH] = MAC_CLOCK_HIGH;
-
-	if (request_irq(IRQ_MAC_TIMER_1, func, 0, "timer", func))
-		pr_err("Couldn't register %s interrupt\n", "timer");
-}
-
 /*
  * Debugging dump, used in various places to see what's going on.
  */
@@ -310,29 +284,6 @@ void via_debug_dump(void)
 	}
 }
 
-/*
- * This is always executed with interrupts disabled.
- *
- * TBI: get time offset between scheduling timer ticks
- */
-
-u32 mac_gettimeoffset(void)
-{
-	unsigned long ticks, offset = 0;
-
-	/* read VIA1 timer 2 current value */
-	ticks = via1[vT1CL] | (via1[vT1CH] << 8);
-	/* The probability of underflow is less than 2% */
-	if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50)
-		/* Check for pending timer interrupt in VIA1 IFR */
-		if (via1[vIFR] & 0x40) offset = TICK_SIZE;
-
-	ticks = MAC_CLOCK_TICK - ticks;
-	ticks = ticks * 10000L / MAC_CLOCK_TICK;
-
-	return (ticks + offset) * 1000;
-}
-
 /*
  * Flush the L2 cache on Macs that have it by flipping
  * the system into 24-bit mode for an instant.
@@ -618,3 +569,56 @@ int via2_scsi_drq_pending(void)
 	return via2[gIFR] & (1 << IRQ_IDX(IRQ_MAC_SCSIDRQ));
 }
 EXPORT_SYMBOL(via2_scsi_drq_pending);
+
+/* timer and clock source */
+
+#define VIA_CLOCK_FREQ     783360                /* VIA "phase 2" clock in Hz */
+#define VIA_TIMER_INTERVAL (1000000 / HZ)        /* microseconds per jiffy */
+#define VIA_TIMER_CYCLES   (VIA_CLOCK_FREQ / HZ) /* clock cycles per jiffy */
+
+#define VIA_TC             (VIA_TIMER_CYCLES - 2) /* including 0 and -1 */
+#define VIA_TC_LOW         (VIA_TC & 0xFF)
+#define VIA_TC_HIGH        (VIA_TC >> 8)
+
+void __init via_init_clock(irq_handler_t timer_routine)
+{
+	if (request_irq(IRQ_MAC_TIMER_1, timer_routine, 0, "timer", NULL)) {
+		pr_err("Couldn't register %s interrupt\n", "timer");
+		return;
+	}
+
+	via1[vT1LL] = VIA_TC_LOW;
+	via1[vT1LH] = VIA_TC_HIGH;
+	via1[vT1CL] = VIA_TC_LOW;
+	via1[vT1CH] = VIA_TC_HIGH;
+	via1[vACR] |= 0x40;
+}
+
+u32 mac_gettimeoffset(void)
+{
+	unsigned long flags;
+	u8 count_high;
+	u16 count, offset = 0;
+
+	/*
+	 * Timer counter wrap-around is detected with the timer interrupt flag
+	 * but reading the counter low byte (vT1CL) would reset the flag.
+	 * Also, accessing both counter registers is essentially a data race.
+	 * These problems are avoided by ignoring the low byte. Clock accuracy
+	 * is 256 times worse (error can reach 0.327 ms) but CPU overhead is
+	 * reduced by avoiding slow VIA register accesses.
+	 */
+
+	local_irq_save(flags);
+	count_high = via1[vT1CH];
+	if (count_high == 0xFF)
+		count_high = 0;
+	if (count_high > 0 && (via1[vIFR] & VIA_TIMER_1_INT))
+		offset = VIA_TIMER_CYCLES;
+	local_irq_restore(flags);
+
+	count = count_high << 8;
+	count = VIA_TIMER_CYCLES - count + offset;
+
+	return ((count * VIA_TIMER_INTERVAL) / VIA_TIMER_CYCLES) * 1000;
+}
-- 
2.18.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v4 08/14] m68k: hp300: Convert to clocksource API
  2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
                   ` (10 preceding siblings ...)
  2018-12-01  0:53 ` [PATCH v4 14/14] m68k: mvme16x: Handle timer counter overflow Finn Thain
@ 2018-12-01  0:53 ` Finn Thain
  2018-12-01  0:53 ` [PATCH v4 06/14] m68k: atari: " Finn Thain
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Finn Thain @ 2018-12-01  0:53 UTC (permalink / raw)
  To: Geert Uytterhoeven, Philip Blundell
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
Changed since v1:
 - Moved clk_total access to within the irq lock.
 - Use type u32 for tick counter.
---
 arch/m68k/hp300/time.c | 37 ++++++++++++++++++++++++++++++-------
 1 file changed, 30 insertions(+), 7 deletions(-)

diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
index d30b03ea93a2..90982803a629 100644
--- a/arch/m68k/hp300/time.c
+++ b/arch/m68k/hp300/time.c
@@ -8,6 +8,7 @@
  */
 
 #include <asm/ptrace.h>
+#include <linux/clocksource.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/sched.h>
@@ -19,6 +20,18 @@
 #include <asm/traps.h>
 #include <asm/blinken.h>
 
+static u64 hp300_read_clk(struct clocksource *cs);
+
+static struct clocksource hp300_clk = {
+	.name   = "timer",
+	.rating = 250,
+	.read   = hp300_read_clk,
+	.mask   = CLOCKSOURCE_MASK(32),
+	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static u32 clk_total;
+
 /* Clock hardware definitions */
 
 #define CLOCKBASE	0xf05f8000
@@ -32,9 +45,10 @@
 #define	CLKMSB3		0xD
 
 /* This is for machines which generate the exact clock. */
-#define USECS_PER_JIFFY (1000000/HZ)
 
-#define INTVAL ((10000 / 4) - 1)
+#define HP300_TIMER_CLOCK_FREQ 250000
+#define HP300_TIMER_CYCLES     (HP300_TIMER_CLOCK_FREQ / HZ)
+#define INTVAL                 (HP300_TIMER_CYCLES - 1)
 
 static irqreturn_t hp300_tick(int irq, void *dev_id)
 {
@@ -45,6 +59,7 @@ static irqreturn_t hp300_tick(int irq, void *dev_id)
 	local_irq_save(flags);
 	in_8(CLOCKBASE + CLKSR);
 	asm volatile ("movpw %1@(5),%0" : "=d" (tmp) : "a" (CLOCKBASE));
+	clk_total += INTVAL;
 	timer_routine(0, NULL);
 	local_irq_restore(flags);
 
@@ -53,20 +68,26 @@ static irqreturn_t hp300_tick(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-u32 hp300_gettimeoffset(void)
+static u64 hp300_read_clk(struct clocksource *cs)
 {
-  /* Read current timer 1 value */
+  unsigned long flags;
   unsigned char lsb, msb1, msb2;
-  unsigned short ticks;
+  u32 ticks;
 
+  local_irq_save(flags);
+  /* Read current timer 1 value */
   msb1 = in_8(CLOCKBASE + 5);
   lsb = in_8(CLOCKBASE + 7);
   msb2 = in_8(CLOCKBASE + 5);
   if (msb1 != msb2)
     /* A carry happened while we were reading.  Read it again */
     lsb = in_8(CLOCKBASE + 7);
+
   ticks = INTVAL - ((msb2 << 8) | lsb);
-  return ((USECS_PER_JIFFY * ticks) / INTVAL) * 1000;
+  ticks += clk_total;
+  local_irq_restore(flags);
+
+  return ticks;
 }
 
 void __init hp300_sched_init(irq_handler_t vector)
@@ -76,9 +97,11 @@ void __init hp300_sched_init(irq_handler_t vector)
 
   asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
 
-  if (request_irq(IRQ_AUTO_6, hp300_tick, 0, "timer tick", vector))
+  if (request_irq(IRQ_AUTO_6, hp300_tick, IRQF_TIMER, "timer tick", vector))
     pr_err("Couldn't register timer interrupt\n");
 
   out_8(CLOCKBASE + CLKCR2, 0x1);		/* select CR1 */
   out_8(CLOCKBASE + CLKCR1, 0x40);		/* enable irq */
+
+  clocksource_register_hz(&hp300_clk, HP300_TIMER_CLOCK_FREQ);
 }
-- 
2.18.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v4 13/14] m68k: mvme16x: Convert to clocksource API
  2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
                   ` (5 preceding siblings ...)
  2018-12-01  0:53 ` [PATCH v4 12/14] m68k: mvme147: Handle timer counter overflow Finn Thain
@ 2018-12-01  0:53 ` Finn Thain
  2018-12-01  0:53 ` [PATCH v4 10/14] m68k: mac: " Finn Thain
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Finn Thain @ 2018-12-01  0:53 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
Changed since v1:
 - Moved clk_total access to within the irq lock.
---
 arch/m68k/mvme16x/config.c | 37 +++++++++++++++++++++++++++++++------
 1 file changed, 31 insertions(+), 6 deletions(-)

diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index 3a3129e6f0bc..2c109ee2a1a5 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -19,6 +19,7 @@
 #include <linux/mm.h>
 #include <linux/seq_file.h>
 #include <linux/tty.h>
+#include <linux/clocksource.h>
 #include <linux/console.h>
 #include <linux/linkage.h>
 #include <linux/init.h>
@@ -343,6 +344,21 @@ static irqreturn_t mvme16x_abort_int (int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static u64 mvme16x_read_clk(struct clocksource *cs);
+
+static struct clocksource mvme16x_clk = {
+	.name   = "pcc",
+	.rating = 250,
+	.read   = mvme16x_read_clk,
+	.mask   = CLOCKSOURCE_MASK(32),
+	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static u32 clk_total;
+
+#define PCC_TIMER_CLOCK_FREQ 1000000
+#define PCC_TIMER_CYCLES     (PCC_TIMER_CLOCK_FREQ / HZ)
+
 static irqreturn_t mvme16x_timer_int (int irq, void *dev_id)
 {
 	irq_handler_t timer_routine = dev_id;
@@ -350,6 +366,7 @@ static irqreturn_t mvme16x_timer_int (int irq, void *dev_id)
 
 	local_irq_save(flags);
 	*(volatile unsigned char *)0xfff4201b |= 8;
+	clk_total += PCC_TIMER_CYCLES;
 	timer_routine(0, NULL);
 	local_irq_restore(flags);
 
@@ -363,13 +380,15 @@ void mvme16x_sched_init (irq_handler_t timer_routine)
 
     /* Using PCCchip2 or MC2 chip tick timer 1 */
     *(volatile unsigned long *)0xfff42008 = 0;
-    *(volatile unsigned long *)0xfff42004 = 10000;	/* 10ms */
+    *(volatile unsigned long *)0xfff42004 = PCC_TIMER_CYCLES;
     *(volatile unsigned char *)0xfff42017 |= 3;
     *(volatile unsigned char *)0xfff4201b = 0x16;
-    if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, 0, "timer",
+    if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, IRQF_TIMER, "timer",
                     timer_routine))
 	panic ("Couldn't register timer int");
 
+    clocksource_register_hz(&mvme16x_clk, PCC_TIMER_CLOCK_FREQ);
+
     if (brdno == 0x0162 || brdno == 0x172)
 	irq = MVME162_IRQ_ABORT;
     else
@@ -379,11 +398,17 @@ void mvme16x_sched_init (irq_handler_t timer_routine)
 	panic ("Couldn't register abort int");
 }
 
-
-/* This is always executed with interrupts disabled.  */
-u32 mvme16x_gettimeoffset(void)
+static u64 mvme16x_read_clk(struct clocksource *cs)
 {
-    return (*(volatile u32 *)0xfff42008) * 1000;
+	unsigned long flags;
+	u32 ticks;
+
+	local_irq_save(flags);
+	ticks = *(volatile u32 *)0xfff42008;
+	ticks += clk_total;
+	local_irq_restore(flags);
+
+	return ticks;
 }
 
 int bcd2int (unsigned char b)
-- 
2.18.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v4 05/14] m68k: amiga: Convert to clocksource API
  2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
@ 2018-12-01  0:53 ` Finn Thain
  2018-12-01  0:53 ` [PATCH v4 02/14] m68k: mac: Fix VIA timer counter accesses Finn Thain
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Finn Thain @ 2018-12-01  0:53 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Tested-by: Michael Schmitz <schmitzmic@gmail.com>
---
Changed since v3:
 - Don't test for timer counter > 0 as that should always be true.
 - Use clk_offset variable to track the offset when the irq check is skipped.

Changed since v2:
 - Don't check for timer interrupt in amiga_read_clk() when the timer is
about to be reloaded.

Changed since v1:
 - Moved clk_total access to within the irq lock.
---
 arch/m68k/amiga/config.c | 46 ++++++++++++++++++++++++++++++++--------
 1 file changed, 37 insertions(+), 9 deletions(-)

diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index d4976c1aa0cc..c32ab8041cf6 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -17,6 +17,7 @@
 #include <linux/mm.h>
 #include <linux/seq_file.h>
 #include <linux/tty.h>
+#include <linux/clocksource.h>
 #include <linux/console.h>
 #include <linux/rtc.h>
 #include <linux/init.h>
@@ -461,7 +462,29 @@ void __init config_amiga(void)
 		*(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80;
 }
 
+static u64 amiga_read_clk(struct clocksource *cs);
+
+static struct clocksource amiga_clk = {
+	.name   = "ciab",
+	.rating = 250,
+	.read   = amiga_read_clk,
+	.mask   = CLOCKSOURCE_MASK(32),
+	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
 static unsigned short jiffy_ticks;
+static u32 clk_total, clk_offset;
+
+static irqreturn_t ciab_timer_handler(int irq, void *dev_id)
+{
+	irq_handler_t timer_routine = dev_id;
+
+	clk_total += jiffy_ticks;
+	clk_offset = 0;
+	timer_routine(0, NULL);
+
+	return IRQ_HANDLED;
+}
 
 static void __init amiga_sched_init(irq_handler_t timer_routine)
 {
@@ -481,19 +504,22 @@ static void __init amiga_sched_init(irq_handler_t timer_routine)
 	 * Please don't change this to use ciaa, as it interferes with the
 	 * SCSI code. We'll have to take a look at this later
 	 */
-	if (request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL))
+	if (request_irq(IRQ_AMIGA_CIAB_TA, ciab_timer_handler, IRQF_TIMER,
+			"timer", timer_routine))
 		pr_err("Couldn't register timer interrupt\n");
 	/* start timer */
 	ciab.cra |= 0x11;
-}
 
-#define TICK_SIZE 10000
+	clocksource_register_hz(&amiga_clk, amiga_eclock);
+}
 
-/* This is always executed with interrupts disabled.  */
-static u32 amiga_gettimeoffset(void)
+static u64 amiga_read_clk(struct clocksource *cs)
 {
 	unsigned short hi, lo, hi2;
-	u32 ticks, offset = 0;
+	unsigned long flags;
+	u32 ticks;
+
+	local_irq_save(flags);
 
 	/* read CIA B timer A current value */
 	hi  = ciab.tahi;
@@ -510,12 +536,14 @@ static u32 amiga_gettimeoffset(void)
 	if (ticks > jiffy_ticks / 2)
 		/* check for pending interrupt */
 		if (cia_set_irq(&ciab_base, 0) & CIA_ICR_TA)
-			offset = 10000;
+			clk_offset = jiffy_ticks;
 
 	ticks = jiffy_ticks - ticks;
-	ticks = (10000 * ticks) / jiffy_ticks;
+	ticks += clk_offset + clk_total;
+
+	local_irq_restore(flags);
 
-	return (ticks + offset) * 1000;
+	return ticks;
 }
 
 static void amiga_reset(void)  __noreturn;
-- 
2.18.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v4 07/14] m68k: bvme6000: Convert to clocksource API
  2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
                   ` (8 preceding siblings ...)
  2018-12-01  0:53 ` [PATCH v4 04/14] m68k: Drop ARCH_USES_GETTIMEOFFSET Finn Thain
@ 2018-12-01  0:53 ` Finn Thain
  2018-12-01  0:53 ` [PATCH v4 14/14] m68k: mvme16x: Handle timer counter overflow Finn Thain
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Finn Thain @ 2018-12-01  0:53 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
Changed since v3:
 - Use clk_offset variable to track the offset when the irq check is skipped.

Changed since v2:
 - Don't check for timer interrupt in bvme6000_read_clk() when the timer is
about to be reloaded.

Changed since v1:
 - Moved clk_total access to within the irq lock.
---
 arch/m68k/bvme6000/config.c | 57 ++++++++++++++++++++++++++-----------
 1 file changed, 41 insertions(+), 16 deletions(-)

diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index c8b99d5516d1..8ebaabc931cd 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
+#include <linux/clocksource.h>
 #include <linux/console.h>
 #include <linux/linkage.h>
 #include <linux/init.h>
@@ -147,6 +148,21 @@ irqreturn_t bvme6000_abort_int (int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static u64 bvme6000_read_clk(struct clocksource *cs);
+
+static struct clocksource bvme6000_clk = {
+	.name   = "rtc",
+	.rating = 250,
+	.read   = bvme6000_read_clk,
+	.mask   = CLOCKSOURCE_MASK(32),
+	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static u32 clk_total, clk_offset;
+
+#define RTC_TIMER_CLOCK_FREQ 8000000
+#define RTC_TIMER_CYCLES     (RTC_TIMER_CLOCK_FREQ / HZ)
+#define RTC_TIMER_COUNT      ((RTC_TIMER_CYCLES / 2) - 1)
 
 static irqreturn_t bvme6000_timer_int (int irq, void *dev_id)
 {
@@ -158,6 +174,8 @@ static irqreturn_t bvme6000_timer_int (int irq, void *dev_id)
     local_irq_save(flags);
     msr = rtc->msr & 0xc0;
     rtc->msr = msr | 0x20;		/* Ack the interrupt */
+    clk_total += RTC_TIMER_CYCLES;
+    clk_offset = 0;
     timer_routine(0, NULL);
     local_irq_restore(flags);
 
@@ -180,13 +198,13 @@ void bvme6000_sched_init (irq_handler_t timer_routine)
 
     rtc->msr = 0;	/* Ensure timer registers accessible */
 
-    if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, 0, "timer",
+    if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, IRQF_TIMER, "timer",
                     timer_routine))
 	panic ("Couldn't register timer int");
 
     rtc->t1cr_omr = 0x04;	/* Mode 2, ext clk */
-    rtc->t1msb = 39999 >> 8;
-    rtc->t1lsb = 39999 & 0xff;
+    rtc->t1msb = RTC_TIMER_COUNT >> 8;
+    rtc->t1lsb = RTC_TIMER_COUNT & 0xff;
     rtc->irr_icr1 &= 0xef;	/* Route timer 1 to INTR pin */
     rtc->msr = 0x40;		/* Access int.cntrl, etc */
     rtc->pfr_icr0 = 0x80;	/* Just timer 1 ints enabled */
@@ -198,14 +216,14 @@ void bvme6000_sched_init (irq_handler_t timer_routine)
 
     rtc->msr = msr;
 
+    clocksource_register_hz(&bvme6000_clk, RTC_TIMER_CLOCK_FREQ);
+
     if (request_irq(BVME_IRQ_ABORT, bvme6000_abort_int, 0,
 				"abort", bvme6000_abort_int))
 	panic ("Couldn't register abort int");
 }
 
 
-/* This is always executed with interrupts disabled.  */
-
 /*
  * NOTE:  Don't accept any readings within 5us of rollover, as
  * the T1INT bit may be a little slow getting set.  There is also
@@ -213,14 +231,18 @@ void bvme6000_sched_init (irq_handler_t timer_routine)
  * results...
  */
 
-u32 bvme6000_gettimeoffset(void)
+static u64 bvme6000_read_clk(struct clocksource *cs)
 {
+    unsigned long flags;
     volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
     volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE;
-    unsigned char msr = rtc->msr & 0xc0;
+    unsigned char msr, msb;
     unsigned char t1int, t1op;
     u32 v = 800000, ov;
 
+    local_irq_save(flags);
+
+    msr = rtc->msr & 0xc0;
     rtc->msr = 0;	/* Ensure timer registers accessible */
 
     do {
@@ -228,22 +250,25 @@ u32 bvme6000_gettimeoffset(void)
 	t1int = rtc->msr & 0x20;
 	t1op  = pit->pcdr & 0x04;
 	rtc->t1cr_omr |= 0x40;		/* Latch timer1 */
-	v = rtc->t1msb << 8;		/* Read timer1 */
-	v |= rtc->t1lsb;		/* Read timer1 */
+	msb = rtc->t1msb;		/* Read timer1 */
+	v = (msb << 8) | rtc->t1lsb;	/* Read timer1 */
     } while (t1int != (rtc->msr & 0x20) ||
 		t1op != (pit->pcdr & 0x04) ||
 			abs(ov-v) > 80 ||
-				v > 39960);
+				v > RTC_TIMER_COUNT - (RTC_TIMER_COUNT / 100));
 
-    v = 39999 - v;
+    v = RTC_TIMER_COUNT - v;
     if (!t1op)				/* If in second half cycle.. */
-	v += 40000;
-    v /= 8;				/* Convert ticks to microseconds */
-    if (t1int)
-	v += 10000;			/* Int pending, + 10ms */
+	v += RTC_TIMER_CYCLES / 2;
+    if (msb > 0 && t1int)
+	clk_offset = RTC_TIMER_CYCLES;
     rtc->msr = msr;
 
-    return v * 1000;
+    v += clk_offset + clk_total;
+
+    local_irq_restore(flags);
+
+    return v;
 }
 
 /*
-- 
2.18.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v4 12/14] m68k: mvme147: Handle timer counter overflow
  2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
                   ` (4 preceding siblings ...)
  2018-12-01  0:53 ` [PATCH v4 03/14] m68k: apollo, q40, sun3, sun3x: Remove arch_gettimeoffset implementations Finn Thain
@ 2018-12-01  0:53 ` Finn Thain
  2018-12-01  0:53 ` [PATCH v4 13/14] m68k: mvme16x: Convert to clocksource API Finn Thain
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Finn Thain @ 2018-12-01  0:53 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

Reading the timer counter races with timer overflow (and the
corresponding interrupt). This is resolved by reading the overflow
register and taking this value into account. The interrupt handler
must clear the overflow register when it eventually executes.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
TODO: find a spare counter for the clocksource, rather than hanging
it off the HZ timer.
---
 arch/m68k/include/asm/mvme147hw.h |  1 +
 arch/m68k/mvme147/config.c        | 21 +++++++++++----------
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/arch/m68k/include/asm/mvme147hw.h b/arch/m68k/include/asm/mvme147hw.h
index 7c3dd513128e..257b29184af9 100644
--- a/arch/m68k/include/asm/mvme147hw.h
+++ b/arch/m68k/include/asm/mvme147hw.h
@@ -66,6 +66,7 @@ struct pcc_regs {
 #define PCC_INT_ENAB		0x08
 
 #define PCC_TIMER_INT_CLR	0x80
+#define PCC_TIMER_CLR_OVF	0x04
 
 #define PCC_LEVEL_ABORT		0x07
 #define PCC_LEVEL_SERIAL	0x04
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index c44a254e8a8c..545a1fe0e119 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -118,7 +118,7 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
 
 	local_irq_save(flags);
 	m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;
-	m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
+	m147_pcc->t1_cntrl = PCC_TIMER_CLR_OVF;
 	clk_total += PCC_TIMER_CYCLES;
 	timer_routine(0, NULL);
 	local_irq_restore(flags);
@@ -144,21 +144,22 @@ void mvme147_sched_init (irq_handler_t timer_routine)
 	clocksource_register_hz(&mvme147_clk, PCC_TIMER_CLOCK_FREQ);
 }
 
-/* XXX There are race hazards in this code XXX */
 static u64 mvme147_read_clk(struct clocksource *cs)
 {
 	unsigned long flags;
-	volatile unsigned short *cp = (volatile unsigned short *)0xfffe1012;
-	unsigned short n;
+	u8 overflow, tmp;
+	u16 count;
 	u32 ticks;
 
 	local_irq_save(flags);
-	n = *cp;
-	while (n != *cp)
-		n = *cp;
-
-	n -= PCC_TIMER_PRELOAD;
-	ticks = clk_total + n;
+	tmp = m147_pcc->t1_cntrl >> 4;
+	count = m147_pcc->t1_count;
+	overflow = m147_pcc->t1_cntrl >> 4;
+	if (overflow != tmp)
+		count = m147_pcc->t1_count;
+	count -= PCC_TIMER_PRELOAD;
+	ticks = count + overflow * PCC_TIMER_CYCLES;
+	ticks += clk_total;
 	local_irq_restore(flags);
 
 	return ticks;
-- 
2.18.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v4 03/14] m68k: apollo, q40, sun3, sun3x: Remove arch_gettimeoffset implementations
  2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
                   ` (3 preceding siblings ...)
  2018-12-01  0:53 ` [PATCH v4 09/14] m68k: hp300: Handle timer counter overflow Finn Thain
@ 2018-12-01  0:53 ` Finn Thain
  2018-12-01  0:53 ` [PATCH v4 12/14] m68k: mvme147: Handle timer counter overflow Finn Thain
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Finn Thain @ 2018-12-01  0:53 UTC (permalink / raw)
  To: Geert Uytterhoeven, Sam Creasey
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

These dummy implementations are no better than
default_arch_gettimeoffset() so remove them.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
 arch/m68k/apollo/config.c | 7 -------
 arch/m68k/q40/config.c    | 9 ---------
 arch/m68k/sun3/config.c   | 2 --
 arch/m68k/sun3/intersil.c | 7 -------
 arch/m68k/sun3x/config.c  | 1 -
 arch/m68k/sun3x/time.c    | 5 -----
 arch/m68k/sun3x/time.h    | 1 -
 7 files changed, 32 deletions(-)

diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
index aef8d42e078d..7d168e6dfb01 100644
--- a/arch/m68k/apollo/config.c
+++ b/arch/m68k/apollo/config.c
@@ -29,7 +29,6 @@ u_long apollo_model;
 
 extern void dn_sched_init(irq_handler_t handler);
 extern void dn_init_IRQ(void);
-extern u32 dn_gettimeoffset(void);
 extern int dn_dummy_hwclk(int, struct rtc_time *);
 extern void dn_dummy_reset(void);
 #ifdef CONFIG_HEARTBEAT
@@ -152,7 +151,6 @@ void __init config_apollo(void)
 
 	mach_sched_init=dn_sched_init; /* */
 	mach_init_IRQ=dn_init_IRQ;
-	arch_gettimeoffset   = dn_gettimeoffset;
 	mach_max_dma_address = 0xffffffff;
 	mach_hwclk           = dn_dummy_hwclk; /* */
 	mach_reset	     = dn_dummy_reset;  /* */
@@ -205,11 +203,6 @@ void dn_sched_init(irq_handler_t timer_routine)
 		pr_err("Couldn't register timer interrupt\n");
 }
 
-u32 dn_gettimeoffset(void)
-{
-	return 0xdeadbeef;
-}
-
 int dn_dummy_hwclk(int op, struct rtc_time *t) {
 
 
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 96810d91da2b..e63eb5f06999 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -40,7 +40,6 @@ extern void q40_init_IRQ(void);
 static void q40_get_model(char *model);
 extern void q40_sched_init(irq_handler_t handler);
 
-static u32 q40_gettimeoffset(void);
 static int q40_hwclk(int, struct rtc_time *);
 static unsigned int q40_get_ss(void);
 static int q40_get_rtc_pll(struct rtc_pll_info *pll);
@@ -169,7 +168,6 @@ void __init config_q40(void)
 	mach_sched_init = q40_sched_init;
 
 	mach_init_IRQ = q40_init_IRQ;
-	arch_gettimeoffset = q40_gettimeoffset;
 	mach_hwclk = q40_hwclk;
 	mach_get_ss = q40_get_ss;
 	mach_get_rtc_pll = q40_get_rtc_pll;
@@ -201,13 +199,6 @@ int __init q40_parse_bootinfo(const struct bi_record *rec)
 	return 1;
 }
 
-
-static u32 q40_gettimeoffset(void)
-{
-	return 5000 * (ql_ticks != 0) * 1000;
-}
-
-
 /*
  * Looks like op is non-zero for setting the clock, and zero for
  * reading the clock.
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index 79a2bb857906..867e68d92c71 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -37,7 +37,6 @@
 
 char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
 
-extern u32 sun3_gettimeoffset(void);
 static void sun3_sched_init(irq_handler_t handler);
 extern void sun3_get_model (char* model);
 extern int sun3_hwclk(int set, struct rtc_time *t);
@@ -138,7 +137,6 @@ void __init config_sun3(void)
         mach_sched_init      =  sun3_sched_init;
         mach_init_IRQ        =  sun3_init_IRQ;
         mach_reset           =  sun3_reboot;
-	arch_gettimeoffset   =  sun3_gettimeoffset;
 	mach_get_model	     =  sun3_get_model;
 	mach_hwclk           =  sun3_hwclk;
 	mach_halt	     =  sun3_halt;
diff --git a/arch/m68k/sun3/intersil.c b/arch/m68k/sun3/intersil.c
index d911070af02a..8fc74864de81 100644
--- a/arch/m68k/sun3/intersil.c
+++ b/arch/m68k/sun3/intersil.c
@@ -22,13 +22,6 @@
 #define STOP_VAL (INTERSIL_STOP | INTERSIL_INT_ENABLE | INTERSIL_24H_MODE)
 #define START_VAL (INTERSIL_RUN | INTERSIL_INT_ENABLE | INTERSIL_24H_MODE)
 
-/* does this need to be implemented? */
-u32 sun3_gettimeoffset(void)
-{
-  return 1000;
-}
-
-
 /* get/set hwclock */
 
 int sun3_hwclk(int set, struct rtc_time *t)
diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c
index 33d3a1c6fba0..03ce7f9facfe 100644
--- a/arch/m68k/sun3x/config.c
+++ b/arch/m68k/sun3x/config.c
@@ -49,7 +49,6 @@ void __init config_sun3x(void)
 	mach_sched_init      = sun3x_sched_init;
 	mach_init_IRQ        = sun3_init_IRQ;
 
-	arch_gettimeoffset   = sun3x_gettimeoffset;
 	mach_reset           = sun3x_reboot;
 
 	mach_hwclk           = sun3x_hwclk;
diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c
index 3c8a86d08508..9163294b0fb6 100644
--- a/arch/m68k/sun3x/time.c
+++ b/arch/m68k/sun3x/time.c
@@ -73,11 +73,6 @@ int sun3x_hwclk(int set, struct rtc_time *t)
 
 	return 0;
 }
-/* Not much we can do here */
-u32 sun3x_gettimeoffset(void)
-{
-    return 0L;
-}
 
 #if 0
 static irqreturn_t sun3x_timer_tick(int irq, void *dev_id)
diff --git a/arch/m68k/sun3x/time.h b/arch/m68k/sun3x/time.h
index 496f406412ad..86ce78bb3c28 100644
--- a/arch/m68k/sun3x/time.h
+++ b/arch/m68k/sun3x/time.h
@@ -3,7 +3,6 @@
 #define SUN3X_TIME_H
 
 extern int sun3x_hwclk(int set, struct rtc_time *t);
-u32 sun3x_gettimeoffset(void);
 void sun3x_sched_init(irq_handler_t vector);
 
 struct mostek_dt {
-- 
2.18.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v4 04/14] m68k: Drop ARCH_USES_GETTIMEOFFSET
  2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
                   ` (7 preceding siblings ...)
  2018-12-01  0:53 ` [PATCH v4 10/14] m68k: mac: " Finn Thain
@ 2018-12-01  0:53 ` Finn Thain
  2018-12-01  0:53 ` [PATCH v4 07/14] m68k: bvme6000: Convert to clocksource API Finn Thain
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Finn Thain @ 2018-12-01  0:53 UTC (permalink / raw)
  To: Geert Uytterhoeven, Philip Blundell, Joshua Thompson
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

The functions that implement arch_gettimeoffset are re-used by
new clocksource drivers in subsequent patches.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/m68k/Kconfig           | 1 -
 arch/m68k/amiga/config.c    | 3 ---
 arch/m68k/atari/config.c    | 2 --
 arch/m68k/bvme6000/config.c | 2 --
 arch/m68k/hp300/config.c    | 1 -
 arch/m68k/hp300/time.h      | 1 -
 arch/m68k/mac/config.c      | 3 ---
 arch/m68k/mvme147/config.c  | 2 --
 arch/m68k/mvme16x/config.c  | 2 --
 9 files changed, 17 deletions(-)

diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 070553791e97..cc62660a5760 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -19,7 +19,6 @@ config M68K
 	select GENERIC_STRNCPY_FROM_USER if MMU
 	select GENERIC_STRNLEN_USER if MMU
 	select ARCH_WANT_IPC_PARSE_VERSION
-	select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE
 	select HAVE_FUTEX_CMPXCHG if MMU && FUTEX
 	select HAVE_MOD_ARCH_SPECIFIC
 	select MODULES_USE_ELF_REL
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 65f63a457130..d4976c1aa0cc 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -95,8 +95,6 @@ static char amiga_model_name[13] = "Amiga ";
 static void amiga_sched_init(irq_handler_t handler);
 static void amiga_get_model(char *model);
 static void amiga_get_hardware_list(struct seq_file *m);
-/* amiga specific timer functions */
-static u32 amiga_gettimeoffset(void);
 extern void amiga_mksound(unsigned int count, unsigned int ticks);
 static void amiga_reset(void);
 extern void amiga_init_sound(void);
@@ -386,7 +384,6 @@ void __init config_amiga(void)
 	mach_init_IRQ        = amiga_init_IRQ;
 	mach_get_model       = amiga_get_model;
 	mach_get_hardware_list = amiga_get_hardware_list;
-	arch_gettimeoffset   = amiga_gettimeoffset;
 
 	/*
 	 * default MAX_DMA=0xffffffff on all machines. If we don't do so, the SCSI
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index bd96702a1ad0..89e65be2655f 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -78,7 +78,6 @@ static void atari_heartbeat(int on);
 
 /* atari specific timer functions (in time.c) */
 extern void atari_sched_init(irq_handler_t);
-extern u32 atari_gettimeoffset(void);
 extern int atari_mste_hwclk (int, struct rtc_time *);
 extern int atari_tt_hwclk (int, struct rtc_time *);
 
@@ -205,7 +204,6 @@ void __init config_atari(void)
 	mach_init_IRQ        = atari_init_IRQ;
 	mach_get_model	 = atari_get_model;
 	mach_get_hardware_list = atari_get_hardware_list;
-	arch_gettimeoffset   = atari_gettimeoffset;
 	mach_reset           = atari_reset;
 	mach_max_dma_address = 0xffffff;
 #if IS_ENABLED(CONFIG_INPUT_M68K_BEEP)
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index 0e5efed4da86..c8b99d5516d1 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -39,7 +39,6 @@
 
 static void bvme6000_get_model(char *model);
 extern void bvme6000_sched_init(irq_handler_t handler);
-extern u32 bvme6000_gettimeoffset(void);
 extern int bvme6000_hwclk (int, struct rtc_time *);
 extern void bvme6000_reset (void);
 void bvme6000_set_vectors (void);
@@ -105,7 +104,6 @@ void __init config_bvme6000(void)
     mach_max_dma_address = 0xffffffff;
     mach_sched_init      = bvme6000_sched_init;
     mach_init_IRQ        = bvme6000_init_IRQ;
-    arch_gettimeoffset   = bvme6000_gettimeoffset;
     mach_hwclk           = bvme6000_hwclk;
     mach_reset		 = bvme6000_reset;
     mach_get_model       = bvme6000_get_model;
diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c
index a19bcd23f80b..a161d44fd20b 100644
--- a/arch/m68k/hp300/config.c
+++ b/arch/m68k/hp300/config.c
@@ -254,7 +254,6 @@ void __init config_hp300(void)
 	mach_sched_init      = hp300_sched_init;
 	mach_init_IRQ        = hp300_init_IRQ;
 	mach_get_model       = hp300_get_model;
-	arch_gettimeoffset   = hp300_gettimeoffset;
 	mach_hwclk	     = hp300_hwclk;
 	mach_get_ss	     = hp300_get_ss;
 	mach_reset           = hp300_reset;
diff --git a/arch/m68k/hp300/time.h b/arch/m68k/hp300/time.h
index f5583ec4033d..1d77b55cc72a 100644
--- a/arch/m68k/hp300/time.h
+++ b/arch/m68k/hp300/time.h
@@ -1,2 +1 @@
 extern void hp300_sched_init(irq_handler_t vector);
-extern u32 hp300_gettimeoffset(void);
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index cd9317d53276..11be08f4f750 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -54,8 +54,6 @@ struct mac_booter_data mac_bi_data;
 /* The phys. video addr. - might be bogus on some machines */
 static unsigned long mac_orig_videoaddr;
 
-/* Mac specific timer functions */
-extern u32 mac_gettimeoffset(void);
 extern int mac_hwclk(int, struct rtc_time *);
 extern void iop_preinit(void);
 extern void iop_init(void);
@@ -155,7 +153,6 @@ void __init config_mac(void)
 	mach_sched_init = mac_sched_init;
 	mach_init_IRQ = mac_init_IRQ;
 	mach_get_model = mac_get_model;
-	arch_gettimeoffset = mac_gettimeoffset;
 	mach_hwclk = mac_hwclk;
 	mach_reset = mac_reset;
 	mach_halt = mac_poweroff;
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index 93c68d2b8e0e..4ef4faa5ed8b 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -38,7 +38,6 @@
 
 static void mvme147_get_model(char *model);
 extern void mvme147_sched_init(irq_handler_t handler);
-extern u32 mvme147_gettimeoffset(void);
 extern int mvme147_hwclk (int, struct rtc_time *);
 extern void mvme147_reset (void);
 
@@ -84,7 +83,6 @@ void __init config_mvme147(void)
 	mach_max_dma_address	= 0x01000000;
 	mach_sched_init		= mvme147_sched_init;
 	mach_init_IRQ		= mvme147_init_IRQ;
-	arch_gettimeoffset	= mvme147_gettimeoffset;
 	mach_hwclk		= mvme147_hwclk;
 	mach_reset		= mvme147_reset;
 	mach_get_model		= mvme147_get_model;
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index 5feb3ab484d0..3a3129e6f0bc 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -44,7 +44,6 @@ 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 u32 mvme16x_gettimeoffset(void);
 extern int mvme16x_hwclk (int, struct rtc_time *);
 extern void mvme16x_reset (void);
 
@@ -272,7 +271,6 @@ void __init config_mvme16x(void)
     mach_max_dma_address = 0xffffffff;
     mach_sched_init      = mvme16x_sched_init;
     mach_init_IRQ        = mvme16x_init_IRQ;
-    arch_gettimeoffset   = mvme16x_gettimeoffset;
     mach_hwclk           = mvme16x_hwclk;
     mach_reset		 = mvme16x_reset;
     mach_get_model       = mvme16x_get_model;
-- 
2.18.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API
@ 2018-12-01  0:53 Finn Thain
  2018-12-01  0:53 ` [PATCH v4 05/14] m68k: amiga: Convert to " Finn Thain
                   ` (14 more replies)
  0 siblings, 15 replies; 20+ messages in thread
From: Finn Thain @ 2018-12-01  0:53 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

This series removes "select ARCH_USES_GETTIMEOFFSET" from arch/m68k
and converts users of arch_gettimeoffset to the clocksource API.
Various bugs are fixed along the way.

Those platforms which do not actually implement arch_gettimeoffset
(apollo, q40, sun3, sun3x) use the "jiffies" clocksource by default.

The difficulty with these patches is the use of the timer interrupt to
update the counter for the clock source. The timer interrupt handler races
with clocksource read method, and both of those functions race with the
timer hardware.

Hence, more testing would be appreciated. To my knowledge, the conversion
patches for bvme6000, hp300, mvme147 and mvme16x are still untested.

Changed since v3:
 - Various improvements to amiga, mac, bvme6000 and hp300 conversions
summarized in the relevant patches.
 - Added tested-by tags.

Changed since v2:
 - Reinstated patch "m68k: hp300: Convert to clocksource API", and added
a new patch "m68k: hp300: Handle timer counter overflow" to address 
monotonicity issues.
 - Omitted a minor cleanup patch which may be merged independently.
 - Various other changes summarized in the relevant patches.

Changed since v1:
 - Dropped patches 1/13 and 2/13. These were a failed attempt to fix
5cfc8ee0bb51 and 4ad4c76b7afb. By adopting the clocksource API we can fix
this issue in mainline. By backporting this series we can fix it for -stable
(for m68k at least).
 - Dropped patch "m68k: hp300: Convert to clocksource API" and added
patch "m68k: hp300: Remove hp300_gettimeoffset".
 - Added a new patch to address an old m68k bug pointed out by Thomas
Gleixner. The bug can arise when a timer interrupt handler gets interrupted.
 - Added new patches to address old mvme16x and mvme147 bugs pointed out
by Thomas Gleixner. The bug could cause the clock to jump backwards.
 - Various other changes summarized in the relevant patches.


Finn Thain (14):
  m68k: Call timer_interrupt() with interrupts disabled
  m68k: mac: Fix VIA timer counter accesses
  m68k: apollo, q40, sun3, sun3x: Remove arch_gettimeoffset
    implementations
  m68k: Drop ARCH_USES_GETTIMEOFFSET
  m68k: amiga: Convert to clocksource API
  m68k: atari: Convert to clocksource API
  m68k: bvme6000: Convert to clocksource API
  m68k: hp300: Convert to clocksource API
  m68k: hp300: Handle timer counter overflow
  m68k: mac: Convert to clocksource API
  m68k: mvme147: Convert to clocksource API
  m68k: mvme147: Handle timer counter overflow
  m68k: mvme16x: Convert to clocksource API
  m68k: mvme16x: Handle timer counter overflow

 arch/m68k/Kconfig                 |   1 -
 arch/m68k/amiga/cia.c             |   9 ++
 arch/m68k/amiga/config.c          |  49 +++++++---
 arch/m68k/apollo/config.c         |   7 --
 arch/m68k/atari/ataints.c         |   4 +-
 arch/m68k/atari/config.c          |   2 -
 arch/m68k/atari/time.c            |  70 ++++++++++----
 arch/m68k/bvme6000/config.c       |  77 ++++++++++------
 arch/m68k/hp300/config.c          |   1 -
 arch/m68k/hp300/time.c            |  73 +++++++++++----
 arch/m68k/hp300/time.h            |   1 -
 arch/m68k/include/asm/mvme147hw.h |   2 +-
 arch/m68k/mac/config.c            |   3 -
 arch/m68k/mac/via.c               | 146 ++++++++++++++++++++----------
 arch/m68k/mvme147/config.c        |  73 ++++++++++-----
 arch/m68k/mvme16x/config.c        |  97 ++++++++++++++------
 arch/m68k/q40/config.c            |   9 --
 arch/m68k/q40/q40ints.c           |  19 ++--
 arch/m68k/sun3/config.c           |   2 -
 arch/m68k/sun3/intersil.c         |   7 --
 arch/m68k/sun3/sun3ints.c         |   3 +
 arch/m68k/sun3x/config.c          |   1 -
 arch/m68k/sun3x/time.c            |  21 ++---
 arch/m68k/sun3x/time.h            |   1 -
 24 files changed, 445 insertions(+), 233 deletions(-)

-- 
2.18.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API
  2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
                   ` (13 preceding siblings ...)
  2018-12-01  0:53 ` [PATCH v4 11/14] m68k: mvme147: " Finn Thain
@ 2019-03-05  6:13 ` Finn Thain
  2019-03-05  7:50   ` Geert Uytterhoeven
  14 siblings, 1 reply; 20+ messages in thread
From: Finn Thain @ 2019-03-05  6:13 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k, linux-kernel

On Sat, 1 Dec 2018, Finn Thain wrote:

> This series removes "select ARCH_USES_GETTIMEOFFSET" from arch/m68k
> and converts users of arch_gettimeoffset to the clocksource API.
> Various bugs are fixed along the way.

Are there any plans to merge this series, Geert?

-- 

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API
  2019-03-05  6:13 ` [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt " Finn Thain
@ 2019-03-05  7:50   ` Geert Uytterhoeven
  2019-03-05  9:55     ` Finn Thain
  0 siblings, 1 reply; 20+ messages in thread
From: Geert Uytterhoeven @ 2019-03-05  7:50 UTC (permalink / raw)
  To: Finn Thain
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k,
	Linux Kernel Mailing List

Hi Finn,

On Tue, Mar 5, 2019 at 7:13 AM Finn Thain <fthain@telegraphics.com.au> wrote:
> On Sat, 1 Dec 2018, Finn Thain wrote:
> > This series removes "select ARCH_USES_GETTIMEOFFSET" from arch/m68k
> > and converts users of arch_gettimeoffset to the clocksource API.
> > Various bugs are fixed along the way.
>
> Are there any plans to merge this series, Geert?

Has this been tested on all/most platforms? Or do you think is it safe to
apply regardless?

Thanks!

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API
  2019-03-05  7:50   ` Geert Uytterhoeven
@ 2019-03-05  9:55     ` Finn Thain
  2019-03-05 12:01       ` Linus Walleij
  2019-03-25  9:25       ` Geert Uytterhoeven
  0 siblings, 2 replies; 20+ messages in thread
From: Finn Thain @ 2019-03-05  9:55 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k,
	Linux Kernel Mailing List

On Tue, 5 Mar 2019, Geert Uytterhoeven wrote:

> On Tue, Mar 5, 2019 at 7:13 AM Finn Thain <fthain@telegraphics.com.au> wrote:
> > On Sat, 1 Dec 2018, Finn Thain wrote:
> > > This series removes "select ARCH_USES_GETTIMEOFFSET" from arch/m68k
> > > and converts users of arch_gettimeoffset to the clocksource API.
> > > Various bugs are fixed along the way.
> >
> > Are there any plans to merge this series, Geert?
> 
> Has this been tested on all/most platforms? Or do you think is it safe to
> apply regardless?
> 

The amiga, atari and mac patches have been tested.

The apollo, q40, sun3 and sun3x patches are safe though untested, AFAIK. I 
confirmed that, in qemu at least, the default jiffies clocksource will 
work, and the patch is trivial.

That leaves bvme6000, hp300, mvme147 and mvme16x. Those have not been 
tested. Here are some options for those platforms:

1) Apply the patches untested (gaining new clocksources and some API 
modernization for m68k, while fixing old bugs and potentially introducing 
new bugs).

2) Do nothing until someone tests the patch series on those 4 platforms.

3) Rewrite patches such that those 4 platforms get the same treatment as 
apollo, q40, sun3 and sun3x (this plan was already nak'd in the hp300 
case).

4) Keep using the gettimeoffset API. Redo the patch series to keep the bug 
fixes for the 3 platforms that can be readily tested. When the API change 
becomes unavoidable, remove difficult platforms.

Maybe there are other possibilities?

-- 

> Thanks!
> 
> Gr{oetje,eeting}s,
> 
>                         Geert
> 
> 

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API
  2019-03-05  9:55     ` Finn Thain
@ 2019-03-05 12:01       ` Linus Walleij
  2019-03-25  9:25       ` Geert Uytterhoeven
  1 sibling, 0 replies; 20+ messages in thread
From: Linus Walleij @ 2019-03-05 12:01 UTC (permalink / raw)
  To: Finn Thain
  Cc: Geert Uytterhoeven, Andreas Schwab, Arnd Bergmann,
	Stephen N Chivers, Thomas Gleixner, Kars de Jong, Daniel Lezcano,
	Michael Schmitz, John Stultz, linux-m68k,
	Linux Kernel Mailing List

On Tue, Mar 5, 2019 at 10:55 AM Finn Thain <fthain@telegraphics.com.au> wrote:

> That leaves bvme6000, hp300, mvme147 and mvme16x. Those have not been
> tested. Here are some options for those platforms:
>
> 1) Apply the patches untested (gaining new clocksources and some API
> modernization for m68k, while fixing old bugs and potentially introducing
> new bugs).

This is what I usually do with ARM machines when I don't get any
tests or reviews after a reasonable time lap, > month for sure is
a reasonable time for users to have all opportunity in the world to
test patches.

If things break, users will report it as is custom and the author will
be expected to work with them to fix them then, we do this all the
time.

Those users who want everything tested before it gets merged should
provide resources or time for testing.

Just my €0.01
Linus Walleij

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API
  2019-03-05  9:55     ` Finn Thain
  2019-03-05 12:01       ` Linus Walleij
@ 2019-03-25  9:25       ` Geert Uytterhoeven
  1 sibling, 0 replies; 20+ messages in thread
From: Geert Uytterhoeven @ 2019-03-25  9:25 UTC (permalink / raw)
  To: Finn Thain
  Cc: Andreas Schwab, Arnd Bergmann, Stephen N Chivers,
	Thomas Gleixner, Kars de Jong, Daniel Lezcano, Michael Schmitz,
	John Stultz, Linus Walleij, linux-m68k,
	Linux Kernel Mailing List

Hi Finn,

On Tue, Mar 5, 2019 at 10:55 AM Finn Thain <fthain@telegraphics.com.au> wrote:
> On Tue, 5 Mar 2019, Geert Uytterhoeven wrote:
> > On Tue, Mar 5, 2019 at 7:13 AM Finn Thain <fthain@telegraphics.com.au> wrote:
> > > On Sat, 1 Dec 2018, Finn Thain wrote:
> > > > This series removes "select ARCH_USES_GETTIMEOFFSET" from arch/m68k
> > > > and converts users of arch_gettimeoffset to the clocksource API.
> > > > Various bugs are fixed along the way.
> > >
> > > Are there any plans to merge this series, Geert?
> >
> > Has this been tested on all/most platforms? Or do you think is it safe to
> > apply regardless?
> >
>
> The amiga, atari and mac patches have been tested.
>
> The apollo, q40, sun3 and sun3x patches are safe though untested, AFAIK. I
> confirmed that, in qemu at least, the default jiffies clocksource will
> work, and the patch is trivial.
>
> That leaves bvme6000, hp300, mvme147 and mvme16x. Those have not been
> tested. Here are some options for those platforms:
>
> 1) Apply the patches untested (gaining new clocksources and some API
> modernization for m68k, while fixing old bugs and potentially introducing
> new bugs).

Thank you, applied and queued for v5.2.

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

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

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2019-03-25  9:25 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-01  0:53 [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
2018-12-01  0:53 ` [PATCH v4 05/14] m68k: amiga: Convert to " Finn Thain
2018-12-01  0:53 ` [PATCH v4 02/14] m68k: mac: Fix VIA timer counter accesses Finn Thain
2018-12-01  0:53 ` [PATCH v4 01/14] m68k: Call timer_interrupt() with interrupts disabled Finn Thain
2018-12-01  0:53 ` [PATCH v4 09/14] m68k: hp300: Handle timer counter overflow Finn Thain
2018-12-01  0:53 ` [PATCH v4 03/14] m68k: apollo, q40, sun3, sun3x: Remove arch_gettimeoffset implementations Finn Thain
2018-12-01  0:53 ` [PATCH v4 12/14] m68k: mvme147: Handle timer counter overflow Finn Thain
2018-12-01  0:53 ` [PATCH v4 13/14] m68k: mvme16x: Convert to clocksource API Finn Thain
2018-12-01  0:53 ` [PATCH v4 10/14] m68k: mac: " Finn Thain
2018-12-01  0:53 ` [PATCH v4 04/14] m68k: Drop ARCH_USES_GETTIMEOFFSET Finn Thain
2018-12-01  0:53 ` [PATCH v4 07/14] m68k: bvme6000: Convert to clocksource API Finn Thain
2018-12-01  0:53 ` [PATCH v4 14/14] m68k: mvme16x: Handle timer counter overflow Finn Thain
2018-12-01  0:53 ` [PATCH v4 08/14] m68k: hp300: Convert to clocksource API Finn Thain
2018-12-01  0:53 ` [PATCH v4 06/14] m68k: atari: " Finn Thain
2018-12-01  0:53 ` [PATCH v4 11/14] m68k: mvme147: " Finn Thain
2019-03-05  6:13 ` [PATCH v4 00/14] m68k: Drop arch_gettimeoffset and adopt " Finn Thain
2019-03-05  7:50   ` Geert Uytterhoeven
2019-03-05  9:55     ` Finn Thain
2019-03-05 12:01       ` Linus Walleij
2019-03-25  9:25       ` Geert Uytterhoeven

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).