Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2162691imu; Sun, 18 Nov 2018 17:26:01 -0800 (PST) X-Google-Smtp-Source: AFSGD/WCnr8FOJqwtd7M8blSor3iA9Xo4VAFKC8dEuXHX7l5oLy05TrSxeVvdEbR+w41l1eC7kyo X-Received: by 2002:a17:902:7686:: with SMTP id m6mr6150633pll.179.1542590761728; Sun, 18 Nov 2018 17:26:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542590761; cv=none; d=google.com; s=arc-20160816; b=lQZJDx/8dE9dpQ0W//TAojtsW/bOHOstGSjhmVsI4a09ystV5LaZ6NwJyDj7nhKFcm OT26CAGAbEaMRys7uYGRqE/xOXsdi8cP/kr/DoEFul5SZmhGvptYzH4wqyLdl/rFyFuo zcud0s+fIrSlgurQ9ctC0vnzNpR+3sDeOfJL3Ki8O4En/PRu1zvUZDBiSDGgEoPcD639 HN7VU6Y6YCnOW9kWzSpdwz9oeLVHnLMbxxQuAA0AVFSwctdQJ1UT5uvz4S/C5w2P0Aon OdGFzXC85yskIHu8G2fUhuw98qEdA7BvJOrbzZBk82h5HtaLHWSbKj+hHjUOE/uOhkgL +ySQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:date:subject:from:references:in-reply-to :message-id:cc:to; bh=Mi/XOo9REizw7t24wub0cKSeALdch0vOTDst83YO3bM=; b=YBShJ2M/F2bJZ7UdU+P2EUW04zpMQf0Rr6quCBDObcGF3gxPuh110RaBpmY71E+nOh g8Bqu1awcj3NUkkAKKAGaeFok+xSBfM9vKxxSQoImIbVU2mE5hFqG9fvXNShOtvOFsxk 0lnPNiXkT3SfHXZeg570YVu5sXeHdF2MieyczozqpsN+AL/d+ZERB4oDv3EKKtTFeDb1 86G4AFHED5iNoEi5rdLTj6T9GvoB/brwbuWoZdtAII7AOMOM/HVvrh/6kzqFTMErYvkU 3AycIytQO4MA0JTL6G9GIT8eTfifXZbZOUgZw0lizIfq8GjuonDWbtOwk88cZOifiAc3 xT6Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e9si25503896plt.330.2018.11.18.17.25.47; Sun, 18 Nov 2018 17:26:01 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727943AbeKSLoR (ORCPT + 99 others); Mon, 19 Nov 2018 06:44:17 -0500 Received: from kvm5.telegraphics.com.au ([98.124.60.144]:49114 "EHLO kvm5.telegraphics.com.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726235AbeKSLoR (ORCPT ); Mon, 19 Nov 2018 06:44:17 -0500 Received: by kvm5.telegraphics.com.au (Postfix, from userid 502) id 7960B29DF6; Sun, 18 Nov 2018 20:22:17 -0500 (EST) To: Geert Uytterhoeven , Joshua Thompson Cc: Andreas Schwab , Arnd Bergmann , Stephen N Chivers , Thomas Gleixner , Daniel Lezcano , Michael Schmitz , John Stultz , Linus Walleij , linux-m68k@lists.linux-m68k.org, linux-kernel@vger.kernel.org Message-Id: <423caba434560f3cff60ab68ae0b71d5e635663c.1542589838.git.fthain@telegraphics.com.au> In-Reply-To: References: From: Finn Thain Subject: [RFC PATCH v2 02/14] m68k: mac: Fix VIA timer counter accesses Date: Mon, 19 Nov 2018 12:10:38 +1100 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- 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 | 105 +++++++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 49 deletions(-) diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index 2ab85b6eb4fe..d1dbf9017300 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,59 @@ 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; + while (via1[vT1CH] == 0xFF) + /* spin */; + } + if (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