Re: m68k using deprecated internal APIs?

2018-11-11 Thread Finn Thain
On Mon, 12 Nov 2018, Michael Schmitz wrote:

> I'm wondering if disabling interrupts really is required when updating 
> the ticks counter in mfp_timer_handler, or whether READ_ONCE() and 
> WRITE_ONCE() would work as well.
> 

I get the impression from Documentation/core-api/atomic_ops.rst that the 
author is opposed to that kind of usage of READ_ONCE() and WRITE_ONCE().
Apparently these operations are to be used solely for avoiding certain 
compiler optimizations.

In this patch series I've used the same synchronization pattern for each 
platform for expediency. It is probably overkill in some places.

But looking at the atari patch agin, I think there is a bug. In 
atari_read_clk(), clk_total is accessed outside the irq lock. But it is 
supposed to be synchronized with the timer interrupt handler and timer 
interrupt flag. I'll have to change this.

> Note that there's a mfptimer_handler() in arch/m68k/atari/ataints.c 
> already (timer D, for polling interrupt-less hardware - I used to have 
> patches to adjust the rate of that timer at runtime...). Might be best 
> to rename the two (mfp_timerc_handler(), mfp_timerd_handler()) for 
> clarity. Or hook that timer function into the generic clocksource timer.
> 

OK, I'll rename them.

> > If I understand correctly, removing arch_gettimeoffset without adding 
> > a clocksource would reduce timer accuracy to 10 ms regardless of 
> > platform (because that's what the default jiffies clocksource offers).
> That's my understanding. I now see that we could quite easily change the 
> timer C divisor to 10 while retaining the timer C data (246) and obtain 
> a clocksource rate of 2500. Setting that in the clocksource 'rating' 
> field will keep the scheduling timer at 100 Hz, is that correct?
> 

The rating is arbitrary AFAICT. I gather that it just allows the 
clocksource core to select the best clocksource. The more accurate the 
clocksource, the higher its rating. You can see the available clocksources 
in dmesg.

> With only the timer C interrupt running at increased rate, I don't think 
> the impact on the system would be all that severe.
> 


If you need more timer accuracy, you'll need a faster oscillator driving 
the counter. But then you get counter overflow sooner, which may or may 
not be a problem.

This patch series avoids changing any device configuration (clock rates, 
dividers, interrupt rates etc.)

The exception is a VIA driver bug fix patch that is part of this series 
even though it is not related to the clocksource conversion. That patch 
got included just because of the mechanics of testing and merging patches.

If you were to write a timer patch relevant to -stable, it could go before 
my series, and I could rebase. Otherwise I suggest that it go afterwards, 
either at the end of this series or submitted separately with a note about 
the dependency.

-- 

> Cheers,
> 
> ??? Michael
> 
> 


Re: m68k using deprecated internal APIs?

2018-11-11 Thread Michael Schmitz
Hi Finn,

Am 12.11.18 um 17:34 schrieb Finn Thain:
> On Mon, 12 Nov 2018, Michael Schmitz wrote:
>
>> That's ultimately for Geert to decide - I'll yet have to look at your 
>> mac patches to even get a vague idea what this conversion involves, but 
>> I can certainly test whatever you came up with for Mac on Atari.
>>
> Thanks. I'll send out the latest patches for people to test.
Thanks - I just had a look at the Atari clocksource implementation and
it looks fine to me. I'm wondering if disabling interrupts really is
required when updating the ticks counter in mfp_timer_handler, or
whether READ_ONCE() and WRITE_ONCE() would work as well.

Note that there's a mfptimer_handler() in arch/m68k/atari/ataints.c
already (timer D, for polling interrupt-less hardware - I used to have
patches to adjust the rate of that timer at runtime...). Might be best
to rename the two (mfp_timerc_handler(), mfp_timerd_handler()) for
clarity. Or hook that timer function into the generic clocksource timer.

>
>> Tick granularity is 40 us at best on Atari with the current timer 
>> configuration, and can't be increased without increasing HZ. I suspect 
>> the limitations on Mac are similar?
>>
> If I understand correctly, removing arch_gettimeoffset without adding a 
> clocksource would reduce timer accuracy to 10 ms regardless of platform 
> (because that's what the default jiffies clocksource offers).
That's my understanding. I now see that we could quite easily change the
timer C divisor to 10 while retaining the timer C data (246) and obtain
a clocksource rate of 2500. Setting that in the clocksource 'rating'
field will keep the scheduling timer at 100 Hz, is that correct?

With only the timer C interrupt running at increased rate, I don't think
the impact on the system would be all that severe.

Cheers,

    Michael



[RFC PATCH 04/13] m68k: mac: Clean up unused timer definitions

2018-11-11 Thread Finn Thain
Cc: Joshua Thompson 
Signed-off-by: Finn Thain 
---
 arch/m68k/include/asm/macints.h | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/arch/m68k/include/asm/macints.h b/arch/m68k/include/asm/macints.h
index cddb2d3ea49b..4da172bd048c 100644
--- a/arch/m68k/include/asm/macints.h
+++ b/arch/m68k/include/asm/macints.h
@@ -121,7 +121,4 @@
 #define SLOT2IRQ(x)  (x + 47)
 #define IRQ2SLOT(x)  (x - 47)
 
-#define INT_CLK   24576/* CLK while int_clk =2.456MHz and divide = 
100 */
-#define INT_TICKS 246  /* to make sched_time = 99.902... HZ */
-
 #endif /* asm/macints.h */
-- 
2.18.1



[RFC PATCH 02/13] m68k: Fix mutual exclusion in arch_gettimeoffset

2018-11-11 Thread Finn Thain
Implementations of arch_gettimeoffset are generally not re-entrant
and assume that interrupts have been disabled. Unfortunately this
pre-condition got broken in v2.6.32.

Cc: Philip Blundell 
Cc: Michael Schmitz 
Cc: Joshua Thompson 
Fixes: 4ad4c76b7afb ("m68k: convert to use arch_gettimeoffset()")
Signed-off-by: Finn Thain 
---
 arch/m68k/amiga/config.c|  6 +-
 arch/m68k/atari/time.c  |  6 +-
 arch/m68k/bvme6000/config.c | 10 +++---
 arch/m68k/hp300/time.c  |  8 +++-
 arch/m68k/mac/via.c |  5 +
 arch/m68k/mvme147/config.c  |  6 +-
 arch/m68k/mvme16x/config.c  |  1 -
 7 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 65f63a457130..5ec3687984a9 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -492,12 +492,14 @@ static void __init amiga_sched_init(irq_handler_t 
timer_routine)
 
 #define TICK_SIZE 1
 
-/* This is always executed with interrupts disabled.  */
 static u32 amiga_gettimeoffset(void)
 {
+   unsigned long flags;
unsigned short hi, lo, hi2;
u32 ticks, offset = 0;
 
+   local_irq_save(flags);
+
/* read CIA B timer A current value */
hi  = ciab.tahi;
lo  = ciab.talo;
@@ -515,6 +517,8 @@ static u32 amiga_gettimeoffset(void)
if (cia_set_irq(_base, 0) & CIA_ICR_TA)
offset = 1;
 
+   local_irq_restore(flags);
+
ticks = jiffy_ticks - ticks;
ticks = (1 * ticks) / jiffy_ticks;
 
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index 9cca64286464..4765e9a58293 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -40,11 +40,13 @@ atari_sched_init(irq_handler_t timer_routine)
 
 #define TICK_SIZE 1
 
-/* This is always executed with interrupts disabled.  */
 u32 atari_gettimeoffset(void)
 {
+  unsigned long flags;
   u32 ticks, offset = 0;
 
+  local_irq_save(flags);
+
   /* read MFP timer C current value */
   ticks = st_mfp.tim_dt_c;
   /* The probability of underflow is less than 2% */
@@ -53,6 +55,8 @@ u32 atari_gettimeoffset(void)
 if (st_mfp.int_pn_b & (1 << 5))
   offset = TICK_SIZE;
 
+  local_irq_restore(flags);
+
   ticks = INT_TICKS - ticks;
   ticks = ticks * 1L / INT_TICKS;
 
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index 143ee9fa3893..0afdef10a5a4 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -206,8 +206,6 @@ void bvme6000_sched_init (irq_handler_t timer_routine)
 }
 
 
-/* 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
@@ -217,12 +215,16 @@ void bvme6000_sched_init (irq_handler_t timer_routine)
 
 u32 bvme6000_gettimeoffset(void)
 {
+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;
 unsigned char t1int, t1op;
 u32 v = 80, ov;
 
+local_irq_save(flags);
+
+msr = rtc->msr & 0xc0;
 rtc->msr = 0;  /* Ensure timer registers accessible */
 
 do {
@@ -245,6 +247,8 @@ u32 bvme6000_gettimeoffset(void)
v += 1; /* Int pending, + 10ms */
 rtc->msr = msr;
 
+local_irq_restore(flags);
+
 return v * 1000;
 }
 
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
index 289d928a46cb..5cf711fd0858 100644
--- a/arch/m68k/hp300/time.c
+++ b/arch/m68k/hp300/time.c
@@ -49,16 +49,22 @@ static irqreturn_t hp300_tick(int irq, void *dev_id)
 
 u32 hp300_gettimeoffset(void)
 {
-  /* Read current timer 1 value */
+  unsigned long flags;
   unsigned char lsb, msb1, msb2;
   unsigned short 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);
+
+  local_irq_restore(flags);
+
   ticks = INTVAL - ((msb2 << 8) | lsb);
   return ((USECS_PER_JIFFY * ticks) / INTVAL) * 1000;
 }
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index e4facff0c1f3..e5dff74f59b3 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -318,8 +318,11 @@ void via_debug_dump(void)
 
 u32 mac_gettimeoffset(void)
 {
+   unsigned long flags;
unsigned long ticks, offset = 0;
 
+   local_irq_save(flags);
+
/* read VIA1 timer 2 current value */
ticks = via1[vT1CL] | (via1[vT1CH] << 8);
/* The probability of underflow is less than 2% */
@@ -327,6 +330,8 @@ u32 mac_gettimeoffset(void)
/* Check for pending timer interrupt in VIA1 IFR */
if (via1[vIFR] & 0x40) offset = TICK_SIZE;
 
+   local_irq_restore(flags);
+

[RFC PATCH 09/13] m68k: bvme6000: Convert to clocksource API

2018-11-11 Thread Finn Thain
Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Signed-off-by: Finn Thain 
---
 arch/m68k/bvme6000/config.c | 54 -
 1 file changed, 35 insertions(+), 19 deletions(-)

diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index 3bd56bd04690..099cc6edebc8 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -43,12 +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)
 {
if (be16_to_cpu(bi->tag) == BI_VME_TYPE)
@@ -152,13 +147,34 @@ 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;
+
+#define RTC_TIMER_CLOCK_FREQ 800
+#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)
 {
+irq_handler_t tick_handler = dev_id;
 volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
-unsigned char msr = rtc->msr & 0xc0;
+unsigned char msr;
+unsigned long flags;
 
+local_irq_save(flags);
+msr = rtc->msr & 0xc0;
 rtc->msr = msr | 0x20; /* Ack the interrupt */
+clk_total += RTC_TIMER_CYCLES;
+local_irq_restore(flags);
 
 return tick_handler(irq, dev_id);
 }
@@ -179,14 +195,13 @@ 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, IRQF_TIMER,
+   "timer", timer_routine))
panic ("Couldn't register timer int");
 
 rtc->t1cr_omr = 0x04;  /* Mode 2, ext clk */
-rtc->t1msb = 3 >> 8;
-rtc->t1lsb = 3 & 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,6 +213,8 @@ void bvme6000_sched_init (irq_handler_t timer_routine)
 
 rtc->msr = msr;
 
+clocksource_register_hz(_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");
@@ -211,7 +228,7 @@ 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;
@@ -235,19 +252,18 @@ u32 bvme6000_gettimeoffset(void)
 } while (t1int != (rtc->msr & 0x20) ||
t1op != (pit->pcdr & 0x04) ||
abs(ov-v) > 80 ||
-   v > 39960);
+   v > RTC_TIMER_COUNT - (RTC_TIMER_COUNT / 100));
 
-v = 3 - v;
+v = RTC_TIMER_COUNT - v;
 if (!t1op) /* If in second half cycle.. */
-   v += 4;
-v /= 8;/* Convert ticks to microseconds */
+   v += RTC_TIMER_CYCLES / 2;
 if (t1int)
-   v += 1; /* Int pending, + 10ms */
+   v += RTC_TIMER_CYCLES;
 rtc->msr = msr;
 
 local_irq_restore(flags);
 
-return v * 1000;
+return clk_total + v;
 }
 
 /*
-- 
2.18.1



[RFC PATCH 03/13] m68k: mac: Fix VIA timer counter accesses

2018-11-11 Thread Finn Thain
This resolves some bugs that affect VIA timer counter accesses.
Firstly, keep track of lost interrupts caused by reading the counter.
Secondly, check for inconsistent results when reading the counter.
Finally, make allowance for the fact that the counter will be
decremented to 0x before being reloaded.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: Joshua Thompson 
Signed-off-by: Finn Thain 
---
 arch/m68k/mac/config.c |   7 +--
 arch/m68k/mac/via.c| 135 -
 2 files changed, 82 insertions(+), 60 deletions(-)

diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index cd9317d53276..2367c3792dc7 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -72,11 +72,6 @@ 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)
-{
-   via_init_clock(vector);
-}
-
 /*
  * Parse a Macintosh-specific record in the bootinfo
  */
@@ -152,7 +147,7 @@ void __init config_mac(void)
if (!MACH_IS_MAC)
pr_err("ERROR: no Mac, but config_mac() called!!\n");
 
-   mach_sched_init = mac_sched_init;
+   mach_sched_init = via_init_clock;
mach_init_IRQ = mac_init_IRQ;
mach_get_model = mac_get_model;
arch_gettimeoffset = mac_gettimeoffset;
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index e5dff74f59b3..7130abec0b77 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  1
-#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,34 +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 flags;
-   unsigned long ticks, offset = 0;
-
-   local_irq_save(flags);
-
-   /* 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;
-
-   local_irq_restore(flags);
-
-   ticks = MAC_CLOCK_TICK - ticks;
-   ticks = ticks * 1L / 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.
@@ -606,3 +552,84 @@ 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 (100 / 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 bool lost_timer_intr;
+
+static irqreturn_t via_timer_handler(int irq, void *data)
+{
+   irq_handler_t func = data;
+   unsigned long flags;
+
+   local_irq_save(flags);
+   if (lost_timer_intr) {
+   lost_timer_intr = false;
+   local_irq_restore(flags);
+   func(irq, data);
+   } else
+   local_irq_restore(flags);
+   return func(irq, data);
+}
+
+void __init via_init_clock(irq_handler_t func)
+{
+   if (request_irq(IRQ_MAC_TIMER_1, via_timer_handler, 0, "timer", func)) {
+   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;
+}
+
+#define VIA_T1_INT_FLAG BIT(6)
+
+u32 

[RFC PATCH 10/13] m68k: hp300: Convert to clocksource API

2018-11-11 Thread Finn Thain
Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Cc: Philip Blundell 
Signed-off-by: Finn Thain 
---
 arch/m68k/hp300/time.c | 33 -
 1 file changed, 28 insertions(+), 5 deletions(-)

diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
index 5cf711fd0858..ff2fc65bc5e7 100644
--- a/arch/m68k/hp300/time.c
+++ b/arch/m68k/hp300/time.c
@@ -8,6 +8,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -19,6 +20,18 @@
 #include 
 #include 
 
+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,22 +45,29 @@
 #defineCLKMSB3 0xD
 
 /* This is for machines which generate the exact clock. */
-#define USECS_PER_JIFFY (100/HZ)
 
-#define INTVAL ((1 / 4) - 1)
+#define HP300_TIMER_CLOCK_FREQ 25
+#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)
 {
+   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));
+   clk_total += INTVAL;
+   local_irq_restore(flags);
+
/* Turn off the network and SCSI leds */
blinken_leds(0, 0xe0);
return vector(irq, NULL);
 }
 
-u32 hp300_gettimeoffset(void)
+static u64 hp300_read_clk(struct clocksource *cs)
 {
   unsigned long flags;
   unsigned char lsb, msb1, msb2;
@@ -66,7 +86,8 @@ u32 hp300_gettimeoffset(void)
   local_irq_restore(flags);
 
   ticks = INTVAL - ((msb2 << 8) | lsb);
-  return ((USECS_PER_JIFFY * ticks) / INTVAL) * 1000;
+
+  return clk_total + 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(_clk, HP300_TIMER_CLOCK_FREQ);
 }
-- 
2.18.1



[RFC PATCH 11/13] m68k: mac: Convert to clocksource API

2018-11-11 Thread Finn Thain
Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Cc: Joshua Thompson 
Signed-off-by: Finn Thain 
---
 arch/m68k/mac/via.c | 31 +++
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 7130abec0b77..c4c304470fae 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -23,6 +23,7 @@
  *
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -556,13 +557,23 @@ 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 (100 / 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;
 static bool lost_timer_intr;
 
 static irqreturn_t via_timer_handler(int irq, void *data)
@@ -573,16 +584,18 @@ static irqreturn_t via_timer_handler(int irq, void *data)
local_irq_save(flags);
if (lost_timer_intr) {
lost_timer_intr = false;
-   local_irq_restore(flags);
-   func(irq, data);
-   } else
-   local_irq_restore(flags);
+   clk_total += VIA_TIMER_CYCLES;
+   }
+   clk_total += VIA_TIMER_CYCLES;
+   local_irq_restore(flags);
+
return func(irq, data);
 }
 
 void __init via_init_clock(irq_handler_t func)
 {
-   if (request_irq(IRQ_MAC_TIMER_1, via_timer_handler, 0, "timer", func)) {
+   if (request_irq(IRQ_MAC_TIMER_1, via_timer_handler, IRQF_TIMER,
+   "timer", func)) {
pr_err("Couldn't register %s interrupt\n", "timer");
return;
}
@@ -592,11 +605,13 @@ void __init via_init_clock(irq_handler_t func)
via1[vT1CL] = VIA_TC_LOW;
via1[vT1CH] = VIA_TC_HIGH;
via1[vACR] |= 0x40;
+
+   clocksource_register_hz(_clk, VIA_CLOCK_FREQ);
 }
 
 #define VIA_T1_INT_FLAG BIT(6)
 
-u32 mac_gettimeoffset(void)
+static u64 mac_read_clk(struct clocksource *cs)
 {
unsigned long flags;
u8 count_high, count_high_new, count_low;
@@ -631,5 +646,5 @@ u32 mac_gettimeoffset(void)
count = ((count_high << 8) | count_low) + 1;
count = VIA_TIMER_CYCLES - count + offset;
 
-   return ((count * VIA_TIMER_INTERVAL) / VIA_TIMER_CYCLES) * 1000;
+   return clk_total + count;
 }
-- 
2.18.1



[RFC PATCH 13/13] m68k: mvme16x: Convert to clocksource API

2018-11-11 Thread Finn Thain
Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Signed-off-by: Finn Thain 
---
 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 f1ed52331df3..7bd3a25b2d75 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -49,12 +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);
 
@@ -348,9 +343,31 @@ 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 100
+#define PCC_TIMER_CYCLES (PCC_TIMER_CLOCK_FREQ / HZ)
+
 static irqreturn_t mvme16x_timer_int (int irq, void *dev_id)
 {
+irq_handler_t tick_handler = dev_id;
+unsigned long flags;
+
+local_irq_save(flags);
 *(volatile unsigned char *)0xfff4201b |= 8;
+clk_total += PCC_TIMER_CYCLES;
+local_irq_restore(flags);
+
 return tick_handler(irq, dev_id);
 }
 
@@ -359,16 +376,17 @@ 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 = 1; /* 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", mvme16x_timer_int))
+if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, IRQF_TIMER,
+   "timer", timer_routine))
panic ("Couldn't register timer int");
 
+clocksource_register_hz(_clk, PCC_TIMER_CLOCK_FREQ);
+
 if (brdno == 0x0162 || brdno == 0x172)
irq = MVME162_IRQ_ABORT;
 else
@@ -378,10 +396,11 @@ void mvme16x_sched_init (irq_handler_t timer_routine)
panic ("Couldn't register abort int");
 }
 
-
-u32 mvme16x_gettimeoffset(void)
+static u64 mvme16x_read_clk(struct clocksource *cs)
 {
-return (*(volatile u32 *)0xfff42008) * 1000;
+u32 count = *(volatile u32 *)0xfff42008;
+
+return clk_total + count;
 }
 
 int bcd2int (unsigned char b)
-- 
2.18.1



[RFC PATCH 00/13] m68k: Drop arch_gettimeoffset and adopt clocksource API

2018-11-11 Thread Finn Thain
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.

More testing and code review would be appreciated.


Finn Thain (13):
  arm: Fix mutual exclusion in arch_gettimeoffset
  m68k: Fix mutual exclusion in arch_gettimeoffset
  m68k: mac: Fix VIA timer counter accesses
  m68k: mac: Clean up unused timer definitions
  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: mac: Convert to clocksource API
  m68k: mvme147: Convert to clocksource API
  m68k: mvme16x: Convert to clocksource API

 arch/arm/mach-ebsa110/core.c  |   5 ++
 arch/arm/mach-rpc/time.c  |   5 ++
 arch/m68k/Kconfig |   1 -
 arch/m68k/amiga/config.c  |  47 +++---
 arch/m68k/apollo/config.c |   7 --
 arch/m68k/atari/config.c  |   2 -
 arch/m68k/atari/time.c|  45 --
 arch/m68k/bvme6000/config.c   |  66 +-
 arch/m68k/hp300/config.c  |   1 -
 arch/m68k/hp300/time.c|  41 +++--
 arch/m68k/hp300/time.h|   1 -
 arch/m68k/include/asm/macints.h   |   3 -
 arch/m68k/include/asm/mvme147hw.h |   1 -
 arch/m68k/mac/config.c|  10 +--
 arch/m68k/mac/via.c   | 145 --
 arch/m68k/mvme147/config.c|  51 ---
 arch/m68k/mvme16x/config.c|  48 ++
 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 -
 23 files changed, 326 insertions(+), 178 deletions(-)

-- 
2.18.1



[RFC PATCH 01/13] arm: Fix mutual exclusion in arch_gettimeoffset

2018-11-11 Thread Finn Thain
Implementations of arch_gettimeoffset are generally not re-entrant
and assume that interrupts have been disabled. Unfortunately this
pre-condition got broken in v2.6.32.

Fixes: 5cfc8ee0bb51 ("ARM: convert arm to arch_gettimeoffset()")
Signed-off-by: Finn Thain 
---
 arch/arm/mach-ebsa110/core.c | 5 +
 arch/arm/mach-rpc/time.c | 5 +
 2 files changed, 10 insertions(+)

diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c
index 688e5fed49a7..479f89a1accf 100644
--- a/arch/arm/mach-ebsa110/core.c
+++ b/arch/arm/mach-ebsa110/core.c
@@ -160,12 +160,17 @@ static void __init ebsa110_init_early(void)
  */
 static u32 ebsa110_gettimeoffset(void)
 {
+   unsigned long flags;
unsigned long offset, count;
 
+   local_irq_save(flags);
+
__raw_writeb(0x40, PIT_CTRL);
count = __raw_readb(PIT_T1);
count |= __raw_readb(PIT_T1) << 8;
 
+   local_irq_restore(flags);
+
/*
 * If count > COUNT, make the number negative.
 */
diff --git a/arch/arm/mach-rpc/time.c b/arch/arm/mach-rpc/time.c
index 2689771c1d38..852bb3801638 100644
--- a/arch/arm/mach-rpc/time.c
+++ b/arch/arm/mach-rpc/time.c
@@ -29,9 +29,12 @@
 
 static u32 ioc_timer_gettimeoffset(void)
 {
+   unsigned long flags;
unsigned int count1, count2, status;
long offset;
 
+   local_irq_save(flags);
+
ioc_writeb (0, IOC_T0LATCH);
barrier ();
count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
@@ -42,6 +45,8 @@ static u32 ioc_timer_gettimeoffset(void)
barrier ();
count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
 
+   local_irq_restore(flags);
+
offset = count2;
if (count2 < count1) {
/*
-- 
2.18.1



[RFC PATCH 05/13] m68k: apollo, q40, sun3, sun3x: Remove arch_gettimeoffset implementations

2018-11-11 Thread Finn Thain
These dummy implementations are no better than
default_arch_gettimeoffset() so remove them.

Cc: Sam Creasey 
Signed-off-by: Finn Thain 
---
 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 = 0x;
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 047e2bcee3d7..5328220ed2d8 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 void sun3x_timer_tick(int irq, void *dev_id, struct pt_regs *regs)
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 

[RFC PATCH 12/13] m68k: mvme147: Convert to clocksource API

2018-11-11 Thread Finn Thain
Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Signed-off-by: Finn Thain 
---
 arch/m68k/include/asm/mvme147hw.h |  1 -
 arch/m68k/mvme147/config.c| 43 +++
 2 files changed, 32 insertions(+), 12 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_ABORT0x07
 #define PCC_LEVEL_SERIAL   0x04
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index ff7141cf27d1..e7bd40e510d9 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -44,12 +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)
 {
uint16_t tag = be16_to_cpu(bi->tag);
@@ -97,34 +92,59 @@ 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 16
+#define PCC_TIMER_CYCLES (PCC_TIMER_CLOCK_FREQ / HZ)
+#define PCC_TIMER_PRELOAD(0x1 - PCC_TIMER_CYCLES)
 
 /* Using pcc tick timer 1 */
 
 static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
 {
+   irq_handler_t tick_handler = dev_id;
+   unsigned long flags;
+
m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;
m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
+
+   local_irq_save(flags);
+   clk_total += PCC_TIMER_CYCLES;
+   local_irq_restore(flags);
+
return tick_handler(irq, dev_id);
 }
 
 
 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, 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 0x 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(_clk, PCC_TIMER_CLOCK_FREQ);
 }
 
 /* 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;
@@ -139,7 +159,8 @@ u32 mvme147_gettimeoffset(void)
local_irq_restore(flags);
 
n -= PCC_TIMER_PRELOAD;
-   return ((unsigned long)n * 25 / 4) * 1000;
+
+   return clk_total + n;
 }
 
 static int bcd2int (unsigned char b)
-- 
2.18.1



[RFC PATCH 06/13] m68k: Drop ARCH_USES_GETTIMEOFFSET

2018-11-11 Thread Finn Thain
The functions that implement arch_gettimeoffset are re-used by
new clocksource drivers in subsequent patches.

Cc: Philip Blundell 
Cc: Michael Schmitz 
Cc: Joshua Thompson 
Signed-off-by: Finn Thain 
---
 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 5ec3687984a9..a575ad419b23 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=0x 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 = 0xff;
 #if IS_ENABLED(CONFIG_INPUT_M68K_BEEP)
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index 0afdef10a5a4..3bd56bd04690 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);
@@ -110,7 +109,6 @@ void __init config_bvme6000(void)
 mach_max_dma_address = 0x;
 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 2367c3792dc7..cecaaa100791 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 

[RFC PATCH 07/13] m68k: amiga: Convert to clocksource API

2018-11-11 Thread Finn Thain
Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Signed-off-by: Finn Thain 
---
 arch/m68k/amiga/config.c | 38 +++---
 1 file changed, 31 insertions(+), 7 deletions(-)

diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index a575ad419b23..40ebd471cc3c 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -461,7 +462,30 @@ 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;
+
+static irqreturn_t ciab_timer_handler(int irq, void *data)
+{
+   irq_handler_t timer_routine = data;
+   unsigned long flags;
+
+   local_irq_save(flags);
+   clk_total += jiffy_ticks;
+   local_irq_restore(flags);
+
+   return timer_routine(irq, data);
+}
 
 static void __init amiga_sched_init(irq_handler_t timer_routine)
 {
@@ -481,15 +505,16 @@ 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 1
+   clocksource_register_hz(_clk, amiga_eclock);
+}
 
-static u32 amiga_gettimeoffset(void)
+static u64 amiga_read_clk(struct clocksource *cs)
 {
unsigned long flags;
unsigned short hi, lo, hi2;
@@ -512,14 +537,13 @@ static u32 amiga_gettimeoffset(void)
if (ticks > jiffy_ticks / 2)
/* check for pending interrupt */
if (cia_set_irq(_base, 0) & CIA_ICR_TA)
-   offset = 1;
+   offset = jiffy_ticks;
 
local_irq_restore(flags);
 
ticks = jiffy_ticks - ticks;
-   ticks = (1 * ticks) / jiffy_ticks;
 
-   return (ticks + offset) * 1000;
+   return clk_total + ticks + offset;
 }
 
 static void amiga_reset(void)  __noreturn;
-- 
2.18.1



Re: m68k using deprecated internal APIs?

2018-11-11 Thread Finn Thain
On Mon, 12 Nov 2018, Michael Schmitz wrote:

> 
> That's ultimately for Geert to decide - I'll yet have to look at your 
> mac patches to even get a vague idea what this conversion involves, but 
> I can certainly test whatever you came up with for Mac on Atari.
> 

Thanks. I'll send out the latest patches for people to test.

> Tick granularity is 40 us at best on Atari with the current timer 
> configuration, and can't be increased without increasing HZ. I suspect 
> the limitations on Mac are similar?
> 

If I understand correctly, removing arch_gettimeoffset without adding a 
clocksource would reduce timer accuracy to 10 ms regardless of platform 
(because that's what the default jiffies clocksource offers).

-- 

> Cheers,
> 
>   Michael
> 


Re: [PATCH 02/17] x86: Add support for ZSTD-compressed kernel

2018-11-11 Thread Ingo Molnar


* Adam Borowski  wrote:

> From: Nick Terrell 
> 
> Integrates the ZSTD decompression code to the x86 pre-boot code.
> 
> Zstandard requires slightly more memory during the kernel decompression
> on x86 (192 KB vs 64 KB), and the memory usage is independent of the
> window size.
> 
> Zstandard requires memory proportional to the window size used during
> compression for decompressing the ramdisk image, since streaming mode is
> used. Newer versions of zstd (1.3.2+) list the window size of a file
> with `zstd -lv '. The absolute maximum amount of memory required
> is just over 8 MB.
> 
> Signed-off-by: Nick Terrell 
> ---
>  Documentation/x86/boot.txt| 6 +++---
>  arch/x86/Kconfig  | 1 +
>  arch/x86/boot/compressed/Makefile | 5 -
>  arch/x86/boot/compressed/misc.c   | 4 
>  arch/x86/boot/header.S| 8 +++-
>  arch/x86/include/asm/boot.h   | 6 --
>  6 files changed, 23 insertions(+), 7 deletions(-)

Acked-by: Ingo Molnar 

> diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
> index 4c881c850125..af2efb256527 100644
> --- a/arch/x86/boot/header.S
> +++ b/arch/x86/boot/header.S
> @@ -526,8 +526,14 @@ pref_address:.quad LOAD_PHYSICAL_ADDR
> # preferred load addr
>  # the size-dependent part now grows so fast.
>  #
>  # extra_bytes = (uncompressed_size >> 8) + 65536
> +#
> +# ZSTD compressed data grows by at most 3 bytes per 128K, and only has a 22
> +# byte fixed overhead but has a maximum block size of 128K, so it needs a
> +# larger margin.
> +#
> +# extra_bytes = (uncompressed_size >> 8) + 131072
>  
> -#define ZO_z_extra_bytes ((ZO_z_output_len >> 8) + 65536)
> +#define ZO_z_extra_bytes ((ZO_z_output_len >> 8) + 131072)

This change would also affect other decompressors, not just ZSTD, 
correct?

Might want to split this change out into a separate preparatory patch to 
allow it to be bisected to, or at least mention it in the changelog more 
explicitly?

Thanks,

Ingo


Re: m68k using deprecated internal APIs?

2018-11-11 Thread Michael Schmitz

Thanks Finn,

Am 09.11.2018 um 12:42 schrieb Finn Thain:

On Sun, 28 Oct 2018, Geert Uytterhoeven wrote:



The example I gave was GENERIC_CLOCKEVENTS on m68, which is
supported on most but not all machines there.


That suggests that the removal of just those machines would suffice
(as opposed to the removal of the entire arch).

Also, Documentation/features/time/clockevents/arch-support.txt says,
|m68k: |  ok  |

These two observations make me wonder whether the clockevents feature
is related to the discussion quoted above (?)


GENERIC_CLOCKEVENTS is selected only for a few Coldfire CPU types.



!GENERIC_CLOCKEVENTS implies PREEMPT_NONE, and disables the "Timers
subsystem" (i.e. the NO_HZ config options), but it works fine -- I was
able to convert the Mac port to !ARCH_USES_GETTIMEOFFSET &&
!GENERIC_CLOCKEVENTS. (Like many of the Coldfire CPU types.)

You can see those patches here,
https://github.com/fthain/linux/commits/mac68k-queue/

Note that !ARCH_USES_GETTIMEOFFSET is a build-time choice, meaning that
all platforms need to be converted together.

Also, some platforms will need to adopt the clocksource API, otherwise the
built-in "jiffies" clocksource will get used, causing a regression in
timer accuracy.

Conversion to the clocksource API is straight-forward where the platform
already implements arch_gettimeoffset. The conversion is discussed in
include/linux/time.h:

/* Some architectures do not supply their own clocksource.
 * This is mainly the case in architectures that get their
 * inter-tick times by reading the counter on their interval
 * timer. Since these timers wrap every tick, they're not really
 * useful as clocksources. Wrapping them to act like one is possible
 * but not very efficient. So we provide a callout these arches
 * can implement for use with the jiffies clocksource to provide
 * finer then tick granular time.
 */

(Not sure what is meant by "not very efficient" here.)

Certain 680x0 platforms do not implement arch_gettimeoffset: apollo, q40,
sun3, sun3x. These platforms can fall back on the "jiffies" clocksource
with no loss of timer accuracy, so conversion for these platforms is
trivial.

Should I continue with the clocksource API conversion for the other
platforms: amiga, atari, bvme6000, hp300, mvme147, mvme16x? This would
allow for removal of "select ARCH_USES_GETTIMEOFFSET" (and satisfy
Documentation/features/time/modern-timekeeping) without loss of timer
accuracy.

Alternatively, we could defer the clocksource API conversion, leaving it
up to the platform maintainers (who can actually test the driver changes).
But that would mean that many platforms would suffer a regression in timer
accuracy upon removal of arch_gettimeoffset.



That's ultimately for Geert to decide - I'll yet have to look at your 
mac patches to even get a vague idea what this conversion involves, but 
I can certainly test whatever you came up with for Mac on Atari.


Tick granularity is 40 us at best on Atari with the current timer 
configuration, and can't be increased without increasing HZ. I suspect 
the limitations on Mac are similar?


Cheers,

Michael